Actual source code: bvec2.c
1: /*$Id: bvec2.c,v 1.195 2001/04/10 19:34:56 bsmith Exp $*/
2: /*
3: Implements the sequential vectors.
4: */
6: #include src/vec/vecimpl.h
7: #include src/vec/impls/dvecimpl.h
8: #include petscblaslapack.h
9: #if defined(PETSC_HAVE_AMS)
10: EXTERN int PetscViewerAMSGetAMSComm(PetscViewer,AMS_Comm *);
11: #endif
13: int VecNorm_Seq(Vec xin,NormType type,PetscReal* z)
14: {
15: Vec_Seq *x = (Vec_Seq*)xin->data;
16: int ierr,one = 1;
19: if (type == NORM_2) {
20: /*
21: This is because the Fortran BLAS 1 Norm is very slow!
22: */
23: #if defined(PETSC_HAVE_SLOW_NRM2)
24: {
25: int i;
26: Scalar sum=0.0;
27: for (i=0; i<xin->n; i++) {
28: sum += (x->array[i])*(PetscConj(x->array[i]));
29: }
30: *z = sqrt(PetscRealPart(sum));
31: }
32: #else
33: *z = BLnrm2_(&xin->n,x->array,&one);
34: #endif
35: PetscLogFlops(2*xin->n-1);
36: } else if (type == NORM_INFINITY) {
37: int i,n = xin->n;
38: PetscReal max = 0.0,tmp;
39: Scalar *xx = x->array;
41: for (i=0; i<n; i++) {
42: if ((tmp = PetscAbsScalar(*xx)) > max) max = tmp;
43: /* check special case of tmp == NaN */
44: if (tmp != tmp) {max = tmp; break;}
45: xx++;
46: }
47: *z = max;
48: } else if (type == NORM_1) {
49: *z = BLasum_(&xin->n,x->array,&one);
50: PetscLogFlops(xin->n-1);
51: } else if (type == NORM_1_AND_2) {
52: VecNorm_Seq(xin,NORM_1,z);
53: VecNorm_Seq(xin,NORM_2,z+1);
54: }
55: return(0);
56: }
58: int VecGetOwnershipRange_Seq(Vec xin,int *low,int *high)
59: {
61: *low = 0; *high = xin->n;
62: return(0);
63: }
64: #include petscviewer.h
65: #include petscsys.h
67: int VecView_Seq_File(Vec xin,PetscViewer viewer)
68: {
69: Vec_Seq *x = (Vec_Seq *)xin->data;
70: int i,n = xin->n,ierr;
71: char *name;
72: PetscViewerFormat format;
75: PetscViewerGetFormat(viewer,&format);
76: if (format == PETSC_VIEWER_ASCII_MATLAB) {
77: PetscObjectGetName((PetscObject)viewer,&name);
78: PetscViewerASCIIPrintf(viewer,"%s = [n",name);
79: for (i=0; i<n; i++) {
80: #if defined(PETSC_USE_COMPLEX)
81: if (PetscImaginaryPart(x->array[i]) > 0.0) {
82: PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ein",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
83: } else if (PetscImaginaryPart(x->array[i]) < 0.0) {
84: PetscViewerASCIIPrintf(viewer,"%18.16e - %18.16ein",PetscRealPart(x->array[i]),-PetscImaginaryPart(x->array[i]));
85: } else {
86: PetscViewerASCIIPrintf(viewer,"%18.16en",PetscRealPart(x->array[i]));
87: }
88: #else
89: PetscViewerASCIIPrintf(viewer,"%18.16en",x->array[i]);
90: #endif
91: }
92: PetscViewerASCIIPrintf(viewer,"];n");
93: } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
94: for (i=0; i<n; i++) {
95: #if defined(PETSC_USE_COMPLEX)
96: PetscViewerASCIIPrintf(viewer,"%18.16e %18.16en",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
97: #else
98: PetscViewerASCIIPrintf(viewer,"%18.16en",x->array[i]);
99: #endif
100: }
101: } else {
102: for (i=0; i<n; i++) {
103: if (format == PETSC_VIEWER_ASCII_INDEX) {
104: PetscViewerASCIIPrintf(viewer,"%d: ",i);
105: }
106: #if defined(PETSC_USE_COMPLEX)
107: if (PetscImaginaryPart(x->array[i]) > 0.0) {
108: PetscViewerASCIIPrintf(viewer,"%g + %g in",PetscRealPart(x->array[i]),PetscImaginaryPart(x->array[i]));
109: } else if (PetscImaginaryPart(x->array[i]) < 0.0) {
110: PetscViewerASCIIPrintf(viewer,"%g - %g in",PetscRealPart(x->array[i]),-PetscImaginaryPart(x->array[i]));
111: } else {
112: PetscViewerASCIIPrintf(viewer,"%gn",PetscRealPart(x->array[i]));
113: }
114: #else
115: PetscViewerASCIIPrintf(viewer,"%gn",x->array[i]);
116: #endif
117: }
118: }
119: PetscViewerFlush(viewer);
120: return(0);
121: }
123: static int VecView_Seq_Draw_LG(Vec xin,PetscViewer v)
124: {
125: Vec_Seq *x = (Vec_Seq *)xin->data;
126: int i,n = xin->n,ierr;
127: PetscDraw win;
128: PetscReal *xx;
129: PetscDrawLG lg;
132: PetscViewerDrawGetDrawLG(v,0,&lg);
133: PetscDrawLGGetDraw(lg,&win);
134: PetscDrawCheckResizedWindow(win);
135: PetscDrawLGReset(lg);
136: PetscMalloc((n+1)*sizeof(PetscReal),&xx);
137: for (i=0; i<n; i++) {
138: xx[i] = (PetscReal) i;
139: }
140: #if !defined(PETSC_USE_COMPLEX)
141: PetscDrawLGAddPoints(lg,n,&xx,&x->array);
142: #else
143: {
144: PetscReal *yy;
145: PetscMalloc((n+1)*sizeof(PetscReal),&yy);
146: for (i=0; i<n; i++) {
147: yy[i] = PetscRealPart(x->array[i]);
148: }
149: PetscDrawLGAddPoints(lg,n,&xx,&yy);
150: PetscFree(yy);
151: }
152: #endif
153: PetscFree(xx);
154: PetscDrawLGDraw(lg);
155: PetscDrawSynchronizedFlush(win);
156: return(0);
157: }
159: static int VecView_Seq_Draw(Vec xin,PetscViewer v)
160: {
161: int ierr;
162: PetscDraw draw;
163: PetscTruth isnull;
164: PetscViewerFormat format;
167: PetscViewerDrawGetDraw(v,0,&draw);
168: PetscDrawIsNull(draw,&isnull); if (isnull) return(0);
169:
170: PetscViewerGetFormat(v,&format);
171: /*
172: Currently it only supports drawing to a line graph */
173: if (format != PETSC_VIEWER_DRAW_LG) {
174: PetscViewerPushFormat(v,PETSC_VIEWER_DRAW_LG);
175: }
176: VecView_Seq_Draw_LG(xin,v);
177: if (format != PETSC_VIEWER_DRAW_LG) {
178: PetscViewerPopFormat(v);
179: }
181: return(0);
182: }
184: static int VecView_Seq_Binary(Vec xin,PetscViewer viewer)
185: {
186: Vec_Seq *x = (Vec_Seq *)xin->data;
187: int ierr,fdes,n = xin->n;
188: FILE *file;
191: ierr = PetscViewerBinaryGetDescriptor(viewer,&fdes);
192: /* Write vector header */
193: PetscBinaryWrite(fdes,&xin->cookie,1,PETSC_INT,0);
194: PetscBinaryWrite(fdes,&n,1,PETSC_INT,0);
196: /* Write vector contents */
197: PetscBinaryWrite(fdes,x->array,n,PETSC_SCALAR,0);
199: PetscViewerBinaryGetInfoPointer(viewer,&file);
200: if (file && xin->bs > 1) {
201: fprintf(file,"-vecload_block_size %dn",xin->bs);
202: }
203: return(0);
204: }
207: int VecView_Seq(Vec xin,PetscViewer viewer)
208: {
209: Vec_Seq *x = (Vec_Seq *)xin->data;
210: int ierr;
211: PetscTruth isdraw,isascii,issocket,isbinary;
214: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);
215: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
216: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);
217: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);
218: if (isdraw){
219: VecView_Seq_Draw(xin,viewer);
220: } else if (isascii){
221: VecView_Seq_File(xin,viewer);
222: } else if (issocket) {
223: PetscViewerSocketPutScalar(viewer,xin->n,1,x->array);
224: } else if (isbinary) {
225: VecView_Seq_Binary(xin,viewer);
226: } else {
227: SETERRQ1(1,"Viewer type %s not supported by this vector object",((PetscObject)viewer)->type_name);
228: }
229: return(0);
230: }
232: int VecSetValues_Seq(Vec xin,int ni,const int ix[],const Scalar y[],InsertMode m)
233: {
234: Vec_Seq *x = (Vec_Seq *)xin->data;
235: Scalar *xx = x->array;
236: int i;
239: if (m == INSERT_VALUES) {
240: for (i=0; i<ni; i++) {
241: if (ix[i] < 0) continue;
242: #if defined(PETSC_USE_BOPT_g)
243: if (ix[i] >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",ix[i],xin->n);
244: #endif
245: xx[ix[i]] = y[i];
246: }
247: } else {
248: for (i=0; i<ni; i++) {
249: if (ix[i] < 0) continue;
250: #if defined(PETSC_USE_BOPT_g)
251: if (ix[i] >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",ix[i],xin->n);
252: #endif
253: xx[ix[i]] += y[i];
254: }
255: }
256: return(0);
257: }
259: int VecSetValuesBlocked_Seq(Vec xin,int ni,const int ix[],const Scalar yin[],InsertMode m)
260: {
261: Vec_Seq *x = (Vec_Seq *)xin->data;
262: Scalar *xx = x->array,*y = (Scalar*)yin;
263: int i,bs = xin->bs,start,j;
265: /*
266: For optimization could treat bs = 2, 3, 4, 5 as special cases with loop unrolling
267: */
269: if (m == INSERT_VALUES) {
270: for (i=0; i<ni; i++) {
271: start = bs*ix[i];
272: if (start < 0) continue;
273: #if defined(PETSC_USE_BOPT_g)
274: if (start >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",start,xin->n);
275: #endif
276: for (j=0; j<bs; j++) {
277: xx[start+j] = y[j];
278: }
279: y += bs;
280: }
281: } else {
282: for (i=0; i<ni; i++) {
283: start = bs*ix[i];
284: if (start < 0) continue;
285: #if defined(PETSC_USE_BOPT_g)
286: if (start >= xin->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Out of range index value %d maximum %d",start,xin->n);
287: #endif
288: for (j=0; j<bs; j++) {
289: xx[start+j] += y[j];
290: }
291: y += bs;
292: }
293: }
294: return(0);
295: }
298: int VecDestroy_Seq(Vec v)
299: {
300: Vec_Seq *vs = (Vec_Seq*)v->data;
301: int ierr;
305: /* if memory was published with AMS then destroy it */
306: PetscObjectDepublish(v);
308: #if defined(PETSC_USE_LOG)
309: PetscLogObjectState((PetscObject)v,"Length=%d",v->n);
310: #endif
311: if (vs->array_allocated) {PetscFree(vs->array_allocated);}
312: PetscFree(vs);
314: return(0);
315: }
317: static int VecPublish_Seq(PetscObject obj)
318: {
319: #if defined(PETSC_HAVE_AMS)
320: Vec v = (Vec) obj;
321: Vec_Seq *s = (Vec_Seq*)v->data;
322: int ierr,(*f)(AMS_Memory,char *,Vec);
323: #endif
327: #if defined(PETSC_HAVE_AMS)
328: /* if it is already published then return */
329: if (v->amem >=0) return(0);
331: /* if array in vector was not allocated (for example PCSetUp_BJacobi_Singleblock()) then
332: cannot AMS publish the object*/
333: if (!s->array) return(0);
335: PetscObjectPublishBaseBegin(obj);
336: AMS_Memory_add_field((AMS_Memory)v->amem,"values",s->array,v->n,AMS_DOUBLE,AMS_READ,
337: AMS_DISTRIBUTED,AMS_REDUCT_UNDEF);
339: /* if the vector knows its "layout" let it set it*/
340: PetscObjectQueryFunction(obj,"AMSSetFieldBlock_C",(void (**)())&f);
341: if (f) {
342: (*f)((AMS_Memory)v->amem,"values",v);
343: }
344: PetscObjectPublishBaseEnd(obj);
345: #endif
347: return(0);
348: }
350: static struct _VecOps DvOps = {VecDuplicate_Seq,
351: VecDuplicateVecs_Default,
352: VecDestroyVecs_Default,
353: VecDot_Seq,
354: VecMDot_Seq,
355: VecNorm_Seq,
356: VecTDot_Seq,
357: VecMTDot_Seq,
358: VecScale_Seq,
359: VecCopy_Seq,
360: VecSet_Seq,
361: VecSwap_Seq,
362: VecAXPY_Seq,
363: VecAXPBY_Seq,
364: VecMAXPY_Seq,
365: VecAYPX_Seq,
366: VecWAXPY_Seq,
367: VecPointwiseMult_Seq,
368: VecPointwiseDivide_Seq,
369: VecSetValues_Seq,0,0,
370: VecGetArray_Seq,
371: VecGetSize_Seq,
372: VecGetSize_Seq,
373: VecGetOwnershipRange_Seq,
374: VecRestoreArray_Seq,
375: VecMax_Seq,
376: VecMin_Seq,
377: VecSetRandom_Seq,0,
378: VecSetValuesBlocked_Seq,
379: VecDestroy_Seq,
380: VecView_Seq,
381: VecPlaceArray_Seq,
382: VecReplaceArray_Seq,
383: VecGetMap_Seq,
384: VecDot_Seq,
385: VecTDot_Seq,
386: VecNorm_Seq,
387: VecLoadIntoVector_Default,
388: VecReciprocal_Default,
389: 0, /* VecViewNative */
390: VecConjugate_Seq,
391: 0,
392: 0,
393: VecResetArray_Seq};
396: /*
397: This is called by VecCreate_Seq() (i.e. VecCreateSeq()) and VecCreateSeqWithArray()
398: */
399: static int VecCreate_Seq_Private(Vec v,const Scalar array[])
400: {
401: Vec_Seq *s;
402: int ierr;
405: PetscMemcpy(v->ops,&DvOps,sizeof(DvOps));
406: PetscMalloc(sizeof(Vec_Seq),&s);
407: v->data = (void*)s;
408: v->bops->publish = VecPublish_Seq;
409: v->n = PetscMax(v->n,v->N);
410: v->N = PetscMax(v->n,v->N);
411: v->bs = -1;
412: s->array = (Scalar *)array;
413: s->array_allocated = 0;
414: if (!v->map) {
415: MapCreateMPI(v->comm,v->n,v->N,&v->map);
416: }
417: PetscObjectChangeTypeName((PetscObject)v,VEC_SEQ);
418: #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX)
419: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscMatlabEnginePut_C","VecMatlabEnginePut_Default",VecMatlabEnginePut_Default);
420: PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscMatlabEngineGet_C","VecMatlabEngineGet_Default",VecMatlabEngineGet_Default);
421: #endif
422: PetscPublishAll(v);
423: return(0);
424: }
426: /*@C
427: VecCreateSeqWithArray - Creates a standard,sequential array-style vector,
428: where the user provides the array space to store the vector values.
430: Collective on MPI_Comm
432: Input Parameter:
433: + comm - the communicator, should be PETSC_COMM_SELF
434: . n - the vector length
435: - array - memory where the vector elements are to be stored.
437: Output Parameter:
438: . V - the vector
440: Notes:
441: Use VecDuplicate() or VecDuplicateVecs() to form additional vectors of the
442: same type as an existing vector.
444: If the user-provided array is PETSC_NULL, then VecPlaceArray() can be used
445: at a later stage to SET the array for storing the vector values.
447: PETSc does NOT free the array when the vector is destroyed via VecDestroy().
448: The user should not free the array until the vector is destroyed.
450: Level: intermediate
452: Concepts: vectors^creating with array
454: .seealso: VecCreateMPIWithArray(), VecCreate(), VecDuplicate(), VecDuplicateVecs(),
455: VecCreateGhost(), VecCreateSeq(), VecPlaceArray()
456: @*/
457: int VecCreateSeqWithArray(MPI_Comm comm,int n,const Scalar array[],Vec *V)
458: {
459: int ierr;
462: VecCreate(comm,n,n,V);
463: VecCreate_Seq_Private(*V,array);
464: return(0);
465: }
467: EXTERN_C_BEGIN
468: int VecCreate_Seq(Vec V)
469: {
470: Vec_Seq *s;
471: Scalar *array;
472: int ierr,n = PetscMax(V->n,V->N);
475: PetscMalloc((n+1)*sizeof(Scalar),&array);
476: PetscMemzero(array,n*sizeof(Scalar));
477: VecCreate_Seq_Private(V,array);
478: s = (Vec_Seq*)V->data;
479: s->array_allocated = array;
480: return(0);
481: }
482: EXTERN_C_END
485: int VecGetMap_Seq(Vec win,Map *m)
486: {
488: *m = win->map;
489: return(0);
490: }
492: int VecDuplicate_Seq(Vec win,Vec *V)
493: {
494: int ierr;
497: VecCreateSeq(win->comm,win->n,V);
498: if (win->mapping) {
499: (*V)->mapping = win->mapping;
500: PetscObjectReference((PetscObject)win->mapping);
501: }
502: if (win->bmapping) {
503: (*V)->bmapping = win->bmapping;
504: PetscObjectReference((PetscObject)win->bmapping);
505: }
506: (*V)->bs = win->bs;
507: PetscOListDuplicate(win->olist,&(*V)->olist);
508: PetscFListDuplicate(win->qlist,&(*V)->qlist);
509: return(0);
510: }