1 #include "../src/dm/impls/swarm/data_bucket.h" 2 3 /* string helpers */ 4 PetscErrorCode DMSwarmDataFieldStringInList(const char name[],const PetscInt N,const DMSwarmDataField gfield[],PetscBool *val) 5 { 6 PetscInt i; 7 PetscErrorCode ierr; 8 9 PetscFunctionBegin; 10 *val = PETSC_FALSE; 11 for (i = 0; i < N; ++i) { 12 PetscBool flg; 13 ierr = PetscStrcmp(name, gfield[i]->name, &flg);CHKERRQ(ierr); 14 if (flg) { 15 *val = PETSC_TRUE; 16 PetscFunctionReturn(0); 17 } 18 } 19 PetscFunctionReturn(0); 20 } 21 22 PetscErrorCode DMSwarmDataFieldStringFindInList(const char name[],const PetscInt N,const DMSwarmDataField gfield[],PetscInt *index) 23 { 24 PetscInt i; 25 PetscErrorCode ierr; 26 27 PetscFunctionBegin; 28 *index = -1; 29 for (i = 0; i < N; ++i) { 30 PetscBool flg; 31 ierr = PetscStrcmp(name, gfield[i]->name, &flg);CHKERRQ(ierr); 32 if (flg) { 33 *index = i; 34 PetscFunctionReturn(0); 35 } 36 } 37 PetscFunctionReturn(0); 38 } 39 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; 44 45 PetscFunctionBegin; 46 ierr = PetscMalloc(sizeof(struct _p_DMSwarmDataField), &df);CHKERRQ(ierr); 47 ierr = PetscMemzero(df, sizeof(struct _p_DMSwarmDataField));CHKERRQ(ierr); 48 ierr = PetscStrallocpy(registration_function, &df->registration_function);CHKERRQ(ierr); 49 ierr = PetscStrallocpy(name, &df->name);CHKERRQ(ierr); 50 df->atomic_size = size; 51 df->L = L; 52 df->bs = 1; 53 /* allocate something so we don't have to reallocate */ 54 ierr = PetscMalloc(size * L, &df->data);CHKERRQ(ierr); 55 ierr = PetscMemzero(df->data, size * L);CHKERRQ(ierr); 56 *DF = df; 57 PetscFunctionReturn(0); 58 } 59 60 PetscErrorCode DMSwarmDataFieldDestroy(DMSwarmDataField *DF) 61 { 62 DMSwarmDataField df = *DF; 63 PetscErrorCode ierr; 64 65 PetscFunctionBegin; 66 ierr = PetscFree(df->registration_function);CHKERRQ(ierr); 67 ierr = PetscFree(df->name);CHKERRQ(ierr); 68 ierr = PetscFree(df->data);CHKERRQ(ierr); 69 ierr = PetscFree(df);CHKERRQ(ierr); 70 *DF = NULL; 71 PetscFunctionReturn(0); 72 } 73 74 /* data bucket */ 75 PetscErrorCode DMSwarmDataBucketCreate(DMSwarmDataBucket *DB) 76 { 77 DMSwarmDataBucket db; 78 PetscErrorCode ierr; 79 80 PetscFunctionBegin; 81 ierr = PetscMalloc(sizeof(struct _p_DMSwarmDataBucket), &db);CHKERRQ(ierr); 82 ierr = PetscMemzero(db, sizeof(struct _p_DMSwarmDataBucket));CHKERRQ(ierr); 83 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 ierr = PetscMalloc1(1, &db->field);CHKERRQ(ierr); 91 *DB = db; 92 PetscFunctionReturn(0); 93 } 94 95 PetscErrorCode DMSwarmDataBucketDestroy(DMSwarmDataBucket *DB) 96 { 97 DMSwarmDataBucket db = *DB; 98 PetscInt f; 99 PetscErrorCode ierr; 100 101 PetscFunctionBegin; 102 /* release fields */ 103 for (f = 0; f < db->nfields; ++f) { 104 ierr = DMSwarmDataFieldDestroy(&db->field[f]);CHKERRQ(ierr); 105 } 106 /* this will catch the initially allocated objects in the event that no fields are registered */ 107 if (db->field != NULL) { 108 ierr = PetscFree(db->field);CHKERRQ(ierr); 109 } 110 ierr = PetscFree(db);CHKERRQ(ierr); 111 *DB = NULL; 112 PetscFunctionReturn(0); 113 } 114 115 PetscErrorCode DMSwarmDataBucketQueryForActiveFields(DMSwarmDataBucket db,PetscBool *any_active_fields) 116 { 117 PetscInt f; 118 119 PetscFunctionBegin; 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 PetscFunctionReturn(0); 125 } 126 } 127 PetscFunctionReturn(0); 128 } 129 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; 138 PetscErrorCode ierr; 139 140 PetscFunctionBegin; 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 ierr = DMSwarmDataFieldStringInList(field_name, db->nfields, (const DMSwarmDataField*) db->field, &val);CHKERRQ(ierr); 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 ierr = PetscRealloc(sizeof(DMSwarmDataField)*(db->nfields+1), &db->field);CHKERRQ(ierr); 153 /* add field */ 154 ierr = DMSwarmDataFieldCreate(registration_function, field_name, atomic_size, db->allocated, &fp);CHKERRQ(ierr); 155 db->field[db->nfields] = fp; 156 db->nfields++; 157 if (_gfield != NULL) { 158 *_gfield = fp; 159 } 160 PetscFunctionReturn(0); 161 } 162 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 ierr = PetscFree(location);\ 169 } 170 */ 171 172 PetscErrorCode DMSwarmDataBucketGetDMSwarmDataFieldByName(DMSwarmDataBucket db,const char name[],DMSwarmDataField *gfield) 173 { 174 PetscInt idx; 175 PetscBool found; 176 PetscErrorCode ierr; 177 178 PetscFunctionBegin; 179 ierr = DMSwarmDataFieldStringInList(name,db->nfields,(const DMSwarmDataField*)db->field,&found);CHKERRQ(ierr); 180 if (!found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot find DMSwarmDataField with name %s",name); 181 ierr = DMSwarmDataFieldStringFindInList(name,db->nfields,(const DMSwarmDataField*)db->field,&idx);CHKERRQ(ierr); 182 *gfield = db->field[idx]; 183 PetscFunctionReturn(0); 184 } 185 186 PetscErrorCode DMSwarmDataBucketQueryDMSwarmDataFieldByName(DMSwarmDataBucket db,const char name[],PetscBool *found) 187 { 188 PetscErrorCode ierr; 189 190 PetscFunctionBegin; 191 *found = PETSC_FALSE; 192 ierr = DMSwarmDataFieldStringInList(name,db->nfields,(const DMSwarmDataField*)db->field,found);CHKERRQ(ierr); 193 PetscFunctionReturn(0); 194 } 195 196 PetscErrorCode DMSwarmDataBucketFinalize(DMSwarmDataBucket db) 197 { 198 PetscFunctionBegin; 199 db->finalised = PETSC_TRUE; 200 PetscFunctionReturn(0); 201 } 202 203 PetscErrorCode DMSwarmDataFieldGetNumEntries(DMSwarmDataField df,PetscInt *sum) 204 { 205 PetscFunctionBegin; 206 *sum = df->L; 207 PetscFunctionReturn(0); 208 } 209 210 PetscErrorCode DMSwarmDataFieldSetBlockSize(DMSwarmDataField df,PetscInt blocksize) 211 { 212 PetscFunctionBegin; 213 df->bs = blocksize; 214 PetscFunctionReturn(0); 215 } 216 217 PetscErrorCode DMSwarmDataFieldSetSize(DMSwarmDataField df,const PetscInt new_L) 218 { 219 PetscErrorCode ierr; 220 221 PetscFunctionBegin; 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) PetscFunctionReturn(0); 224 if (new_L > df->L) { 225 ierr = PetscRealloc(df->atomic_size * (new_L), &df->data);CHKERRQ(ierr); 226 /* init new contents */ 227 ierr = PetscMemzero(( ((char*)df->data)+df->L*df->atomic_size), (new_L-df->L)*df->atomic_size);CHKERRQ(ierr); 228 } else { 229 /* reallocate pointer list, add +1 in case new_L = 0 */ 230 ierr = PetscRealloc(df->atomic_size * (new_L+1), &df->data);CHKERRQ(ierr); 231 } 232 df->L = new_L; 233 PetscFunctionReturn(0); 234 } 235 236 PetscErrorCode DMSwarmDataFieldZeroBlock(DMSwarmDataField df,const PetscInt start,const PetscInt end) 237 { 238 PetscErrorCode ierr; 239 240 PetscFunctionBegin; 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 ierr = PetscMemzero((((char*)df->data)+start*df->atomic_size), (end-start)*df->atomic_size);CHKERRQ(ierr); 245 PetscFunctionReturn(0); 246 } 247 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; 255 PetscErrorCode ierr; 256 257 PetscFunctionBegin; 258 if (db->finalised == PETSC_FALSE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"You must call DMSwarmDataBucketFinalize() before DMSwarmDataBucketSetSizes()"); 259 ierr = DMSwarmDataBucketQueryForActiveFields(db,&any_active_fields);CHKERRQ(ierr); 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"); 261 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 ierr = DMSwarmDataFieldSetSize(db->field[f], new_allocated);CHKERRQ(ierr); 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 ierr = DMSwarmDataFieldSetSize(db->field[f], new_allocated);CHKERRQ(ierr); 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 ierr = DMSwarmDataFieldZeroBlock(field, db->L,db->allocated);CHKERRQ(ierr); 297 } 298 PetscFunctionReturn(0); 299 } 300 301 PetscErrorCode DMSwarmDataBucketSetInitialSizes(DMSwarmDataBucket db,const PetscInt L,const PetscInt buffer) 302 { 303 PetscInt f; 304 PetscErrorCode ierr; 305 306 PetscFunctionBegin; 307 ierr = DMSwarmDataBucketSetSizes(db,L,buffer);CHKERRQ(ierr); 308 for (f = 0; f < db->nfields; ++f) { 309 DMSwarmDataField field = db->field[f]; 310 ierr = DMSwarmDataFieldZeroBlock(field,0,db->allocated);CHKERRQ(ierr); 311 } 312 PetscFunctionReturn(0); 313 } 314 315 PetscErrorCode DMSwarmDataBucketGetSizes(DMSwarmDataBucket db,PetscInt *L,PetscInt *buffer,PetscInt *allocated) 316 { 317 PetscFunctionBegin; 318 if (L) {*L = db->L;} 319 if (buffer) {*buffer = db->buffer;} 320 if (allocated) {*allocated = db->allocated;} 321 PetscFunctionReturn(0); 322 } 323 324 PetscErrorCode DMSwarmDataBucketGetGlobalSizes(MPI_Comm comm,DMSwarmDataBucket db,PetscInt *L,PetscInt *buffer,PetscInt *allocated) 325 { 326 PetscInt ierr; 327 328 PetscFunctionBegin; 329 if (L) { ierr = MPI_Allreduce(&db->L,L,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); } 330 if (buffer) { ierr = MPI_Allreduce(&db->buffer,buffer,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); } 331 if (allocated) { ierr = MPI_Allreduce(&db->allocated,allocated,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); } 332 PetscFunctionReturn(0); 333 } 334 335 PetscErrorCode DMSwarmDataBucketGetDMSwarmDataFields(DMSwarmDataBucket db,PetscInt *L,DMSwarmDataField *fields[]) 336 { 337 PetscFunctionBegin; 338 if (L) {*L = db->nfields;} 339 if (fields) {*fields = db->field;} 340 PetscFunctionReturn(0); 341 } 342 343 PetscErrorCode DMSwarmDataFieldGetAccess(const DMSwarmDataField gfield) 344 { 345 PetscFunctionBegin; 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 PetscFunctionReturn(0); 349 } 350 351 PetscErrorCode DMSwarmDataFieldAccessPoint(const DMSwarmDataField gfield,const PetscInt pid,void **ctx_p) 352 { 353 PetscFunctionBegin; 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 PetscFunctionReturn(0); 364 } 365 366 PetscErrorCode DMSwarmDataFieldAccessPointOffset(const DMSwarmDataField gfield,const size_t offset,const PetscInt pid,void **ctx_p) 367 { 368 PetscFunctionBegin; 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 PetscFunctionReturn(0); 382 } 383 384 PetscErrorCode DMSwarmDataFieldRestoreAccess(DMSwarmDataField gfield) 385 { 386 PetscFunctionBegin; 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 PetscFunctionReturn(0); 390 } 391 392 PetscErrorCode DMSwarmDataFieldVerifyAccess(const DMSwarmDataField gfield,const size_t size) 393 { 394 PetscFunctionBegin; 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 PetscFunctionReturn(0); 399 } 400 401 PetscErrorCode DMSwarmDataFieldGetAtomicSize(const DMSwarmDataField gfield,size_t *size) 402 { 403 PetscFunctionBegin; 404 if (size) {*size = gfield->atomic_size;} 405 PetscFunctionReturn(0); 406 } 407 408 PetscErrorCode DMSwarmDataFieldGetEntries(const DMSwarmDataField gfield,void **data) 409 { 410 PetscFunctionBegin; 411 if (data) {*data = gfield->data;} 412 PetscFunctionReturn(0); 413 } 414 415 PetscErrorCode DMSwarmDataFieldRestoreEntries(const DMSwarmDataField gfield,void **data) 416 { 417 PetscFunctionBegin; 418 if (data) {*data = NULL;} 419 PetscFunctionReturn(0); 420 } 421 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; 427 PetscErrorCode ierr; 428 429 PetscFunctionBegin; 430 for (f = 0; f < xb->nfields; ++f) { 431 void *dest; 432 void *src; 433 434 ierr = DMSwarmDataFieldGetAccess(xb->field[f]);CHKERRQ(ierr); 435 if (xb != yb) { ierr = DMSwarmDataFieldGetAccess( yb->field[f]);CHKERRQ(ierr); } 436 ierr = DMSwarmDataFieldAccessPoint(xb->field[f],pid_x, &src);CHKERRQ(ierr); 437 ierr = DMSwarmDataFieldAccessPoint(yb->field[f],pid_y, &dest);CHKERRQ(ierr); 438 ierr = PetscMemcpy(dest, src, xb->field[f]->atomic_size);CHKERRQ(ierr); 439 ierr = DMSwarmDataFieldRestoreAccess(xb->field[f]);CHKERRQ(ierr); 440 if (xb != yb) {ierr = DMSwarmDataFieldRestoreAccess(yb->field[f]);CHKERRQ(ierr);} 441 } 442 PetscFunctionReturn(0); 443 } 444 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; 450 PetscErrorCode ierr; 451 452 PetscFunctionBegin; 453 ierr = DMSwarmDataBucketCreate(DB);CHKERRQ(ierr); 454 /* copy contents of DBIn */ 455 ierr = DMSwarmDataBucketGetDMSwarmDataFields(DBIn,&nfields,&fields);CHKERRQ(ierr); 456 ierr = DMSwarmDataBucketGetSizes(DBIn,&L,&buffer,&allocated);CHKERRQ(ierr); 457 for (f = 0; f < nfields; ++f) { 458 ierr = DMSwarmDataBucketRegisterField(*DB,"DMSwarmDataBucketCreateFromSubset",fields[f]->name,fields[f]->atomic_size,NULL);CHKERRQ(ierr); 459 } 460 ierr = DMSwarmDataBucketFinalize(*DB);CHKERRQ(ierr); 461 ierr = DMSwarmDataBucketSetSizes(*DB,L,buffer);CHKERRQ(ierr); 462 /* now copy the desired guys from DBIn => DB */ 463 for (p = 0; p < N; ++p) { 464 ierr = DMSwarmDataBucketCopyPoint(DBIn,list[p], *DB,p);CHKERRQ(ierr); 465 } 466 PetscFunctionReturn(0); 467 } 468 469 /* insert into an exisitng location */ 470 PetscErrorCode DMSwarmDataFieldInsertPoint(const DMSwarmDataField field,const PetscInt index,const void *ctx) 471 { 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 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 ierr = PetscMemcpy(DMSWARM_DATAFIELD_point_access(field->data,index,field->atomic_size), ctx, field->atomic_size);CHKERRQ(ierr); 481 PetscFunctionReturn(0); 482 } 483 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; 489 PetscErrorCode ierr; 490 491 PetscFunctionBegin; 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 ierr = DMSwarmDataBucketQueryForActiveFields(db,&any_active_fields);CHKERRQ(ierr); 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]; 505 506 /* copy then remove */ 507 ierr = DMSwarmDataFieldCopyPoint(db->L-1, field, index, field);CHKERRQ(ierr); 508 /* DMSwarmDataFieldZeroPoint(field,index); */ 509 } 510 } 511 /* decrement size */ 512 /* this will zero out an crap at the end of the list */ 513 ierr = DMSwarmDataBucketRemovePoint(db);CHKERRQ(ierr); 514 PetscFunctionReturn(0); 515 } 516 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 { 521 PetscErrorCode ierr; 522 523 PetscFunctionBegin; 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 ierr = 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);CHKERRQ(ierr); 533 PetscFunctionReturn(0); 534 } 535 536 537 /* zero only the datafield at this point */ 538 PetscErrorCode DMSwarmDataFieldZeroPoint(const DMSwarmDataField field,const PetscInt index) 539 { 540 PetscErrorCode ierr; 541 542 PetscFunctionBegin; 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 ierr = PetscMemzero(DMSWARM_DATAFIELD_point_access(field->data,index,field->atomic_size), field->atomic_size);CHKERRQ(ierr); 549 PetscFunctionReturn(0); 550 } 551 552 /* zero ALL data for this point */ 553 PetscErrorCode DMSwarmDataBucketZeroPoint(const DMSwarmDataBucket db,const PetscInt index) 554 { 555 PetscInt f; 556 PetscErrorCode ierr; 557 558 PetscFunctionBegin; 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 ierr = DMSwarmDataFieldZeroPoint(field,index);CHKERRQ(ierr); 565 } 566 PetscFunctionReturn(0); 567 } 568 569 /* increment */ 570 PetscErrorCode DMSwarmDataBucketAddPoint(DMSwarmDataBucket db) 571 { 572 PetscErrorCode ierr; 573 574 PetscFunctionBegin; 575 ierr = DMSwarmDataBucketSetSizes(db,db->L+1,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr); 576 PetscFunctionReturn(0); 577 } 578 579 /* decrement */ 580 PetscErrorCode DMSwarmDataBucketRemovePoint(DMSwarmDataBucket db) 581 { 582 PetscErrorCode ierr; 583 584 PetscFunctionBegin; 585 ierr = DMSwarmDataBucketSetSizes(db,db->L-1,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr); 586 PetscFunctionReturn(0); 587 } 588 589 PetscErrorCode DMSwarmDataBucketView_stdout(MPI_Comm comm,DMSwarmDataBucket db) 590 { 591 PetscInt f; 592 double memory_usage_total,memory_usage_total_local = 0.0; 593 PetscErrorCode ierr; 594 595 PetscFunctionBegin; 596 ierr = PetscPrintf(comm,"DMSwarmDataBucketView: \n");CHKERRQ(ierr); 597 ierr = PetscPrintf(comm," L = %D \n", db->L);CHKERRQ(ierr); 598 ierr = PetscPrintf(comm," buffer = %D \n", db->buffer);CHKERRQ(ierr); 599 ierr = PetscPrintf(comm," allocated = %D \n", db->allocated);CHKERRQ(ierr); 600 ierr = PetscPrintf(comm," nfields registered = %D \n", db->nfields);CHKERRQ(ierr); 601 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 ierr = MPI_Allreduce(&memory_usage_total_local,&memory_usage_total,1,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr); 607 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 ierr = PetscPrintf(comm," [%3D] %15s : Mem. usage = %1.2e (MB) [rank0]\n", f, db->field[f]->name, memory_usage_f );CHKERRQ(ierr); 611 ierr = PetscPrintf(comm," blocksize = %D \n", db->field[f]->bs);CHKERRQ(ierr); 612 if (db->field[f]->bs != 1) { 613 ierr = PetscPrintf(comm," atomic size = %zu [full block, bs=%D]\n", db->field[f]->atomic_size,db->field[f]->bs);CHKERRQ(ierr); 614 ierr = PetscPrintf(comm," atomic size/item = %zu \n", db->field[f]->atomic_size/db->field[f]->bs);CHKERRQ(ierr); 615 } else { 616 ierr = PetscPrintf(comm," atomic size = %zu \n", db->field[f]->atomic_size);CHKERRQ(ierr); 617 } 618 } 619 ierr = PetscPrintf(comm," Total mem. usage = %1.2e (MB) (collective)\n", memory_usage_total);CHKERRQ(ierr); 620 PetscFunctionReturn(0); 621 } 622 623 PetscErrorCode DMSwarmDataBucketView_SEQ(MPI_Comm comm,DMSwarmDataBucket db,const char filename[],DMSwarmDataBucketViewType type) 624 { 625 PetscErrorCode ierr; 626 627 PetscFunctionBegin; 628 switch (type) { 629 case DATABUCKET_VIEW_STDOUT: 630 ierr = DMSwarmDataBucketView_stdout(PETSC_COMM_SELF,db);CHKERRQ(ierr); 631 break; 632 case DATABUCKET_VIEW_ASCII: 633 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for ascii output"); 634 break; 635 case DATABUCKET_VIEW_BINARY: 636 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for binary output"); 637 break; 638 case DATABUCKET_VIEW_HDF5: 639 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for HDF5 output"); 640 break; 641 default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested"); 642 } 643 PetscFunctionReturn(0); 644 } 645 646 PetscErrorCode DMSwarmDataBucketView_MPI(MPI_Comm comm,DMSwarmDataBucket db,const char filename[],DMSwarmDataBucketViewType type) 647 { 648 PetscErrorCode ierr; 649 650 PetscFunctionBegin; 651 switch (type) { 652 case DATABUCKET_VIEW_STDOUT: 653 ierr = DMSwarmDataBucketView_stdout(comm,db);CHKERRQ(ierr); 654 break; 655 case DATABUCKET_VIEW_ASCII: 656 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for ascii output"); 657 break; 658 case DATABUCKET_VIEW_BINARY: 659 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for binary output"); 660 break; 661 case DATABUCKET_VIEW_HDF5: 662 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for HDF5 output"); 663 break; 664 default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer method requested"); 665 } 666 PetscFunctionReturn(0); 667 } 668 669 PetscErrorCode DMSwarmDataBucketView(MPI_Comm comm,DMSwarmDataBucket db,const char filename[],DMSwarmDataBucketViewType type) 670 { 671 PetscMPIInt size; 672 PetscErrorCode ierr; 673 674 PetscFunctionBegin; 675 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 676 if (size == 1) { 677 ierr = DMSwarmDataBucketView_SEQ(comm,db,filename,type);CHKERRQ(ierr); 678 } else { 679 ierr = DMSwarmDataBucketView_MPI(comm,db,filename,type);CHKERRQ(ierr); 680 } 681 PetscFunctionReturn(0); 682 } 683 684 PetscErrorCode DMSwarmDataBucketDuplicateFields(DMSwarmDataBucket dbA,DMSwarmDataBucket *dbB) 685 { 686 DMSwarmDataBucket db2; 687 PetscInt f; 688 PetscErrorCode ierr; 689 690 PetscFunctionBegin; 691 ierr = DMSwarmDataBucketCreate(&db2);CHKERRQ(ierr); 692 /* copy contents from dbA into db2 */ 693 for (f = 0; f < dbA->nfields; ++f) { 694 DMSwarmDataField field; 695 size_t atomic_size; 696 char *name; 697 698 field = dbA->field[f]; 699 atomic_size = field->atomic_size; 700 name = field->name; 701 ierr = DMSwarmDataBucketRegisterField(db2,"DMSwarmDataBucketDuplicateFields",name,atomic_size,NULL);CHKERRQ(ierr); 702 } 703 ierr = DMSwarmDataBucketFinalize(db2);CHKERRQ(ierr); 704 ierr = DMSwarmDataBucketSetInitialSizes(db2,0,1000);CHKERRQ(ierr); 705 *dbB = db2; 706 PetscFunctionReturn(0); 707 } 708 709 /* 710 Insert points from db2 into db1 711 db1 <<== db2 712 */ 713 PetscErrorCode DMSwarmDataBucketInsertValues(DMSwarmDataBucket db1,DMSwarmDataBucket db2) 714 { 715 PetscInt n_mp_points1,n_mp_points2; 716 PetscInt n_mp_points1_new,p; 717 PetscErrorCode ierr; 718 719 PetscFunctionBegin; 720 ierr = DMSwarmDataBucketGetSizes(db1,&n_mp_points1,0,0);CHKERRQ(ierr); 721 ierr = DMSwarmDataBucketGetSizes(db2,&n_mp_points2,0,0);CHKERRQ(ierr); 722 n_mp_points1_new = n_mp_points1 + n_mp_points2; 723 ierr = DMSwarmDataBucketSetSizes(db1,n_mp_points1_new,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr); 724 for (p = 0; p < n_mp_points2; ++p) { 725 /* db1 <<== db2 */ 726 ierr = DMSwarmDataBucketCopyPoint(db2,p, db1,(n_mp_points1 + p));CHKERRQ(ierr); 727 } 728 PetscFunctionReturn(0); 729 } 730 731 /* helpers for parallel send/recv */ 732 PetscErrorCode DMSwarmDataBucketCreatePackedArray(DMSwarmDataBucket db,size_t *bytes,void **buf) 733 { 734 PetscInt f; 735 size_t sizeof_marker_contents; 736 void *buffer; 737 PetscErrorCode ierr; 738 739 PetscFunctionBegin; 740 sizeof_marker_contents = 0; 741 for (f = 0; f < db->nfields; ++f) { 742 DMSwarmDataField df = db->field[f]; 743 sizeof_marker_contents += df->atomic_size; 744 } 745 ierr = PetscMalloc(sizeof_marker_contents, &buffer);CHKERRQ(ierr); 746 ierr = PetscMemzero(buffer, sizeof_marker_contents);CHKERRQ(ierr); 747 if (bytes) {*bytes = sizeof_marker_contents;} 748 if (buf) {*buf = buffer;} 749 PetscFunctionReturn(0); 750 } 751 752 PetscErrorCode DMSwarmDataBucketDestroyPackedArray(DMSwarmDataBucket db,void **buf) 753 { 754 PetscErrorCode ierr; 755 756 PetscFunctionBegin; 757 if (buf) { 758 ierr = PetscFree(*buf);CHKERRQ(ierr); 759 *buf = NULL; 760 } 761 PetscFunctionReturn(0); 762 } 763 764 PetscErrorCode DMSwarmDataBucketFillPackedArray(DMSwarmDataBucket db,const PetscInt index,void *buf) 765 { 766 PetscInt f; 767 void *data, *data_p; 768 size_t asize, offset; 769 PetscErrorCode ierr; 770 771 PetscFunctionBegin; 772 offset = 0; 773 for (f = 0; f < db->nfields; ++f) { 774 DMSwarmDataField df = db->field[f]; 775 776 asize = df->atomic_size; 777 data = (void*)( df->data ); 778 data_p = (void*)( (char*)data + index*asize ); 779 ierr = PetscMemcpy((void*)((char*)buf + offset), data_p, asize);CHKERRQ(ierr); 780 offset = offset + asize; 781 } 782 PetscFunctionReturn(0); 783 } 784 785 PetscErrorCode DMSwarmDataBucketInsertPackedArray(DMSwarmDataBucket db,const PetscInt idx,void *data) 786 { 787 PetscInt f; 788 void *data_p; 789 size_t offset; 790 PetscErrorCode ierr; 791 792 PetscFunctionBegin; 793 offset = 0; 794 for (f = 0; f < db->nfields; ++f) { 795 DMSwarmDataField df = db->field[f]; 796 797 data_p = (void*)( (char*)data + offset ); 798 ierr = DMSwarmDataFieldInsertPoint(df, idx, (void*)data_p);CHKERRQ(ierr); 799 offset = offset + df->atomic_size; 800 } 801 PetscFunctionReturn(0); 802 } 803