xref: /petsc/src/dm/impls/swarm/data_bucket.c (revision 2635f51937deeb34105c00bbd4aa264ff3f215f6)
1 
2 #include "data_bucket.h"
3 
4 /* string helpers */
5 #undef __FUNCT__
6 #define __FUNCT__ "StringInList"
7 PetscErrorCode StringInList(const char name[],const PetscInt N,const DataField gfield[],PetscBool *val)
8 {
9 	PetscInt i;
10 
11 	*val = PETSC_FALSE;
12 	for (i=0; i<N; i++) {
13 		if (strcmp( name, gfield[i]->name) == 0 ) {
14 			*val = PETSC_TRUE;
15       PetscFunctionReturn(0);
16 		}
17 	}
18   PetscFunctionReturn(0);
19 }
20 
21 #undef __FUNCT__
22 #define __FUNCT__ "StringFindInList"
23 PetscErrorCode StringFindInList(const char name[],const PetscInt N,const DataField gfield[],PetscInt *index)
24 {
25 	PetscInt i;
26 
27 	*index = -1;
28 	for (i=0; i<N; i++) {
29 		if (strcmp( name, gfield[i]->name ) == 0) {
30 			*index = i;
31       PetscFunctionReturn(0);
32 		}
33 	}
34   PetscFunctionReturn(0);
35 }
36 
37 #undef __FUNCT__
38 #define __FUNCT__ "DataFieldCreate"
39 PetscErrorCode DataFieldCreate(const char registeration_function[],const char name[],const size_t size,const PetscInt L,DataField *DF)
40 {
41 	DataField df;
42 
43 	df = malloc( sizeof(struct _p_DataField) );
44 	memset( df, 0, sizeof(struct _p_DataField) );
45 
46 
47 	asprintf( &df->registeration_function, "%s", registeration_function );
48 	asprintf( &df->name, "%s", name );
49 	df->atomic_size = size;
50 	df->L = L;
51 
52 	df->data = malloc( size * L ); /* allocate something so we don't have to reallocate */
53 	memset( df->data, 0, size * L );
54 
55 	*DF = df;
56   PetscFunctionReturn(0);
57 }
58 
59 #undef __FUNCT__
60 #define __FUNCT__ "DataFieldDestroy"
61 PetscErrorCode DataFieldDestroy(DataField *DF)
62 {
63 	DataField df = *DF;
64 
65 	free(df->registeration_function);
66 	free(df->name);
67 	free(df->data);
68 	free(df);
69 
70 	*DF = NULL;
71   PetscFunctionReturn(0);
72 }
73 
74 /* data bucket */
75 #undef __FUNCT__
76 #define __FUNCT__ "DataBucketCreate"
77 PetscErrorCode DataBucketCreate(DataBucket *DB)
78 {
79 	DataBucket db;
80 
81 
82 	db = malloc( sizeof(struct _p_DataBucket) );
83 	memset( db, 0, sizeof(struct _p_DataBucket) );
84 
85 	db->finalised = PETSC_FALSE;
86 
87 	/* create empty spaces for fields */
88 	db->L         = -1;
89 	db->buffer    = 1;
90 	db->allocated = 1;
91 
92 	db->nfields   = 0;
93 	db->field     = malloc(sizeof(DataField));
94 
95 	*DB = db;
96   PetscFunctionReturn(0);
97 }
98 
99 #undef __FUNCT__
100 #define __FUNCT__ "DataBucketDestroy"
101 PetscErrorCode DataBucketDestroy(DataBucket *DB)
102 {
103 	DataBucket db = *DB;
104 	PetscInt f;
105 	PetscErrorCode ierr;
106 
107 	/* release fields */
108 	for (f=0; f<db->nfields; f++) {
109 		ierr = DataFieldDestroy(&db->field[f]);CHKERRQ(ierr);
110 	}
111 
112 	/* this will catch the initially allocated objects in the event that no fields are registered */
113 	if (db->field != NULL) {
114 		free(db->field);
115 	}
116 
117 	free(db);
118 
119 	*DB = NULL;
120   PetscFunctionReturn(0);
121 }
122 
123 #undef __FUNCT__
124 #define __FUNCT__ "DataBucketRegisterField"
125 PetscErrorCode DataBucketRegisterField(
126                               DataBucket db,
127                               const char registeration_function[],
128                               const char field_name[],
129                               size_t atomic_size, DataField *_gfield)
130 {
131 	PetscBool val;
132 	DataField *field,fp;
133 	PetscErrorCode ierr;
134 
135 	/* check we haven't finalised the registration of fields */
136 	/*
137    if(db->finalised==PETSC_TRUE) {
138    printf("ERROR: DataBucketFinalize() has been called. Cannot register more fields\n");
139    ERROR();
140    }
141    */
142 
143 	/* check for repeated name */
144 	ierr = StringInList( field_name, db->nfields, (const DataField*)db->field, &val );CHKERRQ(ierr);
145 	if (val == PETSC_TRUE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field %s already exists. Cannot add same field twice",field_name);
146 
147 	/* create new space for data */
148 	field = realloc( db->field,     sizeof(DataField)*(db->nfields+1));
149 	db->field     = field;
150 
151 	/* add field */
152 	ierr = DataFieldCreate( registeration_function, field_name, atomic_size, db->allocated, &fp );CHKERRQ(ierr);
153 	db->field[ db->nfields ] = fp;
154 
155 	db->nfields++;
156 
157 	if (_gfield != NULL) {
158 		*_gfield = fp;
159 	}
160   PetscFunctionReturn(0);
161 }
162 
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  free(location);\
169  }
170  */
171 
172 #undef __FUNCT__
173 #define __FUNCT__ "DataBucketGetDataFieldByName"
174 PetscErrorCode DataBucketGetDataFieldByName(DataBucket db,const char name[],DataField *gfield)
175 {
176   PetscErrorCode ierr;
177 	PetscInt idx;
178 	PetscBool found;
179 
180 	ierr = StringInList(name,db->nfields,(const DataField*)db->field,&found);CHKERRQ(ierr);
181 	if (!found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot find DataField with name %s",name);
182 
183 	ierr = StringFindInList(name,db->nfields,(const DataField*)db->field,&idx);CHKERRQ(ierr);
184 
185 	*gfield = db->field[idx];
186   PetscFunctionReturn(0);
187 }
188 
189 #undef __FUNCT__
190 #define __FUNCT__ "DataBucketQueryDataFieldByName"
191 PetscErrorCode DataBucketQueryDataFieldByName(DataBucket db,const char name[],PetscBool *found)
192 {
193   PetscErrorCode ierr;
194 	*found = PETSC_FALSE;
195 	ierr = StringInList(name,db->nfields,(const DataField*)db->field,found);CHKERRQ(ierr);
196   PetscFunctionReturn(0);
197 }
198 
199 #undef __FUNCT__
200 #define __FUNCT__ "DataBucketFinalize"
201 PetscErrorCode DataBucketFinalize(DataBucket db)
202 {
203 	db->finalised = PETSC_TRUE;
204   PetscFunctionReturn(0);
205 }
206 
207 #undef __FUNCT__
208 #define __FUNCT__ "DataFieldGetNumEntries"
209 PetscErrorCode DataFieldGetNumEntries(DataField df,PetscInt *sum)
210 {
211 	*sum = df->L;
212   PetscFunctionReturn(0);
213 }
214 
215 #undef __FUNCT__
216 #define __FUNCT__ "DataFieldSetSize"
217 PetscErrorCode DataFieldSetSize(DataField df,const PetscInt new_L)
218 {
219 	void *tmp_data;
220 
221 	if (new_L <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot set size of DataField to be <= 0");
222 
223 	if (new_L == df->L) PetscFunctionReturn(0);
224 
225 	if (new_L > df->L) {
226 
227 		tmp_data = realloc( df->data, df->atomic_size * (new_L) );
228 		df->data = tmp_data;
229 
230 		/* init new contents */
231 		memset( ( ((char*)df->data)+df->L*df->atomic_size), 0, (new_L-df->L)*df->atomic_size );
232 
233 	} else {
234 		/* reallocate pointer list, add +1 in case new_L = 0 */
235 		tmp_data = realloc( df->data, df->atomic_size * (new_L+1) );
236 		df->data = tmp_data;
237 	}
238 
239 	df->L = new_L;
240   PetscFunctionReturn(0);
241 }
242 
243 #undef __FUNCT__
244 #define __FUNCT__ "DataFieldZeroBlock"
245 PetscErrorCode DataFieldZeroBlock(DataField df,const PetscInt start,const PetscInt end)
246 {
247 	if (start > end) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot zero a block of entries if start(%D) > end(%D)",start,end);
248 
249 	if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot zero a block of entries if start(%D) < 0",start);
250 
251 	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);
252 
253 	memset( ( ((char*)df->data)+start*df->atomic_size), 0, (end-start)*df->atomic_size );
254   PetscFunctionReturn(0);
255 }
256 
257 /*
258  A negative buffer value will simply be ignored and the old buffer value will be used.
259  */
260 #undef __FUNCT__
261 #define __FUNCT__ "DataBucketSetSizes"
262 PetscErrorCode DataBucketSetSizes(DataBucket db,const PetscInt L,const PetscInt buffer)
263 {
264 	PetscInt current_allocated,new_used,new_unused,new_buffer,new_allocated,f;
265   PetscErrorCode ierr;
266 
267 	if (db->finalised == PETSC_FALSE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"You must call DataBucketFinalize() before DataBucketSetSizes()");
268 
269 	current_allocated = db->allocated;
270 
271 	new_used   = L;
272 	new_unused = current_allocated - new_used;
273 	new_buffer = db->buffer;
274 	if (buffer >= 0) { /* update the buffer value */
275 		new_buffer = buffer;
276 	}
277 	new_allocated = new_used + new_buffer;
278 
279 	/* action */
280 	if (new_allocated > current_allocated) {
281 		/* increase size to new_used + new_buffer */
282 		for (f=0; f<db->nfields; f++) {
283 			ierr = DataFieldSetSize( db->field[f], new_allocated );CHKERRQ(ierr);
284 		}
285 
286 		db->L         = new_used;
287 		db->buffer    = new_buffer;
288 		db->allocated = new_used + new_buffer;
289 	}
290 	else {
291 		if (new_unused > 2 * new_buffer) {
292 
293 			/* shrink array to new_used + new_buffer */
294 			for (f=0; f<db->nfields; f++) {
295 				ierr = DataFieldSetSize( db->field[f], new_allocated );CHKERRQ(ierr);
296 			}
297 
298 			db->L         = new_used;
299 			db->buffer    = new_buffer;
300 			db->allocated = new_used + new_buffer;
301 		}
302 		else {
303 			db->L      = new_used;
304 			db->buffer = new_buffer;
305 		}
306 	}
307 
308 	/* zero all entries from db->L to db->allocated */
309 	for (f=0; f<db->nfields; f++) {
310 		DataField field = db->field[f];
311 		ierr = DataFieldZeroBlock(field, db->L,db->allocated);CHKERRQ(ierr);
312 	}
313   PetscFunctionReturn(0);
314 }
315 
316 #undef __FUNCT__
317 #define __FUNCT__ "DataBucketSetInitialSizes"
318 PetscErrorCode DataBucketSetInitialSizes(DataBucket db,const PetscInt L,const PetscInt buffer)
319 {
320 	PetscInt f;
321   PetscErrorCode ierr;
322 
323 	ierr = DataBucketSetSizes(db,L,buffer);CHKERRQ(ierr);
324 
325 	for (f=0; f<db->nfields; f++) {
326 		DataField field = db->field[f];
327 		ierr = DataFieldZeroBlock(field,0,db->allocated);CHKERRQ(ierr);
328 	}
329   PetscFunctionReturn(0);
330 }
331 
332 #undef __FUNCT__
333 #define __FUNCT__ "DataBucketGetSizes"
334 PetscErrorCode DataBucketGetSizes(DataBucket db,PetscInt *L,PetscInt *buffer,PetscInt *allocated)
335 {
336 	if (L) { *L = db->L; }
337 	if (buffer) { *buffer = db->buffer; }
338 	if (allocated) { *allocated = db->allocated; }
339   PetscFunctionReturn(0);
340 }
341 
342 #undef __FUNCT__
343 #define __FUNCT__ "DataBucketGetGlobalSizes"
344 PetscErrorCode DataBucketGetGlobalSizes(MPI_Comm comm,DataBucket db,PetscInt *L,PetscInt *buffer,PetscInt *allocated)
345 {
346 	PetscInt _L,_buffer,_allocated;
347 	PetscInt ierr;
348 
349 	_L = db->L;
350 	_buffer = db->buffer;
351 	_allocated = db->allocated;
352 
353 	if (L) {         ierr = MPI_Allreduce(&_L,L,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); }
354 	if (buffer) {    ierr = MPI_Allreduce(&_buffer,buffer,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); }
355 	if (allocated) { ierr = MPI_Allreduce(&_allocated,allocated,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); }
356   PetscFunctionReturn(0);
357 }
358 
359 #undef __FUNCT__
360 #define __FUNCT__ "DataBucketGetDataFields"
361 PetscErrorCode DataBucketGetDataFields(DataBucket db,PetscInt *L,DataField *fields[])
362 {
363 	if (L) {      *L      = db->nfields; }
364 	if (fields) { *fields = db->field; }
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "DataFieldGetAccess"
370 PetscErrorCode DataFieldGetAccess(const DataField gfield)
371 {
372 	if (gfield->active) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is already active. You must call DataFieldRestoreAccess()",gfield->name);
373 
374 	gfield->active = PETSC_TRUE;
375   PetscFunctionReturn(0);
376 }
377 
378 #undef __FUNCT__
379 #define __FUNCT__ "DataFieldAccessPoint"
380 PetscErrorCode DataFieldAccessPoint(const DataField gfield,const PetscInt pid,void **ctx_p)
381 {
382 #ifdef DATAFIELD_POINT_ACCESS_GUARD
383 	/* debug mode */
384 	/* check point is valid */
385 	if (pid < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
386 	if (pid >= gfield->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",gfield->L);
387 
388 	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);
389 #endif
390 
391 	//*ctx_p  = (void*)( ((char*)gfield->data) + pid * gfield->atomic_size);
392 	*ctx_p = __DATATFIELD_point_access(gfield->data,pid,gfield->atomic_size);
393   PetscFunctionReturn(0);
394 }
395 
396 #undef __FUNCT__
397 #define __FUNCT__ "DataFieldAccessPointOffset"
398 PetscErrorCode DataFieldAccessPointOffset(const DataField gfield,const size_t offset,const PetscInt pid,void **ctx_p)
399 {
400 #ifdef DATAFIELD_POINT_ACCESS_GUARD
401 	/* debug mode */
402 
403 	/* check point is valid */
404 	/* if( offset < 0 ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"offset must be >= 0");*//* Note compiler realizes this can never happen with an unsigned PetscInt */
405 	if (offset >= gfield->atomic_size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"offset must be < %zu",gfield->atomic_size);
406 
407 	/* check point is valid */
408 	if (pid < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
409 	if (pid >= gfield->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",gfield->L);
410 
411 	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);
412 #endif
413 
414 	*ctx_p = __DATATFIELD_point_access_offset(gfield->data,pid,gfield->atomic_size,offset);
415   PetscFunctionReturn(0);
416 }
417 
418 #undef __FUNCT__
419 #define __FUNCT__ "DataFieldRestoreAccess"
420 PetscErrorCode DataFieldRestoreAccess(DataField gfield)
421 {
422 	if (gfield->active == PETSC_FALSE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is not active. You must call DataFieldGetAccess()", gfield->name );
423 
424 	gfield->active = PETSC_FALSE;
425   PetscFunctionReturn(0);
426 }
427 
428 #undef __FUNCT__
429 #define __FUNCT__ "DataFieldVerifyAccess"
430 PetscErrorCode DataFieldVerifyAccess(const DataField gfield,const size_t size)
431 {
432 #ifdef DATAFIELD_POINT_ACCESS_GUARD
433 	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.",
434            gfield->name, gfield->atomic_size, size );
435 #endif
436   PetscFunctionReturn(0);
437 }
438 
439 #undef __FUNCT__
440 #define __FUNCT__ "DataFieldGetAtomicSize"
441 PetscErrorCode DataFieldGetAtomicSize(const DataField gfield,size_t *size)
442 {
443   if (size) { *size = gfield->atomic_size; }
444   PetscFunctionReturn(0);
445 }
446 
447 #undef __FUNCT__
448 #define __FUNCT__ "DataFieldGetEntries"
449 PetscErrorCode DataFieldGetEntries(const DataField gfield,void **data)
450 {
451   if (data) {
452     *data = gfield->data;
453   }
454   PetscFunctionReturn(0);
455 }
456 
457 #undef __FUNCT__
458 #define __FUNCT__ "DataFieldRestoreEntries"
459 PetscErrorCode DataFieldRestoreEntries(const DataField gfield,void **data)
460 {
461   if (data) {
462     *data = NULL;
463   }
464   PetscFunctionReturn(0);
465 }
466 
467 /* y = x */
468 #undef __FUNCT__
469 #define __FUNCT__ "DataBucketCopyPoint"
470 PetscErrorCode DataBucketCopyPoint(const DataBucket xb,const PetscInt pid_x,
471                          const DataBucket yb,const PetscInt pid_y)
472 {
473 	PetscInt f;
474 	PetscErrorCode ierr;
475 
476 	for (f=0; f<xb->nfields; f++) {
477 		void *dest;
478 		void *src;
479 
480 		ierr = DataFieldGetAccess( xb->field[f] );CHKERRQ(ierr);
481 		if (xb != yb) { ierr = DataFieldGetAccess( yb->field[f] );CHKERRQ(ierr); }
482 
483 		ierr = DataFieldAccessPoint( xb->field[f],pid_x, &src );CHKERRQ(ierr);
484 		ierr = DataFieldAccessPoint( yb->field[f],pid_y, &dest );CHKERRQ(ierr);
485 
486 		memcpy( dest, src, xb->field[f]->atomic_size );
487 
488 		ierr = DataFieldRestoreAccess( xb->field[f] );CHKERRQ(ierr);
489 		if (xb != yb) { ierr = DataFieldRestoreAccess( yb->field[f] );CHKERRQ(ierr); }
490 	}
491   PetscFunctionReturn(0);
492 }
493 
494 #undef __FUNCT__
495 #define __FUNCT__ "DataBucketCreateFromSubset"
496 PetscErrorCode DataBucketCreateFromSubset(DataBucket DBIn,const PetscInt N,const PetscInt list[],DataBucket *DB)
497 {
498 	PetscInt nfields;
499 	DataField *fields;
500 	DataBucketCreate(DB);
501 	PetscInt f,L,buffer,allocated,p;
502 	PetscErrorCode ierr;
503 
504 	/* copy contents of DBIn */
505 	ierr = DataBucketGetDataFields(DBIn,&nfields,&fields);CHKERRQ(ierr);
506 	ierr = DataBucketGetSizes(DBIn,&L,&buffer,&allocated);CHKERRQ(ierr);
507 
508 	for (f=0; f<nfields; f++) {
509 		ierr = DataBucketRegisterField(*DB,"DataBucketCreateFromSubset",fields[f]->name,fields[f]->atomic_size,NULL);CHKERRQ(ierr);
510 	}
511 	ierr = DataBucketFinalize(*DB);CHKERRQ(ierr);
512 
513 	ierr = DataBucketSetSizes(*DB,L,buffer);CHKERRQ(ierr);
514 
515 	/* now copy the desired guys from DBIn => DB */
516 	for (p=0; p<N; p++) {
517 		ierr = DataBucketCopyPoint(DBIn,list[p], *DB,p);CHKERRQ(ierr);
518 	}
519   PetscFunctionReturn(0);
520 }
521 
522 // insert into an exisitng location
523 #undef __FUNCT__
524 #define __FUNCT__ "DataFieldInsertPoint"
525 PetscErrorCode DataFieldInsertPoint(const DataField field,const PetscInt index,const void *ctx)
526 {
527 
528 #ifdef DATAFIELD_POINT_ACCESS_GUARD
529 	/* check point is valid */
530 	if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
531 	if (index >= field->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",field->L);
532 #endif
533 
534   //	memcpy( (void*)((char*)field->data + index*field->atomic_size), ctx, field->atomic_size );
535 	memcpy( __DATATFIELD_point_access(field->data,index,field->atomic_size), ctx, field->atomic_size );
536   PetscFunctionReturn(0);
537 }
538 
539 // remove data at index - replace with last point
540 #undef __FUNCT__
541 #define __FUNCT__ "DataBucketRemovePointAtIndex"
542 PetscErrorCode DataBucketRemovePointAtIndex(const DataBucket db,const PetscInt index)
543 {
544 	PetscInt f;
545 	PetscErrorCode ierr;
546 
547 #ifdef DATAFIELD_POINT_ACCESS_GUARD
548 	/* check point is valid */
549 	if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
550 	if (index >= db->allocated) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",db->L+db->buffer);
551 #endif
552 
553 	if (index >= db->L) { /* this point is not in the list - no need to error, but I will anyway */
554 		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 );
555 	}
556 
557 	if (index != db->L-1) { /* not last point in list */
558 		for (f=0; f<db->nfields; f++) {
559 			DataField field = db->field[f];
560 
561 			/* copy then remove */
562 			ierr = DataFieldCopyPoint( db->L-1,field, index,field );CHKERRQ(ierr);
563 
564 			//DataFieldZeroPoint(field,index);
565 		}
566 	}
567 
568 	/* decrement size */
569 	/* this will zero out an crap at the end of the list */
570 	ierr = DataBucketRemovePoint(db);CHKERRQ(ierr);
571   PetscFunctionReturn(0);
572 }
573 
574 /* copy x into y */
575 #undef __FUNCT__
576 #define __FUNCT__ "DataFieldCopyPoint"
577 PetscErrorCode DataFieldCopyPoint(const PetscInt pid_x,const DataField field_x,
578                         const PetscInt pid_y,const DataField field_y )
579 {
580 
581 #ifdef DATAFIELD_POINT_ACCESS_GUARD
582 	/* check point is valid */
583 	if (pid_x < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"(IN) index must be >= 0");
584 	if (pid_x >= field_x->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"(IN) index must be < %D",field_x->L);
585 
586 	if (pid_y < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"(OUT) index must be >= 0");
587 	if (pid_y >= field_y->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"(OUT) index must be < %D",field_y->L);
588 
589 	if( field_y->atomic_size != field_x->atomic_size ) {
590 		SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"atomic size must match");
591 	}
592 #endif
593 	/*
594    memcpy( (void*)((char*)field_y->data + pid_y*field_y->atomic_size),
595    (void*)((char*)field_x->data + pid_x*field_x->atomic_size),
596    field_x->atomic_size );
597    */
598 	memcpy(		__DATATFIELD_point_access(field_y->data,pid_y,field_y->atomic_size),
599          __DATATFIELD_point_access(field_x->data,pid_x,field_x->atomic_size),
600          field_y->atomic_size );
601   PetscFunctionReturn(0);
602 }
603 
604 
605 // zero only the datafield at this point
606 #undef __FUNCT__
607 #define __FUNCT__ "DataFieldZeroPoint"
608 PetscErrorCode DataFieldZeroPoint(const DataField field,const PetscInt index)
609 {
610 #ifdef DATAFIELD_POINT_ACCESS_GUARD
611 	/* check point is valid */
612 	if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
613 	if (index >= field->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",field->L);
614 #endif
615 
616   //	memset( (void*)((char*)field->data + index*field->atomic_size), 0, field->atomic_size );
617 	memset( __DATATFIELD_point_access(field->data,index,field->atomic_size), 0, field->atomic_size );
618   PetscFunctionReturn(0);
619 }
620 
621 // zero ALL data for this point
622 #undef __FUNCT__
623 #define __FUNCT__ "DataBucketZeroPoint"
624 PetscErrorCode DataBucketZeroPoint(const DataBucket db,const PetscInt index)
625 {
626 	PetscInt f;
627 	PetscErrorCode ierr;
628 
629 	/* check point is valid */
630 	if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
631 	if (index >= db->allocated) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",db->allocated);
632 
633 	for (f=0; f<db->nfields; f++) {
634 		DataField field = db->field[f];
635 
636 		ierr = DataFieldZeroPoint(field,index);CHKERRQ(ierr);
637 	}
638   PetscFunctionReturn(0);
639 }
640 
641 /* increment */
642 #undef __FUNCT__
643 #define __FUNCT__ "DataBucketAddPoint"
644 PetscErrorCode DataBucketAddPoint(DataBucket db)
645 {
646 	PetscErrorCode ierr;
647 
648 	ierr = DataBucketSetSizes(db,db->L+1,-1);CHKERRQ(ierr);
649   PetscFunctionReturn(0);
650 }
651 
652 /* decrement */
653 #undef __FUNCT__
654 #define __FUNCT__ "DataBucketRemovePoint"
655 PetscErrorCode DataBucketRemovePoint(DataBucket db)
656 {
657 	PetscErrorCode ierr;
658 
659 	ierr = DataBucketSetSizes(db,db->L-1,-1);CHKERRQ(ierr);
660   PetscFunctionReturn(0);
661 }
662 
663 #undef __FUNCT__
664 #define __FUNCT__ "_DataFieldViewBinary"
665 PetscErrorCode _DataFieldViewBinary(DataField field,FILE *fp)
666 {
667 	fprintf(fp,"<DataField>\n");
668 	fprintf(fp,"%d\n", field->L);
669 	fprintf(fp,"%zu\n",field->atomic_size);
670 	fprintf(fp,"%s\n", field->registeration_function);
671 	fprintf(fp,"%s\n", field->name);
672 
673 	fwrite(field->data, field->atomic_size, field->L, fp);
674   /*
675    printf("  ** wrote %zu bytes for DataField \"%s\" \n", field->atomic_size * field->L, field->name );
676    */
677 	fprintf(fp,"\n</DataField>\n");
678   PetscFunctionReturn(0);
679 }
680 
681 #undef __FUNCT__
682 #define __FUNCT__ "_DataBucketRegisterFieldFromFile"
683 PetscErrorCode _DataBucketRegisterFieldFromFile(FILE *fp,DataBucket db)
684 {
685 	PetscBool val;
686 	DataField *field;
687 
688 	DataField gfield;
689 	char dummy[100];
690 	char registeration_function[5000];
691 	char field_name[5000];
692 	PetscInt L;
693 	size_t atomic_size,strL;
694 	PetscErrorCode ierr;
695 
696 	/* check we haven't finalised the registration of fields */
697 	/*
698    if(db->finalised==PETSC_TRUE) {
699    printf("ERROR: DataBucketFinalize() has been called. Cannot register more fields\n");
700    ERROR();
701    }
702    */
703 
704 
705 	/* read file contents */
706 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
707 
708 	fscanf( fp, "%d\n",&L); //printf("read(L): %d\n", L);
709 
710 	fscanf( fp, "%zu\n",&atomic_size); //printf("read(size): %zu\n",atomic_size);
711 
712 	fgets(registeration_function,4999,fp); //printf("read(reg func): %s", registeration_function );
713 	strL = strlen(registeration_function);
714 	if (strL > 1) {
715 		registeration_function[strL-1] = 0;
716 	}
717 
718 	fgets(field_name,4999,fp); //printf("read(name): %s", field_name );
719 	strL = strlen(field_name);
720 	if (strL > 1) {
721 		field_name[strL-1] = 0;
722 	}
723 
724 #ifdef DATA_BUCKET_LOG
725 	PetscPrintf(PETSC_COMM_SELF,"  ** read L=%D; atomic_size=%zu; reg_func=\"%s\"; name=\"%s\" \n", L,atomic_size,registeration_function,field_name);
726 #endif
727 
728 
729 	/* check for repeated name */
730 	ierr = StringInList( field_name, db->nfields, (const DataField*)db->field, &val );CHKERRQ(ierr);
731 	if (val == PETSC_TRUE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot add same field twice");
732 
733 	/* create new space for data */
734 	field = realloc( db->field,     sizeof(DataField)*(db->nfields+1));
735 	db->field     = field;
736 
737 	/* add field */
738 	ierr = DataFieldCreate( registeration_function, field_name, atomic_size, L, &gfield );CHKERRQ(ierr);
739 
740 	/* copy contents of file */
741 	fread(gfield->data, gfield->atomic_size, gfield->L, fp);
742 #ifdef DATA_BUCKET_LOG
743 	PetscPrintf(PETSC_COMM_SELF,"  ** read %zu bytes for DataField \"%s\" \n", gfield->atomic_size * gfield->L, field_name );
744 #endif
745 	/* finish reading meta data */
746 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
747 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
748 
749 	db->field[ db->nfields ] = gfield;
750 
751 	db->nfields++;
752   PetscFunctionReturn(0);
753 }
754 
755 #undef __FUNCT__
756 #define __FUNCT__ "_DataBucketViewAscii_HeaderWrite_v00"
757 PetscErrorCode _DataBucketViewAscii_HeaderWrite_v00(FILE *fp)
758 {
759 	fprintf(fp,"<DataBucketHeader>\n");
760 	fprintf(fp,"type=DataBucket\n");
761 	fprintf(fp,"format=ascii\n");
762 	fprintf(fp,"version=0.0\n");
763 	fprintf(fp,"options=\n");
764 	fprintf(fp,"</DataBucketHeader>\n");
765   PetscFunctionReturn(0);
766 }
767 
768 #undef __FUNCT__
769 #define __FUNCT__ "_DataBucketViewAscii_HeaderRead_v00"
770 PetscErrorCode _DataBucketViewAscii_HeaderRead_v00(FILE *fp)
771 {
772 	char dummy[100];
773 	size_t strL;
774 
775 	// header open
776 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
777 
778 	// type
779 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
780 	strL = strlen(dummy);
781 	if (strL > 1) { dummy[strL-1] = 0; }
782 	if (strcmp(dummy,"type=DataBucket") != 0) {
783 		SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Data file doesn't contain a DataBucket type");
784 	}
785 
786 	// format
787 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
788 
789 	// version
790 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
791 	strL = strlen(dummy);
792 	if (strL > 1) { dummy[strL-1] = 0; }
793 	if (strcmp(dummy,"version=0.0") != 0) {
794 		SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"DataBucket file must be parsed with version=0.0 : You tried %s", dummy);
795 	}
796 
797 	// options
798 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
799 	// header close
800 	fgets(dummy,99,fp); //printf("read(header): %s", dummy );
801   PetscFunctionReturn(0);
802 }
803 
804 #undef __FUNCT__
805 #define __FUNCT__ "_DataBucketLoadFromFileBinary_SEQ"
806 PetscErrorCode _DataBucketLoadFromFileBinary_SEQ(const char filename[],DataBucket *_db)
807 {
808 	DataBucket db;
809 	FILE *fp;
810 	PetscInt L,buffer,f,nfields;
811 	PetscErrorCode ierr;
812 
813 
814 #ifdef DATA_BUCKET_LOG
815 	PetscPrintf(PETSC_COMM_SELF,"** DataBucketLoadFromFile **\n");
816 #endif
817 
818 	/* open file */
819 	fp = fopen(filename,"rb");
820 	if (fp == NULL) {
821 		SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file with name %s", filename);
822 	}
823 
824 	/* read header */
825 	ierr = _DataBucketViewAscii_HeaderRead_v00(fp);CHKERRQ(ierr);
826 
827 	fscanf(fp,"%d\n%d\n%d\n",&L,&buffer,&nfields);
828 
829 	ierr = DataBucketCreate(&db);CHKERRQ(ierr);
830 
831 	for (f=0; f<nfields; f++) {
832 		ierr = _DataBucketRegisterFieldFromFile(fp,db);CHKERRQ(ierr);
833 	}
834 	fclose(fp);
835 
836 	ierr = DataBucketFinalize(db);CHKERRQ(ierr);
837 
838   /*
839    DataBucketSetSizes(db,L,buffer);
840    */
841 	db->L = L;
842 	db->buffer = buffer;
843 	db->allocated = L + buffer;
844 
845 	*_db = db;
846   PetscFunctionReturn(0);
847 }
848 
849 #undef __FUNCT__
850 #define __FUNCT__ "DataBucketLoadFromFile"
851 PetscErrorCode DataBucketLoadFromFile(MPI_Comm comm,const char filename[],DataBucketViewType type,DataBucket *db)
852 {
853 	PetscMPIInt nproc,rank;
854 	PetscErrorCode ierr;
855 
856 	ierr = MPI_Comm_size(comm,&nproc);CHKERRQ(ierr);
857 	ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
858 
859 #ifdef DATA_BUCKET_LOG
860 	PetscPrintf(PETSC_COMM_SELF,"** DataBucketLoadFromFile **\n");
861 #endif
862 	if (type == DATABUCKET_VIEW_STDOUT) {
863 
864 	} else if (type == DATABUCKET_VIEW_ASCII) {
865 		SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot be implemented as we don't know the underlying particle data structure");
866 	} else if (type == DATABUCKET_VIEW_BINARY) {
867 		if (nproc == 1) {
868 			ierr = _DataBucketLoadFromFileBinary_SEQ(filename,db);CHKERRQ(ierr);
869 		} else {
870 			char *name;
871 
872 			asprintf(&name,"%s_p%1.5d",filename, rank );
873 			ierr = _DataBucketLoadFromFileBinary_SEQ(name,db);CHKERRQ(ierr);
874 			free(name);
875 		}
876 	} else {
877 		SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer requested");
878 	}
879   PetscFunctionReturn(0);
880 }
881 
882 #undef __FUNCT__
883 #define __FUNCT__ "_DataBucketViewBinary"
884 PetscErrorCode _DataBucketViewBinary(DataBucket db,const char filename[])
885 {
886 	FILE *fp = NULL;
887 	PetscInt f;
888 	PetscErrorCode ierr;
889 
890 	fp = fopen(filename,"wb");
891 	if (fp == NULL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot open file with name %s", filename);
892 
893 	/* db header */
894 	ierr =_DataBucketViewAscii_HeaderWrite_v00(fp);CHKERRQ(ierr);
895 
896 	/* meta-data */
897 	fprintf(fp,"%d\n%d\n%d\n", db->L,db->buffer,db->nfields);
898 
899 	for (f=0; f<db->nfields; f++) {
900     /* load datafields */
901 		ierr = _DataFieldViewBinary(db->field[f],fp);CHKERRQ(ierr);
902 	}
903 
904 	fclose(fp);
905   PetscFunctionReturn(0);
906 }
907 
908 #undef __FUNCT__
909 #define __FUNCT__ "DataBucketView_SEQ"
910 PetscErrorCode DataBucketView_SEQ(DataBucket db,const char filename[],DataBucketViewType type)
911 {
912   PetscErrorCode ierr;
913 
914 	switch (type) {
915 		case DATABUCKET_VIEW_STDOUT:
916 		{
917 			PetscInt f;
918 			double memory_usage_total = 0.0;
919 
920 			PetscPrintf(PETSC_COMM_SELF,"DataBucketView(SEQ): (\"%s\")\n",filename);
921 			PetscPrintf(PETSC_COMM_SELF,"  L                  = %D \n", db->L );
922 			PetscPrintf(PETSC_COMM_SELF,"  buffer             = %D \n", db->buffer );
923 			PetscPrintf(PETSC_COMM_SELF,"  allocated          = %D \n", db->allocated );
924 
925 			PetscPrintf(PETSC_COMM_SELF,"  nfields registered = %D \n", db->nfields );
926 			for (f=0; f<db->nfields; f++) {
927 				double memory_usage_f = (double)(db->field[f]->atomic_size * db->allocated) * 1.0e-6;
928 
929 				PetscPrintf(PETSC_COMM_SELF,"    [%3D]: field name  ==>> %30s : Mem. usage = %1.2e (MB) \n", f, db->field[f]->name, memory_usage_f  );
930 				memory_usage_total += memory_usage_f;
931 			}
932 			PetscPrintf(PETSC_COMM_SELF,"  Total mem. usage                                                      = %1.2e (MB) \n", memory_usage_total );
933 		}
934 			break;
935 
936 		case DATABUCKET_VIEW_ASCII:
937 		{
938 			SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot be implemented as we don't know the underlying particle data structure");
939 		}
940 			break;
941 
942 		case DATABUCKET_VIEW_BINARY:
943 		{
944 			ierr = _DataBucketViewBinary(db,filename);CHKERRQ(ierr);
945 		}
946 			break;
947 
948 		case DATABUCKET_VIEW_HDF5:
949 		{
950 			SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No HDF5 support");
951 		}
952 			break;
953 
954 		default:
955 			SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested");
956 			break;
957 	}
958   PetscFunctionReturn(0);
959 }
960 
961 #undef __FUNCT__
962 #define __FUNCT__ "DataBucketView_MPI"
963 PetscErrorCode DataBucketView_MPI(MPI_Comm comm,DataBucket db,const char filename[],DataBucketViewType type)
964 {
965   PetscErrorCode ierr;
966 
967 	switch (type) {
968 		case DATABUCKET_VIEW_STDOUT:
969 		{
970 			PetscInt f;
971 			PetscInt L,buffer,allocated;
972 			double memory_usage_total,memory_usage_total_local = 0.0;
973 			PetscMPIInt rank;
974 
975 			ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
976 
977 			ierr = DataBucketGetGlobalSizes(comm,db,&L,&buffer,&allocated);CHKERRQ(ierr);
978 
979 			for (f=0; f<db->nfields; f++) {
980 				double memory_usage_f = (double)(db->field[f]->atomic_size * db->allocated) * 1.0e-6;
981 
982 				memory_usage_total_local += memory_usage_f;
983 			}
984 			ierr = MPI_Allreduce(&memory_usage_total_local,&memory_usage_total,1,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr);
985 
986 			if (rank == 0) {
987 				PetscPrintf(comm,"DataBucketView(MPI): (\"%s\")\n",filename);
988 				PetscPrintf(comm,"  L                  = %D \n", L );
989 				PetscPrintf(comm,"  buffer (max)       = %D \n", buffer );
990 				PetscPrintf(comm,"  allocated          = %D \n", allocated );
991 
992 				PetscPrintf(comm,"  nfields registered = %D \n", db->nfields );
993 				for (f=0; f<db->nfields; f++) {
994 					double memory_usage_f = (double)(db->field[f]->atomic_size * db->allocated) * 1.0e-6;
995 
996 					PetscPrintf(PETSC_COMM_SELF,"    [%3D]: field name  ==>> %30s : Mem. usage = %1.2e (MB) : rank0\n", f, db->field[f]->name, memory_usage_f  );
997 				}
998 
999 				PetscPrintf(PETSC_COMM_SELF,"  Total mem. usage                                                      = %1.2e (MB) : collective\n", memory_usage_total );
1000 			}
1001 
1002 		}
1003 			break;
1004 
1005 		case DATABUCKET_VIEW_ASCII:
1006 		{
1007 			SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot be implemented as we don't know the underlying data structure");
1008 		}
1009 			break;
1010 
1011 		case DATABUCKET_VIEW_BINARY:
1012 		{
1013 			char *name;
1014 			PetscMPIInt rank;
1015 
1016 			/* create correct extension */
1017 			ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1018 			asprintf(&name,"%s_p%1.5d",filename, rank );
1019 
1020 			ierr = _DataBucketViewBinary(db,name);CHKERRQ(ierr);
1021 
1022 			free(name);
1023 		}
1024 			break;
1025 
1026 		case DATABUCKET_VIEW_HDF5:
1027 		{
1028 			SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for HDF5");
1029 		}
1030 			break;
1031 
1032 		default:
1033 			SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested");
1034 			break;
1035 	}
1036   PetscFunctionReturn(0);
1037 }
1038 
1039 #undef __FUNCT__
1040 #define __FUNCT__ "DataBucketView"
1041 PetscErrorCode DataBucketView(MPI_Comm comm,DataBucket db,const char filename[],DataBucketViewType type)
1042 {
1043 	PetscMPIInt nproc;
1044   PetscErrorCode ierr;
1045 
1046 	ierr = MPI_Comm_size(comm,&nproc);CHKERRQ(ierr);
1047 	if (nproc == 1) {
1048 		ierr =DataBucketView_SEQ(db,filename,type);CHKERRQ(ierr);
1049 	} else {
1050 		ierr = DataBucketView_MPI(comm,db,filename,type);CHKERRQ(ierr);
1051 	}
1052   PetscFunctionReturn(0);
1053 }
1054 
1055 #undef __FUNCT__
1056 #define __FUNCT__ "DataBucketDuplicateFields"
1057 PetscErrorCode DataBucketDuplicateFields(DataBucket dbA,DataBucket *dbB)
1058 {
1059 	DataBucket db2;
1060 	PetscInt f;
1061 	PetscErrorCode ierr;
1062 
1063 	ierr = DataBucketCreate(&db2);CHKERRQ(ierr);
1064 
1065 	/* copy contents from dbA into db2 */
1066 	for (f=0; f<dbA->nfields; f++) {
1067 		DataField field;
1068 		size_t    atomic_size;
1069 		char      *name;
1070 
1071 		field = dbA->field[f];
1072 
1073 		atomic_size = field->atomic_size;
1074 		name        = field->name;
1075 
1076 		ierr = DataBucketRegisterField(db2,"DataBucketDuplicateFields",name,atomic_size,NULL);CHKERRQ(ierr);
1077 	}
1078 	ierr = DataBucketFinalize(db2);CHKERRQ(ierr);
1079 	ierr = DataBucketSetInitialSizes(db2,0,1000);CHKERRQ(ierr);
1080 
1081 	/* set pointer */
1082 	*dbB = db2;
1083   PetscFunctionReturn(0);
1084 }
1085 
1086 /*
1087  Insert points from db2 into db1
1088  db1 <<== db2
1089  */
1090 #undef __FUNCT__
1091 #define __FUNCT__ "DataBucketInsertValues"
1092 PetscErrorCode DataBucketInsertValues(DataBucket db1,DataBucket db2)
1093 {
1094 	PetscInt n_mp_points1,n_mp_points2;
1095 	PetscInt n_mp_points1_new,p;
1096 	PetscErrorCode ierr;
1097 
1098 	ierr = DataBucketGetSizes(db1,&n_mp_points1,0,0);CHKERRQ(ierr);
1099 	ierr = DataBucketGetSizes(db2,&n_mp_points2,0,0);CHKERRQ(ierr);
1100 
1101 	n_mp_points1_new = n_mp_points1 + n_mp_points2;
1102 	ierr = DataBucketSetSizes(db1,n_mp_points1_new,-1);CHKERRQ(ierr);
1103 
1104 	for (p=0; p<n_mp_points2; p++) {
1105 		// db1 <<== db2 //
1106 		ierr =DataBucketCopyPoint( db2,p, db1,(n_mp_points1 + p) );CHKERRQ(ierr);
1107 	}
1108   PetscFunctionReturn(0);
1109 }
1110 
1111 /* helpers for parallel send/recv */
1112 #undef __FUNCT__
1113 #define __FUNCT__ "DataBucketCreatePackedArray"
1114 PetscErrorCode DataBucketCreatePackedArray(DataBucket db,size_t *bytes,void **buf)
1115 {
1116   PetscInt       f;
1117   size_t    sizeof_marker_contents;
1118   void      *buffer;
1119 
1120   sizeof_marker_contents = 0;
1121   for (f=0; f<db->nfields; f++) {
1122     DataField df = db->field[f];
1123 
1124     sizeof_marker_contents += df->atomic_size;
1125   }
1126 
1127   buffer = malloc(sizeof_marker_contents);
1128   memset(buffer,0,sizeof_marker_contents);
1129 
1130   if (bytes) { *bytes = sizeof_marker_contents; }
1131   if (buf)   { *buf   = buffer; }
1132   PetscFunctionReturn(0);
1133 }
1134 
1135 #undef __FUNCT__
1136 #define __FUNCT__ "DataBucketDestroyPackedArray"
1137 PetscErrorCode DataBucketDestroyPackedArray(DataBucket db,void **buf)
1138 {
1139   if (buf) {
1140     free(*buf);
1141     *buf = NULL;
1142   }
1143   PetscFunctionReturn(0);
1144 }
1145 
1146 #undef __FUNCT__
1147 #define __FUNCT__ "DataBucketFillPackedArray"
1148 PetscErrorCode DataBucketFillPackedArray(DataBucket db,const PetscInt index,void *buf)
1149 {
1150   PetscInt    f;
1151   void   *data,*data_p;
1152   size_t asize,offset;
1153 
1154   offset = 0;
1155   for (f=0; f<db->nfields; f++) {
1156     DataField df = db->field[f];
1157 
1158     asize = df->atomic_size;
1159 
1160     data = (void*)( df->data );
1161     data_p = (void*)( (char*)data + index*asize );
1162 
1163     memcpy( (void*)((char*)buf + offset),  data_p,  asize);
1164     offset = offset + asize;
1165   }
1166   PetscFunctionReturn(0);
1167 }
1168 
1169 #undef __FUNCT__
1170 #define __FUNCT__ "DataBucketInsertPackedArray"
1171 PetscErrorCode DataBucketInsertPackedArray(DataBucket db,const PetscInt idx,void *data)
1172 {
1173   PetscInt f;
1174   void *data_p;
1175   size_t offset;
1176 	PetscErrorCode ierr;
1177 
1178   offset = 0;
1179   for (f=0; f<db->nfields; f++) {
1180     DataField df = db->field[f];
1181 
1182     data_p = (void*)( (char*)data + offset );
1183 
1184     ierr = DataFieldInsertPoint(df, idx, (void*)data_p );CHKERRQ(ierr);
1185     offset = offset + df->atomic_size;
1186   }
1187   PetscFunctionReturn(0);
1188 }
1189