Actual source code: data_bucket.c
petsc-3.8.4 2018-03-24
1: #include "data_bucket.h"
3: /* string helpers */
4: PetscErrorCode StringInList(const char name[],const PetscInt N,const DataField gfield[],PetscBool *val)
5: {
6: PetscInt i;
10: *val = PETSC_FALSE;
11: for (i = 0; i < N; ++i) {
12: PetscBool flg;
13: PetscStrcmp(name, gfield[i]->name, &flg);
14: if (flg) {
15: *val = PETSC_TRUE;
16: return(0);
17: }
18: }
19: return(0);
20: }
22: PetscErrorCode StringFindInList(const char name[],const PetscInt N,const DataField gfield[],PetscInt *index)
23: {
24: PetscInt i;
28: *index = -1;
29: for (i = 0; i < N; ++i) {
30: PetscBool flg;
31: PetscStrcmp(name, gfield[i]->name, &flg);
32: if (flg) {
33: *index = i;
34: return(0);
35: }
36: }
37: return(0);
38: }
40: PetscErrorCode DataFieldCreate(const char registeration_function[],const char name[],const size_t size,const PetscInt L,DataField *DF)
41: {
42: DataField df;
46: PetscMalloc(sizeof(struct _p_DataField), &df);
47: PetscMemzero(df, sizeof(struct _p_DataField));
48: PetscStrallocpy(registeration_function, &df->registeration_function);
49: PetscStrallocpy(name, &df->name);
50: df->atomic_size = size;
51: df->L = L;
52: df->bs = 1;
53: /* allocate something so we don't have to reallocate */
54: PetscMalloc(size * L, &df->data);
55: PetscMemzero(df->data, size * L);
56: *DF = df;
57: return(0);
58: }
60: PetscErrorCode DataFieldDestroy(DataField *DF)
61: {
62: DataField df = *DF;
66: PetscFree(df->registeration_function);
67: PetscFree(df->name);
68: PetscFree(df->data);
69: PetscFree(df);
70: *DF = NULL;
71: return(0);
72: }
74: /* data bucket */
75: PetscErrorCode DataBucketCreate(DataBucket *DB)
76: {
77: DataBucket db;
81: PetscMalloc(sizeof(struct _p_DataBucket), &db);
82: PetscMemzero(db, sizeof(struct _p_DataBucket));
84: db->finalised = PETSC_FALSE;
85: /* create empty spaces for fields */
86: db->L = -1;
87: db->buffer = 1;
88: db->allocated = 1;
89: db->nfields = 0;
90: PetscMalloc1(1, &db->field);
91: *DB = db;
92: return(0);
93: }
95: PetscErrorCode DataBucketDestroy(DataBucket *DB)
96: {
97: DataBucket db = *DB;
98: PetscInt f;
102: /* release fields */
103: for (f = 0; f < db->nfields; ++f) {
104: DataFieldDestroy(&db->field[f]);
105: }
106: /* this will catch the initially allocated objects in the event that no fields are registered */
107: if (db->field != NULL) {
108: PetscFree(db->field);
109: }
110: PetscFree(db);
111: *DB = NULL;
112: return(0);
113: }
115: PetscErrorCode DataBucketQueryForActiveFields(DataBucket db,PetscBool *any_active_fields)
116: {
117: PetscInt f;
120: *any_active_fields = PETSC_FALSE;
121: for (f = 0; f < db->nfields; ++f) {
122: if (db->field[f]->active) {
123: *any_active_fields = PETSC_TRUE;
124: return(0);
125: }
126: }
127: return(0);
128: }
130: PetscErrorCode DataBucketRegisterField(
131: DataBucket db,
132: const char registeration_function[],
133: const char field_name[],
134: size_t atomic_size, DataField *_gfield)
135: {
136: PetscBool val;
137: DataField fp;
141: /* check we haven't finalised the registration of fields */
142: /*
143: if(db->finalised==PETSC_TRUE) {
144: printf("ERROR: DataBucketFinalize() has been called. Cannot register more fields\n");
145: ERROR();
146: }
147: */
148: /* check for repeated name */
149: StringInList(field_name, db->nfields, (const DataField*) db->field, &val);
150: if (val == PETSC_TRUE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field %s already exists. Cannot add same field twice",field_name);
151: /* create new space for data */
152: PetscRealloc(sizeof(DataField)*(db->nfields+1), &db->field);
153: /* add field */
154: DataFieldCreate(registeration_function, field_name, atomic_size, db->allocated, &fp);
155: db->field[db->nfields] = fp;
156: db->nfields++;
157: if (_gfield != NULL) {
158: *_gfield = fp;
159: }
160: return(0);
161: }
163: /*
164: #define DataBucketRegisterField(db,name,size,k) {\
165: char *location;\
166: asprintf(&location,"Registered by %s() at line %d within file %s", __FUNCTION__, __LINE__, __FILE__);\
167: _DataBucketRegisterField( (db), location, (name), (size), (k) );\
168: PetscFree(location);\
169: }
170: */
172: PetscErrorCode DataBucketGetDataFieldByName(DataBucket db,const char name[],DataField *gfield)
173: {
174: PetscInt idx;
175: PetscBool found;
179: StringInList(name,db->nfields,(const DataField*)db->field,&found);
180: if (!found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot find DataField with name %s",name);
181: StringFindInList(name,db->nfields,(const DataField*)db->field,&idx);
182: *gfield = db->field[idx];
183: return(0);
184: }
186: PetscErrorCode DataBucketQueryDataFieldByName(DataBucket db,const char name[],PetscBool *found)
187: {
191: *found = PETSC_FALSE;
192: StringInList(name,db->nfields,(const DataField*)db->field,found);
193: return(0);
194: }
196: PetscErrorCode DataBucketFinalize(DataBucket db)
197: {
199: db->finalised = PETSC_TRUE;
200: return(0);
201: }
203: PetscErrorCode DataFieldGetNumEntries(DataField df,PetscInt *sum)
204: {
206: *sum = df->L;
207: return(0);
208: }
210: PetscErrorCode DataFieldSetBlockSize(DataField df,PetscInt blocksize)
211: {
213: df->bs = blocksize;
214: return(0);
215: }
217: PetscErrorCode DataFieldSetSize(DataField df,const PetscInt new_L)
218: {
222: if (new_L < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot set size of DataField to be < 0");
223: if (new_L == df->L) return(0);
224: if (new_L > df->L) {
225: PetscRealloc(df->atomic_size * (new_L), &df->data);
226: /* init new contents */
227: PetscMemzero(( ((char*)df->data)+df->L*df->atomic_size), (new_L-df->L)*df->atomic_size);
228: } else {
229: /* reallocate pointer list, add +1 in case new_L = 0 */
230: PetscRealloc(df->atomic_size * (new_L+1), &df->data);
231: }
232: df->L = new_L;
233: return(0);
234: }
236: PetscErrorCode DataFieldZeroBlock(DataField df,const PetscInt start,const PetscInt end)
237: {
241: if (start > end) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot zero a block of entries if start(%D) > end(%D)",start,end);
242: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot zero a block of entries if start(%D) < 0",start);
243: if (end > df->L) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot zero a block of entries if end(%D) >= array size(%D)",end,df->L);
244: PetscMemzero((((char*)df->data)+start*df->atomic_size), (end-start)*df->atomic_size);
245: return(0);
246: }
248: /*
249: A negative buffer value will simply be ignored and the old buffer value will be used.
250: */
251: PetscErrorCode DataBucketSetSizes(DataBucket db,const PetscInt L,const PetscInt buffer)
252: {
253: PetscInt current_allocated,new_used,new_unused,new_buffer,new_allocated,f;
254: PetscBool any_active_fields;
258: if (db->finalised == PETSC_FALSE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"You must call DataBucketFinalize() before DataBucketSetSizes()");
259: DataBucketQueryForActiveFields(db,&any_active_fields);
260: if (any_active_fields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot safely re-size as at least one DataField is currently being accessed");
262: current_allocated = db->allocated;
263: new_used = L;
264: new_unused = current_allocated - new_used;
265: new_buffer = db->buffer;
266: if (buffer >= 0) { /* update the buffer value */
267: new_buffer = buffer;
268: }
269: new_allocated = new_used + new_buffer;
270: /* action */
271: if (new_allocated > current_allocated) {
272: /* increase size to new_used + new_buffer */
273: for (f=0; f<db->nfields; f++) {
274: DataFieldSetSize(db->field[f], new_allocated);
275: }
276: db->L = new_used;
277: db->buffer = new_buffer;
278: db->allocated = new_used + new_buffer;
279: } else {
280: if (new_unused > 2 * new_buffer) {
281: /* shrink array to new_used + new_buffer */
282: for (f = 0; f < db->nfields; ++f) {
283: DataFieldSetSize(db->field[f], new_allocated);
284: }
285: db->L = new_used;
286: db->buffer = new_buffer;
287: db->allocated = new_used + new_buffer;
288: } else {
289: db->L = new_used;
290: db->buffer = new_buffer;
291: }
292: }
293: /* zero all entries from db->L to db->allocated */
294: for (f = 0; f < db->nfields; ++f) {
295: DataField field = db->field[f];
296: DataFieldZeroBlock(field, db->L,db->allocated);
297: }
298: return(0);
299: }
301: PetscErrorCode DataBucketSetInitialSizes(DataBucket db,const PetscInt L,const PetscInt buffer)
302: {
303: PetscInt f;
307: DataBucketSetSizes(db,L,buffer);
308: for (f = 0; f < db->nfields; ++f) {
309: DataField field = db->field[f];
310: DataFieldZeroBlock(field,0,db->allocated);
311: }
312: return(0);
313: }
315: PetscErrorCode DataBucketGetSizes(DataBucket db,PetscInt *L,PetscInt *buffer,PetscInt *allocated)
316: {
318: if (L) {*L = db->L;}
319: if (buffer) {*buffer = db->buffer;}
320: if (allocated) {*allocated = db->allocated;}
321: return(0);
322: }
324: PetscErrorCode DataBucketGetGlobalSizes(MPI_Comm comm,DataBucket db,PetscInt *L,PetscInt *buffer,PetscInt *allocated)
325: {
326: PetscInt _L,_buffer,_allocated;
327: PetscInt ierr;
330: _L = db->L;
331: _buffer = db->buffer;
332: _allocated = db->allocated;
334: if (L) { MPI_Allreduce(&_L,L,1,MPIU_INT,MPI_SUM,comm); }
335: if (buffer) { MPI_Allreduce(&_buffer,buffer,1,MPIU_INT,MPI_SUM,comm); }
336: if (allocated) { MPI_Allreduce(&_allocated,allocated,1,MPIU_INT,MPI_SUM,comm); }
337: return(0);
338: }
340: PetscErrorCode DataBucketGetDataFields(DataBucket db,PetscInt *L,DataField *fields[])
341: {
343: if (L) {*L = db->nfields;}
344: if (fields) {*fields = db->field;}
345: return(0);
346: }
348: PetscErrorCode DataFieldGetAccess(const DataField gfield)
349: {
351: if (gfield->active) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is already active. You must call DataFieldRestoreAccess()",gfield->name);
352: gfield->active = PETSC_TRUE;
353: return(0);
354: }
356: PetscErrorCode DataFieldAccessPoint(const DataField gfield,const PetscInt pid,void **ctx_p)
357: {
359: *ctx_p = NULL;
360: #ifdef DATAFIELD_POINT_ACCESS_GUARD
361: /* debug mode */
362: /* check point is valid */
363: if (pid < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
364: if (pid >= gfield->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",gfield->L);
365: if (gfield->active == PETSC_FALSE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is not active. You must call DataFieldGetAccess() before point data can be retrivied",gfield->name);
366: #endif
367: *ctx_p = __DATATFIELD_point_access(gfield->data,pid,gfield->atomic_size);
368: return(0);
369: }
371: PetscErrorCode DataFieldAccessPointOffset(const DataField gfield,const size_t offset,const PetscInt pid,void **ctx_p)
372: {
374: #ifdef DATAFIELD_POINT_ACCESS_GUARD
375: /* debug mode */
376: /* check point is valid */
377: /* if( offset < 0 ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"offset must be >= 0");*/
378: /* Note compiler realizes this can never happen with an unsigned PetscInt */
379: if (offset >= gfield->atomic_size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"offset must be < %zu",gfield->atomic_size);
380: /* check point is valid */
381: if (pid < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
382: if (pid >= gfield->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",gfield->L);
383: if (gfield->active == PETSC_FALSE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is not active. You must call DataFieldGetAccess() before point data can be retrivied",gfield->name);
384: #endif
385: *ctx_p = __DATATFIELD_point_access_offset(gfield->data,pid,gfield->atomic_size,offset);
386: return(0);
387: }
389: PetscErrorCode DataFieldRestoreAccess(DataField gfield)
390: {
392: if (gfield->active == PETSC_FALSE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is not active. You must call DataFieldGetAccess()", gfield->name);
393: gfield->active = PETSC_FALSE;
394: return(0);
395: }
397: PetscErrorCode DataFieldVerifyAccess(const DataField gfield,const size_t size)
398: {
400: #ifdef DATAFIELD_POINT_ACCESS_GUARD
401: if (gfield->atomic_size != size) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" must be mapped to %zu bytes, your intended structure is %zu bytes in length.",gfield->name, gfield->atomic_size, size );
402: #endif
403: return(0);
404: }
406: PetscErrorCode DataFieldGetAtomicSize(const DataField gfield,size_t *size)
407: {
409: if (size) {*size = gfield->atomic_size;}
410: return(0);
411: }
413: PetscErrorCode DataFieldGetEntries(const DataField gfield,void **data)
414: {
416: if (data) {*data = gfield->data;}
417: return(0);
418: }
420: PetscErrorCode DataFieldRestoreEntries(const DataField gfield,void **data)
421: {
423: if (data) {*data = NULL;}
424: return(0);
425: }
427: /* y = x */
428: PetscErrorCode DataBucketCopyPoint(const DataBucket xb,const PetscInt pid_x,
429: const DataBucket yb,const PetscInt pid_y)
430: {
431: PetscInt f;
435: for (f = 0; f < xb->nfields; ++f) {
436: void *dest;
437: void *src;
439: DataFieldGetAccess(xb->field[f]);
440: if (xb != yb) { DataFieldGetAccess( yb->field[f]); }
441: DataFieldAccessPoint(xb->field[f],pid_x, &src);
442: DataFieldAccessPoint(yb->field[f],pid_y, &dest);
443: PetscMemcpy(dest, src, xb->field[f]->atomic_size);
444: DataFieldRestoreAccess(xb->field[f]);
445: if (xb != yb) {DataFieldRestoreAccess(yb->field[f]);}
446: }
447: return(0);
448: }
450: PetscErrorCode DataBucketCreateFromSubset(DataBucket DBIn,const PetscInt N,const PetscInt list[],DataBucket *DB)
451: {
452: PetscInt nfields;
453: DataField *fields;
454: PetscInt f,L,buffer,allocated,p;
458: DataBucketCreate(DB);
459: /* copy contents of DBIn */
460: DataBucketGetDataFields(DBIn,&nfields,&fields);
461: DataBucketGetSizes(DBIn,&L,&buffer,&allocated);
462: for (f = 0; f < nfields; ++f) {
463: DataBucketRegisterField(*DB,"DataBucketCreateFromSubset",fields[f]->name,fields[f]->atomic_size,NULL);
464: }
465: DataBucketFinalize(*DB);
466: DataBucketSetSizes(*DB,L,buffer);
467: /* now copy the desired guys from DBIn => DB */
468: for (p = 0; p < N; ++p) {
469: DataBucketCopyPoint(DBIn,list[p], *DB,p);
470: }
471: return(0);
472: }
474: /* insert into an exisitng location */
475: PetscErrorCode DataFieldInsertPoint(const DataField field,const PetscInt index,const void *ctx)
476: {
480: #ifdef DATAFIELD_POINT_ACCESS_GUARD
481: /* check point is valid */
482: if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
483: if (index >= field->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",field->L);
484: #endif
485: PetscMemcpy(__DATATFIELD_point_access(field->data,index,field->atomic_size), ctx, field->atomic_size);
486: return(0);
487: }
489: /* remove data at index - replace with last point */
490: PetscErrorCode DataBucketRemovePointAtIndex(const DataBucket db,const PetscInt index)
491: {
492: PetscInt f;
493: PetscBool any_active_fields;
497: #ifdef DATAFIELD_POINT_ACCESS_GUARD
498: /* check point is valid */
499: if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
500: if (index >= db->allocated) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",db->L+db->buffer);
501: #endif
502: DataBucketQueryForActiveFields(db,&any_active_fields);
503: if (any_active_fields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot safely remove point as at least one DataField is currently being accessed");
504: if (index >= db->L) { /* this point is not in the list - no need to error, but I will anyway */
505: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"You should not be trying to remove point at index=%D since it's < db->L = %D", index, db->L);
506: }
507: if (index != db->L-1) { /* not last point in list */
508: for (f = 0; f < db->nfields; ++f) {
509: DataField field = db->field[f];
511: /* copy then remove */
512: DataFieldCopyPoint(db->L-1, field, index, field);
513: /* DataFieldZeroPoint(field,index); */
514: }
515: }
516: /* decrement size */
517: /* this will zero out an crap at the end of the list */
518: DataBucketRemovePoint(db);
519: return(0);
520: }
522: /* copy x into y */
523: PetscErrorCode DataFieldCopyPoint(const PetscInt pid_x,const DataField field_x,
524: const PetscInt pid_y,const DataField field_y )
525: {
529: #ifdef DATAFIELD_POINT_ACCESS_GUARD
530: /* check point is valid */
531: if (pid_x < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"(IN) index must be >= 0");
532: if (pid_x >= field_x->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"(IN) index must be < %D",field_x->L);
533: if (pid_y < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"(OUT) index must be >= 0");
534: if (pid_y >= field_y->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"(OUT) index must be < %D",field_y->L);
535: if( field_y->atomic_size != field_x->atomic_size ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"atomic size must match");
536: #endif
537: PetscMemcpy(__DATATFIELD_point_access(field_y->data,pid_y,field_y->atomic_size),
538: __DATATFIELD_point_access(field_x->data,pid_x,field_x->atomic_size),
539: field_y->atomic_size);
540: return(0);
541: }
544: /* zero only the datafield at this point */
545: PetscErrorCode DataFieldZeroPoint(const DataField field,const PetscInt index)
546: {
550: #ifdef DATAFIELD_POINT_ACCESS_GUARD
551: /* check point is valid */
552: if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
553: if (index >= field->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",field->L);
554: #endif
555: PetscMemzero(__DATATFIELD_point_access(field->data,index,field->atomic_size), field->atomic_size);
556: return(0);
557: }
559: /* zero ALL data for this point */
560: PetscErrorCode DataBucketZeroPoint(const DataBucket db,const PetscInt index)
561: {
562: PetscInt f;
566: /* check point is valid */
567: if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
568: if (index >= db->allocated) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",db->allocated);
569: for (f = 0; f < db->nfields; ++f) {
570: DataField field = db->field[f];
571: DataFieldZeroPoint(field,index);
572: }
573: return(0);
574: }
576: /* increment */
577: PetscErrorCode DataBucketAddPoint(DataBucket db)
578: {
582: DataBucketSetSizes(db,db->L+1,DATA_BUCKET_BUFFER_DEFAULT);
583: return(0);
584: }
586: /* decrement */
587: PetscErrorCode DataBucketRemovePoint(DataBucket db)
588: {
592: DataBucketSetSizes(db,db->L-1,DATA_BUCKET_BUFFER_DEFAULT);
593: return(0);
594: }
596: PetscErrorCode DataBucketView_stdout(MPI_Comm comm,DataBucket db)
597: {
598: PetscInt f;
599: double memory_usage_total,memory_usage_total_local = 0.0;
601:
603: PetscPrintf(comm,"DataBucketView: \n");
604: PetscPrintf(comm," L = %D \n", db->L);
605: PetscPrintf(comm," buffer = %D \n", db->buffer);
606: PetscPrintf(comm," allocated = %D \n", db->allocated);
607: PetscPrintf(comm," nfields registered = %D \n", db->nfields);
608:
609: for (f = 0; f < db->nfields; ++f) {
610: double memory_usage_f = (double)(db->field[f]->atomic_size * db->allocated) * 1.0e-6;
611: memory_usage_total_local += memory_usage_f;
612: }
613: MPI_Allreduce(&memory_usage_total_local,&memory_usage_total,1,MPI_DOUBLE,MPI_SUM,comm);
614:
615: for (f = 0; f < db->nfields; ++f) {
616: double memory_usage_f = (double)(db->field[f]->atomic_size * db->allocated) * 1.0e-6;
617: PetscPrintf(comm," [%3D] %15s : Mem. usage = %1.2e (MB) [rank0]\n", f, db->field[f]->name, memory_usage_f );
618: PetscPrintf(comm," blocksize = %D \n", db->field[f]->bs);
619: if (db->field[f]->bs != 1) {
620: PetscPrintf(comm," atomic size = %zu [full block, bs=%D]\n", db->field[f]->atomic_size,db->field[f]->bs);
621: PetscPrintf(comm," atomic size/item = %zu \n", db->field[f]->atomic_size/db->field[f]->bs);
622: } else {
623: PetscPrintf(comm," atomic size = %zu \n", db->field[f]->atomic_size);
624: }
625: }
626: PetscPrintf(comm," Total mem. usage = %1.2e (MB) (collective)\n", memory_usage_total);
627: return(0);
628: }
630: PetscErrorCode DataBucketView_SEQ(MPI_Comm comm,DataBucket db,const char filename[],DataBucketViewType type)
631: {
635: switch (type) {
636: case DATABUCKET_VIEW_STDOUT:
637: DataBucketView_stdout(PETSC_COMM_SELF,db);
638: break;
639: case DATABUCKET_VIEW_ASCII:
640: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for ascii output");
641: break;
642: case DATABUCKET_VIEW_BINARY:
643: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for binary output");
644: break;
645: case DATABUCKET_VIEW_HDF5:
646: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for HDF5 output");
647: break;
648: default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested");
649: }
650: return(0);
651: }
653: PetscErrorCode DataBucketView_MPI(MPI_Comm comm,DataBucket db,const char filename[],DataBucketViewType type)
654: {
658: switch (type) {
659: case DATABUCKET_VIEW_STDOUT:
660: DataBucketView_stdout(comm,db);
661: break;
662: case DATABUCKET_VIEW_ASCII:
663: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for ascii output");
664: break;
665: case DATABUCKET_VIEW_BINARY:
666: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for binary output");
667: break;
668: case DATABUCKET_VIEW_HDF5:
669: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for HDF5 output");
670: break;
671: default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested");
672: }
673: return(0);
674: }
676: PetscErrorCode DataBucketView(MPI_Comm comm,DataBucket db,const char filename[],DataBucketViewType type)
677: {
678: PetscMPIInt nproc;
682: MPI_Comm_size(comm,&nproc);
683: if (nproc == 1) {
684: DataBucketView_SEQ(comm,db,filename,type);
685: } else {
686: DataBucketView_MPI(comm,db,filename,type);
687: }
688: return(0);
689: }
691: PetscErrorCode DataBucketDuplicateFields(DataBucket dbA,DataBucket *dbB)
692: {
693: DataBucket db2;
694: PetscInt f;
698: DataBucketCreate(&db2);
699: /* copy contents from dbA into db2 */
700: for (f = 0; f < dbA->nfields; ++f) {
701: DataField field;
702: size_t atomic_size;
703: char *name;
705: field = dbA->field[f];
706: atomic_size = field->atomic_size;
707: name = field->name;
708: DataBucketRegisterField(db2,"DataBucketDuplicateFields",name,atomic_size,NULL);
709: }
710: DataBucketFinalize(db2);
711: DataBucketSetInitialSizes(db2,0,1000);
712: *dbB = db2;
713: return(0);
714: }
716: /*
717: Insert points from db2 into db1
718: db1 <<== db2
719: */
720: PetscErrorCode DataBucketInsertValues(DataBucket db1,DataBucket db2)
721: {
722: PetscInt n_mp_points1,n_mp_points2;
723: PetscInt n_mp_points1_new,p;
727: DataBucketGetSizes(db1,&n_mp_points1,0,0);
728: DataBucketGetSizes(db2,&n_mp_points2,0,0);
729: n_mp_points1_new = n_mp_points1 + n_mp_points2;
730: DataBucketSetSizes(db1,n_mp_points1_new,DATA_BUCKET_BUFFER_DEFAULT);
731: for (p = 0; p < n_mp_points2; ++p) {
732: /* db1 <<== db2 */
733: DataBucketCopyPoint(db2,p, db1,(n_mp_points1 + p));
734: }
735: return(0);
736: }
738: /* helpers for parallel send/recv */
739: PetscErrorCode DataBucketCreatePackedArray(DataBucket db,size_t *bytes,void **buf)
740: {
741: PetscInt f;
742: size_t sizeof_marker_contents;
743: void *buffer;
747: sizeof_marker_contents = 0;
748: for (f = 0; f < db->nfields; ++f) {
749: DataField df = db->field[f];
750: sizeof_marker_contents += df->atomic_size;
751: }
752: PetscMalloc(sizeof_marker_contents, &buffer);
753: PetscMemzero(buffer, sizeof_marker_contents);
754: if (bytes) {*bytes = sizeof_marker_contents;}
755: if (buf) {*buf = buffer;}
756: return(0);
757: }
759: PetscErrorCode DataBucketDestroyPackedArray(DataBucket db,void **buf)
760: {
764: if (buf) {
765: PetscFree(*buf);
766: *buf = NULL;
767: }
768: return(0);
769: }
771: PetscErrorCode DataBucketFillPackedArray(DataBucket db,const PetscInt index,void *buf)
772: {
773: PetscInt f;
774: void *data, *data_p;
775: size_t asize, offset;
779: offset = 0;
780: for (f = 0; f < db->nfields; ++f) {
781: DataField df = db->field[f];
783: asize = df->atomic_size;
784: data = (void*)( df->data );
785: data_p = (void*)( (char*)data + index*asize );
786: PetscMemcpy((void*)((char*)buf + offset), data_p, asize);
787: offset = offset + asize;
788: }
789: return(0);
790: }
792: PetscErrorCode DataBucketInsertPackedArray(DataBucket db,const PetscInt idx,void *data)
793: {
794: PetscInt f;
795: void *data_p;
796: size_t offset;
800: offset = 0;
801: for (f = 0; f < db->nfields; ++f) {
802: DataField df = db->field[f];
804: data_p = (void*)( (char*)data + offset );
805: DataFieldInsertPoint(df, idx, (void*)data_p);
806: offset = offset + df->atomic_size;
807: }
808: return(0);
809: }