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