Actual source code: bvec2.c

  1: /*$Id: bvec2.c,v 1.202 2001/09/12 03:26:24 bsmith Exp $*/
  2: /*
  3:    Implements the sequential vectors.
  4: */

 6:  #include vecimpl.h
 7:  #include src/vec/impls/dvecimpl.h
 8:  #include src/inline/dot.h
 9:  #include petscblaslapack.h
 10: #if defined(PETSC_HAVE_PNETCDF)
 11: EXTERN_C_BEGIN
 12: #include "pnetcdf.h"
 13: EXTERN_C_END
 14: #endif
 15: #if defined(PETSC_HAVE_AMS)
 16: EXTERN int PetscViewerAMSGetAMSComm(PetscViewer,AMS_Comm *);
 17: #endif

 21: int VecNorm_Seq(Vec xin,NormType type,PetscReal* z)
 22: {
 23:   PetscScalar *xx;
 24:   int         n=xin->n,ierr,one = 1;

 27:   if (type == NORM_2 || type == NORM_FROBENIUS) {
 28:     VecGetArray(xin,&xx);
 29:     /*
 30:       This is because the Fortran BLAS 1 Norm is very slow! 
 31:     */
 32: #if defined(PETSC_HAVE_SLOW_NRM2)
 33: #if defined(PETSC_USE_FORTRAN_KERNEL_NORM)
 34:     fortrannormsqr_(xx,&n,z);
 35:     *z = sqrt(*z);
 36: #elif defined(PETSC_USE_UNROLLED_NORM)
 37:     {
 38:     PetscReal work = 0.0;
 39:     switch (n & 0x3) {
 40:       case 3: work += PetscRealPart(xx[0]*PetscConj(xx[0])); xx++;
 41:       case 2: work += PetscRealPart(xx[0]*PetscConj(xx[0])); xx++;
 42:       case 1: work += PetscRealPart(xx[0]*PetscConj(xx[0])); xx++; n -= 4;
 43:     }
 44:     while (n>0) {
 45:       work += PetscRealPart(xx[0]*PetscConj(xx[0])+xx[1]*PetscConj(xx[1])+
 46:                         xx[2]*PetscConj(xx[2])+xx[3]*PetscConj(xx[3]));
 47:       xx += 4; n -= 4;
 48:     }
 49:     *z = sqrt(work);}
 50: #else
 51:     {
 52:       int         i;
 53:       PetscScalar sum=0.0;
 54:       for (i=0; i<n; i++) {
 55:         sum += (xx[i])*(PetscConj(xx[i]));
 56:       }
 57:       *z = sqrt(PetscRealPart(sum));
 58:     }
 59: #endif
 60: #else
 61:     *z = BLnrm2_(&n,xx,&one);
 62: #endif
 63:     VecRestoreArray(xin,&xx);
 64:     PetscLogFlops(2*n-1);
 65:   } else if (type == NORM_INFINITY) {
 66:     int          i;
 67:     PetscReal    max = 0.0,tmp;

 69:     VecGetArray(xin,&xx);
 70:     for (i=0; i<n; i++) {
 71:       if ((tmp = PetscAbsScalar(*xx)) > max) max = tmp;
 72:       /* check special case of tmp == NaN */
 73:       if (tmp != tmp) {max = tmp; break;}
 74:       xx++;
 75:     }
 76:     VecRestoreArray(xin,&xx);
 77:     *z   = max;
 78:   } else if (type == NORM_1) {
 79:     VecGetArray(xin,&xx);
 80:     *z = BLasum_(&n,xx,&one);
 81:     VecRestoreArray(xin,&xx);
 82:     PetscLogFlops(n-1);
 83:   } else if (type == NORM_1_AND_2) {
 84:     VecNorm_Seq(xin,NORM_1,z);
 85:     VecNorm_Seq(xin,NORM_2,z+1);
 86:   }
 87:   return(0);
 88: }

 90:  #include petscviewer.h
 91:  #include petscsys.h

 95: int VecView_Seq_File(Vec xin,PetscViewer viewer)
 96: {
 97:   Vec_Seq           *x = (Vec_Seq *)xin->data;
 98:   int               i,n = xin->n,ierr;
 99:   char              *name;
100:   PetscViewerFormat format;

103:   PetscViewerGetFormat(viewer,&format);
104:   if (format == PETSC_VIEWER_ASCII_MATLAB) {
105:     PetscObjectGetName((PetscObject)xin,&name);
106:     PetscViewerASCIIPrintf(viewer,"%s = [\n",name);
107:     for (i=0; i<n; i++) {
108: #if defined(PETSC_USE_COMPLEX)
109:       if (PetscImaginaryPart(x->array[i]) > 0.0) {
110:         PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ei\n",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
111:       } else if (PetscImaginaryPart(x->array[i]) < 0.0) {
112:         PetscViewerASCIIPrintf(viewer,"%18.16e - %18.16ei\n",PetscRealPart(x->array[i]),-PetscImaginaryPart(x->array[i]));
113:       } else {
114:         PetscViewerASCIIPrintf(viewer,"%18.16e\n",PetscRealPart(x->array[i]));
115:       }
116: #else
117:       PetscViewerASCIIPrintf(viewer,"%18.16e\n",x->array[i]);
118: #endif
119:     }
120:     PetscViewerASCIIPrintf(viewer,"];\n");
121:   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
122:     for (i=0; i<n; i++) {
123: #if defined(PETSC_USE_COMPLEX)
124:       PetscViewerASCIIPrintf(viewer,"%18.16e %18.16e\n",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
125: #else
126:       PetscViewerASCIIPrintf(viewer,"%18.16e\n",x->array[i]);
127: #endif
128:     }
129:   } else {
130:     for (i=0; i<n; i++) {
131:       if (format == PETSC_VIEWER_ASCII_INDEX) {
132:         PetscViewerASCIIPrintf(viewer,"%d: ",i);
133:       }
134: #if defined(PETSC_USE_COMPLEX)
135:       if (PetscImaginaryPart(x->array[i]) > 0.0) {
136:         PetscViewerASCIIPrintf(viewer,"%g + %g i\n",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
137:       } else if (PetscImaginaryPart(x->array[i]) < 0.0) {
138:         PetscViewerASCIIPrintf(viewer,"%g - %g i\n",PetscRealPart(x->array[i]),-PetscImaginaryPart(x->array[i]));
139:       } else {
140:         PetscViewerASCIIPrintf(viewer,"%g\n",PetscRealPart(x->array[i]));
141:       }
142: #else
143:       PetscViewerASCIIPrintf(viewer,"%g\n",x->array[i]);
144: #endif
145:     }
146:   }
147:   PetscViewerFlush(viewer);
148:   return(0);
149: }

153: static int VecView_Seq_Draw_LG(Vec xin,PetscViewer v)
154: {
155:   Vec_Seq     *x = (Vec_Seq *)xin->data;
156:   int         i,n = xin->n,ierr;
157:   PetscDraw   win;
158:   PetscReal   *xx;
159:   PetscDrawLG lg;

162:   PetscViewerDrawGetDrawLG(v,0,&lg);
163:   PetscDrawLGGetDraw(lg,&win);
164:   PetscDrawCheckResizedWindow(win);
165:   PetscDrawLGReset(lg);
166:   PetscMalloc((n+1)*sizeof(PetscReal),&xx);
167:   for (i=0; i<n; i++) {
168:     xx[i] = (PetscReal) i;
169:   }
170: #if !defined(PETSC_USE_COMPLEX)
171:   PetscDrawLGAddPoints(lg,n,&xx,&x->array);
172: #else 
173:   {
174:     PetscReal *yy;
175:     PetscMalloc((n+1)*sizeof(PetscReal),&yy);
176:     for (i=0; i<n; i++) {
177:       yy[i] = PetscRealPart(x->array[i]);
178:     }
179:     PetscDrawLGAddPoints(lg,n,&xx,&yy);
180:     PetscFree(yy);
181:   }
182: #endif
183:   PetscFree(xx);
184:   PetscDrawLGDraw(lg);
185:   PetscDrawSynchronizedFlush(win);
186:   return(0);
187: }

191: static int VecView_Seq_Draw(Vec xin,PetscViewer v)
192: {
193:   int               ierr;
194:   PetscDraw         draw;
195:   PetscTruth        isnull;
196:   PetscViewerFormat format;

199:   PetscViewerDrawGetDraw(v,0,&draw);
200:   PetscDrawIsNull(draw,&isnull); if (isnull) return(0);
201: 
202:   PetscViewerGetFormat(v,&format);
203:   /*
204:      Currently it only supports drawing to a line graph */
205:   if (format != PETSC_VIEWER_DRAW_LG) {
206:     PetscViewerPushFormat(v,PETSC_VIEWER_DRAW_LG);
207:   }
208:   VecView_Seq_Draw_LG(xin,v);
209:   if (format != PETSC_VIEWER_DRAW_LG) {
210:     PetscViewerPopFormat(v);
211:   }

213:   return(0);
214: }

218: static int VecView_Seq_Binary(Vec xin,PetscViewer viewer)
219: {
220:   Vec_Seq  *x = (Vec_Seq *)xin->data;
221:   int      ierr,fdes,n = xin->n,cookie=VEC_FILE_COOKIE;
222:   FILE     *file;

225:   PetscViewerBinaryGetDescriptor(viewer,&fdes);
226:   /* Write vector header */
227:   PetscBinaryWrite(fdes,&cookie,1,PETSC_INT,0);
228:   PetscBinaryWrite(fdes,&n,1,PETSC_INT,0);

230:   /* Write vector contents */
231:   PetscBinaryWrite(fdes,x->array,n,PETSC_SCALAR,0);

233:   PetscViewerBinaryGetInfoPointer(viewer,&file);
234:   if (file && xin->bs > 1) {
235:     if (xin->prefix) {
236:       fprintf(file,"-%s_vecload_block_size %d\n",xin->prefix,xin->bs);
237:     } else {
238:       fprintf(file,"-vecload_block_size %d\n",xin->bs);
239:     }
240:   }
241:   return(0);
242: }

244: #if defined(PETSC_HAVE_PNETCDF)
247: int VecView_Seq_Netcdf(Vec xin,PetscViewer v)
248: {
249:   int         n = xin->n,ierr,ncid,xdim,xdim_num=1,xin_id,xstart=0;
250:   MPI_Comm    comm = xin->comm;
251:   PetscScalar *values,*xarray;

254: #if !defined(PETSC_USE_COMPLEX)
255:   VecGetArray(xin,&xarray);
256:   PetscViewerNetcdfGetID(v,&ncid);
257:   if (ncid < 0) SETERRQ(1,"First call PetscViewerNetcdfOpen to create NetCDF dataset");
258:   /* define dimensions */
259:   ncmpi_def_dim(ncid,"PETSc_Vector_Global_Size",n,&xdim);
260:   /* define variables */
261:   ncmpi_def_var(ncid,"PETSc_Vector_Seq",NC_DOUBLE,xdim_num,&xdim,&xin_id);
262:   /* leave define mode */
263:   ncmpi_enddef(ncid);
264:   /* store the vector */
265:   VecGetOwnershipRange(xin,&xstart,PETSC_NULL);
266:   ncmpi_put_vara_double_all(ncid,xin_id,(const size_t*)&xstart,(const size_t*)&n,xarray);
267: #else 
268:     PetscPrintf(PETSC_COMM_WORLD,"NetCDF viewer not supported for complex numbers\n");
269: #endif
270:   return(0);
271: }
272: #endif

274: #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
275: #include "mat.h"   /* Matlab include file */
276: EXTERN_C_BEGIN
279: int VecView_Seq_Matlab(Vec vec,PetscViewer viewer)
280: {
281:   int         ierr,n;
282:   PetscScalar *array;
283: 
285:   VecGetArray(vec,&array);
286:   VecGetLocalSize(vec,&n);
287:   PetscObjectName((PetscObject)vec);
288:   PetscViewerMatlabPutArray(viewer,n,1,array,vec->name);
289:   VecRestoreArray(vec,&array);
290:   return(0);
291: }
292: EXTERN_C_END
293: #endif

297: int VecView_Seq(Vec xin,PetscViewer viewer)
298: {
299:   Vec_Seq     *x = (Vec_Seq *)xin->data;
300:   int         ierr;
301:   PetscTruth  isdraw,isascii,issocket,isbinary,ismathematica;
302: #if defined(PETSC_HAVE_PNETCDF)
303:   PetscTruth  isnetcdf;
304: #endif
305: #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
306:   PetscTruth  ismatlab;
307: #endif

310:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);
311:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
312:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);
313:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);
314:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_MATHEMATICA,&ismathematica);
315: #if defined(PETSC_HAVE_PNETCDF)
316:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_NETCDF,&isnetcdf);
317: #endif
318: #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
319:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_MATLAB,&ismatlab);
320: #endif

