1 #include <petsc/private/viewerimpl.h> /*I "petscsys.h" I*/ 2 #include <petscviewerhdf5.h> /*I "petscviewerhdf5.h" I*/ 3 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE < 10800) 4 #error "PETSc needs HDF5 version >= 1.8.0" 5 #endif 6 7 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer, const char[], PetscBool, PetscBool*, H5O_type_t*); 8 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer, const char[], const char[], PetscBool*); 9 10 typedef struct GroupList { 11 const char *name; 12 struct GroupList *next; 13 } GroupList; 14 15 typedef struct { 16 char *filename; 17 PetscFileMode btype; 18 hid_t file_id; 19 PetscInt timestep; 20 GroupList *groups; 21 PetscBool basedimension2; /* save vectors and DMDA vectors with a dimension of at least 2 even if the bs/dof is 1 */ 22 PetscBool spoutput; /* write data in single precision even if PETSc is compiled with double precision PetscReal */ 23 char *mataij_iname; 24 char *mataij_jname; 25 char *mataij_aname; 26 char *mataij_cname; 27 } PetscViewer_HDF5; 28 29 struct _n_HDF5ReadCtx { 30 hid_t file, group, dataset, dataspace, plist; 31 PetscInt timestep; 32 PetscBool complexVal, dim2, horizontal; 33 }; 34 typedef struct _n_HDF5ReadCtx* HDF5ReadCtx; 35 36 static PetscErrorCode PetscViewerHDF5GetAbsolutePath_Internal(PetscViewer viewer, const char objname[], char **fullpath) 37 { 38 const char *group; 39 char buf[PETSC_MAX_PATH_LEN]=""; 40 PetscErrorCode ierr; 41 42 PetscFunctionBegin; 43 ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr); 44 ierr = PetscStrcat(buf, group);CHKERRQ(ierr); 45 ierr = PetscStrcat(buf, "/");CHKERRQ(ierr); 46 ierr = PetscStrcat(buf, objname);CHKERRQ(ierr); 47 ierr = PetscStrallocpy(buf, fullpath);CHKERRQ(ierr); 48 PetscFunctionReturn(0); 49 } 50 51 static PetscErrorCode PetscViewerHDF5CheckNamedObject_Internal(PetscViewer viewer, PetscObject obj) 52 { 53 PetscBool has; 54 const char *group; 55 PetscErrorCode ierr; 56 57 PetscFunctionBegin; 58 if (!obj->name) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONG, "Object must be named"); 59 ierr = PetscViewerHDF5HasObject(viewer, obj, &has);CHKERRQ(ierr); 60 if (!has) { 61 ierr = PetscViewerHDF5GetGroup(viewer, &group);CHKERRQ(ierr); 62 SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Object (dataset) %s not stored in group %s", obj->name, group); 63 } 64 PetscFunctionReturn(0); 65 } 66 67 static PetscErrorCode PetscViewerSetFromOptions_HDF5(PetscOptionItems *PetscOptionsObject,PetscViewer v) 68 { 69 PetscErrorCode ierr; 70 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)v->data; 71 72 PetscFunctionBegin; 73 ierr = PetscOptionsHead(PetscOptionsObject,"HDF5 PetscViewer Options");CHKERRQ(ierr); 74 ierr = PetscOptionsBool("-viewer_hdf5_base_dimension2","1d Vectors get 2 dimensions in HDF5","PetscViewerHDF5SetBaseDimension2",hdf5->basedimension2,&hdf5->basedimension2,NULL);CHKERRQ(ierr); 75 ierr = PetscOptionsBool("-viewer_hdf5_sp_output","Force data to be written in single precision","PetscViewerHDF5SetSPOutput",hdf5->spoutput,&hdf5->spoutput,NULL);CHKERRQ(ierr); 76 ierr = PetscOptionsTail();CHKERRQ(ierr); 77 PetscFunctionReturn(0); 78 } 79 80 static PetscErrorCode PetscViewerFileClose_HDF5(PetscViewer viewer) 81 { 82 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*)viewer->data; 83 PetscErrorCode ierr; 84 85 PetscFunctionBegin; 86 ierr = PetscFree(hdf5->filename);CHKERRQ(ierr); 87 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 88 PetscFunctionReturn(0); 89 } 90 91 PetscErrorCode PetscViewerDestroy_HDF5(PetscViewer viewer) 92 { 93 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 94 PetscErrorCode ierr; 95 96 PetscFunctionBegin; 97 ierr = PetscViewerFileClose_HDF5(viewer);CHKERRQ(ierr); 98 while (hdf5->groups) { 99 GroupList *tmp = hdf5->groups->next; 100 101 ierr = PetscFree(hdf5->groups->name);CHKERRQ(ierr); 102 ierr = PetscFree(hdf5->groups);CHKERRQ(ierr); 103 hdf5->groups = tmp; 104 } 105 ierr = PetscFree(hdf5->mataij_iname);CHKERRQ(ierr); 106 ierr = PetscFree(hdf5->mataij_jname);CHKERRQ(ierr); 107 ierr = PetscFree(hdf5->mataij_aname);CHKERRQ(ierr); 108 ierr = PetscFree(hdf5->mataij_cname);CHKERRQ(ierr); 109 ierr = PetscFree(hdf5);CHKERRQ(ierr); 110 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr); 111 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr); 112 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr); 113 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetBaseDimension2_C",NULL);CHKERRQ(ierr); 114 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetSPOutput_C",NULL);CHKERRQ(ierr); 115 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5SetAIJNames_C",NULL);CHKERRQ(ierr); 116 ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerHDF5GetAIJNames_C",NULL);CHKERRQ(ierr); 117 PetscFunctionReturn(0); 118 } 119 120 PetscErrorCode PetscViewerFileSetMode_HDF5(PetscViewer viewer, PetscFileMode type) 121 { 122 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 123 124 PetscFunctionBegin; 125 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 126 hdf5->btype = type; 127 PetscFunctionReturn(0); 128 } 129 130 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 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 PetscErrorCode PetscViewerFileSetName_HDF5(PetscViewer viewer, const char name[]) 279 { 280 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 281 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 282 MPI_Info info = MPI_INFO_NULL; 283 #endif 284 hid_t plist_id; 285 PetscErrorCode ierr; 286 287 PetscFunctionBegin; 288 if (hdf5->file_id) PetscStackCallHDF5(H5Fclose,(hdf5->file_id)); 289 if (hdf5->filename) {ierr = PetscFree(hdf5->filename);CHKERRQ(ierr);} 290 ierr = PetscStrallocpy(name, &hdf5->filename);CHKERRQ(ierr); 291 /* Set up file access property list with parallel I/O access */ 292 PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_FILE_ACCESS)); 293 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 294 PetscStackCallHDF5(H5Pset_fapl_mpio,(plist_id, PetscObjectComm((PetscObject)viewer), info)); 295 #endif 296 /* Create or open the file collectively */ 297 switch (hdf5->btype) { 298 case FILE_MODE_READ: 299 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDONLY, plist_id)); 300 break; 301 case FILE_MODE_APPEND: 302 PetscStackCallHDF5Return(hdf5->file_id,H5Fopen,(name, H5F_ACC_RDWR, plist_id)); 303 break; 304 case FILE_MODE_WRITE: 305 PetscStackCallHDF5Return(hdf5->file_id,H5Fcreate,(name, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id)); 306 break; 307 default: 308 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 309 } 310 if (hdf5->file_id < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB, "H5Fcreate failed for %s", name); 311 PetscStackCallHDF5(H5Pclose,(plist_id)); 312 PetscFunctionReturn(0); 313 } 314 315 static PetscErrorCode PetscViewerFileGetName_HDF5(PetscViewer viewer,const char **name) 316 { 317 PetscViewer_HDF5 *vhdf5 = (PetscViewer_HDF5*)viewer->data; 318 319 PetscFunctionBegin; 320 *name = vhdf5->filename; 321 PetscFunctionReturn(0); 322 } 323 324 PetscErrorCode PetscViewerHDF5SetAIJNames_HDF5(PetscViewer viewer, const char iname[], const char jname[], const char aname[], const char cname[]) 325 { 326 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 327 PetscErrorCode ierr; 328 329 PetscFunctionBegin; 330 ierr = PetscFree(hdf5->mataij_iname);CHKERRQ(ierr); 331 ierr = PetscFree(hdf5->mataij_jname);CHKERRQ(ierr); 332 ierr = PetscFree(hdf5->mataij_aname);CHKERRQ(ierr); 333 ierr = PetscFree(hdf5->mataij_cname);CHKERRQ(ierr); 334 ierr = PetscStrallocpy(iname,&hdf5->mataij_iname);CHKERRQ(ierr); 335 ierr = PetscStrallocpy(jname,&hdf5->mataij_jname);CHKERRQ(ierr); 336 ierr = PetscStrallocpy(aname,&hdf5->mataij_aname);CHKERRQ(ierr); 337 ierr = PetscStrallocpy(cname,&hdf5->mataij_cname);CHKERRQ(ierr); 338 PetscFunctionReturn(0); 339 } 340 341 /*@C 342 PetscViewerHDF5SetAIJNames - Set the names of the datasets representing the three AIJ (CRS) arrays and the name of the attribute storing the number of columns within the HDF5 file. 343 344 Collective on PetscViewer 345 346 Input Parameters: 347 + viewer - the PetscViewer; either ASCII or binary 348 . iname - name of dataset i representing row pointers; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 349 . jname - name of dataset j representing column indices 350 . aname - name of dataset a representing matrix values 351 - cname - name of attribute stoting column count 352 353 Level: advanced 354 355 Notes: 356 Current defaults are (iname, jname, aname, cname) = ("jc", "ir", "data", "MATLAB_sparse") so that MAT files can be readily loaded. 357 358 .seealso: MatLoad(), PetscViewerCreate(), PetscViewerSetType(), PETSCVIEWERHDF5, PetscViewerHDF5GetAIJNames() 359 @*/ 360 PetscErrorCode PetscViewerHDF5SetAIJNames(PetscViewer viewer, const char iname[], const char jname[], const char aname[], const char cname[]) 361 { 362 PetscErrorCode ierr; 363 364 PetscFunctionBegin; 365 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 366 PetscValidCharPointer(iname,2); 367 PetscValidCharPointer(jname,3); 368 PetscValidCharPointer(aname,4); 369 PetscValidCharPointer(cname,5); 370 ierr = PetscTryMethod(viewer,"PetscViewerHDF5SetAIJNames_C",(PetscViewer,const char[],const char[],const char[],const char[]),(viewer,iname,jname,aname,cname));CHKERRQ(ierr); 371 PetscFunctionReturn(0); 372 } 373 374 PetscErrorCode PetscViewerHDF5GetAIJNames_HDF5(PetscViewer viewer, const char *iname[], const char *jname[], const char *aname[], const char *cname[]) 375 { 376 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 377 378 PetscFunctionBegin; 379 *iname = hdf5->mataij_iname; 380 *jname = hdf5->mataij_jname; 381 *aname = hdf5->mataij_aname; 382 *cname = hdf5->mataij_cname; 383 PetscFunctionReturn(0); 384 } 385 386 /*@C 387 PetscViewerHDF5GetAIJNames - Get the names of the datasets representing the three AIJ (CRS) arrays and the name of the attribute storing the number of columns within the HDF5 file. 388 389 Collective on PetscViewer 390 391 Input Parameters: 392 . viewer - the PetscViewer; either ASCII or binary 393 394 Output Parameters: 395 + iname - name of dataset i representing row pointers; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 396 . jname - name of dataset j representing column indices 397 . aname - name of dataset a representing matrix values 398 - cname - name of attribute stoting column count 399 400 Level: advanced 401 402 Notes: 403 Current defaults are (iname, jname, aname, cname) = ("jc", "ir", "data", "MATLAB_sparse") so that MAT files can be readily loaded. 404 405 .seealso: MatLoad(), PetscViewerCreate(), PetscViewerSetType(), PETSCVIEWERHDF5, PetscViewerHDF5SetAIJNames() 406 @*/ 407 PetscErrorCode PetscViewerHDF5GetAIJNames(PetscViewer viewer, const char *iname[], const char *jname[], const char *aname[], const char *cname[]) 408 { 409 PetscErrorCode ierr; 410 411 PetscFunctionBegin; 412 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 413 PetscValidPointer(iname,2); 414 PetscValidPointer(jname,3); 415 PetscValidPointer(aname,4); 416 PetscValidPointer(cname,5); 417 ierr = PetscUseMethod(viewer,"PetscViewerHDF5GetAIJNames_C",(PetscViewer,const char*[],const char*[],const char*[],const char*[]),(viewer,iname,jname,aname,cname));CHKERRQ(ierr); 418 PetscFunctionReturn(0); 419 } 420 421 /*MC 422 PETSCVIEWERHDF5 - A viewer that writes to an HDF5 file 423 424 425 .seealso: PetscViewerHDF5Open(), PetscViewerStringSPrintf(), PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSCVIEWERSOCKET, 426 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSTRING, 427 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, 428 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType() 429 430 Level: beginner 431 M*/ 432 433 PETSC_EXTERN PetscErrorCode PetscViewerCreate_HDF5(PetscViewer v) 434 { 435 PetscViewer_HDF5 *hdf5; 436 PetscErrorCode ierr; 437 438 PetscFunctionBegin; 439 ierr = PetscNewLog(v,&hdf5);CHKERRQ(ierr); 440 441 v->data = (void*) hdf5; 442 v->ops->destroy = PetscViewerDestroy_HDF5; 443 v->ops->setfromoptions = PetscViewerSetFromOptions_HDF5; 444 v->ops->flush = 0; 445 hdf5->btype = (PetscFileMode) -1; 446 hdf5->filename = 0; 447 hdf5->timestep = -1; 448 hdf5->groups = NULL; 449 450 /* ir and jc are deliberately swapped as MATLAB uses column-major format */ 451 ierr = PetscStrallocpy("jc", &hdf5->mataij_iname);CHKERRQ(ierr); 452 ierr = PetscStrallocpy("ir", &hdf5->mataij_jname);CHKERRQ(ierr); 453 ierr = PetscStrallocpy("data",&hdf5->mataij_aname);CHKERRQ(ierr); 454 ierr = PetscStrallocpy("MATLAB_sparse", &hdf5->mataij_cname);CHKERRQ(ierr); 455 456 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_HDF5);CHKERRQ(ierr); 457 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_HDF5);CHKERRQ(ierr); 458 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_HDF5);CHKERRQ(ierr); 459 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetBaseDimension2_C",PetscViewerHDF5SetBaseDimension2_HDF5);CHKERRQ(ierr); 460 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetSPOutput_C",PetscViewerHDF5SetSPOutput_HDF5);CHKERRQ(ierr); 461 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5SetAIJNames_C",PetscViewerHDF5SetAIJNames_HDF5);CHKERRQ(ierr); 462 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerHDF5GetAIJNames_C",PetscViewerHDF5GetAIJNames_HDF5);CHKERRQ(ierr); 463 PetscFunctionReturn(0); 464 } 465 466 /*@C 467 PetscViewerHDF5Open - Opens a file for HDF5 input/output. 468 469 Collective on MPI_Comm 470 471 Input Parameters: 472 + comm - MPI communicator 473 . name - name of file 474 - type - type of file 475 $ FILE_MODE_WRITE - create new file for binary output 476 $ FILE_MODE_READ - open existing file for binary input 477 $ FILE_MODE_APPEND - open existing file for binary output 478 479 Output Parameter: 480 . hdf5v - PetscViewer for HDF5 input/output to use with the specified file 481 482 Options Database: 483 . -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 484 . -viewer_hdf5_sp_output - forces (if true) the viewer to write data in single precision independent on the precision of PetscReal 485 486 Level: beginner 487 488 Note: 489 This PetscViewer should be destroyed with PetscViewerDestroy(). 490 491 Concepts: HDF5 files 492 Concepts: PetscViewerHDF5^creating 493 494 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerHDF5SetBaseDimension2(), 495 PetscViewerHDF5SetSPOutput(), PetscViewerHDF5GetBaseDimension2(), VecView(), MatView(), VecLoad(), 496 MatLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName() 497 @*/ 498 PetscErrorCode PetscViewerHDF5Open(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *hdf5v) 499 { 500 PetscErrorCode ierr; 501 502 PetscFunctionBegin; 503 ierr = PetscViewerCreate(comm, hdf5v);CHKERRQ(ierr); 504 ierr = PetscViewerSetType(*hdf5v, PETSCVIEWERHDF5);CHKERRQ(ierr); 505 ierr = PetscViewerFileSetMode(*hdf5v, type);CHKERRQ(ierr); 506 ierr = PetscViewerFileSetName(*hdf5v, name);CHKERRQ(ierr); 507 PetscFunctionReturn(0); 508 } 509 510 /*@C 511 PetscViewerHDF5GetFileId - Retrieve the file id, this file ID then can be used in direct HDF5 calls 512 513 Not collective 514 515 Input Parameter: 516 . viewer - the PetscViewer 517 518 Output Parameter: 519 . file_id - The file id 520 521 Level: intermediate 522 523 .seealso: PetscViewerHDF5Open() 524 @*/ 525 PetscErrorCode PetscViewerHDF5GetFileId(PetscViewer viewer, hid_t *file_id) 526 { 527 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 528 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 531 if (file_id) *file_id = hdf5->file_id; 532 PetscFunctionReturn(0); 533 } 534 535 /*@C 536 PetscViewerHDF5PushGroup - Set the current HDF5 group for output 537 538 Not collective 539 540 Input Parameters: 541 + viewer - the PetscViewer 542 - name - The group name 543 544 Level: intermediate 545 546 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup() 547 @*/ 548 PetscErrorCode PetscViewerHDF5PushGroup(PetscViewer viewer, const char *name) 549 { 550 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 551 GroupList *groupNode; 552 PetscErrorCode ierr; 553 554 PetscFunctionBegin; 555 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 556 PetscValidCharPointer(name,2); 557 ierr = PetscNew(&groupNode);CHKERRQ(ierr); 558 ierr = PetscStrallocpy(name, (char**) &groupNode->name);CHKERRQ(ierr); 559 560 groupNode->next = hdf5->groups; 561 hdf5->groups = groupNode; 562 PetscFunctionReturn(0); 563 } 564 565 /*@ 566 PetscViewerHDF5PopGroup - Return the current HDF5 group for output to the previous value 567 568 Not collective 569 570 Input Parameter: 571 . viewer - the PetscViewer 572 573 Level: intermediate 574 575 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5GetGroup(),PetscViewerHDF5OpenGroup() 576 @*/ 577 PetscErrorCode PetscViewerHDF5PopGroup(PetscViewer viewer) 578 { 579 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 580 GroupList *groupNode; 581 PetscErrorCode ierr; 582 583 PetscFunctionBegin; 584 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 585 if (!hdf5->groups) SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "HDF5 group stack is empty, cannot pop"); 586 groupNode = hdf5->groups; 587 hdf5->groups = hdf5->groups->next; 588 ierr = PetscFree(groupNode->name);CHKERRQ(ierr); 589 ierr = PetscFree(groupNode);CHKERRQ(ierr); 590 PetscFunctionReturn(0); 591 } 592 593 /*@C 594 PetscViewerHDF5GetGroup - Get the current HDF5 group name (full path), set with PetscViewerHDF5PushGroup()/PetscViewerHDF5PopGroup(). 595 If none has been assigned, returns NULL. 596 597 Not collective 598 599 Input Parameter: 600 . viewer - the PetscViewer 601 602 Output Parameter: 603 . name - The group name 604 605 Level: intermediate 606 607 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5OpenGroup() 608 @*/ 609 PetscErrorCode PetscViewerHDF5GetGroup(PetscViewer viewer, const char **name) 610 { 611 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5 *) viewer->data; 612 613 PetscFunctionBegin; 614 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 615 PetscValidPointer(name,2); 616 if (hdf5->groups) *name = hdf5->groups->name; 617 else *name = NULL; 618 PetscFunctionReturn(0); 619 } 620 621 /*@ 622 PetscViewerHDF5OpenGroup - Open the HDF5 group with the name (full path) returned by PetscViewerHDF5GetGroup(), 623 and return this group's ID and file ID. 624 If PetscViewerHDF5GetGroup() yields NULL, then group ID is file ID. 625 626 Not collective 627 628 Input Parameter: 629 . viewer - the PetscViewer 630 631 Output Parameter: 632 + fileId - The HDF5 file ID 633 - groupId - The HDF5 group ID 634 635 Level: intermediate 636 637 .seealso: PetscViewerHDF5Open(),PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 638 @*/ 639 PetscErrorCode PetscViewerHDF5OpenGroup(PetscViewer viewer, hid_t *fileId, hid_t *groupId) 640 { 641 hid_t file_id, group; 642 htri_t found; 643 const char *groupName = NULL; 644 PetscErrorCode ierr; 645 646 PetscFunctionBegin; 647 ierr = PetscViewerHDF5GetFileId(viewer, &file_id);CHKERRQ(ierr); 648 ierr = PetscViewerHDF5GetGroup(viewer, &groupName);CHKERRQ(ierr); 649 /* Open group */ 650 if (groupName) { 651 PetscBool root; 652 653 ierr = PetscStrcmp(groupName, "/", &root);CHKERRQ(ierr); 654 PetscStackCall("H5Lexists",found = H5Lexists(file_id, groupName, H5P_DEFAULT)); 655 if (!root && (found <= 0)) { 656 PetscStackCallHDF5Return(group,H5Gcreate2,(file_id, groupName, 0, H5P_DEFAULT, H5P_DEFAULT)); 657 PetscStackCallHDF5(H5Gclose,(group)); 658 } 659 PetscStackCallHDF5Return(group,H5Gopen2,(file_id, groupName, H5P_DEFAULT)); 660 } else group = file_id; 661 662 *fileId = file_id; 663 *groupId = group; 664 PetscFunctionReturn(0); 665 } 666 667 /*@ 668 PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time. 669 670 Not collective 671 672 Input Parameter: 673 . viewer - the PetscViewer 674 675 Level: intermediate 676 677 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep() 678 @*/ 679 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) 680 { 681 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 682 683 PetscFunctionBegin; 684 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 685 ++hdf5->timestep; 686 PetscFunctionReturn(0); 687 } 688 689 /*@ 690 PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep 691 of -1 disables blocking with timesteps. 692 693 Not collective 694 695 Input Parameters: 696 + viewer - the PetscViewer 697 - timestep - The timestep number 698 699 Level: intermediate 700 701 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 702 @*/ 703 PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) 704 { 705 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 706 707 PetscFunctionBegin; 708 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 709 hdf5->timestep = timestep; 710 PetscFunctionReturn(0); 711 } 712 713 /*@ 714 PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time. 715 716 Not collective 717 718 Input Parameter: 719 . viewer - the PetscViewer 720 721 Output Parameter: 722 . timestep - The timestep number 723 724 Level: intermediate 725 726 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep() 727 @*/ 728 PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) 729 { 730 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 731 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 734 PetscValidPointer(timestep,2); 735 *timestep = hdf5->timestep; 736 PetscFunctionReturn(0); 737 } 738 739 /*@C 740 PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name. 741 742 Not collective 743 744 Input Parameter: 745 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 746 747 Output Parameter: 748 . mtype - the MPI datatype (for example MPI_DOUBLE, ...) 749 750 Level: advanced 751 752 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 753 @*/ 754 PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) 755 { 756 PetscFunctionBegin; 757 if (ptype == PETSC_INT) 758 #if defined(PETSC_USE_64BIT_INDICES) 759 *htype = H5T_NATIVE_LLONG; 760 #else 761 *htype = H5T_NATIVE_INT; 762 #endif 763 else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE; 764 else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG; 765 else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT; 766 else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_DOUBLE; 767 else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_DOUBLE; 768 else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT; 769 else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR; 770 else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR; 771 else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1); 772 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype"); 773 PetscFunctionReturn(0); 774 } 775 776 /*@C 777 PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name 778 779 Not collective 780 781 Input Parameter: 782 . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...) 783 784 Output Parameter: 785 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 786 787 Level: advanced 788 789 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 790 @*/ 791 PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) 792 { 793 PetscFunctionBegin; 794 #if defined(PETSC_USE_64BIT_INDICES) 795 if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG; 796 else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT; 797 #else 798 if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT; 799 #endif 800 else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE; 801 else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG; 802 else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT; 803 else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT; 804 else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR; 805 else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR; 806 else if (htype == H5T_C_S1) *ptype = PETSC_STRING; 807 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype"); 808 PetscFunctionReturn(0); 809 } 810 811 /*@C 812 PetscViewerHDF5WriteAttribute - Write an attribute 813 814 Input Parameters: 815 + viewer - The HDF5 viewer 816 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute. 817 . name - The attribute name 818 . datatype - The attribute type 819 - value - The attribute value 820 821 Level: advanced 822 823 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 824 @*/ 825 PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscDataType datatype, const void *value) 826 { 827 char *parent; 828 hid_t h5, dataspace, obj, attribute, dtype; 829 PetscBool has; 830 PetscErrorCode ierr; 831 832 PetscFunctionBegin; 833 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 834 if (dataset) PetscValidCharPointer(dataset, 2); 835 PetscValidCharPointer(name, 3); 836 PetscValidPointer(value, 5); 837 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr); 838 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_TRUE, NULL, NULL);CHKERRQ(ierr); 839 ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, &has);CHKERRQ(ierr); 840 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 841 if (datatype == PETSC_STRING) { 842 size_t len; 843 ierr = PetscStrlen((const char *) value, &len);CHKERRQ(ierr); 844 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 845 } 846 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 847 PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR)); 848 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 849 if (has) { 850 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 851 } else { 852 PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT)); 853 } 854 PetscStackCallHDF5(H5Awrite,(attribute, dtype, value)); 855 if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype)); 856 PetscStackCallHDF5(H5Aclose,(attribute)); 857 PetscStackCallHDF5(H5Oclose,(obj)); 858 PetscStackCallHDF5(H5Sclose,(dataspace)); 859 ierr = PetscFree(parent);CHKERRQ(ierr); 860 PetscFunctionReturn(0); 861 } 862 863 /*@C 864 PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given PetscObject by name 865 866 Input Parameters: 867 + viewer - The HDF5 viewer 868 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 869 . name - The attribute name 870 . datatype - The attribute type 871 - value - The attribute value 872 873 Notes: 874 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 875 You might want to check first if it does using PetscViewerHDF5HasObject(). 876 877 Level: advanced 878 879 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 880 @*/ 881 PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value) 882 { 883 PetscErrorCode ierr; 884 885 PetscFunctionBegin; 886 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 887 PetscValidHeader(obj,2); 888 PetscValidCharPointer(name,3); 889 PetscValidPointer(value,5); 890 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 891 ierr = PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr); 892 PetscFunctionReturn(0); 893 } 894 895 /*@C 896 PetscViewerHDF5ReadAttribute - Read an attribute 897 898 Input Parameters: 899 + viewer - The HDF5 viewer 900 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute. 901 . name - The attribute name 902 - datatype - The attribute type 903 904 Output Parameter: 905 . value - The attribute value 906 907 Level: advanced 908 909 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 910 @*/ 911 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscDataType datatype, void *value) 912 { 913 char *parent; 914 hid_t h5, obj, attribute, atype, dtype; 915 PetscBool has; 916 PetscErrorCode ierr; 917 918 PetscFunctionBegin; 919 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 920 if (dataset) PetscValidCharPointer(dataset, 2); 921 PetscValidCharPointer(name, 3); 922 PetscValidPointer(value, 5); 923 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr); 924 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, &has, NULL);CHKERRQ(ierr); 925 if (has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, &has);CHKERRQ(ierr);} 926 if (!has) SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist", parent, name); 927 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 928 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 929 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 930 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 931 if (datatype == PETSC_STRING) { 932 size_t len; 933 PetscStackCallHDF5Return(atype,H5Aget_type,(attribute)); 934 PetscStackCallHDF5Return(len,H5Tget_size,(atype)); 935 PetscStackCallHDF5(H5Tclose,(atype)); 936 ierr = PetscMalloc((len+1) * sizeof(char *), &value);CHKERRQ(ierr); 937 } 938 PetscStackCallHDF5(H5Aread,(attribute, dtype, value)); 939 PetscStackCallHDF5(H5Aclose,(attribute)); 940 /* H5Oclose can be used to close groups, datasets, or committed datatypes */ 941 PetscStackCallHDF5(H5Oclose,(obj)); 942 ierr = PetscFree(parent);CHKERRQ(ierr); 943 PetscFunctionReturn(0); 944 } 945 946 /*@C 947 PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given PetscObject by name 948 949 Input Parameters: 950 + viewer - The HDF5 viewer 951 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 952 . name - The attribute name 953 - datatype - The attribute type 954 955 Output Parameter: 956 . value - The attribute value 957 958 Notes: 959 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 960 You might want to check first if it does using PetscViewerHDF5HasObject(). 961 962 Level: advanced 963 964 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute() PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 965 @*/ 966 PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *value) 967 { 968 PetscErrorCode ierr; 969 970 PetscFunctionBegin; 971 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 972 PetscValidHeader(obj,2); 973 PetscValidCharPointer(name,3); 974 PetscValidPointer(value, 5); 975 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 976 ierr = PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr); 977 PetscFunctionReturn(0); 978 } 979 980 PETSC_STATIC_INLINE PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_) 981 { 982 htri_t exists; 983 hid_t group; 984 985 PetscFunctionBegin; 986 PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT)); 987 if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT)); 988 if (!exists && createGroup) { 989 PetscStackCallHDF5Return(group,H5Gcreate2,(h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)); 990 PetscStackCallHDF5(H5Gclose,(group)); 991 exists = PETSC_TRUE; 992 } 993 *exists_ = (PetscBool) exists; 994 PetscFunctionReturn(0); 995 } 996 997 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype) 998 { 999 hid_t h5; 1000 PetscBool exists=PETSC_FALSE; 1001 PetscInt i,n; 1002 char **hierarchy; 1003 char buf[PETSC_MAX_PATH_LEN]=""; 1004 PetscErrorCode ierr; 1005 1006 PetscFunctionBegin; 1007 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1008 PetscValidCharPointer(name, 2); 1009 if (has) { 1010 PetscValidIntPointer(has, 3); 1011 *has = PETSC_FALSE; 1012 } 1013 if (otype) { 1014 PetscValidIntPointer(otype, 4); 1015 *otype = H5O_TYPE_UNKNOWN; 1016 } 1017 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1018 1019 /* 1020 Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing. 1021 Hence, each of them needs to be tested separately: 1022 1) whether it's a valid link 1023 2) whether this link resolves to an object 1024 See H5Oexists_by_name() documentation. 1025 */ 1026 ierr = PetscStrToArray(name,'/',&n,&hierarchy);CHKERRQ(ierr); 1027 if (!n) { 1028 /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */ 1029 if (has) *has = PETSC_TRUE; 1030 if (otype) *otype = H5O_TYPE_GROUP; 1031 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1032 PetscFunctionReturn(0); 1033 } 1034 for (i=0; i<n; i++) { 1035 ierr = PetscStrcat(buf,"/");CHKERRQ(ierr); 1036 ierr = PetscStrcat(buf,hierarchy[i]);CHKERRQ(ierr); 1037 ierr = PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists);CHKERRQ(ierr); 1038 if (!exists) break; 1039 } 1040 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1041 1042 /* If the object exists, get its type */ 1043 if (exists && otype) { 1044 H5O_info_t info; 1045 1046 PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT)); 1047 *otype = info.type; 1048 } 1049 if (has) *has = exists; 1050 PetscFunctionReturn(0); 1051 } 1052 1053 /*@ 1054 PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file 1055 1056 Input Parameters: 1057 . viewer - The HDF5 viewer 1058 1059 Output Parameter: 1060 . has - Flag for group existence 1061 1062 Notes: 1063 If the path exists but is not a group, this returns PETSC_FALSE as well. 1064 1065 Level: advanced 1066 1067 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5OpenGroup() 1068 @*/ 1069 PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, PetscBool *has) 1070 { 1071 H5O_type_t type; 1072 const char *name; 1073 PetscErrorCode ierr; 1074 1075 PetscFunctionBegin; 1076 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1077 PetscValidIntPointer(has,2); 1078 ierr = PetscViewerHDF5GetGroup(viewer, &name);CHKERRQ(ierr); 1079 ierr = PetscViewerHDF5Traverse_Internal(viewer, name, PETSC_FALSE, has, &type);CHKERRQ(ierr); 1080 *has = (type == H5O_TYPE_GROUP) ? PETSC_TRUE : PETSC_FALSE; 1081 PetscFunctionReturn(0); 1082 } 1083 1084 /*@ 1085 PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group 1086 1087 Input Parameters: 1088 + viewer - The HDF5 viewer 1089 - obj - The named object 1090 1091 Output Parameter: 1092 . has - Flag for dataset existence; PETSC_FALSE for unnamed object 1093 1094 Notes: 1095 If the path exists but is not a dataset, this returns PETSC_FALSE as well. 1096 1097 Level: advanced 1098 1099 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1100 @*/ 1101 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) 1102 { 1103 H5O_type_t type; 1104 char *path; 1105 PetscErrorCode ierr; 1106 1107 PetscFunctionBegin; 1108 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1109 PetscValidHeader(obj,2); 1110 PetscValidIntPointer(has,3); 1111 *has = PETSC_FALSE; 1112 if (!obj->name) PetscFunctionReturn(0); 1113 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, obj->name, &path);CHKERRQ(ierr); 1114 ierr = PetscViewerHDF5Traverse_Internal(viewer, path, PETSC_FALSE, has, &type);CHKERRQ(ierr); 1115 *has = (type == H5O_TYPE_DATASET) ? PETSC_TRUE : PETSC_FALSE; 1116 ierr = PetscFree(path);CHKERRQ(ierr); 1117 PetscFunctionReturn(0); 1118 } 1119 1120 /*@C 1121 PetscViewerHDF5HasAttribute - Check whether an attribute exists 1122 1123 Input Parameters: 1124 + viewer - The HDF5 viewer 1125 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute. 1126 - name - The attribute name 1127 1128 Output Parameter: 1129 . has - Flag for attribute existence 1130 1131 Level: advanced 1132 1133 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1134 @*/ 1135 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscBool *has) 1136 { 1137 char *parent; 1138 PetscErrorCode ierr; 1139 1140 PetscFunctionBegin; 1141 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1142 if (dataset) PetscValidCharPointer(dataset,2); 1143 PetscValidCharPointer(name,3); 1144 PetscValidIntPointer(has,4); 1145 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr); 1146 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, has, NULL);CHKERRQ(ierr); 1147 if (*has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, has);CHKERRQ(ierr);} 1148 ierr = PetscFree(parent);CHKERRQ(ierr); 1149 PetscFunctionReturn(0); 1150 } 1151 1152 /*@C 1153 PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given PetscObject by name 1154 1155 Input Parameters: 1156 + viewer - The HDF5 viewer 1157 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 1158 - name - The attribute name 1159 1160 Output Parameter: 1161 . has - Flag for attribute existence 1162 1163 Notes: 1164 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 1165 You might want to check first if it does using PetscViewerHDF5HasObject(). 1166 1167 Level: advanced 1168 1169 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1170 @*/ 1171 PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has) 1172 { 1173 PetscErrorCode ierr; 1174 1175 PetscFunctionBegin; 1176 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1177 PetscValidHeader(obj,2); 1178 PetscValidCharPointer(name,3); 1179 PetscValidIntPointer(has,4); 1180 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 1181 ierr = PetscViewerHDF5HasAttribute(viewer, obj->name, name, has);CHKERRQ(ierr); 1182 PetscFunctionReturn(0); 1183 } 1184 1185 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 1186 { 1187 hid_t h5; 1188 htri_t hhas; 1189 PetscErrorCode ierr; 1190 1191 PetscFunctionBegin; 1192 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1193 PetscStackCallHDF5Return(hhas,H5Aexists_by_name,(h5, parent, name, H5P_DEFAULT)); 1194 *has = hhas ? PETSC_TRUE : PETSC_FALSE; 1195 PetscFunctionReturn(0); 1196 } 1197 1198 static PetscErrorCode PetscViewerHDF5ReadInitialize_Private(PetscViewer viewer, const char name[], HDF5ReadCtx *ctx) 1199 { 1200 HDF5ReadCtx h=NULL; 1201 PetscErrorCode ierr; 1202 1203 PetscFunctionBegin; 1204 ierr = PetscNew(&h);CHKERRQ(ierr); 1205 ierr = PetscViewerHDF5OpenGroup(viewer, &h->file, &h->group);CHKERRQ(ierr); 1206 PetscStackCallHDF5Return(h->dataset,H5Dopen2,(h->group, name, H5P_DEFAULT)); 1207 PetscStackCallHDF5Return(h->dataspace,H5Dget_space,(h->dataset)); 1208 ierr = PetscViewerHDF5GetTimestep(viewer, &h->timestep);CHKERRQ(ierr); 1209 ierr = PetscViewerHDF5HasAttribute(viewer,name,"complex",&h->complexVal);CHKERRQ(ierr); 1210 /* MATLAB stores column vectors horizontally */ 1211 ierr = PetscViewerHDF5HasAttribute(viewer,name,"MATLAB_class",&h->horizontal);CHKERRQ(ierr); 1212 /* Create property list for collective dataset read */ 1213 PetscStackCallHDF5Return(h->plist,H5Pcreate,(H5P_DATASET_XFER)); 1214 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 1215 PetscStackCallHDF5(H5Pset_dxpl_mpio,(h->plist, H5FD_MPIO_COLLECTIVE)); 1216 #endif 1217 /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */ 1218 *ctx = h; 1219 PetscFunctionReturn(0); 1220 } 1221 1222 static PetscErrorCode PetscViewerHDF5ReadFinalize_Private(PetscViewer viewer, HDF5ReadCtx *ctx) 1223 { 1224 HDF5ReadCtx h; 1225 PetscErrorCode ierr; 1226 1227 PetscFunctionBegin; 1228 h = *ctx; 1229 PetscStackCallHDF5(H5Pclose,(h->plist)); 1230 if (h->group != h->file) PetscStackCallHDF5(H5Gclose,(h->group)); 1231 PetscStackCallHDF5(H5Sclose,(h->dataspace)); 1232 PetscStackCallHDF5(H5Dclose,(h->dataset)); 1233 ierr = PetscFree(*ctx);CHKERRQ(ierr); 1234 PetscFunctionReturn(0); 1235 } 1236 1237 static PetscErrorCode PetscViewerHDF5ReadSizes_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout *map_) 1238 { 1239 int rdim, dim; 1240 hsize_t dims[4]; 1241 PetscInt bsInd, lenInd, bs, len, N; 1242 PetscLayout map; 1243 PetscErrorCode ierr; 1244 1245 PetscFunctionBegin; 1246 if (!(*map_)) { 1247 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)viewer),map_);CHKERRQ(ierr); 1248 } 1249 map = *map_; 1250 /* calculate expected number of dimensions */ 1251 dim = 0; 1252 if (ctx->timestep >= 0) ++dim; 1253 ++dim; /* length in blocks */ 1254 if (ctx->complexVal) ++dim; 1255 /* get actual number of dimensions in dataset */ 1256 PetscStackCallHDF5Return(rdim,H5Sget_simple_extent_dims,(ctx->dataspace, dims, NULL)); 1257 /* calculate expected dimension indices */ 1258 lenInd = 0; 1259 if (ctx->timestep >= 0) ++lenInd; 1260 bsInd = lenInd + 1; 1261 ctx->dim2 = PETSC_FALSE; 1262 if (rdim == dim) { 1263 bs = 1; /* support vectors stored as 1D array */ 1264 } else if (rdim == dim+1) { 1265 bs = (PetscInt) dims[bsInd]; 1266 if (bs == 1) ctx->dim2 = PETSC_TRUE; /* vector with blocksize of 1, still stored as 2D array */ 1267 } else { 1268 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Dimension of array in file %d not %d as expected", rdim, dim); 1269 } 1270 len = dims[lenInd]; 1271 if (ctx->horizontal) { 1272 if (len != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot have horizontal array with number of rows > 1. In case of MATLAB MAT-file, vectors must be saved as column vectors."); 1273 len = bs; 1274 bs = 1; 1275 } 1276 N = (PetscInt) len*bs; 1277 1278 /* Set Vec sizes,blocksize,and type if not already set */ 1279 if (map->bs < 0) { 1280 ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr); 1281 } else if (map->bs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Block size of array in file is %D, not %D as expected",bs,map->bs); 1282 if (map->N < 0) { 1283 ierr = PetscLayoutSetSize(map, N);CHKERRQ(ierr); 1284 } else if (map->N != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Global size of array in file is %D, not %D as expected",N,map->N); 1285 PetscFunctionReturn(0); 1286 } 1287 1288 static PetscErrorCode PetscViewerHDF5ReadSelectHyperslab_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout map, hid_t *memspace) 1289 { 1290 hsize_t count[4], offset[4]; 1291 int dim; 1292 PetscInt bs, n, low; 1293 PetscErrorCode ierr; 1294 1295 PetscFunctionBegin; 1296 /* Compute local size and ownership range */ 1297 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1298 ierr = PetscLayoutGetBlockSize(map, &bs);CHKERRQ(ierr); 1299 ierr = PetscLayoutGetLocalSize(map, &n);CHKERRQ(ierr); 1300 ierr = PetscLayoutGetRange(map, &low, NULL);CHKERRQ(ierr); 1301 1302 /* Each process defines a dataset and reads it from the hyperslab in the file */ 1303 dim = 0; 1304 if (ctx->timestep >= 0) { 1305 count[dim] = 1; 1306 offset[dim] = ctx->timestep; 1307 ++dim; 1308 } 1309 if (ctx->horizontal) { 1310 count[dim] = 1; 1311 offset[dim] = 0; 1312 ++dim; 1313 } 1314 { 1315 ierr = PetscHDF5IntCast(n/bs, &count[dim]);CHKERRQ(ierr); 1316 ierr = PetscHDF5IntCast(low/bs, &offset[dim]);CHKERRQ(ierr); 1317 ++dim; 1318 } 1319 if (bs > 1 || ctx->dim2) { 1320 if (PetscUnlikely(ctx->horizontal)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "cannot have horizontal array with blocksize > 1"); 1321 count[dim] = bs; 1322 offset[dim] = 0; 1323 ++dim; 1324 } 1325 if (ctx->complexVal) { 1326 count[dim] = 2; 1327 offset[dim] = 0; 1328 ++dim; 1329 } 1330 PetscStackCallHDF5Return(*memspace,H5Screate_simple,(dim, count, NULL)); 1331 PetscStackCallHDF5(H5Sselect_hyperslab,(ctx->dataspace, H5S_SELECT_SET, offset, NULL, count, NULL)); 1332 PetscFunctionReturn(0); 1333 } 1334 1335 static PetscErrorCode PetscViewerHDF5ReadArray_Private(PetscViewer viewer, HDF5ReadCtx h, hid_t datatype, hid_t memspace, void *arr) 1336 { 1337 PetscFunctionBegin; 1338 PetscStackCallHDF5(H5Dread,(h->dataset, datatype, memspace, h->dataspace, h->plist, arr)); 1339 PetscFunctionReturn(0); 1340 } 1341 1342 PetscErrorCode PetscViewerHDF5Load(PetscViewer viewer, const char *name, PetscLayout map, hid_t datatype, void **newarr) 1343 { 1344 HDF5ReadCtx h=NULL; 1345 hid_t memspace=0; 1346 size_t unitsize; 1347 void *arr; 1348 PetscErrorCode ierr; 1349 1350 PetscFunctionBegin; 1351 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1352 #if defined(PETSC_USE_COMPLEX) 1353 if (!h->complexVal) { 1354 H5T_class_t clazz = H5Tget_class(datatype); 1355 if (clazz == H5T_FLOAT) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"File contains real numbers but PETSc is configured for complex. The conversion is not yet implemented. Configure with --with-scalar-type=real."); 1356 } 1357 #else 1358 if (h->complexVal) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"File contains complex numbers but PETSc not configured for them. Configure with --with-scalar-type=complex."); 1359 #endif 1360 1361 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1362 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1363 ierr = PetscViewerHDF5ReadSelectHyperslab_Private(viewer, h, map, &memspace);CHKERRQ(ierr); 1364 1365 unitsize = H5Tget_size(datatype); 1366 if (h->complexVal) unitsize *= 2; 1367 if (unitsize <= 0 || unitsize > PetscMax(sizeof(PetscInt),sizeof(PetscScalar))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Sanity check failed: HDF5 function H5Tget_size(datatype) returned suspicious value %D",unitsize); 1368 ierr = PetscMalloc(map->n*unitsize, &arr);CHKERRQ(ierr); 1369 1370 ierr = PetscViewerHDF5ReadArray_Private(viewer, h, datatype, memspace, arr);CHKERRQ(ierr); 1371 PetscStackCallHDF5(H5Sclose,(memspace)); 1372 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1373 *newarr = arr; 1374 PetscFunctionReturn(0); 1375 } 1376 1377 /*@C 1378 PetscViewerHDF5ReadSizes - Read block size and global size of a vector (Vec or IS) stored in an HDF5 file. 1379 1380 Input Parameters: 1381 + viewer - The HDF5 viewer 1382 - name - The vector name 1383 1384 Output Parameter: 1385 + bs - block size 1386 - N - global size 1387 1388 Note: 1389 A vector is stored as an HDF5 dataspace with 1-4 dimensions in this order: 1390 1) # timesteps (optional), 2) # blocks, 3) # elements per block (optional), 4) real and imaginary part (only for complex). 1391 1392 A vectors can be stored as a 2D dataspace even if its blocksize is 1; see PetscViewerHDF5SetBaseDimension2(). 1393 1394 Level: advanced 1395 1396 .seealso: PetscViewerHDF5Open(), VecLoad(), ISLoad(), VecGetSize(), ISGetSize(), PetscViewerHDF5SetBaseDimension2() 1397 @*/ 1398 PetscErrorCode PetscViewerHDF5ReadSizes(PetscViewer viewer, const char name[], PetscInt *bs, PetscInt *N) 1399 { 1400 HDF5ReadCtx h=NULL; 1401 PetscLayout map=NULL; 1402 PetscErrorCode ierr; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1406 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1407 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1408 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1409 if (bs) *bs = map->bs; 1410 if (N) *N = map->N; 1411 ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1412 PetscFunctionReturn(0); 1413 } 1414 1415 /* 1416 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that 1417 is attached to a communicator, in this case the attribute is a PetscViewer. 1418 */ 1419 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID; 1420 1421 /*@C 1422 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator. 1423 1424 Collective on MPI_Comm 1425 1426 Input Parameter: 1427 . comm - the MPI communicator to share the HDF5 PetscViewer 1428 1429 Level: intermediate 1430 1431 Options Database Keys: 1432 . -viewer_hdf5_filename <name> 1433 1434 Environmental variables: 1435 . PETSC_VIEWER_HDF5_FILENAME 1436 1437 Notes: 1438 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return 1439 an error code. The HDF5 PetscViewer is usually used in the form 1440 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm)); 1441 1442 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy() 1443 @*/ 1444 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) 1445 { 1446 PetscErrorCode ierr; 1447 PetscBool flg; 1448 PetscViewer viewer; 1449 char fname[PETSC_MAX_PATH_LEN]; 1450 MPI_Comm ncomm; 1451 1452 PetscFunctionBegin; 1453 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1454 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) { 1455 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,0); 1456 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1457 } 1458 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg); 1459 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1460 if (!flg) { /* PetscViewer not yet created */ 1461 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 1462 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1463 if (!flg) { 1464 ierr = PetscStrcpy(fname,"output.h5"); 1465 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1466 } 1467 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer); 1468 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1469 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 1470 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1471 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer); 1472 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1473 } 1474 ierr = PetscCommDestroy(&ncomm); 1475 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1476 PetscFunctionReturn(viewer); 1477 } 1478