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