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