xref: /petsc/src/mat/interface/matrix.c (revision 639f9d9dbbc54d6ac4e42e98283c540b41bb2cee)
1 
2 #ifndef lint
3 static char vcid[] = "$Id: matrix.c,v 1.205 1996/10/29 17:02:05 curfman Exp bsmith $";
4 #endif
5 
6 /*
7    This is where the abstract matrix operations are defined
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 #include "draw.h"
15 
16 
17 /*@C
18    MatGetRow - Gets a row of a matrix.  You MUST call MatRestoreRow()
19    for each row that you get to ensure that your application does
20    not bleed memory.
21 
22    Input Parameters:
23 .  mat - the matrix
24 .  row - the row to get
25 
26    Output Parameters:
27 .  ncols -  the number of nonzeros in the row
28 .  cols - if nonzero, the column numbers
29 .  vals - if nonzero, the values
30 
31    Notes:
32    This routine is provided for people who need to have direct access
33    to the structure of a matrix.  We hope that we provide enough
34    high-level matrix routines that few users will need it.
35 
36    For better efficiency, set cols and/or vals to PETSC_NULL if you do
37    not wish to extract these quantities.
38 
39    The user can only examine the values extracted with MatGetRow();
40    the values cannot be altered.  To change the matrix entries, one
41    must use MatSetValues().
42 
43    Caution:
44    Do not try to change the contents of the output arrays (cols and vals).
45    In some cases, this may corrupt the matrix.
46 
47 .keywords: matrix, row, get, extract
48 
49 .seealso: MatRestoreRow(), MatSetValues()
50 @*/
51 int MatGetRow(Mat mat,int row,int *ncols,int **cols,Scalar **vals)
52 {
53   int   ierr;
54   PetscValidHeaderSpecific(mat,MAT_COOKIE);
55   PetscValidIntPointer(ncols);
56   if (!mat->assembled) SETERRQ(1,"MatGetRow:Not for unassembled matrix");
57   if (mat->factor) SETERRQ(1,"MatGetRow:Not for factored matrix");
58   PLogEventBegin(MAT_GetRow,mat,0,0,0);
59   ierr = (*mat->ops.getrow)(mat,row,ncols,cols,vals); CHKERRQ(ierr);
60   PLogEventEnd(MAT_GetRow,mat,0,0,0);
61   return 0;
62 }
63 
64 /*@C
65    MatRestoreRow - Frees any temporary space allocated by MatGetRow().
66 
67    Input Parameters:
68 .  mat - the matrix
69 .  row - the row to get
70 .  ncols, cols - the number of nonzeros and their columns
71 .  vals - if nonzero the column values
72 
73 .keywords: matrix, row, restore
74 
75 .seealso:  MatGetRow()
76 @*/
77 int MatRestoreRow(Mat mat,int row,int *ncols,int **cols,Scalar **vals)
78 {
79   PetscValidHeaderSpecific(mat,MAT_COOKIE);
80   PetscValidIntPointer(ncols);
81   if (!mat->assembled) SETERRQ(1,"MatRestoreRow:Not for unassembled matrix");
82   if (!mat->ops.restorerow) return 0;
83   return (*mat->ops.restorerow)(mat,row,ncols,cols,vals);
84 }
85 /*@
86    MatView - Visualizes a matrix object.
87 
88    Input Parameters:
89 .  mat - the matrix
90 .  ptr - visualization context
91 
92    Notes:
93    The available visualization contexts include
94 $     VIEWER_STDOUT_SELF - standard output (default)
95 $     VIEWER_STDOUT_WORLD - synchronized standard
96 $       output where only the first processor opens
97 $       the file.  All other processors send their
98 $       data to the first processor to print.
99 
100    The user can open alternative vistualization contexts with
101 $    ViewerFileOpenASCII() - output to a specified file
102 $    ViewerFileOpenBinary() - output in binary to a
103 $         specified file; corresponding input uses MatLoad()
104 $    ViewerDrawOpenX() - output nonzero matrix structure to
105 $         an X window display
106 $    ViewerMatlabOpen() - output matrix to Matlab viewer.
107 $         Currently only the sequential dense and AIJ
108 $         matrix types support the Matlab viewer.
109 
110    The user can call ViewerSetFormat() to specify the output
111    format of ASCII printed objects (when using VIEWER_STDOUT_SELF,
112    VIEWER_STDOUT_WORLD and ViewerFileOpenASCII).  Available formats include
113 $    VIEWER_FORMAT_ASCII_DEFAULT - default, prints matrix contents
114 $    VIEWER_FORMAT_ASCII_MATLAB - Matlab format
115 $    VIEWER_FORMAT_ASCII_IMPL - implementation-specific format
116 $      (which is in many cases the same as the default)
117 $    VIEWER_FORMAT_ASCII_INFO - basic information about the matrix
118 $      size and structure (not the matrix entries)
119 $    VIEWER_FORMAT_ASCII_INFO_LONG - more detailed information about the
120 $      matrix structure
121 
122 .keywords: matrix, view, visualize, output, print, write, draw
123 
124 .seealso: ViewerSetFormat(), ViewerFileOpenASCII(), ViewerDrawOpenX(),
125           ViewerMatlabOpen(), ViewerFileOpenBinary(), MatLoad()
126 @*/
127 int MatView(Mat mat,Viewer viewer)
128 {
129   int          format, ierr, rows, cols;
130   FILE         *fd;
131   char         *cstr;
132   ViewerType   vtype;
133   MPI_Comm     comm = mat->comm;
134 
135   PetscValidHeaderSpecific(mat,MAT_COOKIE);
136   if (!mat->assembled) SETERRQ(1,"MatView:Not for unassembled matrix");
137 
138   if (!viewer) {
139     viewer = VIEWER_STDOUT_SELF;
140   }
141 
142   ierr = ViewerGetType(viewer,&vtype);
143   if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
144     ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr);
145     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
146     if (format == VIEWER_FORMAT_ASCII_INFO || format == VIEWER_FORMAT_ASCII_INFO_LONG) {
147       PetscFPrintf(comm,fd,"Matrix Object:\n");
148       ierr = MatGetType(mat,PETSC_NULL,&cstr); CHKERRQ(ierr);
149       ierr = MatGetSize(mat,&rows,&cols); CHKERRQ(ierr);
150       PetscFPrintf(comm,fd,"  type=%s, rows=%d, cols=%d\n",cstr,rows,cols);
151       if (mat->ops.getinfo) {
152         MatInfo info;
153         ierr = MatGetInfo(mat,MAT_GLOBAL_SUM,&info); CHKERRQ(ierr);
154         PetscFPrintf(comm,fd,"  total: nonzeros=%d, allocated nonzeros=%d\n",
155                      (int)info.nz_used,(int)info.nz_allocated);
156       }
157     }
158   }
159   if (mat->view) {ierr = (*mat->view)((PetscObject)mat,viewer); CHKERRQ(ierr);}
160   return 0;
161 }
162 
163 /*@C
164    MatDestroy - Frees space taken by a matrix.
165 
166    Input Parameter:
167 .  mat - the matrix
168 
169 .keywords: matrix, destroy
170 @*/
171 int MatDestroy(Mat mat)
172 {
173   int ierr;
174   PetscValidHeaderSpecific(mat,MAT_COOKIE);
175   ierr = (*mat->destroy)((PetscObject)mat); CHKERRQ(ierr);
176   return 0;
177 }
178 /*@
179    MatValid - Checks whether a matrix object is valid.
180 
181    Input Parameter:
182 .  m - the matrix to check
183 
184    Output Parameter:
185    flg - flag indicating matrix status, either
186 $     PETSC_TRUE if matrix is valid;
187 $     PETSC_FALSE otherwise.
188 
189 .keywords: matrix, valid
190 @*/
191 int MatValid(Mat m,PetscTruth *flg)
192 {
193   PetscValidIntPointer(flg);
194   if (!m)                           *flg = PETSC_FALSE;
195   else if (m->cookie != MAT_COOKIE) *flg = PETSC_FALSE;
196   else                              *flg = PETSC_TRUE;
197   return 0;
198 }
199 
200 /*@
201    MatSetValues - Inserts or adds a block of values into a matrix.
202    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
203    MUST be called after all calls to MatSetValues() have been completed.
204 
205    Input Parameters:
206 .  mat - the matrix
207 .  v - a logically two-dimensional array of values
208 .  m, indexm - the number of rows and their global indices
209 .  n, indexn - the number of columns and their global indices
210 .  addv - either ADD_VALUES or INSERT_VALUES, where
211 $     ADD_VALUES - adds values to any existing entries
212 $     INSERT_VALUES - replaces existing entries with new values
213 
214    Notes:
215    By default the values, v, are row-oriented and unsorted.
216    See MatSetOptions() for other options.
217 
218    Calls to MatSetValues() with the INSERT_VALUES and ADD_VALUES
219    options cannot be mixed without intervening calls to the assembly
220    routines.
221 
222 .keywords: matrix, insert, add, set, values
223 
224 .seealso: MatSetOptions(), MatAssemblyBegin(), MatAssemblyEnd()
225 @*/
226 int MatSetValues(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v,InsertMode addv)
227 {
228   int ierr;
229   PetscValidHeaderSpecific(mat,MAT_COOKIE);
230   if (!m || !n) return 0; /* no values to insert */
231   PetscValidIntPointer(idxm);
232   PetscValidIntPointer(idxn);
233   PetscValidScalarPointer(v);
234   if (mat->factor) SETERRQ(1,"MatSetValues:Not for factored matrix");
235 
236   if (mat->assembled) {
237     mat->was_assembled = PETSC_TRUE;
238     mat->assembled     = PETSC_FALSE;
239   }
240   PLogEventBegin(MAT_SetValues,mat,0,0,0);
241   ierr = (*mat->ops.setvalues)(mat,m,idxm,n,idxn,v,addv);CHKERRQ(ierr);
242   PLogEventEnd(MAT_SetValues,mat,0,0,0);
243   return 0;
244 }
245 
246 /*@
247    MatGetValues - Gets a block of values from a matrix.
248 
249    Input Parameters:
250 .  mat - the matrix
251 .  v - a logically two-dimensional array for storing the values
252 .  m, indexm - the number of rows and their global indices
253 .  n, indexn - the number of columns and their global indices
254 
255    Notes:
256    The user must allocate space (m*n Scalars) for the values, v.
257    The values, v, are then returned in a row-oriented format,
258    analogous to that used by default in MatSetValues().
259 
260 .keywords: matrix, get, values
261 
262 .seealso: MatGetRow(), MatGetSubmatrices(), MatSetValues()
263 @*/
264 int MatGetValues(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v)
265 {
266   int ierr;
267 
268   PetscValidHeaderSpecific(mat,MAT_COOKIE);
269   PetscValidIntPointer(idxm);
270   PetscValidIntPointer(idxn);
271   PetscValidScalarPointer(v);
272   if (!mat->assembled) SETERRQ(1,"MatGetValues:Not for unassembled matrix");
273   if (mat->factor) SETERRQ(1,"MatGetValues:Not for factored matrix");
274 
275   PLogEventBegin(MAT_GetValues,mat,0,0,0);
276   ierr = (*mat->ops.getvalues)(mat,m,idxm,n,idxn,v); CHKERRQ(ierr);
277   PLogEventEnd(MAT_GetValues,mat,0,0,0);
278   return 0;
279 }
280 
281 /* --------------------------------------------------------*/
282 /*@
283    MatMult - Computes the matrix-vector product, y = Ax.
284 
285    Input Parameters:
286 .  mat - the matrix
287 .  x   - the vector to be multilplied
288 
289    Output Parameters:
290 .  y - the result
291 
292    Notes:
293    The vectors x and y cannot be the same.  I.e., one cannot
294    call MatMult(A,y,y).
295 
296 .keywords: matrix, multiply, matrix-vector product
297 
298 .seealso: MatMultTrans(), MatMultAdd(), MatMultTransAdd()
299 @*/
300 int MatMult(Mat mat,Vec x,Vec y)
301 {
302   int ierr;
303   PetscValidHeaderSpecific(mat,MAT_COOKIE);
304   PetscValidHeaderSpecific(x,VEC_COOKIE);PetscValidHeaderSpecific(y,VEC_COOKIE);
305   if (!mat->assembled) SETERRQ(1,"MatMult:Not for unassembled matrix");
306   if (mat->factor) SETERRQ(1,"MatMult:Not for factored matrix");
307   if (x == y) SETERRQ(1,"MatMult:x and y must be different vectors");
308   if (mat->N != x->N) SETERRQ(PETSC_ERR_SIZ,"MatMult:Mat mat,Vec x: global dim");
309   if (mat->M != y->N) SETERRQ(PETSC_ERR_SIZ,"MatMult:Mat mat,Vec y: global dim");
310   if (mat->m != y->n) SETERRQ(PETSC_ERR_SIZ,"MatMult:Mat mat,Vec y: local dim");
311 
312   PLogEventBegin(MAT_Mult,mat,x,y,0);
313   ierr = (*mat->ops.mult)(mat,x,y); CHKERRQ(ierr);
314   PLogEventEnd(MAT_Mult,mat,x,y,0);
315 
316   return 0;
317 }
318 /*@
319    MatMultTrans - Computes matrix transpose times a vector.
320 
321    Input Parameters:
322 .  mat - the matrix
323 .  x   - the vector to be multilplied
324 
325    Output Parameters:
326 .  y - the result
327 
328    Notes:
329    The vectors x and y cannot be the same.  I.e., one cannot
330    call MatMultTrans(A,y,y).
331 
332 .keywords: matrix, multiply, matrix-vector product, transpose
333 
334 .seealso: MatMult(), MatMultAdd(), MatMultTransAdd()
335 @*/
336 int MatMultTrans(Mat mat,Vec x,Vec y)
337 {
338   int ierr;
339   PetscValidHeaderSpecific(mat,MAT_COOKIE);
340   PetscValidHeaderSpecific(x,VEC_COOKIE); PetscValidHeaderSpecific(y,VEC_COOKIE);
341   if (!mat->assembled) SETERRQ(1,"MatMultTrans:Not for unassembled matrix");
342   if (mat->factor) SETERRQ(1,"MatMult:Not for factored matrix");
343   if (x == y) SETERRQ(1,"MatMultTrans:x and y must be different vectors");
344   if (mat->M != x->N) SETERRQ(PETSC_ERR_SIZ,"MatMultTrans:Mat mat,Vec x: global dim");
345   if (mat->N != y->N) SETERRQ(PETSC_ERR_SIZ,"MatMultTrans:Mat mat,Vec y: global dim");
346   PLogEventBegin(MAT_MultTrans,mat,x,y,0);
347   ierr = (*mat->ops.multtrans)(mat,x,y); CHKERRQ(ierr);
348   PLogEventEnd(MAT_MultTrans,mat,x,y,0);
349   return 0;
350 }
351 /*@
352     MatMultAdd -  Computes v3 = v2 + A * v1.
353 
354     Input Parameters:
355 .   mat - the matrix
356 .   v1, v2 - the vectors
357 
358     Output Parameters:
359 .   v3 - the result
360 
361    Notes:
362    The vectors v1 and v3 cannot be the same.  I.e., one cannot
363    call MatMultAdd(A,v1,v2,v1).
364 
365 .keywords: matrix, multiply, matrix-vector product, add
366 
367 .seealso: MatMultTrans(), MatMult(), MatMultTransAdd()
368 @*/
369 int MatMultAdd(Mat mat,Vec v1,Vec v2,Vec v3)
370 {
371   int ierr;
372   PetscValidHeaderSpecific(mat,MAT_COOKIE);PetscValidHeaderSpecific(v1,VEC_COOKIE);
373   PetscValidHeaderSpecific(v2,VEC_COOKIE); PetscValidHeaderSpecific(v3,VEC_COOKIE);
374   if (!mat->assembled) SETERRQ(1,"MatMultAdd:Not for unassembled matrix");
375   if (mat->factor) SETERRQ(1,"MatMult:Not for factored matrix");
376   if (mat->N != v1->N) SETERRQ(PETSC_ERR_SIZ,"MatMultAdd:Mat mat,Vec v1: global dim");
377   if (mat->M != v2->N) SETERRQ(PETSC_ERR_SIZ,"MatMultAdd:Mat mat,Vec v2: global dim");
378   if (mat->M != v3->N) SETERRQ(PETSC_ERR_SIZ,"MatMultAdd:Mat mat,Vec v3: global dim");
379   if (mat->m != v3->n) SETERRQ(PETSC_ERR_SIZ,"MatMultAdd:Mat mat,Vec v3: local dim");
380   if (mat->m != v2->n) SETERRQ(PETSC_ERR_SIZ,"MatMultAdd:Mat mat,Vec v2: local dim");
381   if (v1 == v3) SETERRQ(1,"MatMultAdd:v1 and v3 must be different vectors");
382 
383   PLogEventBegin(MAT_MultAdd,mat,v1,v2,v3);
384   ierr = (*mat->ops.multadd)(mat,v1,v2,v3); CHKERRQ(ierr);
385   PLogEventEnd(MAT_MultAdd,mat,v1,v2,v3);
386   return 0;
387 }
388 /*@
389    MatMultTransAdd - Computes v3 = v2 + A' * v1.
390 
391    Input Parameters:
392 .  mat - the matrix
393 .  v1, v2 - the vectors
394 
395    Output Parameters:
396 .  v3 - the result
397 
398    Notes:
399    The vectors v1 and v3 cannot be the same.  I.e., one cannot
400    call MatMultTransAdd(A,v1,v2,v1).
401 
402 .keywords: matrix, multiply, matrix-vector product, transpose, add
403 
404 .seealso: MatMultTrans(), MatMultAdd(), MatMult()
405 @*/
406 int MatMultTransAdd(Mat mat,Vec v1,Vec v2,Vec v3)
407 {
408   int ierr;
409   PetscValidHeaderSpecific(mat,MAT_COOKIE);PetscValidHeaderSpecific(v1,VEC_COOKIE);
410   PetscValidHeaderSpecific(v2,VEC_COOKIE);PetscValidHeaderSpecific(v3,VEC_COOKIE);
411   if (!mat->assembled) SETERRQ(1,"MatMultTransAdd:Not for unassembled matrix");
412   if (mat->factor) SETERRQ(1,"MatMult:Not for factored matrix");
413   if (!mat->ops.multtransadd) SETERRQ(PETSC_ERR_SUP,"MatMultTransAdd");
414   if (v1 == v3) SETERRQ(1,"MatMultTransAdd:v1 and v3 must be different vectors");
415   if (mat->M != v1->N) SETERRQ(PETSC_ERR_SIZ,"MatMultTransAdd:Mat mat,Vec v1: global dim");
416   if (mat->N != v2->N) SETERRQ(PETSC_ERR_SIZ,"MatMultTransAdd:Mat mat,Vec v2: global dim");
417   if (mat->N != v3->N) SETERRQ(PETSC_ERR_SIZ,"MatMultTransAdd:Mat mat,Vec v3: global dim");
418 
419   PLogEventBegin(MAT_MultTransAdd,mat,v1,v2,v3);
420   ierr = (*mat->ops.multtransadd)(mat,v1,v2,v3); CHKERRQ(ierr);
421   PLogEventEnd(MAT_MultTransAdd,mat,v1,v2,v3);
422   return 0;
423 }
424 /* ------------------------------------------------------------*/
425 /*@C
426    MatGetInfo - Returns information about matrix storage (number of
427    nonzeros, memory, etc.).
428 
429    Input Parameters:
430 .  mat - the matrix
431 
432    Output Parameters:
433 .  flag - flag indicating the type of parameters to be returned
434 $    flag = MAT_LOCAL: local matrix
435 $    flag = MAT_GLOBAL_MAX: maximum over all processors
436 $    flag = MAT_GLOBAL_SUM: sum over all processors
437 .  info - matrix information context
438 
439    Notes:
440    The MatInfo context contains a variety of matrix data, including
441    number of nonzeros allocated and used, number of mallocs during
442    matrix assembly, etc.  Additional information for factored matrices
443    is provided (such as the fill ratio, number of mallocs during
444    factorization, etc.).  Much of this info is printed to STDOUT
445    when using the runtime options
446 $       -log_info -mat_view_info
447 
448    Example for C/C++ Users:
449    See the file $(PETSC_DIR)/include/mat.h for a complete list of
450    data within the MatInfo context.  For example,
451 $
452 $      MatInfo *info;
453 $      Mat     A;
454 $      double  mal, nz_a, nz_u;
455 $
456 $      MatGetInfo(A,MAT_LOCAL,&info);
457 $      mal  = info->mallocs;
458 $      nz_a = info->nz_allocated;
459 $
460 
461    Example for Fortran Users:
462    Fortran users should declare info as a double precision
463    array of dimension MAT_INFO_SIZE, and then extract the parameters
464    of interest.  See the file $(PETSC_DIR)/include/FINCLUDE/mat.h
465    a complete list of parameter names.
466 $
467 $      double  precision info(MAT_INFO_SIZE)
468 $      double  precision mal, nz_a
469 $      Mat     A
470 $      integer ierr
471 $
472 $      call MatGetInfo(A,MAT_LOCAL,info,ierr)
473 $      mal = info(MAT_INFO_MALLOCS)
474 $      nz_a = info(MAT_INFO_NZ_ALLOCATED)
475 $
476 
477 .keywords: matrix, get, info, storage, nonzeros, memory, fill
478 @*/
479 int MatGetInfo(Mat mat,MatInfoType flag,MatInfo *info)
480 {
481   PetscValidHeaderSpecific(mat,MAT_COOKIE);
482   if (!mat->ops.getinfo) SETERRQ(PETSC_ERR_SUP,"MatGetInfo");
483   return  (*mat->ops.getinfo)(mat,flag,info);
484 }
485 /* ----------------------------------------------------------*/
486 /*@
487    MatILUDTFactor - Performs a drop tolerance ILU factorization.
488 
489    Input Parameters:
490 .  mat - the matrix
491 .  dt  - the drop tolerance
492 .  maxnz - the maximum number of nonzeros per row allowed?
493 .  row - row permutation
494 .  col - column permutation
495 
496    Output Parameters:
497 .  fact - the factored matrix
498 
499 .keywords: matrix, factor, LU, in-place
500 
501 .seealso: MatLUFactorSymbolic(), MatLUFactorNumeric(), MatCholeskyFactor()
502 @*/
503 int MatILUDTFactor(Mat mat,double dt,int maxnz,IS row,IS col,Mat *fact)
504 {
505   int ierr;
506   PetscValidHeaderSpecific(mat,MAT_COOKIE);
507   if (!mat->ops.iludtfactor) SETERRQ(PETSC_ERR_SUP,"MatILUDTFactor");
508   if (!mat->assembled) SETERRQ(1,"MatILUDTFactor:Not for unassembled matrix");
509   if (mat->factor) SETERRQ(1,"MatILUDTFactor:Not for factored matrix");
510 
511   PLogEventBegin(MAT_ILUFactor,mat,row,col,0);
512   ierr = (*mat->ops.iludtfactor)(mat,dt,maxnz,row,col,fact); CHKERRQ(ierr);
513   PLogEventEnd(MAT_ILUFactor,mat,row,col,0);
514 
515   return 0;
516 }
517 
518 /*@
519    MatLUFactor - Performs in-place LU factorization of matrix.
520 
521    Input Parameters:
522 .  mat - the matrix
523 .  row - row permutation
524 .  col - column permutation
525 .  f - expected fill as ratio of original fill.
526 
527 .keywords: matrix, factor, LU, in-place
528 
529 .seealso: MatLUFactorSymbolic(), MatLUFactorNumeric(), MatCholeskyFactor()
530 @*/
531 int MatLUFactor(Mat mat,IS row,IS col,double f)
532 {
533   int ierr;
534   PetscValidHeaderSpecific(mat,MAT_COOKIE);
535   if (mat->M != mat->N) SETERRQ(1,"MatLUFactor:matrix must be square");
536   if (!mat->ops.lufactor) SETERRQ(PETSC_ERR_SUP,"MatLUFactor");
537   if (!mat->assembled) SETERRQ(1,"MatLUFactor:Not for unassembled matrix");
538   if (mat->factor) SETERRQ(1,"MatLUFactor:Not for factored matrix");
539 
540   PLogEventBegin(MAT_LUFactor,mat,row,col,0);
541   ierr = (*mat->ops.lufactor)(mat,row,col,f); CHKERRQ(ierr);
542   PLogEventEnd(MAT_LUFactor,mat,row,col,0);
543   return 0;
544 }
545 /*@
546    MatILUFactor - Performs in-place ILU factorization of matrix.
547 
548    Input Parameters:
549 .  mat - the matrix
550 .  row - row permutation
551 .  col - column permutation
552 .  f - expected fill as ratio of original fill.
553 .  level - number of levels of fill.
554 
555    Note: probably really only in-place when level is zero.
556 .keywords: matrix, factor, ILU, in-place
557 
558 .seealso: MatILUFactorSymbolic(), MatLUFactorNumeric(), MatCholeskyFactor()
559 @*/
560 int MatILUFactor(Mat mat,IS row,IS col,double f,int level)
561 {
562   int ierr;
563   PetscValidHeaderSpecific(mat,MAT_COOKIE);
564   if (mat->M != mat->N) SETERRQ(1,"MatILUFactor:matrix must be square");
565   if (!mat->ops.ilufactor) SETERRQ(PETSC_ERR_SUP,"MatILUFactor");
566   if (!mat->assembled) SETERRQ(1,"MatILUFactor:Not for unassembled matrix");
567   if (mat->factor) SETERRQ(1,"MatILUFactor:Not for factored matrix");
568 
569   PLogEventBegin(MAT_ILUFactor,mat,row,col,0);
570   ierr = (*mat->ops.ilufactor)(mat,row,col,f,level); CHKERRQ(ierr);
571   PLogEventEnd(MAT_ILUFactor,mat,row,col,0);
572   return 0;
573 }
574 
575 /*@
576    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
577    Call this routine before calling MatLUFactorNumeric().
578 
579    Input Parameters:
580 .  mat - the matrix
581 .  row, col - row and column permutations
582 .  f - expected fill as ratio of the original number of nonzeros,
583        for example 3.0; choosing this parameter well can result in
584        more efficient use of time and space.
585 
586    Output Parameter:
587 .  fact - new matrix that has been symbolically factored
588 
589    Options Database Key:
590 $     -mat_lu_fill <f>, where f is the fill ratio
591 
592    Notes:
593    See the file $(PETSC_DIR)/Performace for additional information about
594    choosing the fill factor for better efficiency.
595 
596 .keywords: matrix, factor, LU, symbolic, fill
597 
598 .seealso: MatLUFactor(), MatLUFactorNumeric(), MatCholeskyFactor()
599 @*/
600 int MatLUFactorSymbolic(Mat mat,IS row,IS col,double f,Mat *fact)
601 {
602   int ierr,flg;
603   PetscValidHeaderSpecific(mat,MAT_COOKIE);
604   if (mat->M != mat->N) SETERRQ(1,"MatLUFactorSymbolic:matrix must be square");
605   if (!fact) SETERRQ(1,"MatLUFactorSymbolic:Missing factor matrix argument");
606   if (!mat->ops.lufactorsymbolic) SETERRQ(PETSC_ERR_SUP,"MatLUFactorSymbolic");
607   if (!mat->assembled) SETERRQ(1,"MatLUFactorSymbolic:Not for unassembled matrix");
608   if (mat->factor) SETERRQ(1,"MatLUFactorSymbolic:Not for factored matrix");
609 
610   ierr = OptionsGetDouble(PETSC_NULL,"-mat_lu_fill",&f,&flg); CHKERRQ(ierr);
611   PLogEventBegin(MAT_LUFactorSymbolic,mat,row,col,0);
612   ierr = (*mat->ops.lufactorsymbolic)(mat,row,col,f,fact); CHKERRQ(ierr);
613   PLogEventEnd(MAT_LUFactorSymbolic,mat,row,col,0);
614   return 0;
615 }
616 /*@
617    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
618    Call this routine after first calling MatLUFactorSymbolic().
619 
620    Input Parameters:
621 .  mat - the matrix
622 .  row, col - row and  column permutations
623 
624    Output Parameters:
625 .  fact - symbolically factored matrix that must have been generated
626           by MatLUFactorSymbolic()
627 
628    Notes:
629    See MatLUFactor() for in-place factorization.  See
630    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
631 
632 .keywords: matrix, factor, LU, numeric
633 
634 .seealso: MatLUFactorSymbolic(), MatLUFactor(), MatCholeskyFactor()
635 @*/
636 int MatLUFactorNumeric(Mat mat,Mat *fact)
637 {
638   int ierr,flg;
639 
640   PetscValidHeaderSpecific(mat,MAT_COOKIE);
641   if (!fact) SETERRQ(1,"MatLUFactorNumeric:Missing factor matrix argument");
642   if (!mat->ops.lufactornumeric) SETERRQ(PETSC_ERR_SUP,"MatLUFactorNumeric");
643   if (!mat->assembled) SETERRQ(1,"MatLUFactorNumeric:Not for unassembled matrix");
644   if (mat->M != (*fact)->M || mat->N != (*fact)->N)
645     SETERRQ(PETSC_ERR_SIZ,"MatLUFactorNumeric:Mat mat,Mat *fact: global dim");
646 
647   PLogEventBegin(MAT_LUFactorNumeric,mat,*fact,0,0);
648   ierr = (*mat->ops.lufactornumeric)(mat,fact); CHKERRQ(ierr);
649   PLogEventEnd(MAT_LUFactorNumeric,mat,*fact,0,0);
650   ierr = OptionsHasName(PETSC_NULL,"-mat_view_draw",&flg); CHKERRQ(ierr);
651   if (flg) {
652     Viewer  viewer;
653     ierr = ViewerDrawOpenX((*fact)->comm,0,0,0,0,300,300,&viewer);CHKERRQ(ierr);
654     ierr = MatView(*fact,viewer); CHKERRQ(ierr);
655     ierr = ViewerFlush(viewer); CHKERRQ(ierr);
656     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
657   }
658   return 0;
659 }
660 /*@
661    MatCholeskyFactor - Performs in-place Cholesky factorization of a
662    symmetric matrix.
663 
664    Input Parameters:
665 .  mat - the matrix
666 .  perm - row and column permutations
667 .  f - expected fill as ratio of original fill
668 
669    Notes:
670    See MatLUFactor() for the nonsymmetric case.  See also
671    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
672 
673 .keywords: matrix, factor, in-place, Cholesky
674 
675 .seealso: MatLUFactor(), MatCholeskyFactorSymbolic(), MatCholeskyFactorNumeric()
676 @*/
677 int MatCholeskyFactor(Mat mat,IS perm,double f)
678 {
679   int ierr;
680   PetscValidHeaderSpecific(mat,MAT_COOKIE);
681   if (mat->M != mat->N) SETERRQ(1,"MatCholeskyFactor:matrix must be square");
682   if (!mat->ops.choleskyfactor) SETERRQ(PETSC_ERR_SUP,"MatCholeskyFactor");
683   if (!mat->assembled) SETERRQ(1,"MatCholeskyFactor:Not for unassembled matrix");
684   if (mat->factor) SETERRQ(1,"MatCholeskyFactor:Not for factored matrix");
685 
686   PLogEventBegin(MAT_CholeskyFactor,mat,perm,0,0);
687   ierr = (*mat->ops.choleskyfactor)(mat,perm,f); CHKERRQ(ierr);
688   PLogEventEnd(MAT_CholeskyFactor,mat,perm,0,0);
689   return 0;
690 }
691 /*@
692    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
693    of a symmetric matrix.
694 
695    Input Parameters:
696 .  mat - the matrix
697 .  perm - row and column permutations
698 .  f - expected fill as ratio of original
699 
700    Output Parameter:
701 .  fact - the factored matrix
702 
703    Notes:
704    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
705    MatCholeskyFactor() and MatCholeskyFactorNumeric().
706 
707 .keywords: matrix, factor, factorization, symbolic, Cholesky
708 
709 .seealso: MatLUFactorSymbolic(), MatCholeskyFactor(), MatCholeskyFactorNumeric()
710 @*/
711 int MatCholeskyFactorSymbolic(Mat mat,IS perm,double f,Mat *fact)
712 {
713   int ierr;
714   PetscValidHeaderSpecific(mat,MAT_COOKIE);
715   if (mat->M != mat->N) SETERRQ(1,"MatCholeskyFactorSymbolic:matrix must be square");
716   if (!fact) SETERRQ(1,"MatCholeskyFactorSymbolic:Missing factor matrix argument");
717   if (!mat->ops.choleskyfactorsymbolic)SETERRQ(PETSC_ERR_SUP,"MatCholeskyFactorSymbolic");
718   if (!mat->assembled) SETERRQ(1,"MatCholeskyFactorSymbolic:Not for unassembled matrix");
719   if (mat->factor) SETERRQ(1,"MatCholeskyFactorSymbolic:Not for factored matrix");
720 
721   PLogEventBegin(MAT_CholeskyFactorSymbolic,mat,perm,0,0);
722   ierr = (*mat->ops.choleskyfactorsymbolic)(mat,perm,f,fact); CHKERRQ(ierr);
723   PLogEventEnd(MAT_CholeskyFactorSymbolic,mat,perm,0,0);
724   return 0;
725 }
726 /*@
727    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
728    of a symmetric matrix. Call this routine after first calling
729    MatCholeskyFactorSymbolic().
730 
731    Input Parameter:
732 .  mat - the initial matrix
733 
734    Output Parameter:
735 .  fact - the factored matrix
736 
737 .keywords: matrix, factor, numeric, Cholesky
738 
739 .seealso: MatCholeskyFactorSymbolic(), MatCholeskyFactor(), MatLUFactorNumeric()
740 @*/
741 int MatCholeskyFactorNumeric(Mat mat,Mat *fact)
742 {
743   int ierr;
744   PetscValidHeaderSpecific(mat,MAT_COOKIE);
745   if (!fact) SETERRQ(1,"MatCholeskyFactorNumeric:Missing factor matrix argument");
746   if (!mat->ops.choleskyfactornumeric) SETERRQ(PETSC_ERR_SUP,"MatCholeskyFactorNumeric");
747   if (!mat->assembled) SETERRQ(1,"MatCholeskyFactorNumeric:Not for unassembled matrix");
748   if (mat->M != (*fact)->M || mat->N != (*fact)->N)
749     SETERRQ(PETSC_ERR_SIZ,"MatCholeskyFactorNumeric:Mat mat,Mat *fact: global dim");
750 
751   PLogEventBegin(MAT_CholeskyFactorNumeric,mat,*fact,0,0);
752   ierr = (*mat->ops.choleskyfactornumeric)(mat,fact); CHKERRQ(ierr);
753   PLogEventEnd(MAT_CholeskyFactorNumeric,mat,*fact,0,0);
754   return 0;
755 }
756 /* ----------------------------------------------------------------*/
757 /*@
758    MatSolve - Solves A x = b, given a factored matrix.
759 
760    Input Parameters:
761 .  mat - the factored matrix
762 .  b - the right-hand-side vector
763 
764    Output Parameter:
765 .  x - the result vector
766 
767    Notes:
768    The vectors b and x cannot be the same.  I.e., one cannot
769    call MatSolve(A,x,x).
770 
771 .keywords: matrix, linear system, solve, LU, Cholesky, triangular solve
772 
773 .seealso: MatSolveAdd(), MatSolveTrans(), MatSolveTransAdd()
774 @*/
775 int MatSolve(Mat mat,Vec b,Vec x)
776 {
777   int ierr;
778   PetscValidHeaderSpecific(mat,MAT_COOKIE);
779   PetscValidHeaderSpecific(b,VEC_COOKIE); PetscValidHeaderSpecific(x,VEC_COOKIE);
780   if (x == b) SETERRQ(1,"MatSolve:x and b must be different vectors");
781   if (!mat->factor) SETERRQ(1,"MatSolve:Unfactored matrix");
782   if (mat->N != x->N) SETERRQ(PETSC_ERR_SIZ,"MatSolve:Mat mat,Vec x: global dim");
783   if (mat->M != b->N) SETERRQ(PETSC_ERR_SIZ,"MatSolve:Mat mat,Vec b: global dim");
784   if (mat->m != b->n) SETERRQ(PETSC_ERR_SIZ,"MatSolve:Mat mat,Vec b: local dim");
785 
786   if (!mat->ops.solve) SETERRQ(PETSC_ERR_SUP,"MatSolve");
787   PLogEventBegin(MAT_Solve,mat,b,x,0);
788   ierr = (*mat->ops.solve)(mat,b,x); CHKERRQ(ierr);
789   PLogEventEnd(MAT_Solve,mat,b,x,0);
790   return 0;
791 }
792 
793 /* @
794    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU.
795 
796    Input Parameters:
797 .  mat - the factored matrix
798 .  b - the right-hand-side vector
799 
800    Output Parameter:
801 .  x - the result vector
802 
803    Notes:
804    MatSolve() should be used for most applications, as it performs
805    a forward solve followed by a backward solve.
806 
807    The vectors b and x cannot be the same.  I.e., one cannot
808    call MatForwardSolve(A,x,x).
809 
810 .keywords: matrix, forward, LU, Cholesky, triangular solve
811 
812 .seealso: MatSolve(), MatBackwardSolve()
813 @ */
814 int MatForwardSolve(Mat mat,Vec b,Vec x)
815 {
816   int ierr;
817   PetscValidHeaderSpecific(mat,MAT_COOKIE);
818   PetscValidHeaderSpecific(b,VEC_COOKIE);  PetscValidHeaderSpecific(x,VEC_COOKIE);
819   if (x == b) SETERRQ(1,"MatForwardSolve:x and b must be different vectors");
820   if (!mat->factor) SETERRQ(1,"MatForwardSolve:Unfactored matrix");
821   if (!mat->ops.forwardsolve) SETERRQ(PETSC_ERR_SUP,"MatForwardSolve");
822   if (mat->N != x->N) SETERRQ(PETSC_ERR_SIZ,"MatForwardSolve:Mat mat,Vec x: global dim");
823   if (mat->M != b->N) SETERRQ(PETSC_ERR_SIZ,"MatForwardSolve:Mat mat,Vec b: global dim");
824   if (mat->m != b->n) SETERRQ(PETSC_ERR_SIZ,"MatForwardSolve:Mat mat,Vec b: local dim");
825 
826   PLogEventBegin(MAT_ForwardSolve,mat,b,x,0);
827   ierr = (*mat->ops.forwardsolve)(mat,b,x); CHKERRQ(ierr);
828   PLogEventEnd(MAT_ForwardSolve,mat,b,x,0);
829   return 0;
830 }
831 
832 /* @
833    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
834 
835    Input Parameters:
836 .  mat - the factored matrix
837 .  b - the right-hand-side vector
838 
839    Output Parameter:
840 .  x - the result vector
841 
842    Notes:
843    MatSolve() should be used for most applications, as it performs
844    a forward solve followed by a backward solve.
845 
846    The vectors b and x cannot be the same.  I.e., one cannot
847    call MatBackwardSolve(A,x,x).
848 
849 .keywords: matrix, backward, LU, Cholesky, triangular solve
850 
851 .seealso: MatSolve(), MatForwardSolve()
852 @ */
853 int MatBackwardSolve(Mat mat,Vec b,Vec x)
854 {
855   int ierr;
856   PetscValidHeaderSpecific(mat,MAT_COOKIE);
857   PetscValidHeaderSpecific(b,VEC_COOKIE);  PetscValidHeaderSpecific(x,VEC_COOKIE);
858   if (x == b) SETERRQ(1,"MatBackwardSolve:x and b must be different vectors");
859   if (!mat->factor) SETERRQ(1,"MatBackwardSolve:Unfactored matrix");
860   if (!mat->ops.backwardsolve) SETERRQ(PETSC_ERR_SUP,"MatBackwardSolve");
861   if (mat->N != x->N) SETERRQ(PETSC_ERR_SIZ,"MatBackwardSolve:Mat mat,Vec x: global dim");
862   if (mat->M != b->N) SETERRQ(PETSC_ERR_SIZ,"MatBackwardSolve:Mat mat,Vec b: global dim");
863   if (mat->m != b->n) SETERRQ(PETSC_ERR_SIZ,"MatBackwardSolve:Mat mat,Vec b: local dim");
864 
865   PLogEventBegin(MAT_BackwardSolve,mat,b,x,0);
866   ierr = (*mat->ops.backwardsolve)(mat,b,x); CHKERRQ(ierr);
867   PLogEventEnd(MAT_BackwardSolve,mat,b,x,0);
868   return 0;
869 }
870 
871 /*@
872    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
873 
874    Input Parameters:
875 .  mat - the factored matrix
876 .  b - the right-hand-side vector
877 .  y - the vector to be added to
878 
879    Output Parameter:
880 .  x - the result vector
881 
882    Notes:
883    The vectors b and x cannot be the same.  I.e., one cannot
884    call MatSolveAdd(A,x,y,x).
885 
886 .keywords: matrix, linear system, solve, LU, Cholesky, add
887 
888 .seealso: MatSolve(), MatSolveTrans(), MatSolveTransAdd()
889 @*/
890 int MatSolveAdd(Mat mat,Vec b,Vec y,Vec x)
891 {
892   Scalar one = 1.0;
893   Vec    tmp;
894   int    ierr;
895   PetscValidHeaderSpecific(mat,MAT_COOKIE);PetscValidHeaderSpecific(y,VEC_COOKIE);
896   PetscValidHeaderSpecific(b,VEC_COOKIE);  PetscValidHeaderSpecific(x,VEC_COOKIE);
897   if (x == b) SETERRQ(1,"MatSolveAdd:x and b must be different vectors");
898   if (!mat->factor) SETERRQ(1,"MatSolveAdd:Unfactored matrix");
899   if (mat->N != x->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveAdd:Mat mat,Vec x: global dim");
900   if (mat->M != b->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveAdd:Mat mat,Vec b: global dim");
901   if (mat->M != y->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveAdd:Mat mat,Vec y: global dim");
902   if (mat->m != b->n) SETERRQ(PETSC_ERR_SIZ,"MatSolveAdd:Mat mat,Vec b: local dim");
903   if (x->n != y->n) SETERRQ(PETSC_ERR_SIZ,"MatSolveAdd:Vec x,Vec y: local dim");
904 
905   PLogEventBegin(MAT_SolveAdd,mat,b,x,y);
906   if (mat->ops.solveadd)  {
907     ierr = (*mat->ops.solveadd)(mat,b,y,x); CHKERRQ(ierr);
908   }
909   else {
910     /* do the solve then the add manually */
911     if (x != y) {
912       ierr = MatSolve(mat,b,x); CHKERRQ(ierr);
913       ierr = VecAXPY(&one,y,x); CHKERRQ(ierr);
914     }
915     else {
916       ierr = VecDuplicate(x,&tmp); CHKERRQ(ierr);
917       PLogObjectParent(mat,tmp);
918       ierr = VecCopy(x,tmp); CHKERRQ(ierr);
919       ierr = MatSolve(mat,b,x); CHKERRQ(ierr);
920       ierr = VecAXPY(&one,tmp,x); CHKERRQ(ierr);
921       ierr = VecDestroy(tmp); CHKERRQ(ierr);
922     }
923   }
924   PLogEventEnd(MAT_SolveAdd,mat,b,x,y);
925   return 0;
926 }
927 /*@
928    MatSolveTrans - Solves A' x = b, given a factored matrix.
929 
930    Input Parameters:
931 .  mat - the factored matrix
932 .  b - the right-hand-side vector
933 
934    Output Parameter:
935 .  x - the result vector
936 
937    Notes:
938    The vectors b and x cannot be the same.  I.e., one cannot
939    call MatSolveTrans(A,x,x).
940 
941 .keywords: matrix, linear system, solve, LU, Cholesky, transpose
942 
943 .seealso: MatSolve(), MatSolveAdd(), MatSolveTransAdd()
944 @*/
945 int MatSolveTrans(Mat mat,Vec b,Vec x)
946 {
947   int ierr;
948   PetscValidHeaderSpecific(mat,MAT_COOKIE);
949   PetscValidHeaderSpecific(b,VEC_COOKIE);  PetscValidHeaderSpecific(x,VEC_COOKIE);
950   if (!mat->factor) SETERRQ(1,"MatSolveTrans:Unfactored matrix");
951   if (x == b) SETERRQ(1,"MatSolveTrans:x and b must be different vectors");
952   if (!mat->ops.solvetrans) SETERRQ(PETSC_ERR_SUP,"MatSolveTrans");
953   if (mat->M != x->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveTrans:Mat mat,Vec x: global dim");
954   if (mat->N != b->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveTrans:Mat mat,Vec b: global dim");
955 
956   PLogEventBegin(MAT_SolveTrans,mat,b,x,0);
957   ierr = (*mat->ops.solvetrans)(mat,b,x); CHKERRQ(ierr);
958   PLogEventEnd(MAT_SolveTrans,mat,b,x,0);
959   return 0;
960 }
961 /*@
962    MatSolveTransAdd - Computes x = y + inv(trans(A)) b, given a
963                       factored matrix.
964 
965    Input Parameters:
966 .  mat - the factored matrix
967 .  b - the right-hand-side vector
968 .  y - the vector to be added to
969 
970    Output Parameter:
971 .  x - the result vector
972 
973    Notes:
974    The vectors b and x cannot be the same.  I.e., one cannot
975    call MatSolveTransAdd(A,x,y,x).
976 
977 .keywords: matrix, linear system, solve, LU, Cholesky, transpose, add
978 
979 .seealso: MatSolve(), MatSolveAdd(), MatSolveTrans()
980 @*/
981 int MatSolveTransAdd(Mat mat,Vec b,Vec y,Vec x)
982 {
983   Scalar one = 1.0;
984   int    ierr;
985   Vec    tmp;
986   PetscValidHeaderSpecific(mat,MAT_COOKIE);PetscValidHeaderSpecific(y,VEC_COOKIE);
987   PetscValidHeaderSpecific(b,VEC_COOKIE);  PetscValidHeaderSpecific(x,VEC_COOKIE);
988   if (x == b) SETERRQ(1,"MatSolveTransAdd:x and b must be different vectors");
989   if (!mat->factor) SETERRQ(1,"MatSolveTransAdd:Unfactored matrix");
990   if (mat->M != x->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveTransAdd:Mat mat,Vec x: global dim");
991   if (mat->N != b->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveTransAdd:Mat mat,Vec b: global dim");
992   if (mat->N != y->N) SETERRQ(PETSC_ERR_SIZ,"MatSolveTransAdd:Mat mat,Vec y: global dim");
993   if (x->n != y->n) SETERRQ(PETSC_ERR_SIZ,"MatSolveTransAdd:Vec x,Vec y: local dim");
994 
995   PLogEventBegin(MAT_SolveTransAdd,mat,b,x,y);
996   if (mat->ops.solvetransadd) {
997     ierr = (*mat->ops.solvetransadd)(mat,b,y,x); CHKERRQ(ierr);
998   }
999   else {
1000     /* do the solve then the add manually */
1001     if (x != y) {
1002       ierr = MatSolveTrans(mat,b,x); CHKERRQ(ierr);
1003       ierr = VecAXPY(&one,y,x); CHKERRQ(ierr);
1004     }
1005     else {
1006       ierr = VecDuplicate(x,&tmp); CHKERRQ(ierr);
1007       PLogObjectParent(mat,tmp);
1008       ierr = VecCopy(x,tmp); CHKERRQ(ierr);
1009       ierr = MatSolveTrans(mat,b,x); CHKERRQ(ierr);
1010       ierr = VecAXPY(&one,tmp,x); CHKERRQ(ierr);
1011       ierr = VecDestroy(tmp); CHKERRQ(ierr);
1012     }
1013   }
1014   PLogEventEnd(MAT_SolveTransAdd,mat,b,x,y);
1015   return 0;
1016 }
1017 /* ----------------------------------------------------------------*/
1018 
1019 /*@
1020    MatRelax - Computes one relaxation sweep.
1021 
1022    Input Parameters:
1023 .  mat - the matrix
1024 .  b - the right hand side
1025 .  omega - the relaxation factor
1026 .  flag - flag indicating the type of SOR, one of
1027 $     SOR_FORWARD_SWEEP
1028 $     SOR_BACKWARD_SWEEP
1029 $     SOR_SYMMETRIC_SWEEP (SSOR method)
1030 $     SOR_LOCAL_FORWARD_SWEEP
1031 $     SOR_LOCAL_BACKWARD_SWEEP
1032 $     SOR_LOCAL_SYMMETRIC_SWEEP (local SSOR)
1033 $     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
1034 $       upper/lower triangular part of matrix to
1035 $       vector (with omega)
1036 $     SOR_ZERO_INITIAL_GUESS - zero initial guess
1037 .  shift -  diagonal shift
1038 .  its - the number of iterations
1039 
1040    Output Parameters:
1041 .  x - the solution (can contain an initial guess)
1042 
1043    Notes:
1044    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
1045    SOR_LOCAL_SYMMETRIC_SWEEP perform seperate independent smoothings
1046    on each processor.
1047 
1048    Application programmers will not generally use MatRelax() directly,
1049    but instead will employ the SLES/PC interface.
1050 
1051    Notes for Advanced Users:
1052    The flags are implemented as bitwise inclusive or operations.
1053    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
1054    to specify a zero initial guess for SSOR.
1055 
1056 .keywords: matrix, relax, relaxation, sweep
1057 @*/
1058 int MatRelax(Mat mat,Vec b,double omega,MatSORType flag,double shift,
1059              int its,Vec x)
1060 {
1061   int ierr;
1062   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1063   PetscValidHeaderSpecific(b,VEC_COOKIE);  PetscValidHeaderSpecific(x,VEC_COOKIE);
1064   if (!mat->ops.relax) SETERRQ(PETSC_ERR_SUP,"MatRelax");
1065   if (!mat->assembled) SETERRQ(1,"MatRelax:Not for unassembled matrix");
1066   if (mat->factor) SETERRQ(1,"MatRelax:Not for factored matrix");
1067   if (mat->N != x->N) SETERRQ(PETSC_ERR_SIZ,"MatRelax:Mat mat,Vec x: global dim");
1068   if (mat->M != b->N) SETERRQ(PETSC_ERR_SIZ,"MatRelax:Mat mat,Vec b: global dim");
1069   if (mat->m != b->n) SETERRQ(PETSC_ERR_SIZ,"MatRelax:Mat mat,Vec b: local dim");
1070 
1071   PLogEventBegin(MAT_Relax,mat,b,x,0);
1072   ierr =(*mat->ops.relax)(mat,b,omega,flag,shift,its,x); CHKERRQ(ierr);
1073   PLogEventEnd(MAT_Relax,mat,b,x,0);
1074   return 0;
1075 }
1076 
1077 /*
1078       Default matrix copy routine.
1079 */
1080 int MatCopy_Basic(Mat A,Mat B)
1081 {
1082   int    ierr,i,rstart,rend,nz,*cwork;
1083   Scalar *vwork;
1084 
1085   ierr = MatZeroEntries(B); CHKERRQ(ierr);
1086   ierr = MatGetOwnershipRange(A,&rstart,&rend); CHKERRQ(ierr);
1087   for (i=rstart; i<rend; i++) {
1088     ierr = MatGetRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
1089     ierr = MatSetValues(B,1,&i,nz,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
1090     ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
1091   }
1092   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1093   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1094   return 0;
1095 }
1096 
1097 /*@C
1098    MatCopy - Copys a matrix to another matrix.
1099 
1100    Input Parameters:
1101 .  A - the matrix
1102 
1103    Output Parameter:
1104 .  B - where the copy is put
1105 
1106    Notes:
1107    MatCopy() copies the matrix entries of a matrix to another existing
1108    matrix (after first zeroing the second matrix).  A related routine is
1109    MatConvert(), which first creates a new matrix and then copies the data.
1110 
1111 .keywords: matrix, copy, convert
1112 
1113 .seealso: MatConvert()
1114 @*/
1115 int MatCopy(Mat A,Mat B)
1116 {
1117   int ierr;
1118   PetscValidHeaderSpecific(A,MAT_COOKIE); PetscValidHeaderSpecific(B,MAT_COOKIE);
1119   if (!A->assembled) SETERRQ(1,"MatCopy:Not for unassembled matrix");
1120   if (A->factor) SETERRQ(1,"MatCopy:Not for factored matrix");
1121   if (A->M != B->M || A->N != B->N) SETERRQ(PETSC_ERR_SIZ,"MatCopy:Mat A,Mat B: global dim");
1122 
1123   PLogEventBegin(MAT_Copy,A,B,0,0);
1124   if (A->ops.copy) {
1125     ierr = (*A->ops.copy)(A,B); CHKERRQ(ierr);
1126   }
1127   else { /* generic conversion */
1128     ierr = MatCopy_Basic(A,B); CHKERRQ(ierr);
1129   }
1130   PLogEventEnd(MAT_Copy,A,B,0,0);
1131   return 0;
1132 }
1133 
1134 /*@C
1135    MatConvert - Converts a matrix to another matrix, either of the same
1136    or different type.
1137 
1138    Input Parameters:
1139 .  mat - the matrix
1140 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
1141    same type as the original matrix.
1142 
1143    Output Parameter:
1144 .  M - pointer to place new matrix
1145 
1146    Notes:
1147    MatConvert() first creates a new matrix and then copies the data from
1148    the first matrix.  A related routine is MatCopy(), which copies the matrix
1149    entries of one matrix to another already existing matrix context.
1150 
1151 .keywords: matrix, copy, convert
1152 
1153 .seealso: MatCopy()
1154 @*/
1155 int MatConvert(Mat mat,MatType newtype,Mat *M)
1156 {
1157   int ierr;
1158   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1159   if (!M) SETERRQ(1,"MatConvert:Bad new matrix address");
1160   if (!mat->assembled) SETERRQ(1,"MatConvert:Not for unassembled matrix");
1161   if (mat->factor) SETERRQ(1,"MatConvert:Not for factored matrix");
1162 
1163   PLogEventBegin(MAT_Convert,mat,0,0,0);
1164   if (newtype == mat->type || newtype == MATSAME) {
1165     if (mat->ops.convertsametype) { /* customized copy */
1166       ierr = (*mat->ops.convertsametype)(mat,M,COPY_VALUES); CHKERRQ(ierr);
1167     }
1168     else { /* generic conversion */
1169       ierr = MatConvert_Basic(mat,newtype,M); CHKERRQ(ierr);
1170     }
1171   }
1172   else if (mat->ops.convert) { /* customized conversion */
1173     ierr = (*mat->ops.convert)(mat,newtype,M); CHKERRQ(ierr);
1174   }
1175   else { /* generic conversion */
1176     ierr = MatConvert_Basic(mat,newtype,M); CHKERRQ(ierr);
1177   }
1178   PLogEventEnd(MAT_Convert,mat,0,0,0);
1179   return 0;
1180 }
1181 
1182 /*@
1183    MatGetDiagonal - Gets the diagonal of a matrix.
1184 
1185    Input Parameters:
1186 .  mat - the matrix
1187 .  v - the vector for storing the diagonal
1188 
1189    Output Parameter:
1190 .  v - the diagonal of the matrix
1191 
1192 .keywords: matrix, get, diagonal
1193 @*/
1194 int MatGetDiagonal(Mat mat,Vec v)
1195 {
1196   PetscValidHeaderSpecific(mat,MAT_COOKIE);PetscValidHeaderSpecific(v,VEC_COOKIE);
1197   if (!mat->assembled) SETERRQ(1,"MatGetDiagonal:Not for unassembled matrix");
1198   if (mat->factor) SETERRQ(1,"MatGetDiagonal:Not for factored matrix");
1199   if (mat->ops.getdiagonal) return (*mat->ops.getdiagonal)(mat,v);
1200   SETERRQ(PETSC_ERR_SUP,"MatGetDiagonal");
1201 }
1202 
1203 /*@C
1204    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
1205 
1206    Input Parameter:
1207 .  mat - the matrix to transpose
1208 
1209    Output Parameters:
1210 .  B - the transpose (or pass in PETSC_NULL for an in-place transpose)
1211 
1212 .keywords: matrix, transpose
1213 
1214 .seealso: MatMultTrans(), MatMultTransAdd()
1215 @*/
1216 int MatTranspose(Mat mat,Mat *B)
1217 {
1218   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1219   if (!mat->assembled) SETERRQ(1,"MatTranspose:Not for unassembled matrix");
1220   if (mat->factor) SETERRQ(1,"MatTranspose:Not for factored matrix");
1221   if (mat->ops.transpose) return (*mat->ops.transpose)(mat,B);
1222   SETERRQ(PETSC_ERR_SUP,"MatTranspose");
1223 }
1224 
1225 /*@
1226    MatEqual - Compares two matrices.
1227 
1228    Input Parameters:
1229 .  A - the first matrix
1230 .  B - the second matrix
1231 
1232    Output Parameter:
1233 .  flg : PETSC_TRUE if the matrices are equal;
1234          PETSC_FALSE otherwise.
1235 
1236 .keywords: matrix, equal, equivalent
1237 @*/
1238 int MatEqual(Mat A,Mat B,PetscTruth *flg)
1239 {
1240   PetscValidHeaderSpecific(A,MAT_COOKIE); PetscValidHeaderSpecific(B,MAT_COOKIE);
1241   PetscValidIntPointer(flg);
1242   if (!A->assembled) SETERRQ(1,"MatEqual:Not for unassembled matrix");
1243   if (!B->assembled) SETERRQ(1,"MatEqual:Not for unassembled matrix");
1244   if (A->M != B->M || A->N != B->N) SETERRQ(PETSC_ERR_SIZ,"MatCopy:Mat A,Mat B: global dim");
1245   if (A->ops.equal) return (*A->ops.equal)(A,B,flg);
1246   SETERRQ(PETSC_ERR_SUP,"MatEqual");
1247 }
1248 
1249 /*@
1250    MatDiagonalScale - Scales a matrix on the left and right by diagonal
1251    matrices that are stored as vectors.  Either of the two scaling
1252    matrices can be PETSC_NULL.
1253 
1254    Input Parameters:
1255 .  mat - the matrix to be scaled
1256 .  l - the left scaling vector (or PETSC_NULL)
1257 .  r - the right scaling vector (or PETSC_NULL)
1258 
1259    Notes:
1260    MatDiagonalScale() computes A <- LAR, where
1261 $      L = a diagonal matrix
1262 $      R = a diagonal matrix
1263 
1264 .keywords: matrix, diagonal, scale
1265 
1266 .seealso: MatDiagonalScale()
1267 @*/
1268 int MatDiagonalScale(Mat mat,Vec l,Vec r)
1269 {
1270   int ierr;
1271   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1272   if (!mat->ops.diagonalscale) SETERRQ(PETSC_ERR_SUP,"MatDiagonalScale");
1273   if (l) PetscValidHeaderSpecific(l,VEC_COOKIE);
1274   if (r) PetscValidHeaderSpecific(r,VEC_COOKIE);
1275   if (!mat->assembled) SETERRQ(1,"MatDiagonalScale:Not for unassembled matrix");
1276   if (mat->factor) SETERRQ(1,"MatDiagonalScale:Not for factored matrix");
1277 
1278   PLogEventBegin(MAT_Scale,mat,0,0,0);
1279   ierr = (*mat->ops.diagonalscale)(mat,l,r); CHKERRQ(ierr);
1280   PLogEventEnd(MAT_Scale,mat,0,0,0);
1281   return 0;
1282 }
1283 
1284 /*@
1285     MatScale - Scales all elements of a matrix by a given number.
1286 
1287     Input Parameters:
1288 .   mat - the matrix to be scaled
1289 .   a  - the scaling value
1290 
1291     Output Parameter:
1292 .   mat - the scaled matrix
1293 
1294 .keywords: matrix, scale
1295 
1296 .seealso: MatDiagonalScale()
1297 @*/
1298 int MatScale(Scalar *a,Mat mat)
1299 {
1300   int ierr;
1301   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1302   PetscValidScalarPointer(a);
1303   if (!mat->ops.scale) SETERRQ(PETSC_ERR_SUP,"MatScale");
1304   if (!mat->assembled) SETERRQ(1,"MatScale:Not for unassembled matrix");
1305   if (mat->factor) SETERRQ(1,"MatScale:Not for factored matrix");
1306 
1307   PLogEventBegin(MAT_Scale,mat,0,0,0);
1308   ierr = (*mat->ops.scale)(a,mat); CHKERRQ(ierr);
1309   PLogEventEnd(MAT_Scale,mat,0,0,0);
1310   return 0;
1311 }
1312 
1313 /*@
1314    MatNorm - Calculates various norms of a matrix.
1315 
1316    Input Parameters:
1317 .  mat - the matrix
1318 .  type - the type of norm, NORM_1, NORM_2, NORM_FROBENIUS, NORM_INFINITY
1319 
1320    Output Parameters:
1321 .  norm - the resulting norm
1322 
1323 .keywords: matrix, norm, Frobenius
1324 @*/
1325 int MatNorm(Mat mat,NormType type,double *norm)
1326 {
1327   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1328   PetscValidScalarPointer(norm);
1329 
1330   if (!norm) SETERRQ(1,"MatNorm:bad addess for value");
1331   if (!mat->assembled) SETERRQ(1,"MatNorm:Not for unassembled matrix");
1332   if (mat->factor) SETERRQ(1,"MatNorm:Not for factored matrix");
1333   if (mat->ops.norm) return (*mat->ops.norm)(mat,type,norm);
1334   SETERRQ(PETSC_ERR_SUP,"MatNorm:Not for this matrix type");
1335 }
1336 
1337 /*
1338      This variable is used to prevent counting of MatAssemblyBegin() that
1339    are called from within a MatAssemblyEnd().
1340 */
1341 static int MatAssemblyEnd_InUse = 0;
1342 /*@
1343    MatAssemblyBegin - Begins assembling the matrix.  This routine should
1344    be called after completing all calls to MatSetValues().
1345 
1346    Input Parameters:
1347 .  mat - the matrix
1348 .  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
1349 
1350    Notes:
1351    MatSetValues() generally caches the values.  The matrix is ready to
1352    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
1353    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
1354    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
1355    using the matrix.
1356 
1357 .keywords: matrix, assembly, assemble, begin
1358 
1359 .seealso: MatAssemblyEnd(), MatSetValues()
1360 @*/
1361 int MatAssemblyBegin(Mat mat,MatAssemblyType type)
1362 {
1363   int ierr;
1364   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1365   if (mat->factor) SETERRQ(1,"MatAssemblyBegin:Not for factored matrix");
1366   if (mat->assembled) {
1367     mat->was_assembled = PETSC_TRUE;
1368     mat->assembled     = PETSC_FALSE;
1369   }
1370   if (!MatAssemblyEnd_InUse) {
1371     PLogEventBegin(MAT_AssemblyBegin,mat,0,0,0);
1372     if (mat->ops.assemblybegin){ierr = (*mat->ops.assemblybegin)(mat,type);CHKERRQ(ierr);}
1373     PLogEventEnd(MAT_AssemblyBegin,mat,0,0,0);
1374   } else {
1375     if (mat->ops.assemblybegin){ierr = (*mat->ops.assemblybegin)(mat,type);CHKERRQ(ierr);}
1376   }
1377   return 0;
1378 }
1379 
1380 /*@
1381    MatAssemblyEnd - Completes assembling the matrix.  This routine should
1382    be called after MatAssemblyBegin().
1383 
1384    Input Parameters:
1385 .  mat - the matrix
1386 .  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
1387 
1388    Options Database Keys:
1389 $  -mat_view_info : Prints info on matrix at
1390 $      conclusion of MatEndAssembly()
1391 $  -mat_view_info_detailed: Prints more detailed info.
1392 $  -mat_view : Prints matrix in ASCII format.
1393 $  -mat_view_matlab : Prints matrix in Matlab format.
1394 $  -mat_view_draw : Draws nonzero structure of matrix,
1395 $      using MatView() and DrawOpenX().
1396 $  -display <name> : Set display name (default is host)
1397 $  -draw_pause <sec> : Set number of seconds to pause after display
1398 
1399    Notes:
1400    MatSetValues() generally caches the values.  The matrix is ready to
1401    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
1402    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
1403    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
1404    using the matrix.
1405 
1406 .keywords: matrix, assembly, assemble, end
1407 
1408 .seealso: MatAssemblyBegin(), MatSetValues(), DrawOpenX(), MatView()
1409 @*/
1410 int MatAssemblyEnd(Mat mat,MatAssemblyType type)
1411 {
1412   int        ierr,flg;
1413   static int inassm = 0;
1414 
1415   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1416   inassm++;
1417   MatAssemblyEnd_InUse++;
1418   PLogEventBegin(MAT_AssemblyEnd,mat,0,0,0);
1419   if (mat->ops.assemblyend) {
1420     ierr = (*mat->ops.assemblyend)(mat,type); CHKERRQ(ierr);
1421   }
1422   mat->assembled = PETSC_TRUE; mat->num_ass++;
1423   PLogEventEnd(MAT_AssemblyEnd,mat,0,0,0);
1424   MatAssemblyEnd_InUse--;
1425 
1426   if (inassm == 1) {
1427     ierr = OptionsHasName(PETSC_NULL,"-mat_view_info",&flg); CHKERRQ(ierr);
1428     if (flg) {
1429       Viewer viewer;
1430       ierr = ViewerFileOpenASCII(mat->comm,"stdout",&viewer);CHKERRQ(ierr);
1431       ierr = ViewerSetFormat(viewer,VIEWER_FORMAT_ASCII_INFO,0);CHKERRQ(ierr);
1432       ierr = MatView(mat,viewer); CHKERRQ(ierr);
1433       ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
1434     }
1435     ierr = OptionsHasName(PETSC_NULL,"-mat_view_info_detailed",&flg);CHKERRQ(ierr);
1436     if (flg) {
1437       Viewer viewer;
1438       ierr = ViewerFileOpenASCII(mat->comm,"stdout",&viewer);CHKERRQ(ierr);
1439       ierr = ViewerSetFormat(viewer,VIEWER_FORMAT_ASCII_INFO_LONG,0);CHKERRQ(ierr);
1440       ierr = MatView(mat,viewer); CHKERRQ(ierr);
1441       ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
1442     }
1443     ierr = OptionsHasName(PETSC_NULL,"-mat_view",&flg); CHKERRQ(ierr);
1444     if (flg) {
1445       Viewer viewer;
1446       ierr = ViewerFileOpenASCII(mat->comm,"stdout",&viewer);CHKERRQ(ierr);
1447       ierr = MatView(mat,viewer); CHKERRQ(ierr);
1448       ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
1449     }
1450     ierr = OptionsHasName(PETSC_NULL,"-mat_view_matlab",&flg); CHKERRQ(ierr);
1451     if (flg) {
1452       Viewer viewer;
1453       ierr = ViewerFileOpenASCII(mat->comm,"stdout",&viewer);CHKERRQ(ierr);
1454       ierr = ViewerSetFormat(viewer,VIEWER_FORMAT_ASCII_MATLAB,"M");CHKERRQ(ierr);
1455       ierr = MatView(mat,viewer); CHKERRQ(ierr);
1456       ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
1457     }
1458     ierr = OptionsHasName(PETSC_NULL,"-mat_view_draw",&flg); CHKERRQ(ierr);
1459     if (flg) {
1460       Viewer    viewer;
1461       ierr = ViewerDrawOpenX(mat->comm,0,0,0,0,300,300,&viewer); CHKERRQ(ierr);
1462       ierr = MatView(mat,viewer); CHKERRQ(ierr);
1463       ierr = ViewerFlush(viewer); CHKERRQ(ierr);
1464       ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
1465     }
1466   }
1467   inassm--;
1468   return 0;
1469 }
1470 
1471 /*@
1472    MatCompress - Tries to store the matrix in as little space as
1473    possible.  May fail if memory is already fully used, since it
1474    tries to allocate new space.
1475 
1476    Input Parameters:
1477 .  mat - the matrix
1478 
1479 .keywords: matrix, compress
1480 @*/
1481 int MatCompress(Mat mat)
1482 {
1483   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1484   if (mat->ops.compress) return (*mat->ops.compress)(mat);
1485   return 0;
1486 }
1487 /*@
1488    MatSetOption - Sets a parameter option for a matrix. Some options
1489    may be specific to certain storage formats.  Some options
1490    determine how values will be inserted (or added). Sorted,
1491    row-oriented input will generally assemble the fastest. The default
1492    is row-oriented, nonsorted input.
1493 
1494    Input Parameters:
1495 .  mat - the matrix
1496 .  option - the option, one of the following:
1497 $    MAT_ROW_ORIENTED
1498 $    MAT_COLUMN_ORIENTED,
1499 $    MAT_ROWS_SORTED,
1500 $    MAT_COLUMNS_SORTED,
1501 $    MAT_NO_NEW_NONZERO_LOCATIONS,
1502 $    MAT_YES_NEW_NONZERO_LOCATIONS,
1503 $    MAT_SYMMETRIC,
1504 $    MAT_STRUCTURALLY_SYMMETRIC,
1505 $    MAT_NO_NEW_DIAGONALS,
1506 $    MAT_YES_NEW_DIAGONALS,
1507 $    and possibly others.
1508 
1509    Notes:
1510    Some options are relevant only for particular matrix types and
1511    are thus ignored by others.  Other options are not supported by
1512    certain matrix types and will generate an error message if set.
1513 
1514    If using a Fortran 77 module to compute a matrix, one may need to
1515    use the column-oriented option (or convert to the row-oriented
1516    format).
1517 
1518    MAT_NO_NEW_NONZERO_LOCATIONS indicates that any add or insertion
1519    that will generate a new entry in the nonzero structure is ignored.
1520    What this means is if memory is not allocated for this particular
1521    lot, then the insertion is ignored. For dense matrices, where
1522    the entire array is allocated, no entries are ever ignored.
1523 
1524 .keywords: matrix, option, row-oriented, column-oriented, sorted, nonzero
1525 @*/
1526 int MatSetOption(Mat mat,MatOption op)
1527 {
1528   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1529   if (mat->ops.setoption) return (*mat->ops.setoption)(mat,op);
1530   return 0;
1531 }
1532 
1533 /*@
1534    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
1535    this routine retains the old nonzero structure.
1536 
1537    Input Parameters:
1538 .  mat - the matrix
1539 
1540 .keywords: matrix, zero, entries
1541 
1542 .seealso: MatZeroRows()
1543 @*/
1544 int MatZeroEntries(Mat mat)
1545 {
1546   int ierr;
1547   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1548   if (mat->factor) SETERRQ(1,"MatZeroEntries:Not for factored matrix");
1549   if (!mat->ops.zeroentries) SETERRQ(PETSC_ERR_SUP,"MatZeroEntries");
1550 
1551   PLogEventBegin(MAT_ZeroEntries,mat,0,0,0);
1552   ierr = (*mat->ops.zeroentries)(mat); CHKERRQ(ierr);
1553   PLogEventEnd(MAT_ZeroEntries,mat,0,0,0);
1554   return 0;
1555 }
1556 
1557 /*@
1558    MatZeroRows - Zeros all entries (except possibly the main diagonal)
1559    of a set of rows of a matrix.
1560 
1561    Input Parameters:
1562 .  mat - the matrix
1563 .  is - index set of rows to remove
1564 .  diag - pointer to value put in all diagonals of eliminated rows.
1565           Note that diag is not a pointer to an array, but merely a
1566           pointer to a single value.
1567 
1568    Notes:
1569    For the AIJ matrix formats this removes the old nonzero structure,
1570    but does not release memory.  For the dense and block diagonal
1571    formats this does not alter the nonzero structure.
1572 
1573    The user can set a value in the diagonal entry (or for the AIJ and
1574    row formats can optionally remove the main diagonal entry from the
1575    nonzero structure as well, by passing a null pointer as the final
1576    argument).
1577 
1578 .keywords: matrix, zero, rows, boundary conditions
1579 
1580 .seealso: MatZeroEntries(),
1581 @*/
1582 int MatZeroRows(Mat mat,IS is, Scalar *diag)
1583 {
1584   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1585   if (!mat->assembled) SETERRQ(1,"MatZeroRows:Not for unassembled matrix");
1586   if (mat->factor) SETERRQ(1,"MatZeroRows:Not for factored matrix");
1587   if (mat->ops.zerorows) return (*mat->ops.zerorows)(mat,is,diag);
1588   SETERRQ(PETSC_ERR_SUP,"MatZeroRows");
1589 }
1590 
1591 /*@
1592    MatGetSize - Returns the numbers of rows and columns in a matrix.
1593 
1594    Input Parameter:
1595 .  mat - the matrix
1596 
1597    Output Parameters:
1598 .  m - the number of global rows
1599 .  n - the number of global columns
1600 
1601 .keywords: matrix, dimension, size, rows, columns, global, get
1602 
1603 .seealso: MatGetLocalSize()
1604 @*/
1605 int MatGetSize(Mat mat,int *m,int* n)
1606 {
1607   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1608   PetscValidIntPointer(m);
1609   PetscValidIntPointer(n);
1610   return (*mat->ops.getsize)(mat,m,n);
1611 }
1612 
1613 /*@
1614    MatGetLocalSize - Returns the number of rows and columns in a matrix
1615    stored locally.  This information may be implementation dependent, so
1616    use with care.
1617 
1618    Input Parameters:
1619 .  mat - the matrix
1620 
1621    Output Parameters:
1622 .  m - the number of local rows
1623 .  n - the number of local columns
1624 
1625 .keywords: matrix, dimension, size, local, rows, columns, get
1626 
1627 .seealso: MatGetSize()
1628 @*/
1629 int MatGetLocalSize(Mat mat,int *m,int* n)
1630 {
1631   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1632   PetscValidIntPointer(m);
1633   PetscValidIntPointer(n);
1634   return (*mat->ops.getlocalsize)(mat,m,n);
1635 }
1636 
1637 /*@
1638    MatGetOwnershipRange - Returns the range of matrix rows owned by
1639    this processor, assuming that the matrix is laid out with the first
1640    n1 rows on the first processor, the next n2 rows on the second, etc.
1641    For certain parallel layouts this range may not be well defined.
1642 
1643    Input Parameters:
1644 .  mat - the matrix
1645 
1646    Output Parameters:
1647 .  m - the first local row
1648 .  n - one more then the last local row
1649 
1650 .keywords: matrix, get, range, ownership
1651 @*/
1652 int MatGetOwnershipRange(Mat mat,int *m,int* n)
1653 {
1654   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1655   PetscValidIntPointer(m);
1656   PetscValidIntPointer(n);
1657   if (mat->ops.getownershiprange) return (*mat->ops.getownershiprange)(mat,m,n);
1658   SETERRQ(PETSC_ERR_SUP,"MatGetOwnershipRange");
1659 }
1660 
1661 /*@
1662    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
1663    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
1664    to complete the factorization.
1665 
1666    Input Parameters:
1667 .  mat - the matrix
1668 .  row - row permutation
1669 .  column - column permutation
1670 .  fill - number of levels of fill
1671 .  f - expected fill as ratio of the original number of nonzeros,
1672        for example 3.0; choosing this parameter well can result in
1673        more efficient use of time and space.
1674 
1675    Output Parameters:
1676 .  fact - new matrix that has been symbolically factored
1677 
1678    Options Database Key:
1679 $   -mat_ilu_fill <f>, where f is the fill ratio
1680 
1681    Notes:
1682    See the file $(PETSC_DIR)/Performace for additional information about
1683    choosing the fill factor for better efficiency.
1684 
1685 .keywords: matrix, factor, incomplete, ILU, symbolic, fill
1686 
1687 .seealso: MatLUFactorSymbolic(), MatLUFactorNumeric()
1688 @*/
1689 int MatILUFactorSymbolic(Mat mat,IS row,IS col,double f,int fill,Mat *fact)
1690 {
1691   int ierr,flg;
1692 
1693   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1694   if (fill < 0) SETERRQ(1,"MatILUFactorSymbolic:Levels of fill negative");
1695   if (!fact) SETERRQ(1,"MatILUFactorSymbolic:Fact argument is missing");
1696   if (!mat->ops.ilufactorsymbolic) SETERRQ(PETSC_ERR_SUP,"MatILUFactorSymbolic");
1697   if (!mat->assembled) SETERRQ(1,"MatILUFactorSymbolic:Not for unassembled matrix");
1698   if (mat->factor) SETERRQ(1,"MatILUFactorSymbolic:Not for factored matrix");
1699 
1700   ierr = OptionsGetDouble(PETSC_NULL,"-mat_ilu_fill",&f,&flg); CHKERRQ(ierr);
1701   PLogEventBegin(MAT_ILUFactorSymbolic,mat,row,col,0);
1702   ierr = (*mat->ops.ilufactorsymbolic)(mat,row,col,f,fill,fact); CHKERRQ(ierr);
1703   PLogEventEnd(MAT_ILUFactorSymbolic,mat,row,col,0);
1704   return 0;
1705 }
1706 
1707 /*@
1708    MatIncompleteCholeskyFactorSymbolic - Performs symbolic incomplete
1709    Cholesky factorization for a symmetric matrix.  Use
1710    MatCholeskyFactorNumeric() to complete the factorization.
1711 
1712    Input Parameters:
1713 .  mat - the matrix
1714 .  perm - row and column permutation
1715 .  fill - levels of fill
1716 .  f - expected fill as ratio of original fill
1717 
1718    Output Parameter:
1719 .  fact - the factored matrix
1720 
1721    Note:  Currently only no-fill factorization is supported.
1722 
1723 .keywords: matrix, factor, incomplete, ICC, Cholesky, symbolic, fill
1724 
1725 .seealso: MatCholeskyFactorNumeric(), MatCholeskyFactor()
1726 @*/
1727 int MatIncompleteCholeskyFactorSymbolic(Mat mat,IS perm,double f,int fill,
1728                                         Mat *fact)
1729 {
1730   int ierr;
1731   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1732   if (mat->factor) SETERRQ(1,"MatIncompleteCholeskyFactorSymbolic:Not for factored matrix");
1733   if (fill < 0) SETERRQ(1,"MatIncompleteCholeskyFactorSymbolic:Fill negative");
1734   if (!fact) SETERRQ(1,"MatIncompleteCholeskyFactorSymbolic:Missing fact argument");
1735   if (!mat->ops.incompletecholeskyfactorsymbolic)
1736      SETERRQ(PETSC_ERR_SUP,"MatIncompleteCholeskyFactorSymbolic");
1737   if (!mat->assembled)
1738      SETERRQ(1,"MatIncompleteCholeskyFactorSymbolic:Not for unassembled matrix");
1739 
1740   PLogEventBegin(MAT_IncompleteCholeskyFactorSymbolic,mat,perm,0,0);
1741   ierr = (*mat->ops.incompletecholeskyfactorsymbolic)(mat,perm,f,fill,fact);CHKERRQ(ierr);
1742   PLogEventEnd(MAT_IncompleteCholeskyFactorSymbolic,mat,perm,0,0);
1743   return 0;
1744 }
1745 
1746 /*@C
1747    MatGetArray - Returns a pointer to the element values in the matrix.
1748    This routine  is implementation dependent, and may not even work for
1749    certain matrix types. You MUST call MatRestoreArray() when you no
1750    longer need to access the array.
1751 
1752    Input Parameter:
1753 .  mat - the matrix
1754 
1755    Output Parameter:
1756 .  v - the location of the values
1757 
1758    Fortran Note:
1759    The Fortran interface is slightly different from that given below.
1760    See the Fortran chapter of the users manual and
1761    petsc/src/mat/examples for details.
1762 
1763 .keywords: matrix, array, elements, values
1764 
1765 .seeaols: MatRestoreArray()
1766 @*/
1767 int MatGetArray(Mat mat,Scalar **v)
1768 {
1769   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1770   if (!v) SETERRQ(1,"MatGetArray:Bad input, array pointer location");
1771   if (!mat->ops.getarray) SETERRQ(PETSC_ERR_SUP,"MatGetArray");
1772   return (*mat->ops.getarray)(mat,v);
1773 }
1774 
1775 /*@C
1776    MatRestoreArray - Restores the matrix after MatGetArray has been called.
1777 
1778    Input Parameter:
1779 .  mat - the matrix
1780 .  v - the location of the values
1781 
1782    Fortran Note:
1783    The Fortran interface is slightly different from that given below.
1784    See the users manual and petsc/src/mat/examples for details.
1785 
1786 .keywords: matrix, array, elements, values, resrore
1787 
1788 .seealso: MatGetArray()
1789 @*/
1790 int MatRestoreArray(Mat mat,Scalar **v)
1791 {
1792   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1793   if (!v) SETERRQ(1,"MatRestoreArray:Bad input, array pointer location");
1794   if (!mat->ops.restorearray) SETERRQ(PETSC_ERR_SUP,"MatResroreArray");
1795   return (*mat->ops.restorearray)(mat,v);
1796 }
1797 
1798 /*@C
1799    MatGetSubMatrices - Extracts several submatrices from a matrix. If submat
1800    points to an array of valid matrices, it may be reused.
1801 
1802    Input Parameters:
1803 .  mat - the matrix
1804 .  irow, icol - index sets of rows and columns to extract
1805 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1806 
1807    Output Parameter:
1808 .  submat - the array of submatrices
1809 
1810    Limitations:
1811    Currently, MatGetSubMatrices() can extract only sequential submatrices
1812    (from both sequential and parallel matrices).
1813 
1814    Notes:
1815    When extracting submatrices from a parallel matrix, each processor can
1816    form a different submatrix by setting the rows and columns of its
1817    individual index sets according to the local submatrix desired.
1818 
1819    When finished using the submatrices, the user should destroy
1820    them with MatDestroySubMatrices().
1821 
1822 .keywords: matrix, get, submatrix, submatrices
1823 
1824 .seealso: MatDestroyMatrices()
1825 @*/
1826 int MatGetSubMatrices(Mat mat,int n,IS *irow,IS *icol,MatGetSubMatrixCall scall,
1827                       Mat **submat)
1828 {
1829   int ierr;
1830   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1831   if (!mat->ops.getsubmatrices) SETERRQ(PETSC_ERR_SUP,"MatGetSubMatrices");
1832   if (!mat->assembled) SETERRQ(1,"MatGetSubMatrices:Not for unassembled matrix");
1833 
1834   PLogEventBegin(MAT_GetSubMatrices,mat,0,0,0);
1835   ierr = (*mat->ops.getsubmatrices)(mat,n,irow,icol,scall,submat); CHKERRQ(ierr);
1836   PLogEventEnd(MAT_GetSubMatrices,mat,0,0,0);
1837 
1838   return 0;
1839 }
1840 
1841 /*@C
1842    MatDestroyMatrices - Destroys a set of matrices obtained with MatGetSubMatrices().
1843 
1844    Input Parameters:
1845 .  n - the number of local matrices
1846 .  mat - the matrices
1847 
1848 .keywords: matrix, destroy, submatrix, submatrices
1849 
1850 .seealso: MatGetSubMatrices()
1851 @*/
1852 int MatDestroyMatrices(int n,Mat **mat)
1853 {
1854   int ierr,i;
1855 
1856   PetscValidPointer(mat);
1857   for ( i=0; i<n; i++ ) {
1858     ierr = MatDestroy((*mat)[i]); CHKERRQ(ierr);
1859   }
1860   PetscFree(*mat);
1861   return 0;
1862 }
1863 
1864 /*@
1865    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
1866    replaces the index by larger ones that represent submatrices with more
1867    overlap.
1868 
1869    Input Parameters:
1870 .  mat - the matrix
1871 .  n   - the number of index sets
1872 .  is  - the array of pointers to index sets
1873 .  ov  - the additional overlap requested
1874 
1875 .keywords: matrix, overlap, Schwarz
1876 
1877 .seealso: MatGetSubMatrices()
1878 @*/
1879 int MatIncreaseOverlap(Mat mat,int n, IS *is,int ov)
1880 {
1881   int ierr;
1882   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1883   if (!mat->assembled) SETERRQ(1,"MatIncreaseOverlap:Not for unassembled matrix");
1884 
1885   if (ov == 0) return 0;
1886   if (!mat->ops.increaseoverlap) SETERRQ(PETSC_ERR_SUP,"MatIncreaseOverlap");
1887   PLogEventBegin(MAT_IncreaseOverlap,mat,0,0,0);
1888   ierr = (*mat->ops.increaseoverlap)(mat,n,is,ov); CHKERRQ(ierr);
1889   PLogEventEnd(MAT_IncreaseOverlap,mat,0,0,0);
1890   return 0;
1891 }
1892 
1893 /*@
1894    MatPrintHelp - Prints all the options for the matrix.
1895 
1896    Input Parameter:
1897 .  mat - the matrix
1898 
1899    Options Database Keys:
1900 $  -help, -h
1901 
1902 .keywords: mat, help
1903 
1904 .seealso: MatCreate(), MatCreateXXX()
1905 @*/
1906 int MatPrintHelp(Mat mat)
1907 {
1908   static int called = 0;
1909   MPI_Comm   comm = mat->comm;
1910 
1911   if (!called) {
1912     PetscPrintf(comm,"General matrix options:\n");
1913     PetscPrintf(comm,"  -mat_view_info : view basic matrix info during MatAssemblyEnd()\n");
1914     PetscPrintf(comm,"  -mat_view_info_detailed : view detailed matrix info during MatAssemblyEnd()\n");
1915     PetscPrintf(comm,"  -mat_view_draw : draw nonzero matrix structure during MatAssemblyEnd()\n");
1916     PetscPrintf(comm,"      -draw_pause <sec> : set seconds of display pause\n");
1917     PetscPrintf(comm,"      -display <name> : set alternate display\n");
1918     called = 1;
1919   }
1920   if (mat->ops.printhelp) (*mat->ops.printhelp)(mat);
1921   return 0;
1922 }
1923 
1924 /*@
1925    MatGetBlockSize - Returns the matrix block size; useful especially for the
1926    block row and block diagonal formats.
1927 
1928    Input Parameter:
1929 .  mat - the matrix
1930 
1931    Output Parameter:
1932 .  bs - block size
1933 
1934    Notes:
1935 $  block diagonal formats: MATSEQBDIAG, MATMPIBDIAG
1936 $  block row formats: MATSEQBAIJ, MATMPIBAIJ
1937 
1938 .keywords: matrix, get, block, size
1939 
1940 .seealso: MatCreateSeqBAIJ(), MatCreateMPIBAIJ(), MatCreateSeqBDiag(), MatCreateMPIBDiag()
1941 @*/
1942 int MatGetBlockSize(Mat mat,int *bs)
1943 {
1944   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1945   PetscValidIntPointer(bs);
1946   if (!mat->ops.getblocksize) SETERRQ(PETSC_ERR_SUP,"MatGetBlockSize");
1947   return (*mat->ops.getblocksize)(mat,bs);
1948 }
1949 
1950 /*@C
1951       MatGetRowIJ - Returns the compress row storage i and j indices for sequential matrices.
1952                  EXPERTS ONLY.
1953 
1954   Input Parameters:
1955 .   mat - the matrix
1956 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
1957 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
1958                 symmetrized
1959 
1960   Output Parameters:
1961 .   n - number of rows and columns in the (possibly compressed) matrix
1962 .   ia - the row indices
1963 .   ja - the column indices
1964 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
1965 @*/
1966 int MatGetRowIJ(Mat mat,int shift,PetscTruth symmetric,int *n,int **ia,int** ja,PetscTruth *done)
1967 {
1968   int ierr;
1969   PetscValidHeaderSpecific(mat,MAT_COOKIE);
1970   if (ia) PetscValidIntPointer(ia);
1971   if (ja) PetscValidIntPointer(ja);
1972   PetscValidIntPointer(done);
1973   if (!mat->ops.getrowij) *done = PETSC_FALSE;
1974   else {
1975     *done = PETSC_TRUE;
1976     ierr  = (*mat->ops.getrowij)(mat,shift,symmetric,n,ia,ja,done); CHKERRQ(ierr);
1977   }
1978   return 0;
1979 }
1980 
1981 /*@C
1982       MatGetColumnIJ - Returns the compress Column storage i and j indices for sequential matrices.
1983                  EXPERTS ONLY.
1984 
1985   Input Parameters:
1986 .   mat - the matrix
1987 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
1988 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
1989                 symmetrized
1990 
1991   Output Parameters:
1992 .   n - number of Columns and columns in the (possibly compressed) matrix
1993 .   ia - the Column indices
1994 .   ja - the column indices
1995 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
1996 @*/
1997 int MatGetColumnIJ(Mat mat,int shift,PetscTruth symmetric,int *n,int **ia,int** ja,PetscTruth *done)
1998 {
1999   int ierr;
2000   PetscValidHeaderSpecific(mat,MAT_COOKIE);
2001   if (ia) PetscValidIntPointer(ia);
2002   if (ja) PetscValidIntPointer(ja);
2003   PetscValidIntPointer(done);
2004 
2005   if (!mat->ops.getcolumnij) *done = PETSC_FALSE;
2006   else {
2007     *done = PETSC_TRUE;
2008     ierr  = (*mat->ops.getcolumnij)(mat,shift,symmetric,n,ia,ja,done); CHKERRQ(ierr);
2009   }
2010   return 0;
2011 }
2012 
2013 /*@C
2014       MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
2015                      MatGetRowIJ(). EXPERTS ONLY.
2016 
2017   Input Parameters:
2018 .   mat - the matrix
2019 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
2020 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
2021                 symmetrized
2022 
2023   Output Parameters:
2024 .   n - size of (possibly compressed) matrix
2025 .   ia - the row indices
2026 .   ja - the column indices
2027 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
2028 @*/
2029 int MatRestoreRowIJ(Mat mat,int shift,PetscTruth symmetric,int *n,int **ia,int** ja,PetscTruth *done)
2030 {
2031   int ierr;
2032   PetscValidHeaderSpecific(mat,MAT_COOKIE);
2033   if (ia) PetscValidIntPointer(ia);
2034   if (ja) PetscValidIntPointer(ja);
2035   PetscValidIntPointer(done);
2036 
2037   if (!mat->ops.restorerowij) *done = PETSC_FALSE;
2038   else {
2039     *done = PETSC_TRUE;
2040     ierr  = (*mat->ops.restorerowij)(mat,shift,symmetric,n,ia,ja,done); CHKERRQ(ierr);
2041   }
2042   return 0;
2043 }
2044 
2045 /*@C
2046       MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
2047                      MatGetColumnIJ(). EXPERTS ONLY.
2048 
2049   Input Parameters:
2050 .   mat - the matrix
2051 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
2052 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
2053                 symmetrized
2054 
2055   Output Parameters:
2056 .   n - size of (possibly compressed) matrix
2057 .   ia - the Column indices
2058 .   ja - the column indices
2059 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
2060 @*/
2061 int MatRestoreColumnIJ(Mat mat,int shift,PetscTruth symmetric,int *n,int **ia,int** ja,PetscTruth *done)
2062 {
2063   int ierr;
2064   PetscValidHeaderSpecific(mat,MAT_COOKIE);
2065   if (ia) PetscValidIntPointer(ia);
2066   if (ja) PetscValidIntPointer(ja);
2067   PetscValidIntPointer(done);
2068 
2069   if (!mat->ops.restorecolumnij) *done = PETSC_FALSE;
2070   else {
2071     *done = PETSC_TRUE;
2072     ierr  = (*mat->ops.restorecolumnij)(mat,shift,symmetric,n,ia,ja,done); CHKERRQ(ierr);
2073   }
2074   return 0;
2075 }
2076 
2077 /*@C
2078       MatColoringPatch - EXPERTS ONLY, used inside matrix coloring routines that
2079           use matGetRowIJ() and/or MatGetColumnIJ().
2080 
2081   Input Parameters:
2082 .   mat - the matrix
2083 .   n   - number of colors
2084 .   colorarray - array indicating color for each column
2085 
2086   Output Parameters:
2087 .   iscoloring - coloring generated using colorarray information
2088 
2089 @*/
2090 int MatColoringPatch(Mat mat,int n,int *colorarray,ISColoring *iscoloring)
2091 {
2092   int ierr;
2093   PetscValidHeaderSpecific(mat,MAT_COOKIE);
2094   PetscValidIntPointer(colorarray);
2095 
2096   if (!mat->ops.coloringpatch) {SETERRQ(PETSC_ERR_SUP,"MatColoringPatch");}
2097   else {
2098     ierr  = (*mat->ops.coloringpatch)(mat,n,colorarray,iscoloring); CHKERRQ(ierr);
2099   }
2100   return 0;
2101 }
2102 
2103 
2104