1 #include <petsc/private/viewerimpl.h> 2 #include <petsc/private/viewerhdf5impl.h> 3 #include <petscviewerhdf5.h> /*I "petscviewerhdf5.h" I*/ 4 5 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer, const char[], PetscBool, PetscBool*, H5O_type_t*); 6 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer, const char[], const char[], PetscBool*); 7 8 static PetscErrorCode PetscViewerHDF5GetAbsolutePath_Internal(PetscViewer viewer, const char path[], char *abspath[]) 9 { 10 PetscBool relative = PETSC_FALSE; 11 const char *group; 12 char buf[PETSC_MAX_PATH_LEN] = ""; 13 PetscErrorCode ierr; 14 15 PetscFunctionBegin; 16 ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr); 17 ierr = PetscViewerHDF5PathIsRelative(path, PETSC_TRUE, &relative);CHKERRQ(ierr); 18 if (relative) { 19 ierr = PetscStrcpy(buf, group);CHKERRQ(ierr); 20 ierr = PetscStrcat(buf, "/");CHKERRQ(ierr); 21 ierr = PetscStrcat(buf, path);CHKERRQ(ierr); 22 ierr = PetscStrallocpy(buf, abspath);CHKERRQ(ierr); 23 } else { 24 ierr = PetscStrallocpy(path, abspath);CHKERRQ(ierr); 25 } 26 PetscFunctionReturn(0); 27 } 28 29 static PetscErrorCode PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer, PetscObject obj) 30 { 31 PetscBool has; 32 PetscErrorCode ierr; 33 34 PetscFunctionBegin; 35 ierr = PetscViewerHDF5HasObject(viewer, obj, &has);CHKERRQ(ierr); 36 if (!has) { 37 const char *group; 38 ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr); 39 SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) \"%s\" not stored in group %s", obj->name, group ? group : "/"); 40 } 41 PetscFunctionReturn(0); 42 } 43 44 static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v) 45 { 46 PetscErrorCode ierr; 47 PetscBool flg = PETSC_FALSE, set; 48 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data; 49 50 PetscFunctionBegin; 51 ierr = PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");CHKERRQ(ierr); 52 ierr = PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);CHKERRQ(ierr); 53 ierr = PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);CHKERRQ(ierr); 54 ierr = PetscOptionsBool("-viewer_hdf5_collective","Enable collective transfer mode","PetscViewerHDF5SetCollective",flg,&flg,&set);CHKERRQ(ierr); 55 if (set) {ierr = PetscViewerHDF5SetCollective(v,flg);CHKERRQ(ierr);} 56 ierr = PetscOptionsTail();CHKERRQ(ierr); 57 PetscFunctionReturn(0); 58 } 59 60 static PetscErrorCode PetscViewerView_HDF5(PetscViewer v,PetscViewer viewer) 61 { 62 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data; 63 PetscBool flg; 64 PetscErrorCode ierr; 65 66 PetscFunctionBegin; 67 if (hdf5->filename) { 68 ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",hdf5->filename);CHKERRQ(ierr); 69 } 70 ierr = PetscViewerASCIIPrintf(viewer,"Vectors with blocksize 1 saved as 2D datasets: %s\n",PetscBools[hdf5->basedimension2]);CHKERRQ(ierr); 71 ierr = PetscViewerASCIIPrintf(viewer,"Enforce single precision storage: %s\n",PetscBools[hdf5->spoutput]);CHKERRQ(ierr); 72 ierr = PetscViewerHDF5GetCollective(v,&flg);CHKERRQ(ierr); 73 ierr = PetscViewerASCIIPrintf(viewer,"MPI-IO transfer mode: %s\n",flg ? "collective" : "independent");CHKERRQ(ierr); 74 PetscFunctionReturn(0); 75 } 76 77 static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer) 78 { 79 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data; 80 PetscErrorCode ierr; 81 82 PetscFunctionBegin; 83 ierr = PetscFree(hdf5->filename);CHKERRQ(ierr); 84 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 85 PetscFunctionReturn(0); 86 } 87 88 static PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer) 89 { 90 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 91 PetscErrorCode ierr; 92 93 PetscFunctionBegin; 94 PetscStackCallHDF5(H5Pclose,(hdf5->dxpl_id)); 95 ierr = PetscViewerFileClose_HDF5(viewer);CHKERRQ(ierr); 96 while (hdf5->groups) { 97 PetscViewerHDF5GroupList *tmp = hdf5->groups->next; 98 99 ierr = PetscFree(hdf5->groups->name);CHKERRQ(ierr); 100 ierr = PetscFree(hdf5->groups);CHKERRQ(ierr); 101 hdf5->groups = tmp; 102 } 103 ierr = PetscFree(hdf5);CHKERRQ(ierr); 104 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr); 105 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr); 106 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr); 107 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetBaseDimension2_C",NULL);CHKERRQ(ierr); 108 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetSPOutput_C",NULL);CHKERRQ(ierr); 109 PetscFunctionReturn(0); 110 } 111 112 static PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type) 113 { 114 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 115 116 PetscFunctionBegin; 117 hdf5->btype = type; 118 PetscFunctionReturn(0); 119 } 120 121 static PetscErrorCode PetscViewerFileGetMode_HDF5(PetscViewer viewer, PetscFileMode *type) 122 { 123 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 124 125 PetscFunctionBegin; 126 *type = hdf5->btype; 127 PetscFunctionReturn(0); 128 } 129 130 static PetscErrorCode PetscViewerHDF5SetBaseDimension2_HDF5(PetscViewer viewer, PetscBool flg) 131 { 132 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 133 134 PetscFunctionBegin; 135 hdf5->basedimension2 = flg; 136 PetscFunctionReturn(0); 137 } 138 139 /*@ 140 PetscViewerHDF5SetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a 141 dimension of 2. 142 143 Logically Collective on PetscViewer 144 145 Input Parameters: 146 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored 147 - flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1 148 149 Options Database: 150 . -viewer_hdf5_base_dimension2 - turns on (true) or off (false) using a dimension of 2 in the HDF5 file even if the bs/dof of the vector is 1 151 152 153 Notes: 154 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof 155 of one when the dimension is lower. Others think the option is crazy. 156 157 Level: intermediate 158 159 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen() 160 161 @*/ 162 PetscErrorCode PetscViewerHDF5SetBaseDimension2(PetscViewer viewer,PetscBool flg) 163 { 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 168 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetBaseDimension2_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr); 169 PetscFunctionReturn(0); 170 } 171 172 /*@ 173 PetscViewerHDF5GetBaseDimension2 - Vectors of 1 dimension (i.e. bs/dof is 1) will be saved in the HDF5 file with a 174 dimension of 2. 175 176 Logically Collective on PetscViewer 177 178 Input Parameter: 179 . viewer - the PetscViewer, must be of type HDF5 180 181 Output Parameter: 182 . flg - if PETSC_TRUE the vector will always have at least a dimension of 2 even if that first dimension is of size 1 183 184 Notes: 185 Setting this option allegedly makes code that reads the HDF5 in easier since they do not have a "special case" of a bs/dof 186 of one when the dimension is lower. Others think the option is crazy. 187 188 Level: intermediate 189 190 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen() 191 192 @*/ 193 PetscErrorCode PetscViewerHDF5GetBaseDimension2(PetscViewer viewer,PetscBool *flg) 194 { 195 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 196 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 199 *flg = hdf5->basedimension2; 200 PetscFunctionReturn(0); 201 } 202 203 static PetscErrorCode PetscViewerHDF5SetSPOutput_HDF5(PetscViewer viewer, PetscBool flg) 204 { 205 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 206 207 PetscFunctionBegin; 208 hdf5->spoutput = flg; 209 PetscFunctionReturn(0); 210 } 211 212 /*@ 213 PetscViewerHDF5SetSPOutput - Data is written to disk in single precision even if PETSc is 214 compiled with double precision PetscReal. 215 216 Logically Collective on PetscViewer 217 218 Input Parameters: 219 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored 220 - flg - if PETSC_TRUE the data will be written to disk with single precision 221 222 Options Database: 223 . -viewer_hdf5_sp_output - turns on (true) or off (false) output in single precision 224 225 226 Notes: 227 Setting this option does not make any difference if PETSc is compiled with single precision 228 in the first place. It does not affect reading datasets (HDF5 handle this internally). 229 230 Level: intermediate 231 232 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(), 233 PetscReal 234 235 @*/ 236 PetscErrorCode PetscViewerHDF5SetSPOutput(PetscViewer viewer,PetscBool flg) 237 { 238 PetscErrorCode ierr; 239 240 PetscFunctionBegin; 241 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 242 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetSPOutput_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr); 243 PetscFunctionReturn(0); 244 } 245 246 /*@ 247 PetscViewerHDF5GetSPOutput - Data is written to disk in single precision even if PETSc is 248 compiled with double precision PetscReal. 249 250 Logically Collective on PetscViewer 251 252 Input Parameter: 253 . viewer - the PetscViewer, must be of type HDF5 254 255 Output Parameter: 256 . flg - if PETSC_TRUE the data will be written to disk with single precision 257 258 Notes: 259 Setting this option does not make any difference if PETSc is compiled with single precision 260 in the first place. It does not affect reading datasets (HDF5 handle this internally). 261 262 Level: intermediate 263 264 .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(), 265 PetscReal 266 267 @*/ 268 PetscErrorCode PetscViewerHDF5GetSPOutput(PetscViewer viewer,PetscBool *flg) 269 { 270 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 271 272 PetscFunctionBegin; 273 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 274 *flg = hdf5->spoutput; 275 PetscFunctionReturn(0); 276 } 277 278 static PetscErrorCode PetscViewerHDF5SetCollective_HDF5(PetscViewer viewer, PetscBool flg) 279 { 280 PetscFunctionBegin; 281 /* H5FD_MPIO_COLLECTIVE is wrong in hdf5 1.10.2, and is the same as H5FD_MPIO_INDEPENDENT in earlier versions 282 - see e.g. https://gitlab.cosma.dur.ac.uk/swift/swiftsim/issues/431 */ 283 #if H5_VERSION_GE(1,10,3) && defined(H5_HAVE_PARALLEL) 284 { 285 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 286 PetscStackCallHDF5(H5Pset_dxpl_mpio,(hdf5->dxpl_id, flg ? H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT)); 287 } 288 #else 289 if (flg) { 290 PetscErrorCode ierr; 291 ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer), "Warning: PetscViewerHDF5SetCollective(viewer,PETSC_TRUE) is ignored for HDF5 versions prior to 1.10.3 or if built without MPI support\n");CHKERRQ(ierr); 292 } 293 #endif 294 PetscFunctionReturn(0); 295 } 296 297 /*@ 298 PetscViewerHDF5SetCollective - Use collective MPI-IO transfer mode for HDF5 reads and writes. 299 300 Logically Collective; flg must contain common value 301 302 Input Parameters: 303 + viewer - the PetscViewer; if it is not hdf5 then this command is ignored 304 - flg - PETSC_TRUE for collective mode; PETSC_FALSE for independent mode (default) 305 306 Options Database: 307 . -viewer_hdf5_collective - turns on (true) or off (false) collective transfers 308 309 Notes: 310 Collective mode gives the MPI-IO layer underneath HDF5 a chance to do some additional collective optimizations and hence can perform better. 311 However, this works correctly only since HDF5 1.10.3 and if HDF5 is installed for MPI; hence, we ignore this setting for older versions. 312 313 Developer notes: 314 In the HDF5 layer, PETSC_TRUE / PETSC_FALSE means H5Pset_dxpl_mpio() is called with H5FD_MPIO_COLLECTIVE / H5FD_MPIO_INDEPENDENT, respectively. 315 This in turn means use of MPI_File_{read,write}_all / MPI_File_{read,write} in the MPI-IO layer, respectively. 316 See HDF5 documentation and MPI-IO documentation for details. 317 318 Level: intermediate 319 320 .seealso: PetscViewerHDF5GetCollective(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerHDF5Open() 321 322 @*/ 323 PetscErrorCode PetscViewerHDF5SetCollective(PetscViewer viewer,PetscBool flg) 324 { 325 PetscErrorCode ierr; 326 327 PetscFunctionBegin; 328 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 329 PetscValidLogicalCollectiveBool(viewer,flg,2); 330 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetCollective_C",(PetscViewer,PetscBool),(viewer,flg));CHKERRQ(ierr); 331 PetscFunctionReturn(0); 332 } 333 334 static PetscErrorCode PetscViewerHDF5GetCollective_HDF5(PetscViewer viewer, PetscBool *flg) 335 { 336 #if defined(H5_HAVE_PARALLEL) 337 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 338 H5FD_mpio_xfer_t mode; 339 #endif 340 341 PetscFunctionBegin; 342 #if !defined(H5_HAVE_PARALLEL) 343 *flg = PETSC_FALSE; 344 #else 345 PetscStackCallHDF5(H5Pget_dxpl_mpio,(hdf5->dxpl_id, &mode)); 346 *flg = (mode == H5FD_MPIO_COLLECTIVE) ? PETSC_TRUE : PETSC_FALSE; 347 #endif 348 PetscFunctionReturn(0); 349 } 350 351 /*@ 352 PetscViewerHDF5GetCollective - Return flag whether collective MPI-IO transfer mode is used for HDF5 reads and writes. 353 354 Not Collective 355 356 Input Parameters: 357 . viewer - the HDF5 PetscViewer 358 359 Output Parameters: 360 . flg - the flag 361 362 Level: intermediate 363 364 Notes: 365 This setting works correctly only since HDF5 1.10.3 and if HDF5 was installed for MPI. For older versions, PETSC_FALSE will be always returned. 366 For more details, see PetscViewerHDF5SetCollective(). 367 368 .seealso: PetscViewerHDF5SetCollective(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerHDF5Open() 369 370 @*/ 371 PetscErrorCode PetscViewerHDF5GetCollective(PetscViewer viewer,PetscBool *flg) 372 { 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 377 PetscValidBoolPointer(flg,2); 378 379 ierr = PetscUseMethod(viewer,"PetscViewerHDF5GetCollective_C",(PetscViewer,PetscBool*),(viewer,flg));CHKERRQ(ierr); 380 PetscFunctionReturn(0); 381 } 382 383 static PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[]) 384 { 385 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 386 hid_t plist_id; 387 PetscErrorCode ierr; 388 389 PetscFunctionBegin; 390 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 391 if (hdf5->filename) {ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);} 392 ierr = PetscStrallocpy(name, &hdf5->filename);CHKERRQ(ierr); 393 /* Set up file access property list with parallel I/O access */ 394 PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS)); 395 #if defined(H5_HAVE_PARALLEL) 396 PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), MPI_INFO_NULL)); 397 #endif 398 /* Create or open the file collectively */ 399 switch (hdf5->btype) { 400 case FILE_MODE_READ: 401 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id)); 402 break; 403 case FILE_MODE_APPEND: 404 case FILE_MODE_UPDATE: 405 { 406 PetscBool flg; 407 ierr = PetscTestFile(hdf5->filename, 'r', &flg);CHKERRQ(ierr); 408 if (flg) PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id)); 409 else PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_EXCL, H5P_DEFAULT, plist_id)); 410 break; 411 } 412 case FILE_MODE_WRITE: 413 PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id)); 414 break; 415 case FILE_MODE_UNDEFINED: 416 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 417 default: 418 SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[hdf5->btype]); 419 } 420 if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name); 421 PetscStackCallHDF5(H5Pclose,(plist_id)); 422 PetscFunctionReturn(0); 423 } 424 425 static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name) 426 { 427 PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data; 428 429 PetscFunctionBegin; 430 *name = vhdf5->filename; 431 PetscFunctionReturn(0); 432 } 433 434 static PetscErrorCode PetscViewerSetUp_HDF5(PetscViewer viewer) 435 { 436 /* 437 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 438 PetscErrorCode ierr; 439 */ 440 441 PetscFunctionBegin; 442 PetscFunctionReturn(0); 443 } 444 445 /*MC 446 PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file 447 448 449 .seealso: PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET, 450 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING, 451 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, 452 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType() 453 454 Level: beginner 455 M*/ 456 457 PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v) 458 { 459 PetscViewer_HDF5 *hdf5; 460 PetscErrorCode ierr; 461 462 PetscFunctionBegin; 463 ierr = PetscNewLog(v,&hdf5);CHKERRQ(ierr); 464 465 v->data = (void*) hdf5; 466 v->ops->destroy = PetscViewerDestroy_HDF5; 467 v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5; 468 v->ops->setup = PetscViewerSetUp_HDF5; 469 v->ops->view = PetscViewerView_HDF5; 470 v->ops->flush = NULL; 471 hdf5->btype = FILE_MODE_UNDEFINED; 472 hdf5->filename = NULL; 473 hdf5->timestep = -1; 474 hdf5->groups = NULL; 475 476 PetscStackCallHDF5Return(hdf5->dxpl_id,H5Pcreate,(H5P_DATASET_XFER)); 477 478 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);CHKERRQ(ierr); 479 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);CHKERRQ(ierr); 480 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);CHKERRQ(ierr); 481 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_HDF5);CHKERRQ(ierr); 482 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);CHKERRQ(ierr); 483 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);CHKERRQ(ierr); 484 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetCollective_C",PetscViewerHDF5SetCollective_HDF5);CHKERRQ(ierr); 485 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5GetCollective_C",PetscViewerHDF5GetCollective_HDF5);CHKERRQ(ierr); 486 PetscFunctionReturn(0); 487 } 488 489 /*@C 490 PetscViewerHDF5Open - Opens a file for HDF5 input/output. 491 492 Collective 493 494 Input Parameters: 495 + comm - MPI communicator 496 . name - name of file 497 - type - type of file 498 499 Output Parameter: 500 . hdf5v - PetscViewer for HDF5 input/output to use with the specified file 501 502 Options Database: 503 + -viewer_hdf5_base_dimension2 - turns on (true) or off (false) using a dimension of 2 in the HDF5 file even if the bs/dof of the vector is 1 504 - -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal 505 506 Level: beginner 507 508 Notes: 509 Reading is always available, regardless of the mode. Available modes are 510 + FILE_MODE_READ - open existing HDF5 file for read only access, fail if file does not exist [H5Fopen() with H5F_ACC_RDONLY] 511 . FILE_MODE_WRITE - if file exists, fully overwrite it, else create new HDF5 file [H5FcreateH5Fcreate() with H5F_ACC_TRUNC] 512 . FILE_MODE_APPEND - if file exists, keep existing contents [H5Fopen() with H5F_ACC_RDWR], else create new HDF5 file [H5FcreateH5Fcreate() with H5F_ACC_EXCL] 513 - FILE_MODE_UPDATE - same as FILE_MODE_APPEND 514 515 In case of FILE_MODE_APPEND / FILE_MODE_UPDATE, any stored object (dataset, attribute) can be selectively ovewritten if the same fully qualified name (/group/path/to/object) is specified. 516 517 This PetscViewer should be destroyed with PetscViewerDestroy(). 518 519 520 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(), 521 PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(), 522 MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName() 523 @*/ 524 PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v) 525 { 526 PetscErrorCode ierr; 527 528 PetscFunctionBegin; 529 ierr = PetscViewerCreate(comm, hdf5v);CHKERRQ(ierr); 530 ierr = PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);CHKERRQ(ierr); 531 ierr = PetscViewerFileSetMode(*hdf5v, type);CHKERRQ(ierr); 532 ierr = PetscViewerFileSetName(*hdf5v, name);CHKERRQ(ierr); 533 ierr = PetscViewerSetFromOptions(*hdf5v);CHKERRQ(ierr); 534 PetscFunctionReturn(0); 535 } 536 537 /*@C 538 PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls 539 540 Not collective 541 542 Input Parameter: 543 . viewer - the PetscViewer 544 545 Output Parameter: 546 . file_id - The file id 547 548 Level: intermediate 549 550 .seealso: PetscViewerHDF5Open() 551 @*/ 552 PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id) 553 { 554 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 555 556 PetscFunctionBegin; 557 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 558 if (file_id) *file_id = hdf5->file_id; 559 PetscFunctionReturn(0); 560 } 561 562 /*@C 563 PetscViewerHDF5PushGroup - Set the current HDF5 group for output 564 565 Not collective 566 567 Input Parameters: 568 + viewer - the PetscViewer 569 - name - The group name 570 571 Level: intermediate 572 573 Notes: 574 This is designed to mnemonically resemble the Unix cd command. 575 + If name begins with '/', it is interpreted as an absolute path fully replacing current group, otherwise it is taken as relative to the current group. 576 . NULL, empty string, or any sequence of all slashes (e.g. "///") is interpreted as the root group "/". 577 - "." means the current group is pushed again. 578 579 Example: 580 Suppose the current group is "/a". 581 + If name is NULL, empty string, or a sequence of all slashes (e.g. "///"), then the new group will be "/". 582 . If name is ".", then the new group will be "/a". 583 . If name is "b", then the new group will be "/a/b". 584 - If name is "/b", then the new group will be "/b". 585 586 Developer Notes: 587 The root group "/" is internally stored as NULL. 588 589 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup() 590 @*/ 591 PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char name[]) 592 { 593 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 594 PetscViewerHDF5GroupList *groupNode; 595 size_t i,len; 596 char buf[PETSC_MAX_PATH_LEN]; 597 const char *gname; 598 PetscErrorCode ierr; 599 600 PetscFunctionBegin; 601 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 602 if (name) PetscValidCharPointer(name,2); 603 ierr = PetscStrlen(name, &len);CHKERRQ(ierr); 604 gname = NULL; 605 if (len) { 606 if (len == 1 && name[0] == '.') { 607 /* use current name */ 608 gname = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : NULL; 609 } else if (name[0] == '/') { 610 /* absolute */ 611 for (i=1; i<len; i++) { 612 if (name[i] != '/') { 613 gname = name; 614 break; 615 } 616 } 617 } else { 618 /* relative */ 619 const char *parent = (hdf5->groups && hdf5->groups->name) ? hdf5->groups->name : ""; 620 ierr = PetscSNPrintf(buf, sizeof(buf), "%s/%s", parent, name);CHKERRQ(ierr); 621 gname = buf; 622 } 623 } 624 ierr = PetscNew(&groupNode);CHKERRQ(ierr); 625 ierr = PetscStrallocpy(gname, (char**) &groupNode->name);CHKERRQ(ierr); 626 groupNode->next = hdf5->groups; 627 hdf5->groups = groupNode; 628 PetscFunctionReturn(0); 629 } 630 631 /*@ 632 PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value 633 634 Not collective 635 636 Input Parameter: 637 . viewer - the PetscViewer 638 639 Level: intermediate 640 641 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup() 642 @*/ 643 PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer) 644 { 645 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 646 PetscViewerHDF5GroupList *groupNode; 647 PetscErrorCode ierr; 648 649 PetscFunctionBegin; 650 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 651 if (!hdf5->groups) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop"); 652 groupNode = hdf5->groups; 653 hdf5->groups = hdf5->groups->next; 654 ierr = PetscFree(groupNode->name);CHKERRQ(ierr); 655 ierr = PetscFree(groupNode);CHKERRQ(ierr); 656 PetscFunctionReturn(0); 657 } 658 659 /*@C 660 PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with PetscViewerHDF5PushGroup()/PetscViewerHDF5PopGroup(). 661 If none has been assigned, returns NULL. 662 663 Not collective 664 665 Input Parameter: 666 . viewer - the PetscViewer 667 668 Output Parameter: 669 . name - The group name 670 671 Level: intermediate 672 673 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5OpenGroup() 674 @*/ 675 PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char *name[]) 676 { 677 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data; 678 679 PetscFunctionBegin; 680 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 681 PetscValidPointer(name,2); 682 if (hdf5->groups) *name = hdf5->groups->name; 683 else *name = NULL; 684 PetscFunctionReturn(0); 685 } 686 687 /*@ 688 PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by PetscViewerHDF5GetGroup(), 689 and return this group's ID and file ID. 690 If PetscViewerHDF5GetGroup() yields NULL, then group ID is file ID. 691 692 Not collective 693 694 Input Parameter: 695 . viewer - the PetscViewer 696 697 Output Parameter: 698 + fileId - The HDF5 file ID 699 - groupId - The HDF5 group ID 700 701 Notes: 702 If the viewer is writable, the group is created if it doesn't exist yet. 703 704 Level: intermediate 705 706 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 707 @*/ 708 PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId) 709 { 710 hid_t file_id; 711 H5O_type_t type; 712 const char *groupName = NULL; 713 PetscBool create; 714 PetscErrorCode ierr; 715 716 PetscFunctionBegin; 717 ierr = PetscViewerWritable(viewer, &create);CHKERRQ(ierr); 718 ierr = PetscViewerHDF5GetFileId(viewer, &file_id);CHKERRQ(ierr); 719 ierr = PetscViewerHDF5GetGroup(viewer, &groupName);CHKERRQ(ierr); 720 ierr = PetscViewerHDF5Traverse_Internal(viewer, groupName, create, NULL, &type);CHKERRQ(ierr); 721 if (type != H5O_TYPE_GROUP) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Path %s resolves to something which is not a group", groupName); 722 PetscStackCallHDF5Return(*groupId,H5Gopen2,(file_id, groupName ? groupName : "/", H5P_DEFAULT)); 723 *fileId = file_id; 724 PetscFunctionReturn(0); 725 } 726 727 /*@ 728 PetscViewerHDF5PushTimestepping - Activate timestepping mode for subsequent HDF5 reading and writing. 729 730 Not collective 731 732 Input Parameter: 733 . viewer - the PetscViewer 734 735 Level: intermediate 736 737 Notes: 738 On first PetscViewerHDF5PushTimestepping(), the initial time step is set to 0. 739 Next timesteps can then be set using PetscViewerHDF5IncrementTimestep() or PetscViewerHDF5SetTimestep(). 740 Current timestep value determines which timestep is read from or written to any dataset on the next HDF5 I/O operation [e.g. VecView()]. 741 Use PetscViewerHDF5PopTimestepping() to deactivate timestepping mode; calling it by the end of the program is NOT mandatory. 742 Current timestep is remembered between PetscViewerHDF5PopTimestepping() and the next PetscViewerHDF5PushTimestepping(). 743 744 If a dataset was stored with timestepping, it can be loaded only in the timestepping mode again. 745 Loading a timestepped dataset with timestepping disabled, or vice-versa results in an error. 746 747 Developer notes: 748 Timestepped HDF5 dataset has an extra dimension and attribute "timestepping" set to true. 749 750 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PopTimestepping(), PetscViewerHDF5IsTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 751 @*/ 752 PetscErrorCode PetscViewerHDF5PushTimestepping(PetscViewer viewer) 753 { 754 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 755 756 PetscFunctionBegin; 757 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 758 if (hdf5->timestepping) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping is already pushed"); 759 hdf5->timestepping = PETSC_TRUE; 760 if (hdf5->timestep < 0) hdf5->timestep = 0; 761 PetscFunctionReturn(0); 762 } 763 764 /*@ 765 PetscViewerHDF5PopTimestepping - Deactivate timestepping mode for subsequent HDF5 reading and writing. 766 767 Not collective 768 769 Input Parameter: 770 . viewer - the PetscViewer 771 772 Level: intermediate 773 774 Notes: 775 See PetscViewerHDF5PushTimestepping() for details. 776 777 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5IsTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 778 @*/ 779 PetscErrorCode PetscViewerHDF5PopTimestepping(PetscViewer viewer) 780 { 781 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 782 783 PetscFunctionBegin; 784 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 785 if (!hdf5->timestepping) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first"); 786 hdf5->timestepping = PETSC_FALSE; 787 PetscFunctionReturn(0); 788 } 789 790 /*@ 791 PetscViewerHDF5IsTimestepping - Ask the viewer whether it is in timestepping mode currently. 792 793 Not collective 794 795 Input Parameter: 796 . viewer - the PetscViewer 797 798 Output Parameter: 799 . flg - is timestepping active? 800 801 Level: intermediate 802 803 Notes: 804 See PetscViewerHDF5PushTimestepping() for details. 805 806 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5PopTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 807 @*/ 808 PetscErrorCode PetscViewerHDF5IsTimestepping(PetscViewer viewer, PetscBool *flg) 809 { 810 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 811 812 PetscFunctionBegin; 813 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 814 *flg = hdf5->timestepping; 815 PetscFunctionReturn(0); 816 } 817 818 /*@ 819 PetscViewerHDF5IncrementTimestep - Increments current timestep for the HDF5 output. Fields are stacked in time. 820 821 Not collective 822 823 Input Parameter: 824 . viewer - the PetscViewer 825 826 Level: intermediate 827 828 Notes: 829 This can be called only if the viewer is in timestepping mode. See PetscViewerHDF5PushTimestepping() for details. 830 831 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep() 832 @*/ 833 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) 834 { 835 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 836 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 839 if (!hdf5->timestepping) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first"); 840 ++hdf5->timestep; 841 PetscFunctionReturn(0); 842 } 843 844 /*@ 845 PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. 846 847 Logically collective 848 849 Input Parameters: 850 + viewer - the PetscViewer 851 - timestep - The timestep 852 853 Level: intermediate 854 855 Notes: 856 This can be called only if the viewer is in timestepping mode. See PetscViewerHDF5PushTimestepping() for details. 857 858 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 859 @*/ 860 PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) 861 { 862 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 863 864 PetscFunctionBegin; 865 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 866 PetscValidLogicalCollectiveInt(viewer, timestep, 2); 867 if (timestep < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestep %D is negative", timestep); 868 if (!hdf5->timestepping) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first"); 869 hdf5->timestep = timestep; 870 PetscFunctionReturn(0); 871 } 872 873 /*@ 874 PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time. 875 876 Not collective 877 878 Input Parameter: 879 . viewer - the PetscViewer 880 881 Output Parameter: 882 . timestep - The timestep 883 884 Level: intermediate 885 886 Notes: 887 This can be called only if the viewer is in the timestepping mode. See PetscViewerHDF5PushTimestepping() for details. 888 889 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushTimestepping(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep() 890 @*/ 891 PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) 892 { 893 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 894 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 897 PetscValidIntPointer(timestep,2); 898 if (!hdf5->timestepping) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Timestepping has not been pushed yet. Call PetscViewerHDF5PushTimestepping() first"); 899 *timestep = hdf5->timestep; 900 PetscFunctionReturn(0); 901 } 902 903 /*@C 904 PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name. 905 906 Not collective 907 908 Input Parameter: 909 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 910 911 Output Parameter: 912 . mtype - the MPI datatype (for example MPI_DOUBLE, ...) 913 914 Level: advanced 915 916 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 917 @*/ 918 PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) 919 { 920 PetscFunctionBegin; 921 if (ptype == PETSC_INT) 922 #if defined(PETSC_USE_64BIT_INDICES) 923 *htype = H5T_NATIVE_LLONG; 924 #else 925 *htype = H5T_NATIVE_INT; 926 #endif 927 else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE; 928 else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG; 929 else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT; 930 else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_INT; 931 else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_INT; 932 else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT; 933 else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR; 934 else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR; 935 else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1); 936 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype"); 937 PetscFunctionReturn(0); 938 } 939 940 /*@C 941 PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name 942 943 Not collective 944 945 Input Parameter: 946 . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...) 947 948 Output Parameter: 949 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 950 951 Level: advanced 952 953 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 954 @*/ 955 PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) 956 { 957 PetscFunctionBegin; 958 #if defined(PETSC_USE_64BIT_INDICES) 959 if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG; 960 else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT; 961 #else 962 if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT; 963 #endif 964 else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE; 965 else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG; 966 else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT; 967 else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT; 968 else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR; 969 else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR; 970 else if (htype == H5T_C_S1) *ptype = PETSC_STRING; 971 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype"); 972 PetscFunctionReturn(0); 973 } 974 975 /*@C 976 PetscViewerHDF5WriteAttribute - Write an attribute 977 978 Collective 979 980 Input Parameters: 981 + viewer - The HDF5 viewer 982 . parent - The parent dataset/group name 983 . name - The attribute name 984 . datatype - The attribute type 985 - value - The attribute value 986 987 Level: advanced 988 989 Notes: 990 If parent starts with '/', it is taken as an absolute path overriding currently pushed group, else parent is relative to the current pushed group. NULL means the current pushed group. 991 992 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 993 @*/ 994 PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value) 995 { 996 char *parentAbsPath; 997 hid_t h5, dataspace, obj, attribute, dtype; 998 PetscBool has; 999 PetscErrorCode ierr; 1000 1001 PetscFunctionBegin; 1002 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1003 if (parent) PetscValidCharPointer(parent, 2); 1004 PetscValidCharPointer(name, 3); 1005 PetscValidLogicalCollectiveEnum(viewer,datatype,4); 1006 PetscValidPointer(value, 5); 1007 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);CHKERRQ(ierr); 1008 ierr = PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_TRUE, NULL, NULL);CHKERRQ(ierr); 1009 ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has);CHKERRQ(ierr); 1010 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 1011 if (datatype == PETSC_STRING) { 1012 size_t len; 1013 ierr = PetscStrlen((const char *) value, &len);CHKERRQ(ierr); 1014 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 1015 } 1016 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1017 PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR)); 1018 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parentAbsPath, H5P_DEFAULT)); 1019 if (has) { 1020 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 1021 } else { 1022 PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT)); 1023 } 1024 PetscStackCallHDF5(H5Awrite,(attribute, dtype, value)); 1025 if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype)); 1026 PetscStackCallHDF5(H5Aclose,(attribute)); 1027 PetscStackCallHDF5(H5Oclose,(obj)); 1028 PetscStackCallHDF5(H5Sclose,(dataspace)); 1029 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 1030 PetscFunctionReturn(0); 1031 } 1032 1033 /*@C 1034 PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given PetscObject by name 1035 1036 Collective 1037 1038 Input Parameters: 1039 + viewer - The HDF5 viewer 1040 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 1041 . name - The attribute name 1042 . datatype - The attribute type 1043 - value - The attribute value 1044 1045 Notes: 1046 This fails if the path current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 1047 You might want to check first if it does using PetscViewerHDF5HasObject(). 1048 1049 Level: advanced 1050 1051 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1052 @*/ 1053 PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value) 1054 { 1055 PetscErrorCode ierr; 1056 1057 PetscFunctionBegin; 1058 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1059 PetscValidHeader(obj,2); 1060 PetscValidCharPointer(name,3); 1061 PetscValidPointer(value,5); 1062 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 1063 ierr = PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr); 1064 PetscFunctionReturn(0); 1065 } 1066 1067 /*@C 1068 PetscViewerHDF5ReadAttribute - Read an attribute 1069 1070 Collective 1071 1072 Input Parameters: 1073 + viewer - The HDF5 viewer 1074 . parent - The parent dataset/group name 1075 . name - The attribute name 1076 . datatype - The attribute type 1077 - defaultValue - The pointer to the default value 1078 1079 Output Parameter: 1080 . value - The pointer to the read HDF5 attribute value 1081 1082 Notes: 1083 If defaultValue is NULL and the attribute is not found, an error occurs. 1084 If defaultValue is not NULL and the attribute is not found, defaultValue is copied to value. 1085 The pointers defaultValue and value can be the same; for instance 1086 $ flg = PETSC_FALSE; 1087 $ ierr = PetscViewerHDF5ReadAttribute(viewer,name,"attr",PETSC_BOOL,&flg,&flg);CHKERRQ(ierr); 1088 is valid, but make sure the default value is initialized. 1089 1090 If the datatype is PETSC_STRING, the output string is newly allocated so one must PetscFree() it when no longer needed. 1091 1092 If parent starts with '/', it is taken as an absolute path overriding currently pushed group, else parent is relative to the current pushed group. NULL means the current pushed group. 1093 1094 Level: advanced 1095 1096 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1097 @*/ 1098 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *defaultValue, void *value) 1099 { 1100 char *parentAbsPath; 1101 hid_t h5, obj, attribute, dtype; 1102 PetscBool has; 1103 PetscErrorCode ierr; 1104 1105 PetscFunctionBegin; 1106 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1107 if (parent) PetscValidCharPointer(parent, 2); 1108 PetscValidCharPointer(name, 3); 1109 if (defaultValue) PetscValidPointer(defaultValue, 5); 1110 PetscValidPointer(value, 6); 1111 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 1112 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);CHKERRQ(ierr); 1113 ierr = PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, &has, NULL);CHKERRQ(ierr); 1114 if (has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has);CHKERRQ(ierr);} 1115 if (!has) { 1116 if (defaultValue) { 1117 if (defaultValue != value) { 1118 if (datatype == PETSC_STRING) { 1119 ierr = PetscStrallocpy(*(char**)defaultValue, (char**)value);CHKERRQ(ierr); 1120 } else { 1121 size_t len; 1122 PetscStackCallHDF5Return(len,H5Tget_size,(dtype)); 1123 ierr = PetscMemcpy(value, defaultValue, len);CHKERRQ(ierr); 1124 } 1125 } 1126 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 1127 PetscFunctionReturn(0); 1128 } else SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist and default value not provided", parentAbsPath, name); 1129 } 1130 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1131 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parentAbsPath, H5P_DEFAULT)); 1132 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 1133 if (datatype == PETSC_STRING) { 1134 size_t len; 1135 hid_t atype; 1136 PetscStackCallHDF5Return(atype,H5Aget_type,(attribute)); 1137 PetscStackCallHDF5Return(len,H5Tget_size,(atype)); 1138 ierr = PetscMalloc((len+1) * sizeof(char), value);CHKERRQ(ierr); 1139 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 1140 PetscStackCallHDF5(H5Aread,(attribute, dtype, *(char**)value)); 1141 } else { 1142 PetscStackCallHDF5(H5Aread,(attribute, dtype, value)); 1143 } 1144 PetscStackCallHDF5(H5Aclose,(attribute)); 1145 /* H5Oclose can be used to close groups, datasets, or committed datatypes */ 1146 PetscStackCallHDF5(H5Oclose,(obj)); 1147 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 1148 PetscFunctionReturn(0); 1149 } 1150 1151 /*@C 1152 PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given PetscObject by name 1153 1154 Collective 1155 1156 Input Parameters: 1157 + viewer - The HDF5 viewer 1158 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 1159 . name - The attribute name 1160 - datatype - The attribute type 1161 1162 Output Parameter: 1163 . value - The attribute value 1164 1165 Notes: 1166 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 1167 You might want to check first if it does using PetscViewerHDF5HasObject(). 1168 1169 Level: advanced 1170 1171 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute() PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1172 @*/ 1173 PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *defaultValue, void *value) 1174 { 1175 PetscErrorCode ierr; 1176 1177 PetscFunctionBegin; 1178 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1179 PetscValidHeader(obj,2); 1180 PetscValidCharPointer(name,3); 1181 PetscValidPointer(value, 5); 1182 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 1183 ierr = PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, defaultValue, value);CHKERRQ(ierr); 1184 PetscFunctionReturn(0); 1185 } 1186 1187 PETSC_STATIC_INLINE PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_) 1188 { 1189 htri_t exists; 1190 hid_t group; 1191 1192 PetscFunctionBegin; 1193 PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT)); 1194 if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT)); 1195 if (!exists && createGroup) { 1196 PetscStackCallHDF5Return(group,H5Gcreate2,(h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)); 1197 PetscStackCallHDF5(H5Gclose,(group)); 1198 exists = PETSC_TRUE; 1199 } 1200 *exists_ = (PetscBool) exists; 1201 PetscFunctionReturn(0); 1202 } 1203 1204 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype) 1205 { 1206 const char rootGroupName[] = "/"; 1207 hid_t h5; 1208 PetscBool exists=PETSC_FALSE; 1209 PetscInt i; 1210 int n; 1211 char **hierarchy; 1212 char buf[PETSC_MAX_PATH_LEN]=""; 1213 PetscErrorCode ierr; 1214 1215 PetscFunctionBegin; 1216 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1217 if (name) PetscValidCharPointer(name, 2); 1218 else name = rootGroupName; 1219 if (has) { 1220 PetscValidIntPointer(has, 3); 1221 *has = PETSC_FALSE; 1222 } 1223 if (otype) { 1224 PetscValidIntPointer(otype, 4); 1225 *otype = H5O_TYPE_UNKNOWN; 1226 } 1227 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1228 1229 /* 1230 Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing. 1231 Hence, each of them needs to be tested separately: 1232 1) whether it's a valid link 1233 2) whether this link resolves to an object 1234 See H5Oexists_by_name() documentation. 1235 */ 1236 ierr = PetscStrToArray(name,'/',&n,&hierarchy);CHKERRQ(ierr); 1237 if (!n) { 1238 /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */ 1239 if (has) *has = PETSC_TRUE; 1240 if (otype) *otype = H5O_TYPE_GROUP; 1241 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1242 PetscFunctionReturn(0); 1243 } 1244 for (i=0; i<n; i++) { 1245 ierr = PetscStrcat(buf,"/");CHKERRQ(ierr); 1246 ierr = PetscStrcat(buf,hierarchy[i]);CHKERRQ(ierr); 1247 ierr = PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists);CHKERRQ(ierr); 1248 if (!exists) break; 1249 } 1250 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1251 1252 /* If the object exists, get its type */ 1253 if (exists && otype) { 1254 H5O_info_t info; 1255 1256 /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */ 1257 PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT)); 1258 *otype = info.type; 1259 } 1260 if (has) *has = exists; 1261 PetscFunctionReturn(0); 1262 } 1263 1264 /*@C 1265 PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file 1266 1267 Collective 1268 1269 Input Parameters: 1270 + viewer - The HDF5 viewer 1271 - path - The group path 1272 1273 Output Parameter: 1274 . has - Flag for group existence 1275 1276 Level: advanced 1277 1278 Notes: 1279 If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group. NULL means the current pushed group. 1280 If path is NULL or empty, has is set to PETSC_FALSE. 1281 If path exists but is not a group, PETSC_FALSE is returned. 1282 1283 .seealso: PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasDataset(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup(), PetscViewerHDF5OpenGroup() 1284 @*/ 1285 PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, const char path[], PetscBool *has) 1286 { 1287 H5O_type_t type; 1288 char *abspath; 1289 PetscErrorCode ierr; 1290 1291 PetscFunctionBegin; 1292 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1293 if (path) PetscValidCharPointer(path,2); 1294 PetscValidBoolPointer(has,3); 1295 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, path, &abspath);CHKERRQ(ierr); 1296 ierr = PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type);CHKERRQ(ierr); 1297 *has = (PetscBool)(type == H5O_TYPE_GROUP); 1298 ierr = PetscFree(abspath);CHKERRQ(ierr); 1299 PetscFunctionReturn(0); 1300 } 1301 1302 /*@C 1303 PetscViewerHDF5HasDataset - Check whether a given dataset exists in the HDF5 file 1304 1305 Collective 1306 1307 Input Parameters: 1308 + viewer - The HDF5 viewer 1309 - path - The dataset path 1310 1311 Output Parameter: 1312 . has - Flag whether dataset exists 1313 1314 Level: advanced 1315 1316 Notes: 1317 If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group. 1318 If path is NULL or empty, has is set to PETSC_FALSE. 1319 If path exists but is not a dataset, has is set to PETSC_FALSE as well. 1320 1321 .seealso: PetscViewerHDF5HasObject(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasGroup(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup() 1322 @*/ 1323 PetscErrorCode PetscViewerHDF5HasDataset(PetscViewer viewer, const char path[], PetscBool *has) 1324 { 1325 H5O_type_t type; 1326 char *abspath; 1327 PetscErrorCode ierr; 1328 1329 PetscFunctionBegin; 1330 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1331 if (path) PetscValidCharPointer(path,2); 1332 PetscValidBoolPointer(has,3); 1333 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, path, &abspath);CHKERRQ(ierr); 1334 ierr = PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type);CHKERRQ(ierr); 1335 *has = (PetscBool)(type == H5O_TYPE_DATASET); 1336 ierr = PetscFree(abspath);CHKERRQ(ierr); 1337 PetscFunctionReturn(0); 1338 } 1339 1340 /*@ 1341 PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group 1342 1343 Collective 1344 1345 Input Parameters: 1346 + viewer - The HDF5 viewer 1347 - obj - The named object 1348 1349 Output Parameter: 1350 . has - Flag for dataset existence 1351 1352 Notes: 1353 If the object is unnamed, an error occurs. 1354 If the path current_group/object_name exists but is not a dataset, has is set to PETSC_FALSE as well. 1355 1356 Level: advanced 1357 1358 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasDataset(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup() 1359 @*/ 1360 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) 1361 { 1362 size_t len; 1363 PetscErrorCode ierr; 1364 1365 PetscFunctionBegin; 1366 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1367 PetscValidHeader(obj,2); 1368 PetscValidBoolPointer(has,3); 1369 ierr = PetscStrlen(obj->name, &len);CHKERRQ(ierr); 1370 if (!len) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named"); 1371 ierr = PetscViewerHDF5HasDataset(viewer, obj->name, has);CHKERRQ(ierr); 1372 PetscFunctionReturn(0); 1373 } 1374 1375 /*@C 1376 PetscViewerHDF5HasAttribute - Check whether an attribute exists 1377 1378 Collective 1379 1380 Input Parameters: 1381 + viewer - The HDF5 viewer 1382 . parent - The parent dataset/group name 1383 - name - The attribute name 1384 1385 Output Parameter: 1386 . has - Flag for attribute existence 1387 1388 Level: advanced 1389 1390 Notes: 1391 If parent starts with '/', it is taken as an absolute path overriding currently pushed group, else parent is relative to the current pushed group. NULL means the current pushed group. 1392 1393 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1394 @*/ 1395 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 1396 { 1397 char *parentAbsPath; 1398 PetscErrorCode ierr; 1399 1400 PetscFunctionBegin; 1401 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1402 if (parent) PetscValidCharPointer(parent,2); 1403 PetscValidCharPointer(name,3); 1404 PetscValidBoolPointer(has,4); 1405 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);CHKERRQ(ierr); 1406 ierr = PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, has, NULL);CHKERRQ(ierr); 1407 if (*has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, has);CHKERRQ(ierr);} 1408 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 1409 PetscFunctionReturn(0); 1410 } 1411 1412 /*@C 1413 PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given PetscObject by name 1414 1415 Collective 1416 1417 Input Parameters: 1418 + viewer - The HDF5 viewer 1419 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 1420 - name - The attribute name 1421 1422 Output Parameter: 1423 . has - Flag for attribute existence 1424 1425 Notes: 1426 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 1427 You might want to check first if it does using PetscViewerHDF5HasObject(). 1428 1429 Level: advanced 1430 1431 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1432 @*/ 1433 PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has) 1434 { 1435 PetscErrorCode ierr; 1436 1437 PetscFunctionBegin; 1438 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1439 PetscValidHeader(obj,2); 1440 PetscValidCharPointer(name,3); 1441 PetscValidBoolPointer(has,4); 1442 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 1443 ierr = PetscViewerHDF5HasAttribute(viewer, obj->name, name, has);CHKERRQ(ierr); 1444 PetscFunctionReturn(0); 1445 } 1446 1447 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 1448 { 1449 hid_t h5; 1450 htri_t hhas; 1451 PetscErrorCode ierr; 1452 1453 PetscFunctionBegin; 1454 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1455 PetscStackCallHDF5Return(hhas,H5Aexists_by_name,(h5, parent, name, H5P_DEFAULT)); 1456 *has = hhas ? PETSC_TRUE : PETSC_FALSE; 1457 PetscFunctionReturn(0); 1458 } 1459 1460 /* 1461 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that 1462 is attached to a communicator, in this case the attribute is a PetscViewer. 1463 */ 1464 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID; 1465 1466 /*@C 1467 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator. 1468 1469 Collective 1470 1471 Input Parameter: 1472 . comm - the MPI communicator to share the HDF5 PetscViewer 1473 1474 Level: intermediate 1475 1476 Options Database Keys: 1477 . -viewer_hdf5_filename <name> 1478 1479 Environmental variables: 1480 . PETSC_VIEWER_HDF5_FILENAME 1481 1482 Notes: 1483 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return 1484 an error code. The HDF5 PetscViewer is usually used in the form 1485 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm)); 1486 1487 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy() 1488 @*/ 1489 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) 1490 { 1491 PetscErrorCode ierr; 1492 PetscBool flg; 1493 PetscViewer viewer; 1494 char fname[PETSC_MAX_PATH_LEN]; 1495 MPI_Comm ncomm; 1496 1497 PetscFunctionBegin; 1498 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1499 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) { 1500 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,NULL); 1501 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1502 } 1503 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg); 1504 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1505 if (!flg) { /* PetscViewer not yet created */ 1506 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 1507 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1508 if (!flg) { 1509 ierr = PetscStrcpy(fname,"output.h5"); 1510 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1511 } 1512 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer); 1513 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1514 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 1515 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1516 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer); 1517 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1518 } 1519 ierr = PetscCommDestroy(&ncomm); 1520 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1521 PetscFunctionReturn(viewer); 1522 } 1523