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 src/vec/vecimpl.h
7: #include src/vec/impls/dvecimpl.h
8: #include src/inline/dot.h
9: #include petscblaslapack.h
10: #if defined(PETSC_HAVE_AMS)
11: EXTERN int PetscViewerAMSGetAMSComm(PetscViewer,AMS_Comm *);
12: #endif
14: int VecNorm_Seq(Vec xin,NormType type,PetscReal* z)
15: {
16: PetscScalar *xx;
17: int n=xin->n,ierr,one = 1;
20: if (type == NORM_2) {
21: VecGetArrayFast(xin,&xx);
22: /*
23: This is because the Fortran BLAS 1 Norm is very slow!
24: */
25: #if defined(PETSC_HAVE_SLOW_NRM2)
26: #if defined(PETSC_USE_FORTRAN_KERNEL_NORM)
27: fortrannormsqr_(xx,&n,z);
28: *z = sqrt(*z);
29: #elif defined(PETSC_USE_UNROLLED_NORM)
30: {
31: PetscReal work = 0.0;
32: switch (n & 0x3) {
33: case 3: work += PetscRealPart(xx[0]*PetscConj(xx[0])); xx++;
34: case 2: work += PetscRealPart(xx[0]*PetscConj(xx[0])); xx++;
35: case 1: work += PetscRealPart(xx[0]*PetscConj(xx[0])); xx++; n -= 4;
36: }
37: while (n>0) {
38: work += PetscRealPart(xx[0]*PetscConj(xx[0])+xx[1]*PetscConj(xx[1])+
39: xx[2]*PetscConj(xx[2])+xx[3]*PetscConj(xx[3]));
40: xx += 4; n -= 4;
41: }
42: *z = sqrt(work);}
43: #else
44: {
45: int i;
46: PetscScalar sum=0.0;
47: for (i=0; i<n; i++) {
48: sum += (xx[i])*(PetscConj(xx[i]));
49: }
50: *z = sqrt(PetscRealPart(sum));
51: }
52: #endif
53: #else
54: *z = BLnrm2_(&n,xx,&one);
55: #endif
56: VecRestoreArrayFast(xin,&xx);
57: PetscLogFlops(2*n-1);
58: } else if (type == NORM_INFINITY) {
59: int i;
60: PetscReal max = 0.0,tmp;
62: VecGetArrayFast(xin,&xx);
63: for (i=0; i<n; i++) {
64: if ((tmp = PetscAbsScalar(*xx)) > max) max = tmp;
65: /* check special case of tmp == NaN */
66: if (tmp != tmp) {max = tmp; break;}
67: xx++;
68: }
69: VecRestoreArrayFast(xin,&xx);
70: *z = max;
71: } else if (type == NORM_1) {
72: VecGetArrayFast(xin,&xx);
73: *z = BLasum_(&n,xx,&one);
74: VecRestoreArrayFast(xin,&xx);
75: PetscLogFlops(n-1);
76: } else if (type == NORM_1_AND_2) {
77: VecNorm_Seq(xin,NORM_1,z);
78: VecNorm_Seq(xin,NORM_2,z+1);
79: }
80: return(0);
81: }
83: #include petscviewer.h
84: #include petscsys.h
86: int VecView_Seq_File(Vec xin,PetscViewer viewer)
87: {
88: Vec_Seq *x = (Vec_Seq *)xin->data;
89: int i,n = xin->n,ierr;
90: char *name;
91: PetscViewerFormat format;
94: PetscViewerGetFormat(viewer,&format);
95: if (format == PETSC_VIEWER_ASCII_MATLAB) {
96: PetscObjectGetName((PetscObject)xin,&name);
97: PetscViewerASCIIPrintf(viewer,"%s = [n",name);
98: for (i=0; i<n; i++) {
99: #if defined(PETSC_USE_COMPLEX)
100: if (PetscImaginaryPart(x->array[i]) > 0.0) {
101: PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ein",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
102: } else if (PetscImaginaryPart(x->array[i]) < 0.0) {
103: PetscViewerASCIIPrintf(viewer,"%18.16e - %18.16ein",PetscRealPart(x->array[i]),-PetscImaginaryPart(x->array[i]));
104: } else {
105: PetscViewerASCIIPrintf(viewer,"%18.16en",PetscRealPart(x->array[i]));
106: }
107: #else
108: PetscViewerASCIIPrintf(viewer,"%18.16en",x->array[i]);
109: #endif
110: }
111: PetscViewerASCIIPrintf(viewer,"];n");
112: } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
113: for (i=0; i<n; i++) {
114: #if defined(PETSC_USE_COMPLEX)
115: PetscViewerASCIIPrintf(viewer,"%18.16e %18.16en",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
116: #else
117: PetscViewerASCIIPrintf(viewer,"%18.16en",x->array[i]);
118: #endif
119: }
120: } else {
121: for (i=0; i<n; i++) {
122: if (format == PETSC_VIEWER_ASCII_INDEX) {
123: PetscViewerASCIIPrintf(viewer,"%d: ",i);
124: }
125: #if defined(PETSC_USE_COMPLEX)
126: if (PetscImaginaryPart(x->array[i]) > 0.0) {
127: PetscViewerASCIIPrintf(viewer,"%g + %g in",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
128: } else if (PetscImaginaryPart(x->array[i]) < 0.0) {
129: PetscViewerASCIIPrintf(viewer,"%g - %g in",PetscRealPart(x->array[i]),-PetscImaginaryPart(x->array[i]));
130: } else {
131: PetscViewerASCIIPrintf(viewer,"%gn",PetscRealPart(x->array[i]));
132: }
133: #else
134: PetscViewerASCIIPrintf(viewer,"%gn",x->array[i]);
135: #endif
136: }
137: }
138: PetscViewerFlush(viewer);
139: return(0);
140: }
142: static int VecView_Seq_Draw_LG(Vec xin,PetscViewer v)
143: {
144: Vec_Seq *x = (Vec_Seq *)xin->data;
145: int i,n = xin->n,ierr;
146: PetscDraw win;
147: PetscReal *xx;
148: PetscDrawLG lg;
151: PetscViewerDrawGetDrawLG(v,0,&lg);
152: PetscDrawLGGetDraw(lg,&win);
153: PetscDrawCheckResizedWindow(win);
154: PetscDrawLGReset(lg);
155: PetscMalloc((n+1)*sizeof(PetscReal),&xx);
156: for (i=0; i<n; i++) {
157: xx[i] = (PetscReal) i;
158: }
159: #if !defined(PETSC_USE_COMPLEX)
160: PetscDrawLGAddPoints(lg,n,&xx,&x->array);
161: #else
162: {
163: PetscReal *yy;
164: PetscMalloc((n+1)*sizeof(PetscReal),&yy);
165: for (i=0; i<n; i++) {
166: yy[i] = PetscRealPart(x->array[i]);
167: }
168: PetscDrawLGAddPoints(lg,n,&xx,&yy);
169: PetscFree(yy);
170: }
171: #endif
172: PetscFree(xx);
173: PetscDrawLGDraw(lg);
174: PetscDrawSynchronizedFlush(win);
175: return(0);
176: }
178: static int VecView_Seq_Draw(Vec xin,PetscViewer v)
179: {
180: int ierr;
181: PetscDraw draw;
182: PetscTruth isnull;
183: PetscViewerFormat format;
186: PetscViewerDrawGetDraw(v,0,&draw);
187: PetscDrawIsNull(draw,&isnull); if (isnull) return(0);
188:
189: PetscViewerGetFormat(v,&format);
190: /*
191: Currently it only supports drawing to a line graph */
192: if (format != PETSC_VIEWER_DRAW_LG) {
193: PetscViewerPushFormat(v,PETSC_VIEWER_DRAW_LG);
194: }
195: VecView_Seq_Draw_LG(xin,v);
196: if (format != PETSC_VIEWER_DRAW_LG) {
197: PetscViewerPopFormat(v);
198: }
200: return(0);
201: }
203: static int VecView_Seq_Binary(Vec xin,PetscViewer viewer)
204: {
205: Vec_Seq *x = (Vec_Seq *)xin->data;
206: int ierr,fdes,n = xin->n,cookie=VEC_FILE_COOKIE;
207: FILE *file;
210: ierr = PetscViewerBinaryGetDescriptor(viewer,&fdes);
211: /* Write vector header */
212: PetscBinaryWrite(fdes,&cookie,1,PETSC_INT,0);
213: PetscBinaryWrite(fdes,&n,1,PETSC_INT,0);
215: /* Write vector contents */
216: PetscBinaryWrite(fdes,x->array,n,PETSC_SCALAR,0);
218: PetscViewerBinaryGetInfoPointer(viewer,&file);
219: if (file && xin->bs > 1) {
220: fprintf(file,"-vecload_block_size %dn",xin->bs);
221: }
222: return(0);
223: }
226: int VecView_Seq(Vec xin,PetscViewer viewer)
227: {
228: Vec_Seq *x = (Vec_Seq *)xin->data;
229: int ierr;
230: PetscTruth isdraw,isascii,issocket,isbinary,ismathematica;
233: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);
234: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
235: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);
236: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);
237: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_MATHEMATICA,&ismathematica);
238: if (isdraw){
239: VecView_Seq_Draw(xin,viewer);
240: } else if (isascii){
241: VecView_Seq_File(xin,viewer);
242: } else if (issocket) {
243: PetscViewerSocketPutScalar(viewer,xin->n,1,x->array);
244: } else if (isbinary) {
245: VecView_Seq_Binary(xin,viewer);
246: } else if (ismathematica) {
247: PetscViewerMathematicaPutVector(viewer,xin);
248: } else {
249: SETERRQ1(1,"Viewer type %s not supported by this vector object",((PetscObject)viewer)->type_name);
250: }
251: return(0);
252: }
254: int VecSetValues_Seq(Vec xin,int ni,const int ix[],const PetscScalar y[],InsertMode m)
255: {
256: Vec_Seq *x = (Vec_Seq *)xin->data;
257: PetscScalar *xx = x->array;
258: int i;
261: if (m == INSERT_VALUES) {
262: for (i=0; i<ni; i++) {
263: if (ix[i] < 0) continue;
264: #if defined(PETSC_USE_BOPT_g)
265: if (ix[i] >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",ix[i],xin->n);
266: #endif
267: xx[ix[i]] = y[i];
268: }
269: } else {
270: for (i=0; i<ni; i++) {
271: if (ix[i] < 0) continue;
272: #if defined(PETSC_USE_BOPT_g)
273: if (ix[i] >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",ix[i],xin->n);
274: #endif
275: xx[ix[i]] += y[i];
276: }
277: }
278: return(0);
279: }
281: int VecSetValuesBlocked_Seq(Vec xin,int ni,const int ix[],const PetscScalar yin[],InsertMode m)
282: {
283: Vec_Seq *x = (Vec_Seq *)xin->data;
284: PetscScalar *xx = x->array,*y = (PetscScalar*)yin;
285: int i,bs = xin->bs,start,j;
287: /*
288: For optimization could treat bs = 2, 3, 4, 5 as special cases with loop unrolling
289: */
291: if (m == INSERT_VALUES) {
292: for (i=0; i<ni; i++) {
293: start = bs*ix[i];
294: if (start < 0) continue;
295: #if defined(PETSC_USE_BOPT_g)
296: if (start >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",start,xin->n);
297: #endif
298: for (j=0; j<bs; j++) {
299: xx[start+j] = y[j];
300: }
301: y += bs;
302: }
303: } else {
304: for (i=0; i<ni; i++) {
305: start = bs*ix[i];
306: if (start < 0) continue;
307: #if defined(PETSC_USE_BOPT_g)
308: if (start >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",start,xin->n);
309: #endif
310: for (j=0; j<bs; j++) {
311: xx[start+j] += y[j];
312: }
313: y += bs;
314: }
315: }
316: return(0);
317: }
320: int VecDestroy_Seq(Vec v)
321: {
322: Vec_Seq *vs = (Vec_Seq*)v->data;
323: int ierr;
327: /* if memory was published with AMS then destroy it */
328: PetscObjectDepublish(v);
330: #if defined(PETSC_USE_LOG)
331: PetscLogObjectState((PetscObject)v,"Length=%d",v->n);
332: #endif
333: if (vs->array_allocated) {PetscFree(vs->array_allocated);}
334: PetscFree(vs);
336: return(0);
337: }
339: static int VecPublish_Seq(PetscObject obj)
340: {
341: #if defined(PETSC_HAVE_AMS)
342: Vec v = (Vec) obj;
343: Vec_Seq *s = (Vec_Seq*)v->data;
344: int ierr,(*f)(AMS_Memory,char *,Vec);
345: #endif
349: #if defined(PETSC_HAVE_AMS)
350: /* if it is already published then return */
351: if (v->amem >=0) return(0);
353: /* if array in vector was not allocated (for example PCSetUp_BJacobi_Singleblock()) then
354: cannot AMS publish the object*/
355: if (!s->array) return(0);
357: PetscObjectPublishBaseBegin(obj);
358: AMS_Memory_add_field((AMS_Memory)v->amem,"values",s->array,v->n,AMS_DOUBLE,AMS_READ,
359: AMS_DISTRIBUTED,AMS_REDUCT_UNDEF);
361: /* if the vector knows its "layout" let it set it*/
362: PetscObjectQueryFunction(obj,"AMSSetFieldBlock_C",(void (**)(void))&f);
363: if (f) {
364: (*f)((AMS_Memory)v->amem,"values",v);
365: }
366: PetscObjectPublishBaseEnd(obj);
367: #endif
369: return(0);
370: }
372: static struct _VecOps DvOps = {VecDuplicate_Seq,
373: VecDuplicateVecs_Default,
374: VecDestroyVecs_Default,
375: VecDot_Seq,
376: VecMDot_Seq,
377: VecNorm_Seq,
378: VecTDot_Seq,
379: VecMTDot_Seq,
380: VecScale_Seq,
381: VecCopy_Seq,
382: VecSet_Seq,
383: VecSwap_Seq,
384: VecAXPY_Seq,
385: VecAXPBY_Seq,
386: VecMAXPY_Seq,
387: VecAYPX_Seq,
388: VecWAXPY_Seq,
389: VecPointwiseMult_Seq,
390: VecPointwiseDivide_Seq,
391: VecSetValues_Seq,0,0,
392: VecGetArray_Seq,
393: VecGetSize_Seq,
394: VecGetSize_Seq,
395: VecRestoreArray_Seq,
396: VecMax_Seq,
397: VecMin_Seq,
398: VecSetRandom_Seq,0,
399: VecSetValuesBlocked_Seq,
400: VecDestroy_Seq,
401: VecView_Seq,
402: VecPlaceArray_Seq,
403: VecReplaceArray_Seq,
404: VecDot_Seq,
405: VecTDot_Seq,
406: VecNorm_Seq,
407: VecLoadIntoVector_Default,
408: VecReciprocal_Default,
409: 0, /* VecViewNative */
410: VecConjugate_Seq,
411: 0,
412: 0,
413: VecResetArray_Seq};
416: /*
417: This is called by VecCreate_Seq() (i.e. VecCreateSeq()) and VecCreateSeqWithArray()
418: */
419: static int VecCreate_Seq_Private(Vec v,const PetscScalar array[])
420: {
421: Vec_Seq *s;
422: int ierr;
425: PetscMemcpy(v->ops,&DvOps,sizeof(DvOps));
426: PetscNew(Vec_Seq,&s);
427: PetscMemzero(s,sizeof(Vec_Seq));
428: v->data = (void*)s;
429: v->bops->publish = VecPublish_Seq;
430: v->n = PetscMax(v->n,v->N);
431: v->N = PetscMax(v->n,v->N);
432: v->bs = -1;
433: v->petscnative = PETSC_TRUE;
434: s->array = (PetscScalar *)array;
435: s->array_allocated = 0;
436: if (!v->map) {
437: PetscMapCreateMPI(v->comm,v->n,v->N,&v->map);
438: }
439: PetscObjectChangeTypeName((PetscObject)v,VECSEQ);
440: #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
441: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscMatlabEnginePut_C","VecMatlabEnginePut_Default",VecMatlabEnginePut_Default);
442: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscMatlabEngineGet_C","VecMatlabEngineGet_Default",VecMatlabEngineGet_Default);
443: #endif
444: PetscPublishAll(v);
445: return(0);
446: }
448: /*@C
449: VecCreateSeqWithArray - Creates a standard,sequential array-style vector,
450: where the user provides the array space to store the vector values.
452: Collective on MPI_Comm
454: Input Parameter:
455: + comm - the communicator, should be PETSC_COMM_SELF
456: . n - the vector length
457: - array - memory where the vector elements are to be stored.
459: Output Parameter:
460: . V - the vector
462: Notes:
463: Use VecDuplicate() or VecDuplicateVecs() to form additional vectors of the
464: same type as an existing vector.
466: If the user-provided array is PETSC_NULL, then VecPlaceArray() can be used
467: at a later stage to SET the array for storing the vector values.
469: PETSc does NOT free the array when the vector is destroyed via VecDestroy().
470: The user should not free the array until the vector is destroyed.
472: Level: intermediate
474: Concepts: vectors^creating with array
476: .seealso: VecCreateMPIWithArray(), VecCreate(), VecDuplicate(), VecDuplicateVecs(),
477: VecCreateGhost(), VecCreateSeq(), VecPlaceArray()
478: @*/
479: int VecCreateSeqWithArray(MPI_Comm comm,int n,const PetscScalar array[],Vec *V)
480: {
481: int ierr;
484: VecCreate(comm,V);
485: VecSetSizes(*V,n,n);
486: VecCreate_Seq_Private(*V,array);
487: return(0);
488: }
490: EXTERN_C_BEGIN
491: int VecCreate_Seq(Vec V)
492: {
493: Vec_Seq *s;
494: PetscScalar *array;
495: int ierr,n = PetscMax(V->n,V->N);
498: PetscMalloc((n+1)*sizeof(PetscScalar),&array);
499: PetscMemzero(array,n*sizeof(PetscScalar));
500: VecCreate_Seq_Private(V,array);
501: s = (Vec_Seq*)V->data;
502: s->array_allocated = array;
503: VecSetSerializeType(V,VEC_SER_SEQ_BINARY);
504: return(0);
505: }
507: int VecSerialize_Seq(MPI_Comm comm, Vec *vec, PetscViewer viewer, PetscTruth store)
508: {
509: Vec v;
510: Vec_Seq *x;
511: PetscScalar *array;
512: int fd;
513: int vars;
514: int ierr;
517: PetscViewerBinaryGetDescriptor(viewer, &fd);
518: if (store) {
519: v = *vec;
520: x = (Vec_Seq *) v->data;
521: PetscBinaryWrite(fd, &v->n, 1, PETSC_INT, 0);
522: PetscBinaryWrite(fd, x->array, v->n, PETSC_SCALAR, 0);
523: } else {
524: PetscBinaryRead(fd, &vars, 1, PETSC_INT);
525: VecCreate(comm, &v);
526: VecSetSizes(v, vars, vars);
527: PetscMalloc(vars * sizeof(PetscScalar), &array);
528: PetscBinaryRead(fd, array, vars, PETSC_SCALAR);
529: VecCreate_Seq_Private(v, array);
530: ((Vec_Seq *) v->data)->array_allocated = array;
532: VecAssemblyBegin(v);
533: VecAssemblyEnd(v);
534: *vec = v;
535: }
537: return(0);
538: }
539: EXTERN_C_END
542: int VecDuplicate_Seq(Vec win,Vec *V)
543: {
544: int ierr;
547: VecCreateSeq(win->comm,win->n,V);
548: if (win->mapping) {
549: (*V)->mapping = win->mapping;
550: PetscObjectReference((PetscObject)win->mapping);
551: }
552: if (win->bmapping) {
553: (*V)->bmapping = win->bmapping;
554: PetscObjectReference((PetscObject)win->bmapping);
555: }
556: (*V)->bs = win->bs;
557: PetscOListDuplicate(win->olist,&(*V)->olist);
558: PetscFListDuplicate(win->qlist,&(*V)->qlist);
559: return(0);
560: }