xref: /petsc/src/vec/is/utils/isltog.c (revision 606d414c6e034e02e67059b83ebaefc3ebe99698)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*606d414cSSatish Balay static char vcid[] = "$Id: isltog.c,v 1.29 1999/06/30 22:49:49 bsmith Exp balay $";
32362add9SBarry Smith #endif
42362add9SBarry Smith 
52362add9SBarry Smith #include "sys.h"   /*I "sys.h" I*/
683271157SBarry Smith #include "src/vec/is/isimpl.h"    /*I "is.h"  I*/
72362add9SBarry Smith 
85615d1e5SSatish Balay #undef __FUNC__
95a5d4f66SBarry Smith #define __FUNC__ "ISLocalToGlobalMappingView"
105a5d4f66SBarry Smith /*@C
115a5d4f66SBarry Smith     ISLocalToGlobalMappingView - View a local to global mapping
125a5d4f66SBarry Smith 
13b9cd556bSLois Curfman McInnes     Not Collective
14b9cd556bSLois Curfman McInnes 
155a5d4f66SBarry Smith     Input Parameters:
165a5d4f66SBarry Smith .   ltog - local to global mapping
17b9cd556bSLois Curfman McInnes .   viewer - viewer
185a5d4f66SBarry Smith 
19a997ad1aSLois Curfman McInnes     Level: advanced
20a997ad1aSLois Curfman McInnes 
215a5d4f66SBarry Smith .keywords: IS, local-to-global mapping, create
225a5d4f66SBarry Smith 
235a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
245a5d4f66SBarry Smith @*/
255a5d4f66SBarry Smith int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,Viewer viewer)
265a5d4f66SBarry Smith {
275a5d4f66SBarry Smith   int      i;
285a5d4f66SBarry Smith 
295a5d4f66SBarry Smith   PetscFunctionBegin;
305a5d4f66SBarry Smith 
315a5d4f66SBarry Smith   for ( i=0; i<mapping->n; i++ ) {
325a5d4f66SBarry Smith     printf("%d %d\n",i,mapping->indices[i]);
335a5d4f66SBarry Smith   }
345a5d4f66SBarry Smith 
355a5d4f66SBarry Smith   PetscFunctionReturn(0);
365a5d4f66SBarry Smith }
375a5d4f66SBarry Smith 
385a5d4f66SBarry Smith #undef __FUNC__
392bdab257SBarry Smith #define __FUNC__ "ISLocalToGlobalMappingCreateIS"
402bdab257SBarry Smith /*@C
412bdab257SBarry Smith     ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n)
422bdab257SBarry Smith     ordering and a global parallel ordering.
432bdab257SBarry Smith 
44b9cd556bSLois Curfman McInnes     Collective on IS
45b9cd556bSLois Curfman McInnes 
46a997ad1aSLois Curfman McInnes     Input Parameter:
472bdab257SBarry Smith .   is - index set containing the global numbers for each local
482bdab257SBarry Smith 
49a997ad1aSLois Curfman McInnes     Output Parameter:
502bdab257SBarry Smith .   mapping - new mapping data structure
512bdab257SBarry Smith 
52a997ad1aSLois Curfman McInnes     Level: advanced
53a997ad1aSLois Curfman McInnes 
542bdab257SBarry Smith .keywords: IS, local-to-global mapping, create
552bdab257SBarry Smith 
562bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate()
572bdab257SBarry Smith @*/
582bdab257SBarry Smith int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping)
592bdab257SBarry Smith {
602bdab257SBarry Smith   int      n,*indices,ierr;
612bdab257SBarry Smith   MPI_Comm comm;
623a40ed3dSBarry Smith 
633a40ed3dSBarry Smith   PetscFunctionBegin;
642bdab257SBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
652bdab257SBarry Smith 
662bdab257SBarry Smith   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
672bdab257SBarry Smith   ierr = ISGetSize(is,&n);CHKERRQ(ierr);
682bdab257SBarry Smith   ierr = ISGetIndices(is,&indices);CHKERRQ(ierr);
692bdab257SBarry Smith   ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr);
702bdab257SBarry Smith   ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr);
712bdab257SBarry Smith 
723a40ed3dSBarry Smith   PetscFunctionReturn(0);
732bdab257SBarry Smith }
745a5d4f66SBarry Smith 
752bdab257SBarry Smith #undef __FUNC__
76d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingCreate"
77dd7157adSSatish Balay /*@C
7890f02eecSBarry Smith     ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n)
7990f02eecSBarry Smith     ordering and a global parallel ordering.
802362add9SBarry Smith 
81b9cd556bSLois Curfman McInnes     Collective on MPI_Comm
82b9cd556bSLois Curfman McInnes 
832362add9SBarry Smith     Input Parameters:
84b9cd556bSLois Curfman McInnes +   comm - MPI communicator of size 1.
8590f02eecSBarry Smith .   n - the number of local elements
86b9cd556bSLois Curfman McInnes -   indices - the global index for each local element
872362add9SBarry Smith 
88a997ad1aSLois Curfman McInnes     Output Parameter:
8990f02eecSBarry Smith .   mapping - new mapping data structure
902362add9SBarry Smith 
91a997ad1aSLois Curfman McInnes     Level: advanced
92a997ad1aSLois Curfman McInnes 
933acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, create
942362add9SBarry Smith 
952bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS()
962362add9SBarry Smith @*/
97987e4450SSatish Balay int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping)
982362add9SBarry Smith {
99549d3d68SSatish Balay   int ierr;
100549d3d68SSatish Balay 
1013a40ed3dSBarry Smith   PetscFunctionBegin;
10290f02eecSBarry Smith   PetscValidIntPointer(indices);
10390f02eecSBarry Smith   PetscValidPointer(mapping);
1042362add9SBarry Smith 
1053f1db9ecSBarry Smith   PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping",
1063f1db9ecSBarry Smith                     cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);
107d4bb536fSBarry Smith   PLogObjectCreate(*mapping);
108d4bb536fSBarry Smith   PLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int));
109d4bb536fSBarry Smith 
110d4bb536fSBarry Smith   (*mapping)->n       = n;
11190f02eecSBarry Smith   (*mapping)->indices = (int *) PetscMalloc((n+1)*sizeof(int));CHKPTRQ((*mapping)->indices);
112549d3d68SSatish Balay   ierr = PetscMemcpy((*mapping)->indices,indices,n*sizeof(int));CHKERRQ(ierr);
113d4bb536fSBarry Smith 
114d4bb536fSBarry Smith   /*
115d4bb536fSBarry Smith       Do not create the global to local mapping. This is only created if
116d4bb536fSBarry Smith      ISGlobalToLocalMapping() is called
117d4bb536fSBarry Smith   */
118d4bb536fSBarry Smith   (*mapping)->globals = 0;
1193a40ed3dSBarry Smith   PetscFunctionReturn(0);
1202362add9SBarry Smith }
1212362add9SBarry Smith 
1225615d1e5SSatish Balay #undef __FUNC__
123d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingDestroy"
12490f02eecSBarry Smith /*@
12590f02eecSBarry Smith    ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n)
12690f02eecSBarry Smith    ordering and a global parallel ordering.
12790f02eecSBarry Smith 
128b9cd556bSLois Curfman McInnes    Collective on ISLocalToGlobalMapping
129b9cd556bSLois Curfman McInnes 
13090f02eecSBarry Smith    Input Parameters:
13190f02eecSBarry Smith .  mapping - mapping data structure
13290f02eecSBarry Smith 
133a997ad1aSLois Curfman McInnes    Level: advanced
134a997ad1aSLois Curfman McInnes 
1353acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, destroy
13690f02eecSBarry Smith 
1373acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate()
13890f02eecSBarry Smith @*/
13990f02eecSBarry Smith int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping)
14090f02eecSBarry Smith {
141*606d414cSSatish Balay   int ierr;
1423a40ed3dSBarry Smith   PetscFunctionBegin;
14390f02eecSBarry Smith   PetscValidPointer(mapping);
1443a40ed3dSBarry Smith   if (--mapping->refct > 0) PetscFunctionReturn(0);
14585614651SBarry Smith   if (mapping->refct < 0) {
14685614651SBarry Smith     SETERRQ(1,1,"Mapping already destroyed");
14785614651SBarry Smith   }
14890f02eecSBarry Smith 
149*606d414cSSatish Balay   ierr = PetscFree(mapping->indices);CHKERRQ(ierr);
150*606d414cSSatish Balay   if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);}
151d4bb536fSBarry Smith   PLogObjectDestroy(mapping);
152d4bb536fSBarry Smith   PetscHeaderDestroy(mapping);
1533a40ed3dSBarry Smith   PetscFunctionReturn(0);
15490f02eecSBarry Smith }
15590f02eecSBarry Smith 
1565615d1e5SSatish Balay #undef __FUNC__
157d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingApplyIS"
15890f02eecSBarry Smith /*@
1593acfe500SLois Curfman McInnes     ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering
1603acfe500SLois Curfman McInnes     a new index set using the global numbering defined in an ISLocalToGlobalMapping
1613acfe500SLois Curfman McInnes     context.
16290f02eecSBarry Smith 
163b9cd556bSLois Curfman McInnes     Not collective
164b9cd556bSLois Curfman McInnes 
16590f02eecSBarry Smith     Input Parameters:
166b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
167b9cd556bSLois Curfman McInnes -   is - index set in local numbering
16890f02eecSBarry Smith 
16990f02eecSBarry Smith     Output Parameters:
17090f02eecSBarry Smith .   newis - index set in global numbering
17190f02eecSBarry Smith 
172a997ad1aSLois Curfman McInnes     Level: advanced
173a997ad1aSLois Curfman McInnes 
1743acfe500SLois Curfman McInnes .keywords: IS, local-to-global mapping, apply
1753acfe500SLois Curfman McInnes 
17690f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
177d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply()
17890f02eecSBarry Smith @*/
17990f02eecSBarry Smith int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping, IS is, IS *newis)
18090f02eecSBarry Smith {
18190f02eecSBarry Smith   int ierr,n,i,*idxin,*idxmap,*idxout;
1823a40ed3dSBarry Smith 
1833a40ed3dSBarry Smith   PetscFunctionBegin;
18490f02eecSBarry Smith   PetscValidPointer(mapping);
18590f02eecSBarry Smith   PetscValidHeaderSpecific(is,IS_COOKIE);
18690f02eecSBarry Smith   PetscValidPointer(newis);
18790f02eecSBarry Smith 
18890f02eecSBarry Smith   ierr   = ISGetSize(is,&n);CHKERRQ(ierr);
18990f02eecSBarry Smith   ierr   = ISGetIndices(is,&idxin);CHKERRQ(ierr);
19090f02eecSBarry Smith   idxmap = mapping->indices;
19190f02eecSBarry Smith 
19290f02eecSBarry Smith   idxout = (int *) PetscMalloc((n+1)*sizeof(int));CHKPTRQ(idxout);
19390f02eecSBarry Smith   for ( i=0; i<n; i++ ) {
19490f02eecSBarry Smith     idxout[i] = idxmap[idxin[i]];
19590f02eecSBarry Smith   }
196029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr);
197*606d414cSSatish Balay   ierr = PetscFree(idxout);CHKERRQ(ierr);
1983a40ed3dSBarry Smith   PetscFunctionReturn(0);
19990f02eecSBarry Smith }
20090f02eecSBarry Smith 
2015615d1e5SSatish Balay #undef __FUNC__
202d4bb536fSBarry Smith #define __FUNC__ "ISLocalToGlobalMappingApply"
203d4bb536fSBarry Smith /*@C
2043acfe500SLois Curfman McInnes    ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering
2053acfe500SLois Curfman McInnes    and converts them to the global numbering.
20690f02eecSBarry Smith 
207b9cd556bSLois Curfman McInnes    Not collective
208b9cd556bSLois Curfman McInnes 
209bb25748dSBarry Smith    Input Parameters:
210b9cd556bSLois Curfman McInnes +  mapping - the local to global mapping context
211bb25748dSBarry Smith .  N - number of integers
212b9cd556bSLois Curfman McInnes -  in - input indices in local numbering
213bb25748dSBarry Smith 
214bb25748dSBarry Smith    Output Parameter:
215bb25748dSBarry Smith .  out - indices in global numbering
216bb25748dSBarry Smith 
217b9cd556bSLois Curfman McInnes    Notes:
218b9cd556bSLois Curfman McInnes    The in and out array parameters may be identical.
219d4bb536fSBarry Smith 
220a997ad1aSLois Curfman McInnes    Level: advanced
221a997ad1aSLois Curfman McInnes 
222bb25748dSBarry Smith .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(),
2230752156aSBarry Smith           ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(),
224d4bb536fSBarry Smith           AOPetscToApplication(), ISGlobalToLocalMappingApply()
225bb25748dSBarry Smith 
2263acfe500SLois Curfman McInnes .keywords: local-to-global, mapping, apply
227d4bb536fSBarry Smith 
228d4bb536fSBarry Smith @*/
229987e4450SSatish Balay int ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,const int in[],int out[])
230d4bb536fSBarry Smith {
231d4bb536fSBarry Smith   int i,*idx = mapping->indices,Nmax = mapping->n;
2323a40ed3dSBarry Smith 
2333a40ed3dSBarry Smith   PetscFunctionBegin;
234d4bb536fSBarry Smith   for ( i=0; i<N; i++ ) {
235d4bb536fSBarry Smith     if (in[i] < 0) {out[i] = in[i]; continue;}
236596552b5SBarry Smith     if (in[i] >= Nmax) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,1,"Local index %d too large %d (max)",in[i],Nmax);
237d4bb536fSBarry Smith     out[i] = idx[in[i]];
238d4bb536fSBarry Smith   }
2393a40ed3dSBarry Smith   PetscFunctionReturn(0);
240d4bb536fSBarry Smith }
241d4bb536fSBarry Smith 
242d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/
243d4bb536fSBarry Smith 
244d4bb536fSBarry Smith #undef __FUNC__
245d4bb536fSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingSetUp_Private"
246d4bb536fSBarry Smith /*
247d4bb536fSBarry Smith     Creates the global fields in the ISLocalToGlobalMapping structure
248d4bb536fSBarry Smith */
249d4bb536fSBarry Smith static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping)
250d4bb536fSBarry Smith {
251d4bb536fSBarry Smith   int i,*idx = mapping->indices,n = mapping->n,end,start,*globals;
252d4bb536fSBarry Smith 
2533a40ed3dSBarry Smith   PetscFunctionBegin;
254d4bb536fSBarry Smith   end   = 0;
255d4bb536fSBarry Smith   start = 100000000;
256d4bb536fSBarry Smith 
257d4bb536fSBarry Smith   for ( i=0; i<n; i++ ) {
258d4bb536fSBarry Smith     if (idx[i] < 0) continue;
259d4bb536fSBarry Smith     if (idx[i] < start) start = idx[i];
260d4bb536fSBarry Smith     if (idx[i] > end)   end   = idx[i];
261d4bb536fSBarry Smith   }
262d4bb536fSBarry Smith   if (start > end) {start = 0; end = -1;}
263d4bb536fSBarry Smith   mapping->globalstart = start;
264d4bb536fSBarry Smith   mapping->globalend   = end;
265d4bb536fSBarry Smith 
266d4bb536fSBarry Smith   globals = mapping->globals = (int *) PetscMalloc((end-start+2)*sizeof(int));CHKPTRQ(mapping->globals);
267d4bb536fSBarry Smith   for ( i=0; i<end-start+1; i++ ) {
268d4bb536fSBarry Smith     globals[i] = -1;
269d4bb536fSBarry Smith   }
270d4bb536fSBarry Smith   for ( i=0; i<n; i++ ) {
271d4bb536fSBarry Smith     if (idx[i] < 0) continue;
272d4bb536fSBarry Smith     globals[idx[i] - start] = i;
273d4bb536fSBarry Smith   }
274d4bb536fSBarry Smith 
275d4bb536fSBarry Smith   PLogObjectMemory(mapping,(end-start+1)*sizeof(int));
2763a40ed3dSBarry Smith   PetscFunctionReturn(0);
277d4bb536fSBarry Smith }
278d4bb536fSBarry Smith 
279d4bb536fSBarry Smith #undef __FUNC__
280d4bb536fSBarry Smith #define __FUNC__ "ISGlobalToLocalMappingApply"
281d4bb536fSBarry Smith /*@
282a997ad1aSLois Curfman McInnes     ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers
283a997ad1aSLois Curfman McInnes     specified with a global numbering.
284d4bb536fSBarry Smith 
285b9cd556bSLois Curfman McInnes     Not collective
286b9cd556bSLois Curfman McInnes 
287d4bb536fSBarry Smith     Input Parameters:
288b9cd556bSLois Curfman McInnes +   mapping - mapping between local and global numbering
289d4bb536fSBarry Smith .   type - IS_GTOLM_MASK - replaces global indices with no local value with -1
290d4bb536fSBarry Smith            IS_GTOLM_DROP - drops the indices with no local value from the output list
291d4bb536fSBarry Smith .   n - number of global indices to map
292b9cd556bSLois Curfman McInnes -   idx - global indices to map
293d4bb536fSBarry Smith 
294d4bb536fSBarry Smith     Output Parameters:
295b9cd556bSLois Curfman McInnes +   nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n)
296b9cd556bSLois Curfman McInnes -   idxout - local index of each global index, one must pass in an array long enough
297e182c471SBarry Smith              to hold all the indices. You can call ISGlobalToLocalMappingApply() with
298e182c471SBarry Smith              idxout == PETSC_NULL to determine the required length (returned in nout)
299e182c471SBarry Smith              and then allocate the required space and call ISGlobalToLocalMappingApply()
300e182c471SBarry Smith              a second time to set the values.
301d4bb536fSBarry Smith 
302b9cd556bSLois Curfman McInnes     Notes:
303b9cd556bSLois Curfman McInnes     Either nout or idxout may be PETSC_NULL. idx and idxout may be identical.
304d4bb536fSBarry Smith 
305a997ad1aSLois Curfman McInnes     Level: advanced
306a997ad1aSLois Curfman McInnes 
307d4bb536fSBarry Smith .keywords: IS, global-to-local mapping, apply
308d4bb536fSBarry Smith 
309d4bb536fSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),
310d4bb536fSBarry Smith           ISLocalToGlobalMappingDestroy()
311d4bb536fSBarry Smith @*/
312d4bb536fSBarry Smith int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingType type,
313987e4450SSatish Balay                                   int n, const int idx[],int *nout,int idxout[])
314d4bb536fSBarry Smith {
315d4bb536fSBarry Smith   int i,ierr, *globals,nf = 0,tmp,start,end;
316d4bb536fSBarry Smith 
3173a40ed3dSBarry Smith   PetscFunctionBegin;
318d4bb536fSBarry Smith   if (!mapping->globals) {
319d4bb536fSBarry Smith     ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr);
320d4bb536fSBarry Smith   }
321d4bb536fSBarry Smith   globals = mapping->globals;
322d4bb536fSBarry Smith   start   = mapping->globalstart;
323d4bb536fSBarry Smith   end     = mapping->globalend;
324d4bb536fSBarry Smith 
325d4bb536fSBarry Smith   if (type == IS_GTOLM_MASK) {
326d4bb536fSBarry Smith     if (idxout) {
327d4bb536fSBarry Smith       for ( i=0; i<n; i++ ) {
328d4bb536fSBarry Smith         if (idx[i] < 0) idxout[i] = idx[i];
329d4bb536fSBarry Smith         else if (idx[i] < start) idxout[i] = -1;
330d4bb536fSBarry Smith         else if (idx[i] > end)   idxout[i] = -1;
331d4bb536fSBarry Smith         else                     idxout[i] = globals[idx[i] - start];
332d4bb536fSBarry Smith       }
333d4bb536fSBarry Smith     }
334d4bb536fSBarry Smith     if (nout) *nout = n;
335d4bb536fSBarry Smith   } else {
336d4bb536fSBarry Smith     if (idxout) {
337d4bb536fSBarry Smith       for ( i=0; i<n; i++ ) {
338d4bb536fSBarry Smith         if (idx[i] < 0) continue;
339d4bb536fSBarry Smith         if (idx[i] < start) continue;
340d4bb536fSBarry Smith         if (idx[i] > end) continue;
341d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
342d4bb536fSBarry Smith         if (tmp < 0) continue;
343d4bb536fSBarry Smith         idxout[nf++] = tmp;
344d4bb536fSBarry Smith       }
345d4bb536fSBarry Smith     } else {
346d4bb536fSBarry Smith       for ( i=0; i<n; i++ ) {
347d4bb536fSBarry Smith         if (idx[i] < 0) continue;
348d4bb536fSBarry Smith         if (idx[i] < start) continue;
349d4bb536fSBarry Smith         if (idx[i] > end) continue;
350d4bb536fSBarry Smith         tmp = globals[idx[i] - start];
351d4bb536fSBarry Smith         if (tmp < 0) continue;
352d4bb536fSBarry Smith         nf++;
353d4bb536fSBarry Smith       }
354d4bb536fSBarry Smith     }
355d4bb536fSBarry Smith     if (nout) *nout = nf;
356d4bb536fSBarry Smith   }
357d4bb536fSBarry Smith 
3583a40ed3dSBarry Smith   PetscFunctionReturn(0);
359d4bb536fSBarry Smith }
36090f02eecSBarry Smith 
361