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 PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time. 729 730 Not collective 731 732 Input Parameter: 733 . viewer - the PetscViewer 734 735 Level: intermediate 736 737 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep() 738 @*/ 739 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) 740 { 741 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 742 743 PetscFunctionBegin; 744 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 745 ++hdf5->timestep; 746 PetscFunctionReturn(0); 747 } 748 749 /*@ 750 PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep 751 of -1 disables blocking with timesteps. 752 753 Not collective 754 755 Input Parameters: 756 + viewer - the PetscViewer 757 - timestep - The timestep number 758 759 Level: intermediate 760 761 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 762 @*/ 763 PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) 764 { 765 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 766 767 PetscFunctionBegin; 768 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 769 hdf5->timestep = timestep; 770 PetscFunctionReturn(0); 771 } 772 773 /*@ 774 PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time. 775 776 Not collective 777 778 Input Parameter: 779 . viewer - the PetscViewer 780 781 Output Parameter: 782 . timestep - The timestep number 783 784 Level: intermediate 785 786 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep() 787 @*/ 788 PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) 789 { 790 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 791 792 PetscFunctionBegin; 793 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 794 PetscValidPointer(timestep,2); 795 *timestep = hdf5->timestep; 796 PetscFunctionReturn(0); 797 } 798 799 /*@C 800 PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name. 801 802 Not collective 803 804 Input Parameter: 805 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 806 807 Output Parameter: 808 . mtype - the MPI datatype (for example MPI_DOUBLE, ...) 809 810 Level: advanced 811 812 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 813 @*/ 814 PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) 815 { 816 PetscFunctionBegin; 817 if (ptype == PETSC_INT) 818 #if defined(PETSC_USE_64BIT_INDICES) 819 *htype = H5T_NATIVE_LLONG; 820 #else 821 *htype = H5T_NATIVE_INT; 822 #endif 823 else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE; 824 else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG; 825 else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT; 826 else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_INT; 827 else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_INT; 828 else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT; 829 else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR; 830 else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR; 831 else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1); 832 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype"); 833 PetscFunctionReturn(0); 834 } 835 836 /*@C 837 PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name 838 839 Not collective 840 841 Input Parameter: 842 . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...) 843 844 Output Parameter: 845 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 846 847 Level: advanced 848 849 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 850 @*/ 851 PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) 852 { 853 PetscFunctionBegin; 854 #if defined(PETSC_USE_64BIT_INDICES) 855 if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG; 856 else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT; 857 #else 858 if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT; 859 #endif 860 else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE; 861 else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG; 862 else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT; 863 else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT; 864 else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR; 865 else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR; 866 else if (htype == H5T_C_S1) *ptype = PETSC_STRING; 867 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype"); 868 PetscFunctionReturn(0); 869 } 870 871 /*@C 872 PetscViewerHDF5WriteAttribute - Write an attribute 873 874 Collective 875 876 Input Parameters: 877 + viewer - The HDF5 viewer 878 . parent - The parent dataset/group name 879 . name - The attribute name 880 . datatype - The attribute type 881 - value - The attribute value 882 883 Level: advanced 884 885 Notes: 886 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. 887 888 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 889 @*/ 890 PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *value) 891 { 892 char *parentAbsPath; 893 hid_t h5, dataspace, obj, attribute, dtype; 894 PetscBool has; 895 PetscErrorCode ierr; 896 897 PetscFunctionBegin; 898 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 899 if (parent) PetscValidCharPointer(parent, 2); 900 PetscValidCharPointer(name, 3); 901 PetscValidLogicalCollectiveEnum(viewer,datatype,4); 902 PetscValidPointer(value, 5); 903 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);CHKERRQ(ierr); 904 ierr = PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_TRUE, NULL, NULL);CHKERRQ(ierr); 905 ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has);CHKERRQ(ierr); 906 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 907 if (datatype == PETSC_STRING) { 908 size_t len; 909 ierr = PetscStrlen((const char *) value, &len);CHKERRQ(ierr); 910 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 911 } 912 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 913 PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR)); 914 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parentAbsPath, H5P_DEFAULT)); 915 if (has) { 916 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 917 } else { 918 PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT)); 919 } 920 PetscStackCallHDF5(H5Awrite,(attribute, dtype, value)); 921 if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype)); 922 PetscStackCallHDF5(H5Aclose,(attribute)); 923 PetscStackCallHDF5(H5Oclose,(obj)); 924 PetscStackCallHDF5(H5Sclose,(dataspace)); 925 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 926 PetscFunctionReturn(0); 927 } 928 929 /*@C 930 PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given PetscObject by name 931 932 Collective 933 934 Input Parameters: 935 + viewer - The HDF5 viewer 936 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 937 . name - The attribute name 938 . datatype - The attribute type 939 - value - The attribute value 940 941 Notes: 942 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). 943 You might want to check first if it does using PetscViewerHDF5HasObject(). 944 945 Level: advanced 946 947 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 948 @*/ 949 PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value) 950 { 951 PetscErrorCode ierr; 952 953 PetscFunctionBegin; 954 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 955 PetscValidHeader(obj,2); 956 PetscValidCharPointer(name,3); 957 PetscValidPointer(value,5); 958 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 959 ierr = PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr); 960 PetscFunctionReturn(0); 961 } 962 963 /*@C 964 PetscViewerHDF5ReadAttribute - Read an attribute 965 966 Collective 967 968 Input Parameters: 969 + viewer - The HDF5 viewer 970 . parent - The parent dataset/group name 971 . name - The attribute name 972 . datatype - The attribute type 973 - defaultValue - The pointer to the default value 974 975 Output Parameter: 976 . value - The pointer to the read HDF5 attribute value 977 978 Notes: 979 If defaultValue is NULL and the attribute is not found, an error occurs. 980 If defaultValue is not NULL and the attribute is not found, defaultValue is copied to value. 981 The pointers defaultValue and value can be the same; for instance 982 $ flg = PETSC_FALSE; 983 $ ierr = PetscViewerHDF5ReadAttribute(viewer,name,"attr",PETSC_BOOL,&flg,&flg);CHKERRQ(ierr); 984 is valid, but make sure the default value is initialized. 985 986 If the datatype is PETSC_STRING, the output string is newly allocated so one must PetscFree() it when no longer needed. 987 988 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. 989 990 Level: advanced 991 992 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 993 @*/ 994 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char parent[], const char name[], PetscDataType datatype, const void *defaultValue, void *value) 995 { 996 char *parentAbsPath; 997 hid_t h5, 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 if (defaultValue) PetscValidPointer(defaultValue, 5); 1006 PetscValidPointer(value, 6); 1007 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 1008 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);CHKERRQ(ierr); 1009 ierr = PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, &has, NULL);CHKERRQ(ierr); 1010 if (has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, &has);CHKERRQ(ierr);} 1011 if (!has) { 1012 if (defaultValue) { 1013 if (defaultValue != value) { 1014 if (datatype == PETSC_STRING) { 1015 ierr = PetscStrallocpy(*(char**)defaultValue, (char**)value);CHKERRQ(ierr); 1016 } else { 1017 size_t len; 1018 PetscStackCallHDF5Return(len,H5Tget_size,(dtype)); 1019 ierr = PetscMemcpy(value, defaultValue, len);CHKERRQ(ierr); 1020 } 1021 } 1022 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 1023 PetscFunctionReturn(0); 1024 } else SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist and default value not provided", parentAbsPath, name); 1025 } 1026 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1027 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parentAbsPath, H5P_DEFAULT)); 1028 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 1029 if (datatype == PETSC_STRING) { 1030 size_t len; 1031 hid_t atype; 1032 PetscStackCallHDF5Return(atype,H5Aget_type,(attribute)); 1033 PetscStackCallHDF5Return(len,H5Tget_size,(atype)); 1034 ierr = PetscMalloc((len+1) * sizeof(char), value);CHKERRQ(ierr); 1035 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 1036 PetscStackCallHDF5(H5Aread,(attribute, dtype, *(char**)value)); 1037 } else { 1038 PetscStackCallHDF5(H5Aread,(attribute, dtype, value)); 1039 } 1040 PetscStackCallHDF5(H5Aclose,(attribute)); 1041 /* H5Oclose can be used to close groups, datasets, or committed datatypes */ 1042 PetscStackCallHDF5(H5Oclose,(obj)); 1043 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 1044 PetscFunctionReturn(0); 1045 } 1046 1047 /*@C 1048 PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given PetscObject by name 1049 1050 Collective 1051 1052 Input Parameters: 1053 + viewer - The HDF5 viewer 1054 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 1055 . name - The attribute name 1056 - datatype - The attribute type 1057 1058 Output Parameter: 1059 . value - The attribute value 1060 1061 Notes: 1062 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 1063 You might want to check first if it does using PetscViewerHDF5HasObject(). 1064 1065 Level: advanced 1066 1067 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute() PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1068 @*/ 1069 PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *defaultValue, void *value) 1070 { 1071 PetscErrorCode ierr; 1072 1073 PetscFunctionBegin; 1074 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1075 PetscValidHeader(obj,2); 1076 PetscValidCharPointer(name,3); 1077 PetscValidPointer(value, 5); 1078 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 1079 ierr = PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, defaultValue, value);CHKERRQ(ierr); 1080 PetscFunctionReturn(0); 1081 } 1082 1083 PETSC_STATIC_INLINE PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_) 1084 { 1085 htri_t exists; 1086 hid_t group; 1087 1088 PetscFunctionBegin; 1089 PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT)); 1090 if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT)); 1091 if (!exists && createGroup) { 1092 PetscStackCallHDF5Return(group,H5Gcreate2,(h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)); 1093 PetscStackCallHDF5(H5Gclose,(group)); 1094 exists = PETSC_TRUE; 1095 } 1096 *exists_ = (PetscBool) exists; 1097 PetscFunctionReturn(0); 1098 } 1099 1100 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype) 1101 { 1102 const char rootGroupName[] = "/"; 1103 hid_t h5; 1104 PetscBool exists=PETSC_FALSE; 1105 PetscInt i; 1106 int n; 1107 char **hierarchy; 1108 char buf[PETSC_MAX_PATH_LEN]=""; 1109 PetscErrorCode ierr; 1110 1111 PetscFunctionBegin; 1112 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1113 if (name) PetscValidCharPointer(name, 2); 1114 else name = rootGroupName; 1115 if (has) { 1116 PetscValidIntPointer(has, 3); 1117 *has = PETSC_FALSE; 1118 } 1119 if (otype) { 1120 PetscValidIntPointer(otype, 4); 1121 *otype = H5O_TYPE_UNKNOWN; 1122 } 1123 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1124 1125 /* 1126 Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing. 1127 Hence, each of them needs to be tested separately: 1128 1) whether it's a valid link 1129 2) whether this link resolves to an object 1130 See H5Oexists_by_name() documentation. 1131 */ 1132 ierr = PetscStrToArray(name,'/',&n,&hierarchy);CHKERRQ(ierr); 1133 if (!n) { 1134 /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */ 1135 if (has) *has = PETSC_TRUE; 1136 if (otype) *otype = H5O_TYPE_GROUP; 1137 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1138 PetscFunctionReturn(0); 1139 } 1140 for (i=0; i<n; i++) { 1141 ierr = PetscStrcat(buf,"/");CHKERRQ(ierr); 1142 ierr = PetscStrcat(buf,hierarchy[i]);CHKERRQ(ierr); 1143 ierr = PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists);CHKERRQ(ierr); 1144 if (!exists) break; 1145 } 1146 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1147 1148 /* If the object exists, get its type */ 1149 if (exists && otype) { 1150 H5O_info_t info; 1151 1152 /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */ 1153 PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT)); 1154 *otype = info.type; 1155 } 1156 if (has) *has = exists; 1157 PetscFunctionReturn(0); 1158 } 1159 1160 /*@C 1161 PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file 1162 1163 Collective 1164 1165 Input Parameters: 1166 + viewer - The HDF5 viewer 1167 - path - The group path 1168 1169 Output Parameter: 1170 . has - Flag for group existence 1171 1172 Level: advanced 1173 1174 Notes: 1175 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. 1176 If path is NULL or empty, has is set to PETSC_FALSE. 1177 If path exists but is not a group, PETSC_FALSE is returned. 1178 1179 .seealso: PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasDataset(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup(), PetscViewerHDF5OpenGroup() 1180 @*/ 1181 PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, const char path[], PetscBool *has) 1182 { 1183 H5O_type_t type; 1184 char *abspath; 1185 PetscErrorCode ierr; 1186 1187 PetscFunctionBegin; 1188 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1189 if (path) PetscValidCharPointer(path,2); 1190 PetscValidBoolPointer(has,3); 1191 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, path, &abspath);CHKERRQ(ierr); 1192 ierr = PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type);CHKERRQ(ierr); 1193 *has = (PetscBool)(type == H5O_TYPE_GROUP); 1194 ierr = PetscFree(abspath);CHKERRQ(ierr); 1195 PetscFunctionReturn(0); 1196 } 1197 1198 /*@C 1199 PetscViewerHDF5HasDataset - Check whether a given dataset exists in the HDF5 file 1200 1201 Collective 1202 1203 Input Parameters: 1204 + viewer - The HDF5 viewer 1205 - path - The dataset path 1206 1207 Output Parameter: 1208 . has - Flag whether dataset exists 1209 1210 Level: advanced 1211 1212 Notes: 1213 If path starts with '/', it is taken as an absolute path overriding currently pushed group, else path is relative to the current pushed group. 1214 If path is NULL or empty, has is set to PETSC_FALSE. 1215 If path exists but is not a dataset, has is set to PETSC_FALSE as well. 1216 1217 .seealso: PetscViewerHDF5HasObject(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasGroup(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup() 1218 @*/ 1219 PetscErrorCode PetscViewerHDF5HasDataset(PetscViewer viewer, const char path[], PetscBool *has) 1220 { 1221 H5O_type_t type; 1222 char *abspath; 1223 PetscErrorCode ierr; 1224 1225 PetscFunctionBegin; 1226 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1227 if (path) PetscValidCharPointer(path,2); 1228 PetscValidBoolPointer(has,3); 1229 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, path, &abspath);CHKERRQ(ierr); 1230 ierr = PetscViewerHDF5Traverse_Internal(viewer, abspath, PETSC_FALSE, NULL, &type);CHKERRQ(ierr); 1231 *has = (PetscBool)(type == H5O_TYPE_DATASET); 1232 ierr = PetscFree(abspath);CHKERRQ(ierr); 1233 PetscFunctionReturn(0); 1234 } 1235 1236 /*@ 1237 PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group 1238 1239 Collective 1240 1241 Input Parameters: 1242 + viewer - The HDF5 viewer 1243 - obj - The named object 1244 1245 Output Parameter: 1246 . has - Flag for dataset existence 1247 1248 Notes: 1249 If the object is unnamed, an error occurs. 1250 If the path current_group/object_name exists but is not a dataset, has is set to PETSC_FALSE as well. 1251 1252 Level: advanced 1253 1254 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasDataset(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5GetGroup() 1255 @*/ 1256 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) 1257 { 1258 size_t len; 1259 PetscErrorCode ierr; 1260 1261 PetscFunctionBegin; 1262 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1263 PetscValidHeader(obj,2); 1264 PetscValidBoolPointer(has,3); 1265 ierr = PetscStrlen(obj->name, &len);CHKERRQ(ierr); 1266 if (!len) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named"); 1267 ierr = PetscViewerHDF5HasDataset(viewer, obj->name, has);CHKERRQ(ierr); 1268 PetscFunctionReturn(0); 1269 } 1270 1271 /*@C 1272 PetscViewerHDF5HasAttribute - Check whether an attribute exists 1273 1274 Collective 1275 1276 Input Parameters: 1277 + viewer - The HDF5 viewer 1278 . parent - The parent dataset/group name 1279 - name - The attribute name 1280 1281 Output Parameter: 1282 . has - Flag for attribute existence 1283 1284 Level: advanced 1285 1286 Notes: 1287 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. 1288 1289 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1290 @*/ 1291 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 1292 { 1293 char *parentAbsPath; 1294 PetscErrorCode ierr; 1295 1296 PetscFunctionBegin; 1297 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1298 if (parent) PetscValidCharPointer(parent,2); 1299 PetscValidCharPointer(name,3); 1300 PetscValidBoolPointer(has,4); 1301 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, parent, &parentAbsPath);CHKERRQ(ierr); 1302 ierr = PetscViewerHDF5Traverse_Internal(viewer, parentAbsPath, PETSC_FALSE, has, NULL);CHKERRQ(ierr); 1303 if (*has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parentAbsPath, name, has);CHKERRQ(ierr);} 1304 ierr = PetscFree(parentAbsPath);CHKERRQ(ierr); 1305 PetscFunctionReturn(0); 1306 } 1307 1308 /*@C 1309 PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given PetscObject by name 1310 1311 Collective 1312 1313 Input Parameters: 1314 + viewer - The HDF5 viewer 1315 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 1316 - name - The attribute name 1317 1318 Output Parameter: 1319 . has - Flag for attribute existence 1320 1321 Notes: 1322 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 1323 You might want to check first if it does using PetscViewerHDF5HasObject(). 1324 1325 Level: advanced 1326 1327 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1328 @*/ 1329 PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has) 1330 { 1331 PetscErrorCode ierr; 1332 1333 PetscFunctionBegin; 1334 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1335 PetscValidHeader(obj,2); 1336 PetscValidCharPointer(name,3); 1337 PetscValidBoolPointer(has,4); 1338 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 1339 ierr = PetscViewerHDF5HasAttribute(viewer, obj->name, name, has);CHKERRQ(ierr); 1340 PetscFunctionReturn(0); 1341 } 1342 1343 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 1344 { 1345 hid_t h5; 1346 htri_t hhas; 1347 PetscErrorCode ierr; 1348 1349 PetscFunctionBegin; 1350 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1351 PetscStackCallHDF5Return(hhas,H5Aexists_by_name,(h5, parent, name, H5P_DEFAULT)); 1352 *has = hhas ? PETSC_TRUE : PETSC_FALSE; 1353 PetscFunctionReturn(0); 1354 } 1355 1356 /* 1357 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that 1358 is attached to a communicator, in this case the attribute is a PetscViewer. 1359 */ 1360 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID; 1361 1362 /*@C 1363 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator. 1364 1365 Collective 1366 1367 Input Parameter: 1368 . comm - the MPI communicator to share the HDF5 PetscViewer 1369 1370 Level: intermediate 1371 1372 Options Database Keys: 1373 . -viewer_hdf5_filename <name> 1374 1375 Environmental variables: 1376 . PETSC_VIEWER_HDF5_FILENAME 1377 1378 Notes: 1379 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return 1380 an error code. The HDF5 PetscViewer is usually used in the form 1381 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm)); 1382 1383 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy() 1384 @*/ 1385 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) 1386 { 1387 PetscErrorCode ierr; 1388 PetscBool flg; 1389 PetscViewer viewer; 1390 char fname[PETSC_MAX_PATH_LEN]; 1391 MPI_Comm ncomm; 1392 1393 PetscFunctionBegin; 1394 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1395 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) { 1396 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,NULL); 1397 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1398 } 1399 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg); 1400 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1401 if (!flg) { /* PetscViewer not yet created */ 1402 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 1403 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1404 if (!flg) { 1405 ierr = PetscStrcpy(fname,"output.h5"); 1406 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1407 } 1408 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer); 1409 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1410 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 1411 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1412 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer); 1413 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);} 1414 } 1415 ierr = PetscCommDestroy(&ncomm); 1416 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);} 1417 PetscFunctionReturn(viewer); 1418 } 1419