322:   if (isdraw){
323:     VecView_Seq_Draw(xin,viewer);
324:   } else if (isascii){
325:     VecView_Seq_File(xin,viewer);
326:   } else if (issocket) {
327:     PetscViewerSocketPutScalar(viewer,xin->n,1,x->array);
328:   } else if (isbinary) {
329:     VecView_Seq_Binary(xin,viewer);
330:   } else if (ismathematica) {
331:     PetscViewerMathematicaPutVector(viewer,xin);
332: #if defined(PETSC_HAVE_PNETCDF)
333:   } else if (isnetcdf) {
334:     VecView_Seq_Netcdf(xin,viewer);
335: #endif
336: #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
337:   } else if (ismatlab) {
338:     VecView_Seq_Matlab(xin,viewer);
339: #endif
340:   } else {
341:     SETERRQ1(1,"Viewer type %s not supported by this vector object",((PetscObject)viewer)->type_name);
342:   }
343:   return(0);
344: }

348: int VecSetValues_Seq(Vec xin,int ni,const int ix[],const PetscScalar y[],InsertMode m)
349: {
350:   Vec_Seq     *x = (Vec_Seq *)xin->data;
351:   PetscScalar *xx = x->array;
352:   int         i;

355:   if (m == INSERT_VALUES) {
356:     for (i=0; i<ni; i++) {
357:       if (ix[i] < 0) continue;
358: #if defined(PETSC_USE_BOPT_g)
359:       if (ix[i] >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",ix[i],xin->n);
360: #endif
361:       xx[ix[i]] = y[i];
362:     }
363:   } else {
364:     for (i=0; i<ni; i++) {
365:       if (ix[i] < 0) continue;
366: #if defined(PETSC_USE_BOPT_g)
367:       if (ix[i] >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",ix[i],xin->n);
368: #endif
369:       xx[ix[i]] += y[i];
370:     }
371:   }
372:   return(0);
373: }

377: int VecSetValuesBlocked_Seq(Vec xin,int ni,const int ix[],const PetscScalar yin[],InsertMode m)
378: {
379:   Vec_Seq     *x = (Vec_Seq *)xin->data;
380:   PetscScalar *xx = x->array,*y = (PetscScalar*)yin;
381:   int         i,bs = xin->bs,start,j;

383:   /*
384:        For optimization could treat bs = 2, 3, 4, 5 as special cases with loop unrolling
385:   */
387:   if (m == INSERT_VALUES) {
388:     for (i=0; i<ni; i++) {
389:       start = bs*ix[i];
390:       if (start < 0) continue;
391: #if defined(PETSC_USE_BOPT_g)
392:       if (start >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",start,xin->n);
393: #endif
394:       for (j=0; j<bs; j++) {
395:         xx[start+j] = y[j];
396:       }
397:       y += bs;
398:     }
399:   } else {
400:     for (i=0; i<ni; i++) {
401:       start = bs*ix[i];
402:       if (start < 0) continue;
403: #if defined(PETSC_USE_BOPT_g)
404:       if (start >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",start,xin->n);
405: #endif
406:       for (j=0; j<bs; j++) {
407:         xx[start+j] += y[j];
408:       }
409:       y += bs;
410:     }
411:   }
412:   return(0);
413: }


418: int VecDestroy_Seq(Vec v)
419: {
420:   Vec_Seq *vs = (Vec_Seq*)v->data;
421:   int     ierr;


425:   /* if memory was published with AMS then destroy it */
426:   PetscObjectDepublish(v);

428: #if defined(PETSC_USE_LOG)
429:   PetscLogObjectState((PetscObject)v,"Length=%d",v->n);
430: #endif
431:   if (vs->array_allocated) {PetscFree(vs->array_allocated);}
432:   PetscFree(vs);

434:   return(0);
435: }

439: static int VecPublish_Seq(PetscObject obj)
440: {
441: #if defined(PETSC_HAVE_AMS)
442:   Vec          v = (Vec) obj;
443:   Vec_Seq      *s = (Vec_Seq*)v->data;
444:   int          ierr,(*f)(AMS_Memory,char *,Vec);
445: #endif


449: #if defined(PETSC_HAVE_AMS)
450:   /* if it is already published then return */
451:   if (v->amem >=0) return(0);

453:   /* if array in vector was not allocated (for example PCSetUp_BJacobi_Singleblock()) then
454:      cannot AMS publish the object*/
455:   if (!s->array) return(0);

457:   PetscObjectPublishBaseBegin(obj);
458:   AMS_Memory_add_field((AMS_Memory)v->amem,"values",s->array,v->n,AMS_DOUBLE,AMS_READ,
459:                                 AMS_DISTRIBUTED,AMS_REDUCT_UNDEF);

461:   /* if the vector knows its "layout" let it set it*/
462:   PetscObjectQueryFunction(obj,"AMSSetFieldBlock_C",(void (**)(void))&f);
463:   if (f) {
464:     (*f)((AMS_Memory)v->amem,"values",v);
465:   }
466:   PetscObjectPublishBaseEnd(obj);
467: #endif

469:   return(0);
470: }

472: extern int VecLoad_Binary(PetscViewer,const VecType, Vec*);

474: static struct _VecOps DvOps = {VecDuplicate_Seq,
475:             VecDuplicateVecs_Default,
476:             VecDestroyVecs_Default,
477:             VecDot_Seq,
478:             VecMDot_Seq,
479:             VecNorm_Seq,
480:             VecTDot_Seq,
481:             VecMTDot_Seq,
482:             VecScale_Seq,
483:             VecCopy_Seq,
484:             VecSet_Seq,
485:             VecSwap_Seq,
486:             VecAXPY_Seq,
487:             VecAXPBY_Seq,
488:             VecMAXPY_Seq,
489:             VecAYPX_Seq,
490:             VecWAXPY_Seq,
491:             VecPointwiseMult_Seq,
492:             VecPointwiseDivide_Seq,
493:             VecSetValues_Seq,0,0,
494:             VecGetArray_Seq,
495:             VecGetSize_Seq,
496:             VecGetSize_Seq,
497:             VecRestoreArray_Seq,
498:             VecMax_Seq,
499:             VecMin_Seq,
500:             VecSetRandom_Seq,0,
501:             VecSetValuesBlocked_Seq,
502:             VecDestroy_Seq,
503:             VecView_Seq,
504:             VecPlaceArray_Seq,
505:             VecReplaceArray_Seq,
506:             VecDot_Seq,
507:             VecTDot_Seq,
508:             VecNorm_Seq,
509:             VecLoadIntoVector_Default,
510:             VecReciprocal_Default,
511:             0, /* VecViewNative */
512:             VecConjugate_Seq,
513:             0,
514:             0,
515:             VecResetArray_Seq,
516:             0,
517:             VecMaxPointwiseDivide_Seq,
518:             VecLoad_Binary};


521: /*
522:       This is called by VecCreate_Seq() (i.e. VecCreateSeq()) and VecCreateSeqWithArray()
523: */
526: static int VecCreate_Seq_Private(Vec v,const PetscScalar array[])
527: {
528:   Vec_Seq *s;
529:   int     ierr;

532:   PetscMemcpy(v->ops,&DvOps,sizeof(DvOps));
533:   PetscNew(Vec_Seq,&s);
534:   PetscMemzero(s,sizeof(Vec_Seq));
535:   v->data            = (void*)s;
536:   v->bops->publish   = VecPublish_Seq;
537:   v->n               = PetscMax(v->n,v->N);
538:   v->N               = PetscMax(v->n,v->N);
539:   v->petscnative     = PETSC_TRUE;
540:   s->array           = (PetscScalar *)array;
541:   s->array_allocated = 0;
542:   if (!v->map) {
543:     PetscMapCreateMPI(v->comm,v->n,v->N,&v->map);
544:   }
545:   PetscObjectChangeTypeName((PetscObject)v,VECSEQ);
546: #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
547:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscMatlabEnginePut_C","VecMatlabEnginePut_Default",VecMatlabEnginePut_Default);
548:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscMatlabEngineGet_C","VecMatlabEngineGet_Default",VecMatlabEngineGet_Default);
549: #endif
550:   PetscPublishAll(v);
551:   return(0);
552: }

556: /*@C
557:    VecCreateSeqWithArray - Creates a standard,sequential array-style vector,
558:    where the user provides the array space to store the vector values.

560:    Collective on MPI_Comm

562:    Input Parameter:
563: +  comm - the communicator, should be PETSC_COMM_SELF
564: .  n - the vector length 
565: -  array - memory where the vector elements are to be stored.

567:    Output Parameter:
568: .  V - the vector

570:    Notes:
571:    Use VecDuplicate() or VecDuplicateVecs() to form additional vectors of the
572:    same type as an existing vector.

574:    If the user-provided array is PETSC_NULL, then VecPlaceArray() can be used
575:    at a later stage to SET the array for storing the vector values.

577:    PETSc does NOT free the array when the vector is destroyed via VecDestroy().
578:    The user should not free the array until the vector is destroyed.

580:    Level: intermediate

582:    Concepts: vectors^creating with array

584: .seealso: VecCreateMPIWithArray(), VecCreate(), VecDuplicate(), VecDuplicateVecs(), 
585:           VecCreateGhost(), VecCreateSeq(), VecPlaceArray()
586: @*/
587: int VecCreateSeqWithArray(MPI_Comm comm,int n,const PetscScalar array[],Vec *V)
588: {
589:   int  ierr;

592:   VecCreate(comm,V);
593:   VecSetSizes(*V,n,n);
594:   VecCreate_Seq_Private(*V,array);
595:   return(0);
596: }

598: EXTERN_C_BEGIN
601: int VecCreate_Seq(Vec V)
602: {
603:   Vec_Seq      *s;
604:   PetscScalar  *array;
605:   int          ierr,n = PetscMax(V->n,V->N);

608:   PetscMalloc( ( n > 0 ? n : 1)*sizeof(PetscScalar),&array);
609:   PetscMemzero(array,( n > 0 ? n : 1)*sizeof(PetscScalar));
610:   VecCreate_Seq_Private(V,array);
611:   s    = (Vec_Seq*)V->data;
612:   s->array_allocated = array;
613:   return(0);
614: }
615: EXTERN_C_END


620: int VecDuplicate_Seq(Vec win,Vec *V)
621: {
622:   int     ierr;

625:   VecCreateSeq(win->comm,win->n,V);
626:   if (win->mapping) {
627:     (*V)->mapping = win->mapping;
628:     PetscObjectReference((PetscObject)win->mapping);
629:   }
630:   if (win->bmapping) {
631:     (*V)->bmapping = win->bmapping;
632:     PetscObjectReference((PetscObject)win->bmapping);
633:   }
634:   (*V)->bs = win->bs;
635:   PetscOListDuplicate(win->olist,&(*V)->olist);
636:   PetscFListDuplicate(win->qlist,&(*V)->qlist);
637:   return(0);
638: }