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; 642 H5O_type_t type; 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 ierr = PetscViewerHDF5Traverse_Internal(viewer, groupName, PETSC_TRUE, NULL, &type);CHKERRQ(ierr); 650 if (type != H5O_TYPE_GROUP) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Path %s resolves to something which is not a group", groupName); 651 PetscStackCallHDF5Return(*groupId,H5Gopen2,(file_id, groupName ? groupName : "/", H5P_DEFAULT)); 652 *fileId = file_id; 653 PetscFunctionReturn(0); 654 } 655 656 /*@ 657 PetscViewerHDF5IncrementTimestep - Increments the current timestep for the HDF5 output. Fields are stacked in time. 658 659 Not collective 660 661 Input Parameter: 662 . viewer - the PetscViewer 663 664 Level: intermediate 665 666 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5SetTimestep(), PetscViewerHDF5GetTimestep() 667 @*/ 668 PetscErrorCode PetscViewerHDF5IncrementTimestep(PetscViewer viewer) 669 { 670 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 671 672 PetscFunctionBegin; 673 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 674 ++hdf5->timestep; 675 PetscFunctionReturn(0); 676 } 677 678 /*@ 679 PetscViewerHDF5SetTimestep - Set the current timestep for the HDF5 output. Fields are stacked in time. A timestep 680 of -1 disables blocking with timesteps. 681 682 Not collective 683 684 Input Parameters: 685 + viewer - the PetscViewer 686 - timestep - The timestep number 687 688 Level: intermediate 689 690 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5GetTimestep() 691 @*/ 692 PetscErrorCode PetscViewerHDF5SetTimestep(PetscViewer viewer, PetscInt timestep) 693 { 694 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 695 696 PetscFunctionBegin; 697 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 698 hdf5->timestep = timestep; 699 PetscFunctionReturn(0); 700 } 701 702 /*@ 703 PetscViewerHDF5GetTimestep - Get the current timestep for the HDF5 output. Fields are stacked in time. 704 705 Not collective 706 707 Input Parameter: 708 . viewer - the PetscViewer 709 710 Output Parameter: 711 . timestep - The timestep number 712 713 Level: intermediate 714 715 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5IncrementTimestep(), PetscViewerHDF5SetTimestep() 716 @*/ 717 PetscErrorCode PetscViewerHDF5GetTimestep(PetscViewer viewer, PetscInt *timestep) 718 { 719 PetscViewer_HDF5 *hdf5 = (PetscViewer_HDF5*) viewer->data; 720 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 723 PetscValidPointer(timestep,2); 724 *timestep = hdf5->timestep; 725 PetscFunctionReturn(0); 726 } 727 728 /*@C 729 PetscDataTypeToHDF5DataType - Converts the PETSc name of a datatype to its HDF5 name. 730 731 Not collective 732 733 Input Parameter: 734 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 735 736 Output Parameter: 737 . mtype - the MPI datatype (for example MPI_DOUBLE, ...) 738 739 Level: advanced 740 741 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 742 @*/ 743 PetscErrorCode PetscDataTypeToHDF5DataType(PetscDataType ptype, hid_t *htype) 744 { 745 PetscFunctionBegin; 746 if (ptype == PETSC_INT) 747 #if defined(PETSC_USE_64BIT_INDICES) 748 *htype = H5T_NATIVE_LLONG; 749 #else 750 *htype = H5T_NATIVE_INT; 751 #endif 752 else if (ptype == PETSC_DOUBLE) *htype = H5T_NATIVE_DOUBLE; 753 else if (ptype == PETSC_LONG) *htype = H5T_NATIVE_LONG; 754 else if (ptype == PETSC_SHORT) *htype = H5T_NATIVE_SHORT; 755 else if (ptype == PETSC_ENUM) *htype = H5T_NATIVE_DOUBLE; 756 else if (ptype == PETSC_BOOL) *htype = H5T_NATIVE_INT; 757 else if (ptype == PETSC_FLOAT) *htype = H5T_NATIVE_FLOAT; 758 else if (ptype == PETSC_CHAR) *htype = H5T_NATIVE_CHAR; 759 else if (ptype == PETSC_BIT_LOGICAL) *htype = H5T_NATIVE_UCHAR; 760 else if (ptype == PETSC_STRING) *htype = H5Tcopy(H5T_C_S1); 761 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported PETSc datatype"); 762 PetscFunctionReturn(0); 763 } 764 765 /*@C 766 PetscHDF5DataTypeToPetscDataType - Finds the PETSc name of a datatype from its HDF5 name 767 768 Not collective 769 770 Input Parameter: 771 . htype - the HDF5 datatype (for example H5T_NATIVE_DOUBLE, ...) 772 773 Output Parameter: 774 . ptype - the PETSc datatype name (for example PETSC_DOUBLE) 775 776 Level: advanced 777 778 .seealso: PetscDataType, PetscHDF5DataTypeToPetscDataType() 779 @*/ 780 PetscErrorCode PetscHDF5DataTypeToPetscDataType(hid_t htype, PetscDataType *ptype) 781 { 782 PetscFunctionBegin; 783 #if defined(PETSC_USE_64BIT_INDICES) 784 if (htype == H5T_NATIVE_INT) *ptype = PETSC_LONG; 785 else if (htype == H5T_NATIVE_LLONG) *ptype = PETSC_INT; 786 #else 787 if (htype == H5T_NATIVE_INT) *ptype = PETSC_INT; 788 #endif 789 else if (htype == H5T_NATIVE_DOUBLE) *ptype = PETSC_DOUBLE; 790 else if (htype == H5T_NATIVE_LONG) *ptype = PETSC_LONG; 791 else if (htype == H5T_NATIVE_SHORT) *ptype = PETSC_SHORT; 792 else if (htype == H5T_NATIVE_FLOAT) *ptype = PETSC_FLOAT; 793 else if (htype == H5T_NATIVE_CHAR) *ptype = PETSC_CHAR; 794 else if (htype == H5T_NATIVE_UCHAR) *ptype = PETSC_CHAR; 795 else if (htype == H5T_C_S1) *ptype = PETSC_STRING; 796 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported HDF5 datatype"); 797 PetscFunctionReturn(0); 798 } 799 800 /*@C 801 PetscViewerHDF5WriteAttribute - Write an attribute 802 803 Input Parameters: 804 + viewer - The HDF5 viewer 805 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute. 806 . name - The attribute name 807 . datatype - The attribute type 808 - value - The attribute value 809 810 Level: advanced 811 812 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 813 @*/ 814 PetscErrorCode PetscViewerHDF5WriteAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscDataType datatype, const void *value) 815 { 816 char *parent; 817 hid_t h5, dataspace, obj, attribute, dtype; 818 PetscBool has; 819 PetscErrorCode ierr; 820 821 PetscFunctionBegin; 822 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 823 if (dataset) PetscValidCharPointer(dataset, 2); 824 PetscValidCharPointer(name, 3); 825 PetscValidPointer(value, 5); 826 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr); 827 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_TRUE, NULL, NULL);CHKERRQ(ierr); 828 ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, &has);CHKERRQ(ierr); 829 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 830 if (datatype == PETSC_STRING) { 831 size_t len; 832 ierr = PetscStrlen((const char *) value, &len);CHKERRQ(ierr); 833 PetscStackCallHDF5(H5Tset_size,(dtype, len+1)); 834 } 835 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 836 PetscStackCallHDF5Return(dataspace,H5Screate,(H5S_SCALAR)); 837 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 838 if (has) { 839 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 840 } else { 841 PetscStackCallHDF5Return(attribute,H5Acreate2,(obj, name, dtype, dataspace, H5P_DEFAULT, H5P_DEFAULT)); 842 } 843 PetscStackCallHDF5(H5Awrite,(attribute, dtype, value)); 844 if (datatype == PETSC_STRING) PetscStackCallHDF5(H5Tclose,(dtype)); 845 PetscStackCallHDF5(H5Aclose,(attribute)); 846 PetscStackCallHDF5(H5Oclose,(obj)); 847 PetscStackCallHDF5(H5Sclose,(dataspace)); 848 ierr = PetscFree(parent);CHKERRQ(ierr); 849 PetscFunctionReturn(0); 850 } 851 852 /*@C 853 PetscViewerHDF5WriteObjectAttribute - Write an attribute to the dataset matching the given PetscObject by name 854 855 Input Parameters: 856 + viewer - The HDF5 viewer 857 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 858 . name - The attribute name 859 . datatype - The attribute type 860 - value - The attribute value 861 862 Notes: 863 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 864 You might want to check first if it does using PetscViewerHDF5HasObject(). 865 866 Level: advanced 867 868 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 869 @*/ 870 PetscErrorCode PetscViewerHDF5WriteObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, const void *value) 871 { 872 PetscErrorCode ierr; 873 874 PetscFunctionBegin; 875 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 876 PetscValidHeader(obj,2); 877 PetscValidCharPointer(name,3); 878 PetscValidPointer(value,5); 879 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 880 ierr = PetscViewerHDF5WriteAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr); 881 PetscFunctionReturn(0); 882 } 883 884 /*@C 885 PetscViewerHDF5ReadAttribute - Read an attribute 886 887 Input Parameters: 888 + viewer - The HDF5 viewer 889 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute. 890 . name - The attribute name 891 - datatype - The attribute type 892 893 Output Parameter: 894 . value - The attribute value 895 896 Level: advanced 897 898 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 899 @*/ 900 PetscErrorCode PetscViewerHDF5ReadAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscDataType datatype, void *value) 901 { 902 char *parent; 903 hid_t h5, obj, attribute, atype, dtype; 904 PetscBool has; 905 PetscErrorCode ierr; 906 907 PetscFunctionBegin; 908 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 909 if (dataset) PetscValidCharPointer(dataset, 2); 910 PetscValidCharPointer(name, 3); 911 PetscValidPointer(value, 5); 912 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr); 913 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, &has, NULL);CHKERRQ(ierr); 914 if (has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, &has);CHKERRQ(ierr);} 915 if (!has) SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Attribute %s/%s does not exist", parent, name); 916 ierr = PetscDataTypeToHDF5DataType(datatype, &dtype);CHKERRQ(ierr); 917 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 918 PetscStackCallHDF5Return(obj,H5Oopen,(h5, parent, H5P_DEFAULT)); 919 PetscStackCallHDF5Return(attribute,H5Aopen_name,(obj, name)); 920 if (datatype == PETSC_STRING) { 921 size_t len; 922 PetscStackCallHDF5Return(atype,H5Aget_type,(attribute)); 923 PetscStackCallHDF5Return(len,H5Tget_size,(atype)); 924 PetscStackCallHDF5(H5Tclose,(atype)); 925 ierr = PetscMalloc((len+1) * sizeof(char *), &value);CHKERRQ(ierr); 926 } 927 PetscStackCallHDF5(H5Aread,(attribute, dtype, value)); 928 PetscStackCallHDF5(H5Aclose,(attribute)); 929 /* H5Oclose can be used to close groups, datasets, or committed datatypes */ 930 PetscStackCallHDF5(H5Oclose,(obj)); 931 ierr = PetscFree(parent);CHKERRQ(ierr); 932 PetscFunctionReturn(0); 933 } 934 935 /*@C 936 PetscViewerHDF5ReadObjectAttribute - Read an attribute from the dataset matching the given PetscObject by name 937 938 Input Parameters: 939 + viewer - The HDF5 viewer 940 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 941 . name - The attribute name 942 - datatype - The attribute type 943 944 Output Parameter: 945 . value - The attribute value 946 947 Notes: 948 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 949 You might want to check first if it does using PetscViewerHDF5HasObject(). 950 951 Level: advanced 952 953 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5ReadAttribute() PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 954 @*/ 955 PetscErrorCode PetscViewerHDF5ReadObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscDataType datatype, void *value) 956 { 957 PetscErrorCode ierr; 958 959 PetscFunctionBegin; 960 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 961 PetscValidHeader(obj,2); 962 PetscValidCharPointer(name,3); 963 PetscValidPointer(value, 5); 964 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 965 ierr = PetscViewerHDF5ReadAttribute(viewer, obj->name, name, datatype, value);CHKERRQ(ierr); 966 PetscFunctionReturn(0); 967 } 968 969 PETSC_STATIC_INLINE PetscErrorCode PetscViewerHDF5Traverse_Inner_Internal(hid_t h5, const char name[], PetscBool createGroup, PetscBool *exists_) 970 { 971 htri_t exists; 972 hid_t group; 973 974 PetscFunctionBegin; 975 PetscStackCallHDF5Return(exists,H5Lexists,(h5, name, H5P_DEFAULT)); 976 if (exists) PetscStackCallHDF5Return(exists,H5Oexists_by_name,(h5, name, H5P_DEFAULT)); 977 if (!exists && createGroup) { 978 PetscStackCallHDF5Return(group,H5Gcreate2,(h5, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)); 979 PetscStackCallHDF5(H5Gclose,(group)); 980 exists = PETSC_TRUE; 981 } 982 *exists_ = (PetscBool) exists; 983 PetscFunctionReturn(0); 984 } 985 986 static PetscErrorCode PetscViewerHDF5Traverse_Internal(PetscViewer viewer, const char name[], PetscBool createGroup, PetscBool *has, H5O_type_t *otype) 987 { 988 const char rootGroupName[] = "/"; 989 hid_t h5; 990 PetscBool exists=PETSC_FALSE; 991 PetscInt i,n; 992 char **hierarchy; 993 char buf[PETSC_MAX_PATH_LEN]=""; 994 PetscErrorCode ierr; 995 996 PetscFunctionBegin; 997 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 998 if (name) PetscValidCharPointer(name, 2); 999 else name = rootGroupName; 1000 if (has) { 1001 PetscValidIntPointer(has, 3); 1002 *has = PETSC_FALSE; 1003 } 1004 if (otype) { 1005 PetscValidIntPointer(otype, 4); 1006 *otype = H5O_TYPE_UNKNOWN; 1007 } 1008 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1009 1010 /* 1011 Unfortunately, H5Oexists_by_name() fails if any object in hierarchy is missing. 1012 Hence, each of them needs to be tested separately: 1013 1) whether it's a valid link 1014 2) whether this link resolves to an object 1015 See H5Oexists_by_name() documentation. 1016 */ 1017 ierr = PetscStrToArray(name,'/',&n,&hierarchy);CHKERRQ(ierr); 1018 if (!n) { 1019 /* Assume group "/" always exists in accordance with HDF5 >= 1.10.0. See H5Lexists() documentation. */ 1020 if (has) *has = PETSC_TRUE; 1021 if (otype) *otype = H5O_TYPE_GROUP; 1022 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1023 PetscFunctionReturn(0); 1024 } 1025 for (i=0; i<n; i++) { 1026 ierr = PetscStrcat(buf,"/");CHKERRQ(ierr); 1027 ierr = PetscStrcat(buf,hierarchy[i]);CHKERRQ(ierr); 1028 ierr = PetscViewerHDF5Traverse_Inner_Internal(h5, buf, createGroup, &exists);CHKERRQ(ierr); 1029 if (!exists) break; 1030 } 1031 ierr = PetscStrToArrayDestroy(n,hierarchy);CHKERRQ(ierr); 1032 1033 /* If the object exists, get its type */ 1034 if (exists && otype) { 1035 H5O_info_t info; 1036 1037 /* We could use H5Iget_type() here but that would require opening the object. This way we only need its name. */ 1038 PetscStackCallHDF5(H5Oget_info_by_name,(h5, name, &info, H5P_DEFAULT)); 1039 *otype = info.type; 1040 } 1041 if (has) *has = exists; 1042 PetscFunctionReturn(0); 1043 } 1044 1045 /*@ 1046 PetscViewerHDF5HasGroup - Check whether the current (pushed) group exists in the HDF5 file 1047 1048 Input Parameters: 1049 . viewer - The HDF5 viewer 1050 1051 Output Parameter: 1052 . has - Flag for group existence 1053 1054 Notes: 1055 If the path exists but is not a group, this returns PETSC_FALSE as well. 1056 1057 Level: advanced 1058 1059 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5PushGroup(), PetscViewerHDF5PopGroup(), PetscViewerHDF5OpenGroup() 1060 @*/ 1061 PetscErrorCode PetscViewerHDF5HasGroup(PetscViewer viewer, PetscBool *has) 1062 { 1063 H5O_type_t type; 1064 const char *name; 1065 PetscErrorCode ierr; 1066 1067 PetscFunctionBegin; 1068 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1069 PetscValidIntPointer(has,2); 1070 ierr = PetscViewerHDF5GetGroup(viewer, &name);CHKERRQ(ierr); 1071 ierr = PetscViewerHDF5Traverse_Internal(viewer, name, PETSC_FALSE, has, &type);CHKERRQ(ierr); 1072 *has = (type == H5O_TYPE_GROUP) ? PETSC_TRUE : PETSC_FALSE; 1073 PetscFunctionReturn(0); 1074 } 1075 1076 /*@ 1077 PetscViewerHDF5HasObject - Check whether a dataset with the same name as given object exists in the HDF5 file under current group 1078 1079 Input Parameters: 1080 + viewer - The HDF5 viewer 1081 - obj - The named object 1082 1083 Output Parameter: 1084 . has - Flag for dataset existence; PETSC_FALSE for unnamed object 1085 1086 Notes: 1087 If the path exists but is not a dataset, this returns PETSC_FALSE as well. 1088 1089 Level: advanced 1090 1091 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1092 @*/ 1093 PetscErrorCode PetscViewerHDF5HasObject(PetscViewer viewer, PetscObject obj, PetscBool *has) 1094 { 1095 H5O_type_t type; 1096 char *path; 1097 PetscErrorCode ierr; 1098 1099 PetscFunctionBegin; 1100 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1101 PetscValidHeader(obj,2); 1102 PetscValidIntPointer(has,3); 1103 *has = PETSC_FALSE; 1104 if (!obj->name) PetscFunctionReturn(0); 1105 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, obj->name, &path);CHKERRQ(ierr); 1106 ierr = PetscViewerHDF5Traverse_Internal(viewer, path, PETSC_FALSE, has, &type);CHKERRQ(ierr); 1107 *has = (type == H5O_TYPE_DATASET) ? PETSC_TRUE : PETSC_FALSE; 1108 ierr = PetscFree(path);CHKERRQ(ierr); 1109 PetscFunctionReturn(0); 1110 } 1111 1112 /*@C 1113 PetscViewerHDF5HasAttribute - Check whether an attribute exists 1114 1115 Input Parameters: 1116 + viewer - The HDF5 viewer 1117 . dataset - The parent dataset name, relative to the current group. NULL means a group-wise attribute. 1118 - name - The attribute name 1119 1120 Output Parameter: 1121 . has - Flag for attribute existence 1122 1123 Level: advanced 1124 1125 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasObjectAttribute(), PetscViewerHDF5WriteAttribute(), PetscViewerHDF5ReadAttribute(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1126 @*/ 1127 PetscErrorCode PetscViewerHDF5HasAttribute(PetscViewer viewer, const char dataset[], const char name[], PetscBool *has) 1128 { 1129 char *parent; 1130 PetscErrorCode ierr; 1131 1132 PetscFunctionBegin; 1133 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1134 if (dataset) PetscValidCharPointer(dataset,2); 1135 PetscValidCharPointer(name,3); 1136 PetscValidIntPointer(has,4); 1137 ierr = PetscViewerHDF5GetAbsolutePath_Internal(viewer, dataset, &parent);CHKERRQ(ierr); 1138 ierr = PetscViewerHDF5Traverse_Internal(viewer, parent, PETSC_FALSE, has, NULL);CHKERRQ(ierr); 1139 if (*has) {ierr = PetscViewerHDF5HasAttribute_Internal(viewer, parent, name, has);CHKERRQ(ierr);} 1140 ierr = PetscFree(parent);CHKERRQ(ierr); 1141 PetscFunctionReturn(0); 1142 } 1143 1144 /*@C 1145 PetscViewerHDF5HasObjectAttribute - Check whether an attribute is attached to the dataset matching the given PetscObject by name 1146 1147 Input Parameters: 1148 + viewer - The HDF5 viewer 1149 . obj - The object whose name is used to lookup the parent dataset, relative to the current group. 1150 - name - The attribute name 1151 1152 Output Parameter: 1153 . has - Flag for attribute existence 1154 1155 Notes: 1156 This fails if current_group/object_name doesn't resolve to a dataset (the path doesn't exist or is not a dataset). 1157 You might want to check first if it does using PetscViewerHDF5HasObject(). 1158 1159 Level: advanced 1160 1161 .seealso: PetscViewerHDF5Open(), PetscViewerHDF5HasAttribute(), PetscViewerHDF5WriteObjectAttribute(), PetscViewerHDF5ReadObjectAttribute(), PetscViewerHDF5HasObject(), PetscViewerHDF5PushGroup(),PetscViewerHDF5PopGroup(),PetscViewerHDF5GetGroup() 1162 @*/ 1163 PetscErrorCode PetscViewerHDF5HasObjectAttribute(PetscViewer viewer, PetscObject obj, const char name[], PetscBool *has) 1164 { 1165 PetscErrorCode ierr; 1166 1167 PetscFunctionBegin; 1168 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1169 PetscValidHeader(obj,2); 1170 PetscValidCharPointer(name,3); 1171 PetscValidIntPointer(has,4); 1172 ierr = PetscViewerHDF5CheckNamedObject_Internal(viewer, obj);CHKERRQ(ierr); 1173 ierr = PetscViewerHDF5HasAttribute(viewer, obj->name, name, has);CHKERRQ(ierr); 1174 PetscFunctionReturn(0); 1175 } 1176 1177 static PetscErrorCode PetscViewerHDF5HasAttribute_Internal(PetscViewer viewer, const char parent[], const char name[], PetscBool *has) 1178 { 1179 hid_t h5; 1180 htri_t hhas; 1181 PetscErrorCode ierr; 1182 1183 PetscFunctionBegin; 1184 ierr = PetscViewerHDF5GetFileId(viewer, &h5);CHKERRQ(ierr); 1185 PetscStackCallHDF5Return(hhas,H5Aexists_by_name,(h5, parent, name, H5P_DEFAULT)); 1186 *has = hhas ? PETSC_TRUE : PETSC_FALSE; 1187 PetscFunctionReturn(0); 1188 } 1189 1190 static PetscErrorCode PetscViewerHDF5ReadInitialize_Private(PetscViewer viewer, const char name[], HDF5ReadCtx *ctx) 1191 { 1192 HDF5ReadCtx h=NULL; 1193 PetscErrorCode ierr; 1194 1195 PetscFunctionBegin; 1196 ierr = PetscNew(&h);CHKERRQ(ierr); 1197 ierr = PetscViewerHDF5OpenGroup(viewer, &h->file, &h->group);CHKERRQ(ierr); 1198 PetscStackCallHDF5Return(h->dataset,H5Dopen2,(h->group, name, H5P_DEFAULT)); 1199 PetscStackCallHDF5Return(h->dataspace,H5Dget_space,(h->dataset)); 1200 ierr = PetscViewerHDF5GetTimestep(viewer, &h->timestep);CHKERRQ(ierr); 1201 ierr = PetscViewerHDF5HasAttribute(viewer,name,"complex",&h->complexVal);CHKERRQ(ierr); 1202 if (h->complexVal) {ierr = PetscViewerHDF5ReadAttribute(viewer,name,"complex",PETSC_BOOL,&h->complexVal);CHKERRQ(ierr);} 1203 /* MATLAB stores column vectors horizontally */ 1204 ierr = PetscViewerHDF5HasAttribute(viewer,name,"MATLAB_class",&h->horizontal);CHKERRQ(ierr); 1205 /* Create property list for collective dataset read */ 1206 PetscStackCallHDF5Return(h->plist,H5Pcreate,(H5P_DATASET_XFER)); 1207 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO) 1208 PetscStackCallHDF5(H5Pset_dxpl_mpio,(h->plist, H5FD_MPIO_COLLECTIVE)); 1209 #endif 1210 /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */ 1211 *ctx = h; 1212 PetscFunctionReturn(0); 1213 } 1214 1215 static PetscErrorCode PetscViewerHDF5ReadFinalize_Private(PetscViewer viewer, HDF5ReadCtx *ctx) 1216 { 1217 HDF5ReadCtx h; 1218 PetscErrorCode ierr; 1219 1220 PetscFunctionBegin; 1221 h = *ctx; 1222 PetscStackCallHDF5(H5Pclose,(h->plist)); 1223 PetscStackCallHDF5(H5Gclose,(h->group)); 1224 PetscStackCallHDF5(H5Sclose,(h->dataspace)); 1225 PetscStackCallHDF5(H5Dclose,(h->dataset)); 1226 ierr = PetscFree(*ctx);CHKERRQ(ierr); 1227 PetscFunctionReturn(0); 1228 } 1229 1230 static PetscErrorCode PetscViewerHDF5ReadSizes_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout *map_) 1231 { 1232 int rdim, dim; 1233 hsize_t dims[4]; 1234 PetscInt bsInd, lenInd, bs, len, N; 1235 PetscLayout map; 1236 PetscErrorCode ierr; 1237 1238 PetscFunctionBegin; 1239 if (!(*map_)) { 1240 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)viewer),map_);CHKERRQ(ierr); 1241 } 1242 map = *map_; 1243 /* calculate expected number of dimensions */ 1244 dim = 0; 1245 if (ctx->timestep >= 0) ++dim; 1246 ++dim; /* length in blocks */ 1247 if (ctx->complexVal) ++dim; 1248 /* get actual number of dimensions in dataset */ 1249 PetscStackCallHDF5Return(rdim,H5Sget_simple_extent_dims,(ctx->dataspace, dims, NULL)); 1250 /* calculate expected dimension indices */ 1251 lenInd = 0; 1252 if (ctx->timestep >= 0) ++lenInd; 1253 bsInd = lenInd + 1; 1254 ctx->dim2 = PETSC_FALSE; 1255 if (rdim == dim) { 1256 bs = 1; /* support vectors stored as 1D array */ 1257 } else if (rdim == dim+1) { 1258 bs = (PetscInt) dims[bsInd]; 1259 if (bs == 1) ctx->dim2 = PETSC_TRUE; /* vector with blocksize of 1, still stored as 2D array */ 1260 } else { 1261 SETERRQ2(PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Number of dimensions %d not %d as expected", rdim, dim); 1262 } 1263 len = dims[lenInd]; 1264 if (ctx->horizontal) { 1265 if (len != 1) SETERRQ(PetscObjectComm((PetscObject)viewer), 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."); 1266 len = bs; 1267 bs = 1; 1268 } 1269 N = (PetscInt) len*bs; 1270 1271 /* Set Vec sizes,blocksize,and type if not already set */ 1272 if (map->bs < 0) { 1273 ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr); 1274 } 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); 1275 if (map->N < 0) { 1276 ierr = PetscLayoutSetSize(map, N);CHKERRQ(ierr); 1277 } else if (map->N != N) SETERRQ2(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED, "Global size of array in file is %D, not %D as expected",N,map->N); 1278 PetscFunctionReturn(0); 1279 } 1280 1281 static PetscErrorCode PetscViewerHDF5ReadSelectHyperslab_Private(PetscViewer viewer, HDF5ReadCtx ctx, PetscLayout map, hid_t *memspace) 1282 { 1283 hsize_t count[4], offset[4]; 1284 int dim; 1285 PetscInt bs, n, low; 1286 PetscErrorCode ierr; 1287 1288 PetscFunctionBegin; 1289 /* Compute local size and ownership range */ 1290 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1291 ierr = PetscLayoutGetBlockSize(map, &bs);CHKERRQ(ierr); 1292 ierr = PetscLayoutGetLocalSize(map, &n);CHKERRQ(ierr); 1293 ierr = PetscLayoutGetRange(map, &low, NULL);CHKERRQ(ierr); 1294 1295 /* Each process defines a dataset and reads it from the hyperslab in the file */ 1296 dim = 0; 1297 if (ctx->timestep >= 0) { 1298 count[dim] = 1; 1299 offset[dim] = ctx->timestep; 1300 ++dim; 1301 } 1302 if (ctx->horizontal) { 1303 count[dim] = 1; 1304 offset[dim] = 0; 1305 ++dim; 1306 } 1307 { 1308 ierr = PetscHDF5IntCast(n/bs, &count[dim]);CHKERRQ(ierr); 1309 ierr = PetscHDF5IntCast(low/bs, &offset[dim]);CHKERRQ(ierr); 1310 ++dim; 1311 } 1312 if (bs > 1 || ctx->dim2) { 1313 if (PetscUnlikely(ctx->horizontal)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "cannot have horizontal array with blocksize > 1"); 1314 count[dim] = bs; 1315 offset[dim] = 0; 1316 ++dim; 1317 } 1318 if (ctx->complexVal) { 1319 count[dim] = 2; 1320 offset[dim] = 0; 1321 ++dim; 1322 } 1323 PetscStackCallHDF5Return(*memspace,H5Screate_simple,(dim, count, NULL)); 1324 PetscStackCallHDF5(H5Sselect_hyperslab,(ctx->dataspace, H5S_SELECT_SET, offset, NULL, count, NULL)); 1325 PetscFunctionReturn(0); 1326 } 1327 1328 static PetscErrorCode PetscViewerHDF5ReadArray_Private(PetscViewer viewer, HDF5ReadCtx h, hid_t datatype, hid_t memspace, void *arr) 1329 { 1330 PetscFunctionBegin; 1331 PetscStackCallHDF5(H5Dread,(h->dataset, datatype, memspace, h->dataspace, h->plist, arr)); 1332 PetscFunctionReturn(0); 1333 } 1334 1335 PetscErrorCode PetscViewerHDF5Load(PetscViewer viewer, const char *name, PetscLayout map, hid_t datatype, void **newarr) 1336 { 1337 HDF5ReadCtx h=NULL; 1338 hid_t memspace=0; 1339 size_t unitsize; 1340 void *arr; 1341 PetscErrorCode ierr; 1342 1343 PetscFunctionBegin; 1344 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1345 #if defined(PETSC_USE_COMPLEX) 1346 if (!h->complexVal) { 1347 H5T_class_t clazz = H5Tget_class(datatype); 1348 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."); 1349 } 1350 #else 1351 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."); 1352 #endif 1353 1354 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1355 ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1356 ierr = PetscViewerHDF5ReadSelectHyperslab_Private(viewer, h, map, &memspace);CHKERRQ(ierr); 1357 1358 unitsize = H5Tget_size(datatype); 1359 if (h->complexVal) unitsize *= 2; 1360 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); 1361 ierr = PetscMalloc(map->n*unitsize, &arr);CHKERRQ(ierr); 1362 1363 ierr = PetscViewerHDF5ReadArray_Private(viewer, h, datatype, memspace, arr);CHKERRQ(ierr); 1364 PetscStackCallHDF5(H5Sclose,(memspace)); 1365 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1366 *newarr = arr; 1367 PetscFunctionReturn(0); 1368 } 1369 1370 /*@C 1371 PetscViewerHDF5ReadSizes - Read block size and global size of a vector (Vec or IS) stored in an HDF5 file. 1372 1373 Input Parameters: 1374 + viewer - The HDF5 viewer 1375 - name - The vector name 1376 1377 Output Parameter: 1378 + bs - block size 1379 - N - global size 1380 1381 Note: 1382 A vector is stored as an HDF5 dataspace with 1-4 dimensions in this order: 1383 1) # timesteps (optional), 2) # blocks, 3) # elements per block (optional), 4) real and imaginary part (only for complex). 1384 1385 A vectors can be stored as a 2D dataspace even if its blocksize is 1; see PetscViewerHDF5SetBaseDimension2(). 1386 1387 Level: advanced 1388 1389 .seealso: PetscViewerHDF5Open(), VecLoad(), ISLoad(), VecGetSize(), ISGetSize(), PetscViewerHDF5SetBaseDimension2() 1390 @*/ 1391 PetscErrorCode PetscViewerHDF5ReadSizes(PetscViewer viewer, const char name[], PetscInt *bs, PetscInt *N) 1392 { 1393 HDF5ReadCtx h=NULL; 1394 PetscLayout map=NULL; 1395 PetscErrorCode ierr; 1396 1397 PetscFunctionBegin; 1398 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 1399 ierr = PetscViewerHDF5ReadInitialize_Private(viewer, name, &h);CHKERRQ(ierr); 1400 ierr = PetscViewerHDF5ReadSizes_Private(viewer, h, &map);CHKERRQ(ierr); 1401 ierr = PetscViewerHDF5ReadFinalize_Private(viewer, &h);CHKERRQ(ierr); 1402 if (bs) *bs = map->bs; 1403 if (N) *N = map->N; 1404 ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1405 PetscFunctionReturn(0); 1406 } 1407 1408 /* 1409 The variable Petsc_Viewer_HDF5_keyval is used to indicate an MPI attribute that 1410 is attached to a communicator, in this case the attribute is a PetscViewer. 1411 */ 1412 PetscMPIInt Petsc_Viewer_HDF5_keyval = MPI_KEYVAL_INVALID; 1413 1414 /*@C 1415 PETSC_VIEWER_HDF5_ - Creates an HDF5 PetscViewer shared by all processors in a communicator. 1416 1417 Collective on MPI_Comm 1418 1419 Input Parameter: 1420 . comm - the MPI communicator to share the HDF5 PetscViewer 1421 1422 Level: intermediate 1423 1424 Options Database Keys: 1425 . -viewer_hdf5_filename <name> 1426 1427 Environmental variables: 1428 . PETSC_VIEWER_HDF5_FILENAME 1429 1430 Notes: 1431 Unlike almost all other PETSc routines, PETSC_VIEWER_HDF5_ does not return 1432 an error code. The HDF5 PetscViewer is usually used in the form 1433 $ XXXView(XXX object, PETSC_VIEWER_HDF5_(comm)); 1434 1435 .seealso: PetscViewerHDF5Open(), PetscViewerCreate(), PetscViewerDestroy() 1436 @*/ 1437 PetscViewer PETSC_VIEWER_HDF5_(MPI_Comm comm) 1438 { 1439 PetscErrorCode ierr; 1440 PetscBool flg; 1441 PetscViewer viewer; 1442 char fname[PETSC_MAX_PATH_LEN]; 1443 MPI_Comm ncomm; 1444 1445 PetscFunctionBegin; 1446 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1447 if (Petsc_Viewer_HDF5_keyval == MPI_KEYVAL_INVALID) { 1448 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_HDF5_keyval,0); 1449 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1450 } 1451 ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void**)&viewer,(int*)&flg); 1452 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1453 if (!flg) { /* PetscViewer not yet created */ 1454 ierr = PetscOptionsGetenv(ncomm,"PETSC_VIEWER_HDF5_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg); 1455 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1456 if (!flg) { 1457 ierr = PetscStrcpy(fname,"output.h5"); 1458 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1459 } 1460 ierr = PetscViewerHDF5Open(ncomm,fname,FILE_MODE_WRITE,&viewer); 1461 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1462 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 1463 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1464 ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_HDF5_keyval,(void*)viewer); 1465 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1466 } 1467 ierr = PetscCommDestroy(&ncomm); 1468 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_HDF5_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 1469 PetscFunctionReturn(viewer); 1470 } 1471