Actual source code: data_bucket.c

petsc-3.14.6 2021-03-30
Report Typos and Errors
  1: #include "../src/dm/impls/swarm/data_bucket.h"

  3: /* string helpers */
  4: PetscErrorCode DMSwarmDataFieldStringInList(const char name[],const PetscInt N,const DMSwarmDataField 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 DMSwarmDataFieldStringFindInList(const char name[],const PetscInt N,const DMSwarmDataField 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 DMSwarmDataFieldCreate(const char registration_function[],const char name[],const size_t size,const PetscInt L,DMSwarmDataField *DF)
 41: {
 42:   DMSwarmDataField df;
 43:   PetscErrorCode   ierr;

 46:   PetscMalloc(sizeof(struct _p_DMSwarmDataField), &df);
 47:   PetscMemzero(df, sizeof(struct _p_DMSwarmDataField));
 48:   PetscStrallocpy(registration_function, &df->registration_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 DMSwarmDataFieldDestroy(DMSwarmDataField *DF)
 61: {
 62:   DMSwarmDataField df = *DF;
 63:   PetscErrorCode   ierr;

 66:   PetscFree(df->registration_function);
 67:   PetscFree(df->name);
 68:   PetscFree(df->data);
 69:   PetscFree(df);
 70:   *DF  = NULL;
 71:   return(0);
 72: }

 74: /* data bucket */
 75: PetscErrorCode DMSwarmDataBucketCreate(DMSwarmDataBucket *DB)
 76: {
 77:   DMSwarmDataBucket db;
 78:   PetscErrorCode    ierr;

 81:   PetscMalloc(sizeof(struct _p_DMSwarmDataBucket), &db);
 82:   PetscMemzero(db, sizeof(struct _p_DMSwarmDataBucket));

 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 DMSwarmDataBucketDestroy(DMSwarmDataBucket *DB)
 96: {
 97:   DMSwarmDataBucket db = *DB;
 98:   PetscInt          f;
 99:   PetscErrorCode    ierr;

102:   /* release fields */
103:   for (f = 0; f < db->nfields; ++f) {
104:     DMSwarmDataFieldDestroy(&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 DMSwarmDataBucketQueryForActiveFields(DMSwarmDataBucket 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 DMSwarmDataBucketRegisterField(
131:                               DMSwarmDataBucket db,
132:                               const char registration_function[],
133:                               const char field_name[],
134:                               size_t atomic_size, DMSwarmDataField *_gfield)
135: {
136:   PetscBool val;
137:   DMSwarmDataField fp;

141:         /* check we haven't finalised the registration of fields */
142:         /*
143:    if (db->finalised==PETSC_TRUE) {
144:    printf("ERROR: DMSwarmDataBucketFinalize() has been called. Cannot register more fields\n");
145:    ERROR();
146:    }
147:    */
148:   /* check for repeated name */
149:   DMSwarmDataFieldStringInList(field_name, db->nfields, (const DMSwarmDataField*) 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(DMSwarmDataField)*(db->nfields+1), &db->field);
153:   /* add field */
154:   DMSwarmDataFieldCreate(registration_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 DMSwarmDataBucketRegisterField(db,name,size,k) {\
165:  char *location;\
166:  asprintf(&location,"Registered by %s() at line %d within file %s", __FUNCTION__, __LINE__, __FILE__);\
167:  _DMSwarmDataBucketRegisterField( (db), location, (name), (size), (k));\
168:  PetscFree(location);\
169:  }
170:  */

172: PetscErrorCode DMSwarmDataBucketGetDMSwarmDataFieldByName(DMSwarmDataBucket db,const char name[],DMSwarmDataField *gfield)
173: {
174:   PetscInt       idx;
175:   PetscBool      found;

179:   DMSwarmDataFieldStringInList(name,db->nfields,(const DMSwarmDataField*)db->field,&found);
180:   if (!found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot find DMSwarmDataField with name %s",name);
181:   DMSwarmDataFieldStringFindInList(name,db->nfields,(const DMSwarmDataField*)db->field,&idx);
182:   *gfield = db->field[idx];
183:   return(0);
184: }

186: PetscErrorCode DMSwarmDataBucketQueryDMSwarmDataFieldByName(DMSwarmDataBucket db,const char name[],PetscBool *found)
187: {

191:   *found = PETSC_FALSE;
192:   DMSwarmDataFieldStringInList(name,db->nfields,(const DMSwarmDataField*)db->field,found);
193:   return(0);
194: }

196: PetscErrorCode DMSwarmDataBucketFinalize(DMSwarmDataBucket db)
197: {
199:   db->finalised = PETSC_TRUE;
200:   return(0);
201: }

203: PetscErrorCode DMSwarmDataFieldGetNumEntries(DMSwarmDataField df,PetscInt *sum)
204: {
206:   *sum = df->L;
207:   return(0);
208: }

210: PetscErrorCode DMSwarmDataFieldSetBlockSize(DMSwarmDataField df,PetscInt blocksize)
211: {
213:   df->bs = blocksize;
214:   return(0);
215: }

217: PetscErrorCode DMSwarmDataFieldSetSize(DMSwarmDataField df,const PetscInt new_L)
218: {

222:   if (new_L < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot set size of DMSwarmDataField 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 DMSwarmDataFieldZeroBlock(DMSwarmDataField 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 DMSwarmDataBucketSetSizes(DMSwarmDataBucket 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 DMSwarmDataBucketFinalize() before DMSwarmDataBucketSetSizes()");
259:   DMSwarmDataBucketQueryForActiveFields(db,&any_active_fields);
260:   if (any_active_fields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot safely re-size as at least one DMSwarmDataField 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:       DMSwarmDataFieldSetSize(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:         DMSwarmDataFieldSetSize(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:     DMSwarmDataField field = db->field[f];
296:     DMSwarmDataFieldZeroBlock(field, db->L,db->allocated);
297:   }
298:   return(0);
299: }

301: PetscErrorCode DMSwarmDataBucketSetInitialSizes(DMSwarmDataBucket db,const PetscInt L,const PetscInt buffer)
302: {
303:   PetscInt       f;

307:   DMSwarmDataBucketSetSizes(db,L,buffer);
308:   for (f = 0; f < db->nfields; ++f) {
309:     DMSwarmDataField field = db->field[f];
310:     DMSwarmDataFieldZeroBlock(field,0,db->allocated);
311:   }
312:   return(0);
313: }

315: PetscErrorCode DMSwarmDataBucketGetSizes(DMSwarmDataBucket 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 DMSwarmDataBucketGetGlobalSizes(MPI_Comm comm,DMSwarmDataBucket db,PetscInt *L,PetscInt *buffer,PetscInt *allocated)
325: {
326:   PetscInt ierr;

329:   if (L) {         MPI_Allreduce(&db->L,L,1,MPIU_INT,MPI_SUM,comm); }
330:   if (buffer) {    MPI_Allreduce(&db->buffer,buffer,1,MPIU_INT,MPI_SUM,comm); }
331:   if (allocated) { MPI_Allreduce(&db->allocated,allocated,1,MPIU_INT,MPI_SUM,comm); }
332:   return(0);
333: }

335: PetscErrorCode DMSwarmDataBucketGetDMSwarmDataFields(DMSwarmDataBucket db,PetscInt *L,DMSwarmDataField *fields[])
336: {
338:   if (L)      {*L      = db->nfields;}
339:   if (fields) {*fields = db->field;}
340:   return(0);
341: }

343: PetscErrorCode DMSwarmDataFieldGetAccess(const DMSwarmDataField gfield)
344: {
346:   if (gfield->active) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is already active. You must call DMSwarmDataFieldRestoreAccess()",gfield->name);
347:   gfield->active = PETSC_TRUE;
348:   return(0);
349: }

351: PetscErrorCode DMSwarmDataFieldAccessPoint(const DMSwarmDataField gfield,const PetscInt pid,void **ctx_p)
352: {
354:   *ctx_p = NULL;
355: #if defined(DMSWARM_DATAFIELD_POINT_ACCESS_GUARD)
356:   /* debug mode */
357:   /* check point is valid */
358:   if (pid < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
359:   if (pid >= gfield->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",gfield->L);
360:   if (gfield->active == PETSC_FALSE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is not active. You must call DMSwarmDataFieldGetAccess() before point data can be retrivied",gfield->name);
361: #endif
362:   *ctx_p = DMSWARM_DATAFIELD_point_access(gfield->data,pid,gfield->atomic_size);
363:   return(0);
364: }

366: PetscErrorCode DMSwarmDataFieldAccessPointOffset(const DMSwarmDataField gfield,const size_t offset,const PetscInt pid,void **ctx_p)
367: {
369: #if defined(DMSWARM_DATAFIELD_POINT_ACCESS_GUARD)
370:   /* debug mode */
371:   /* check point is valid */
372:   /* if (offset < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"offset must be >= 0");*/
373:   /* Note compiler realizes this can never happen with an unsigned PetscInt */
374:   if (offset >= gfield->atomic_size) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"offset must be < %zu",gfield->atomic_size);
375:   /* check point is valid */
376:   if (pid < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
377:   if (pid >= gfield->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",gfield->L);
378:   if (gfield->active == PETSC_FALSE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is not active. You must call DMSwarmDataFieldGetAccess() before point data can be retrivied",gfield->name);
379: #endif
380:   *ctx_p = DMSWARM_DATAFIELD_point_access_offset(gfield->data,pid,gfield->atomic_size,offset);
381:   return(0);
382: }

384: PetscErrorCode DMSwarmDataFieldRestoreAccess(DMSwarmDataField gfield)
385: {
387:   if (gfield->active == PETSC_FALSE) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Field \"%s\" is not active. You must call DMSwarmDataFieldGetAccess()", gfield->name);
388:   gfield->active = PETSC_FALSE;
389:   return(0);
390: }

392: PetscErrorCode DMSwarmDataFieldVerifyAccess(const DMSwarmDataField gfield,const size_t size)
393: {
395: #if defined(DMSWARM_DATAFIELD_POINT_ACCESS_GUARD)
396:   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);
397: #endif
398:   return(0);
399: }

401: PetscErrorCode DMSwarmDataFieldGetAtomicSize(const DMSwarmDataField gfield,size_t *size)
402: {
404:   if (size) {*size = gfield->atomic_size;}
405:   return(0);
406: }

408: PetscErrorCode DMSwarmDataFieldGetEntries(const DMSwarmDataField gfield,void **data)
409: {
411:   if (data) {*data = gfield->data;}
412:   return(0);
413: }

415: PetscErrorCode DMSwarmDataFieldRestoreEntries(const DMSwarmDataField gfield,void **data)
416: {
418:   if (data) {*data = NULL;}
419:   return(0);
420: }

422: /* y = x */
423: PetscErrorCode DMSwarmDataBucketCopyPoint(const DMSwarmDataBucket xb,const PetscInt pid_x,
424:                          const DMSwarmDataBucket yb,const PetscInt pid_y)
425: {
426:   PetscInt f;

430:   for (f = 0; f < xb->nfields; ++f) {
431:     void *dest;
432:     void *src;

434:     DMSwarmDataFieldGetAccess(xb->field[f]);
435:     if (xb != yb) { DMSwarmDataFieldGetAccess( yb->field[f]); }
436:     DMSwarmDataFieldAccessPoint(xb->field[f],pid_x, &src);
437:     DMSwarmDataFieldAccessPoint(yb->field[f],pid_y, &dest);
438:     PetscMemcpy(dest, src, xb->field[f]->atomic_size);
439:     DMSwarmDataFieldRestoreAccess(xb->field[f]);
440:     if (xb != yb) {DMSwarmDataFieldRestoreAccess(yb->field[f]);}
441:   }
442:   return(0);
443: }

445: PetscErrorCode DMSwarmDataBucketCreateFromSubset(DMSwarmDataBucket DBIn,const PetscInt N,const PetscInt list[],DMSwarmDataBucket *DB)
446: {
447:   PetscInt nfields;
448:   DMSwarmDataField *fields;
449:   PetscInt f,L,buffer,allocated,p;

453:   DMSwarmDataBucketCreate(DB);
454:   /* copy contents of DBIn */
455:   DMSwarmDataBucketGetDMSwarmDataFields(DBIn,&nfields,&fields);
456:   DMSwarmDataBucketGetSizes(DBIn,&L,&buffer,&allocated);
457:   for (f = 0; f < nfields; ++f) {
458:     DMSwarmDataBucketRegisterField(*DB,"DMSwarmDataBucketCreateFromSubset",fields[f]->name,fields[f]->atomic_size,NULL);
459:   }
460:   DMSwarmDataBucketFinalize(*DB);
461:   DMSwarmDataBucketSetSizes(*DB,L,buffer);
462:   /* now copy the desired guys from DBIn => DB */
463:   for (p = 0; p < N; ++p) {
464:     DMSwarmDataBucketCopyPoint(DBIn,list[p], *DB,p);
465:   }
466:   return(0);
467: }

469: /* insert into an exisitng location */
470: PetscErrorCode DMSwarmDataFieldInsertPoint(const DMSwarmDataField field,const PetscInt index,const void *ctx)
471: {

475: #if defined(DMSWARM_DATAFIELD_POINT_ACCESS_GUARD)
476:   /* check point is valid */
477:   if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
478:   if (index >= field->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",field->L);
479: #endif
480:   PetscMemcpy(DMSWARM_DATAFIELD_point_access(field->data,index,field->atomic_size), ctx, field->atomic_size);
481:   return(0);
482: }

484: /* remove data at index - replace with last point */
485: PetscErrorCode DMSwarmDataBucketRemovePointAtIndex(const DMSwarmDataBucket db,const PetscInt index)
486: {
487:   PetscInt       f;
488:   PetscBool      any_active_fields;

492: #if defined(DMSWARM_DATAFIELD_POINT_ACCESS_GUARD)
493:   /* check point is valid */
494:   if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
495:   if (index >= db->allocated) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",db->L+db->buffer);
496: #endif
497:   DMSwarmDataBucketQueryForActiveFields(db,&any_active_fields);
498:   if (any_active_fields) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot safely remove point as at least one DMSwarmDataField is currently being accessed");
499:   if (index >= db->L) { /* this point is not in the list - no need to error, but I will anyway */
500:     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);
501:   }
502:   if (index != db->L-1) { /* not last point in list */
503:     for (f = 0; f < db->nfields; ++f) {
504:       DMSwarmDataField field = db->field[f];

506:       /* copy then remove */
507:       DMSwarmDataFieldCopyPoint(db->L-1, field, index, field);
508:       /* DMSwarmDataFieldZeroPoint(field,index); */
509:     }
510:   }
511:   /* decrement size */
512:   /* this will zero out an crap at the end of the list */
513:   DMSwarmDataBucketRemovePoint(db);
514:   return(0);
515: }

517: /* copy x into y */
518: PetscErrorCode DMSwarmDataFieldCopyPoint(const PetscInt pid_x,const DMSwarmDataField field_x,
519:                         const PetscInt pid_y,const DMSwarmDataField field_y)
520: {

524: #if defined(DMSWARM_DATAFIELD_POINT_ACCESS_GUARD)
525:   /* check point is valid */
526:   if (pid_x < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"(IN) index must be >= 0");
527:   if (pid_x >= field_x->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"(IN) index must be < %D",field_x->L);
528:   if (pid_y < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"(OUT) index must be >= 0");
529:   if (pid_y >= field_y->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"(OUT) index must be < %D",field_y->L);
530:   if (field_y->atomic_size != field_x->atomic_size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"atomic size must match");
531: #endif
532:   PetscMemcpy(DMSWARM_DATAFIELD_point_access(field_y->data,pid_y,field_y->atomic_size),DMSWARM_DATAFIELD_point_access(field_x->data,pid_x,field_x->atomic_size),field_y->atomic_size);
533:   return(0);
534: }


537: /* zero only the datafield at this point */
538: PetscErrorCode DMSwarmDataFieldZeroPoint(const DMSwarmDataField field,const PetscInt index)
539: {

543: #if defined(DMSWARM_DATAFIELD_POINT_ACCESS_GUARD)
544:   /* check point is valid */
545:   if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
546:   if (index >= field->L) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",field->L);
547: #endif
548:   PetscMemzero(DMSWARM_DATAFIELD_point_access(field->data,index,field->atomic_size), field->atomic_size);
549:   return(0);
550: }

552: /* zero ALL data for this point */
553: PetscErrorCode DMSwarmDataBucketZeroPoint(const DMSwarmDataBucket db,const PetscInt index)
554: {
555:   PetscInt f;

559:   /* check point is valid */
560:   if (index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be >= 0");
561:   if (index >= db->allocated) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"index must be < %D",db->allocated);
562:   for (f = 0; f < db->nfields; ++f) {
563:     DMSwarmDataField field = db->field[f];
564:     DMSwarmDataFieldZeroPoint(field,index);
565:   }
566:   return(0);
567: }

569: /* increment */
570: PetscErrorCode DMSwarmDataBucketAddPoint(DMSwarmDataBucket db)
571: {

575:   DMSwarmDataBucketSetSizes(db,db->L+1,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);
576:   return(0);
577: }

579: /* decrement */
580: PetscErrorCode DMSwarmDataBucketRemovePoint(DMSwarmDataBucket db)
581: {

585:   DMSwarmDataBucketSetSizes(db,db->L-1,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);
586:   return(0);
587: }

589: PetscErrorCode DMSwarmDataBucketView_stdout(MPI_Comm comm,DMSwarmDataBucket db)
590: {
591:   PetscInt       f;
592:   double         memory_usage_total,memory_usage_total_local = 0.0;

596:   PetscPrintf(comm,"DMSwarmDataBucketView: \n");
597:   PetscPrintf(comm,"  L                  = %D \n", db->L);
598:   PetscPrintf(comm,"  buffer             = %D \n", db->buffer);
599:   PetscPrintf(comm,"  allocated          = %D \n", db->allocated);
600:   PetscPrintf(comm,"  nfields registered = %D \n", db->nfields);

602:   for (f = 0; f < db->nfields; ++f) {
603:     double memory_usage_f = (double)(db->field[f]->atomic_size * db->allocated) * 1.0e-6;
604:     memory_usage_total_local += memory_usage_f;
605:   }
606:   MPI_Allreduce(&memory_usage_total_local,&memory_usage_total,1,MPI_DOUBLE,MPI_SUM,comm);

608:   for (f = 0; f < db->nfields; ++f) {
609:     double memory_usage_f = (double)(db->field[f]->atomic_size * db->allocated) * 1.0e-6;
610:     PetscPrintf(comm,"    [%3D] %15s : Mem. usage       = %1.2e (MB) [rank0]\n", f, db->field[f]->name, memory_usage_f);
611:     PetscPrintf(comm,"                            blocksize        = %D \n", db->field[f]->bs);
612:     if (db->field[f]->bs != 1) {
613:       PetscPrintf(comm,"                            atomic size      = %zu [full block, bs=%D]\n", db->field[f]->atomic_size,db->field[f]->bs);
614:       PetscPrintf(comm,"                            atomic size/item = %zu \n", db->field[f]->atomic_size/db->field[f]->bs);
615:     } else {
616:       PetscPrintf(comm,"                            atomic size      = %zu \n", db->field[f]->atomic_size);
617:     }
618:   }
619:   PetscPrintf(comm,"  Total mem. usage                           = %1.2e (MB) (collective)\n", memory_usage_total);
620:   return(0);
621: }

623: PetscErrorCode DMSwarmDataBucketView_SEQ(MPI_Comm comm,DMSwarmDataBucket db,const char filename[],DMSwarmDataBucketViewType type)
624: {

628:   switch (type) {
629:   case DATABUCKET_VIEW_STDOUT:
630:     DMSwarmDataBucketView_stdout(PETSC_COMM_SELF,db);
631:     break;
632:   case DATABUCKET_VIEW_ASCII:
633:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for ascii output");
634:   case DATABUCKET_VIEW_BINARY:
635:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for binary output");
636:   case DATABUCKET_VIEW_HDF5:
637:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for HDF5 output");
638:   default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested");
639:   }
640:   return(0);
641: }

643: PetscErrorCode DMSwarmDataBucketView_MPI(MPI_Comm comm,DMSwarmDataBucket db,const char filename[],DMSwarmDataBucketViewType type)
644: {

648:   switch (type) {
649:   case DATABUCKET_VIEW_STDOUT:
650:     DMSwarmDataBucketView_stdout(comm,db);
651:     break;
652:   case DATABUCKET_VIEW_ASCII:
653:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for ascii output");
654:   case DATABUCKET_VIEW_BINARY:
655:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for binary output");
656:   case DATABUCKET_VIEW_HDF5:
657:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for HDF5 output");
658:   default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested");
659:   }
660:   return(0);
661: }

663: PetscErrorCode DMSwarmDataBucketView(MPI_Comm comm,DMSwarmDataBucket db,const char filename[],DMSwarmDataBucketViewType type)
664: {
665:   PetscMPIInt size;

669:   MPI_Comm_size(comm,&size);
670:   if (size == 1) {
671:     DMSwarmDataBucketView_SEQ(comm,db,filename,type);
672:   } else {
673:     DMSwarmDataBucketView_MPI(comm,db,filename,type);
674:   }
675:   return(0);
676: }

678: PetscErrorCode DMSwarmDataBucketDuplicateFields(DMSwarmDataBucket dbA,DMSwarmDataBucket *dbB)
679: {
680:   DMSwarmDataBucket db2;
681:   PetscInt          f;
682:   PetscErrorCode    ierr;

685:   DMSwarmDataBucketCreate(&db2);
686:   /* copy contents from dbA into db2 */
687:   for (f = 0; f < dbA->nfields; ++f) {
688:     DMSwarmDataField field;
689:     size_t    atomic_size;
690:     char      *name;

692:     field = dbA->field[f];
693:     atomic_size = field->atomic_size;
694:     name        = field->name;
695:     DMSwarmDataBucketRegisterField(db2,"DMSwarmDataBucketDuplicateFields",name,atomic_size,NULL);
696:   }
697:   DMSwarmDataBucketFinalize(db2);
698:   DMSwarmDataBucketSetInitialSizes(db2,0,1000);
699:   *dbB = db2;
700:   return(0);
701: }

703: /*
704:  Insert points from db2 into db1
705:  db1 <<== db2
706:  */
707: PetscErrorCode DMSwarmDataBucketInsertValues(DMSwarmDataBucket db1,DMSwarmDataBucket db2)
708: {
709:   PetscInt n_mp_points1,n_mp_points2;
710:   PetscInt n_mp_points1_new,p;

714:   DMSwarmDataBucketGetSizes(db1,&n_mp_points1,NULL,NULL);
715:   DMSwarmDataBucketGetSizes(db2,&n_mp_points2,NULL,NULL);
716:   n_mp_points1_new = n_mp_points1 + n_mp_points2;
717:   DMSwarmDataBucketSetSizes(db1,n_mp_points1_new,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);
718:   for (p = 0; p < n_mp_points2; ++p) {
719:     /* db1 <<== db2 */
720:     DMSwarmDataBucketCopyPoint(db2,p, db1,(n_mp_points1 + p));
721:   }
722:   return(0);
723: }

725: /* helpers for parallel send/recv */
726: PetscErrorCode DMSwarmDataBucketCreatePackedArray(DMSwarmDataBucket db,size_t *bytes,void **buf)
727: {
728:   PetscInt       f;
729:   size_t         sizeof_marker_contents;
730:   void          *buffer;

734:   sizeof_marker_contents = 0;
735:   for (f = 0; f < db->nfields; ++f) {
736:     DMSwarmDataField df = db->field[f];
737:     sizeof_marker_contents += df->atomic_size;
738:   }
739:   PetscMalloc(sizeof_marker_contents, &buffer);
740:   PetscMemzero(buffer, sizeof_marker_contents);
741:   if (bytes) {*bytes = sizeof_marker_contents;}
742:   if (buf)   {*buf   = buffer;}
743:   return(0);
744: }

746: PetscErrorCode DMSwarmDataBucketDestroyPackedArray(DMSwarmDataBucket db,void **buf)
747: {

751:   if (buf) {
752:     PetscFree(*buf);
753:     *buf = NULL;
754:   }
755:   return(0);
756: }

758: PetscErrorCode DMSwarmDataBucketFillPackedArray(DMSwarmDataBucket db,const PetscInt index,void *buf)
759: {
760:   PetscInt       f;
761:   void          *data, *data_p;
762:   size_t         asize, offset;

766:   offset = 0;
767:   for (f = 0; f < db->nfields; ++f) {
768:     DMSwarmDataField df = db->field[f];

770:     asize = df->atomic_size;
771:     data = (void*)( df->data);
772:     data_p = (void*)( (char*)data + index*asize);
773:     PetscMemcpy((void*)((char*)buf + offset), data_p, asize);
774:     offset = offset + asize;
775:   }
776:   return(0);
777: }

779: PetscErrorCode DMSwarmDataBucketInsertPackedArray(DMSwarmDataBucket db,const PetscInt idx,void *data)
780: {
781:   PetscInt f;
782:   void *data_p;
783:   size_t offset;

787:   offset = 0;
788:   for (f = 0; f < db->nfields; ++f) {
789:     DMSwarmDataField df = db->field[f];

791:     data_p = (void*)( (char*)data + offset);
792:     DMSwarmDataFieldInsertPoint(df, idx, (void*)data_p);
793:     offset = offset + df->atomic_size;
794:   }
795:   return(0);
796: }