xref: /petsc/src/vec/is/utils/isio.c (revision 5a7b8bca3c29d15665d9fe2994377cbe2bede2c8)
1 #include <petscis.h>         /*I  "petscis.h"  I*/
2 #include <petsc/private/isimpl.h>
3 #include <petscviewerhdf5.h>
4 
5 #if defined(PETSC_HAVE_HDF5)
6 /*
7      This should handle properly the cases where PetscInt is 32 or 64 and hsize_t is 32 or 64. These means properly casting with
8    checks back and forth between the two types of variables.
9 */
10 PetscErrorCode ISLoad_HDF5(IS is, PetscViewer viewer)
11 {
12   hid_t           inttype;    /* int type (H5T_NATIVE_INT or H5T_NATIVE_LLONG) */
13   hid_t           file_id, group, dset_id, filespace, memspace, plist_id;
14   int             rdim, dim;
15   hsize_t         dims[3], count[3], offset[3];
16   PetscInt        n, N, bs, bsInd, lenInd, low, timestep;
17   const PetscInt *ind;
18   const char     *isname;
19   PetscErrorCode  ierr;
20 
21   PetscFunctionBegin;
22   if (!((PetscObject)is)->name) SETERRQ(PetscObjectComm((PetscObject)is), PETSC_ERR_SUP, "Since HDF5 format gives ASCII name for each object in file; must use ISLoad() after setting name of Vec with PetscObjectSetName()");
23   ierr = PetscViewerHDF5OpenGroup(viewer, &file_id, &group);CHKERRQ(ierr);
24   ierr = PetscViewerHDF5GetTimestep(viewer, &timestep);CHKERRQ(ierr);
25   ierr = ISGetBlockSize(is, &bs);CHKERRQ(ierr);
26   /* Create the dataset with default properties and close filespace */
27   ierr = PetscObjectGetName((PetscObject) is, &isname);CHKERRQ(ierr);
28 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
29   PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, isname, H5P_DEFAULT));
30 #else
31   PetscStackCallHDF5Return(dset_id,H5Dopen,(group, isname));
32 #endif
33   /* Retrieve the dataspace for the dataset */
34   PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id));
35   dim = 0;
36   if (timestep >= 0) ++dim;
37   ++dim;
38   ++dim;
39   PetscStackCallHDF5Return(rdim,H5Sget_simple_extent_dims,(filespace, dims, NULL));
40   bsInd  = rdim-1;
41   lenInd = timestep >= 0 ? 1 : 0;
42   if (rdim != dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Dimension of array in file %d not %d as expected",rdim,dim);
43   else if (bs != (PetscInt) dims[bsInd]) {
44     ierr = ISSetBlockSize(is, dims[bsInd]);CHKERRQ(ierr);
45     bs   = dims[bsInd];
46   }
47 
48   /* Set Vec sizes,blocksize,and type if not already set */
49   ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr);
50   ierr = ISGetSize(is, &N);CHKERRQ(ierr);
51   if (n < 0 && N < 0) {ierr = PetscLayoutSetSize(is->map, dims[lenInd]*bs);CHKERRQ(ierr);}
52   ierr = PetscLayoutSetUp(is->map);CHKERRQ(ierr);
53   /* If sizes and type already set,check if the vector global size is correct */
54   ierr = ISGetSize(is, &N);CHKERRQ(ierr);
55   if (N/bs != (PetscInt) dims[lenInd]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "IS in file different length (%d) then input vector (%d)", (PetscInt) dims[lenInd], N/bs);
56 
57   /* Each process defines a dataset and reads it from the hyperslab in the file */
58   ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr);
59   dim  = 0;
60   if (timestep >= 0) {
61     count[dim] = 1;
62     ++dim;
63   }
64   ierr = PetscHDF5IntCast(n/bs,count + dim);CHKERRQ(ierr);
65   ++dim;
66   if (bs >= 1) {
67     count[dim] = bs;
68     ++dim;
69   }
70   PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL));
71 
72   /* Select hyperslab in the file */
73   ierr = PetscLayoutGetRange(is->map, &low, NULL);CHKERRQ(ierr);
74   dim  = 0;
75   if (timestep >= 0) {
76     offset[dim] = timestep;
77     ++dim;
78   }
79   ierr = PetscHDF5IntCast(low/bs,offset + dim);CHKERRQ(ierr);
80   ++dim;
81   if (bs >= 1) {
82     offset[dim] = 0;
83     ++dim;
84   }
85   PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL));
86 
87   /* Create property list for collective dataset read */
88   PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_DATASET_XFER));
89 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
90   PetscStackCallHDF5(H5Pset_dxpl_mpio,(plist_id, H5FD_MPIO_COLLECTIVE));
91 #endif
92   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */
93 
94 #if defined(PETSC_USE_64BIT_INDICES)
95   inttype = H5T_NATIVE_LLONG;
96 #else
97   inttype = H5T_NATIVE_INT;
98 #endif
99   ierr   = PetscMalloc1(n,&ind);CHKERRQ(ierr);
100   PetscStackCallHDF5(H5Dread,(dset_id, inttype, memspace, filespace, plist_id, (void *) ind));
101   ierr   = ISGeneralSetIndices(is, n, ind, PETSC_OWN_POINTER);CHKERRQ(ierr);
102 
103   /* Close/release resources */
104   if (group != file_id) PetscStackCallHDF5(H5Gclose,(group));
105   PetscStackCallHDF5(H5Pclose,(plist_id));
106   PetscStackCallHDF5(H5Sclose,(filespace));
107   PetscStackCallHDF5(H5Sclose,(memspace));
108   PetscStackCallHDF5(H5Dclose,(dset_id));
109   PetscFunctionReturn(0);
110 }
111 #endif
112 
113 PetscErrorCode ISLoad_Binary(IS is, PetscViewer viewer)
114 {
115   PetscErrorCode ierr;
116   PetscBool      isgeneral,skipHeader,useMPIIO;
117   int            fd;
118   PetscInt       tr[2],N,ln,*idx;
119   MPI_Request    request;
120   MPI_Status     status;
121   MPI_Comm       comm;
122   PetscMPIInt    rank,size,tag;
123 
124   PetscFunctionBegin;
125   ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr);
126   ierr = PetscObjectTypeCompare((PetscObject)is,ISGENERAL,&isgeneral);CHKERRQ(ierr);
127   if (!isgeneral) SETERRQ(comm,PETSC_ERR_ARG_INCOMP,"IS must be of type ISGENERAL to load into it");
128   ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);CHKERRQ(ierr);
129   if (skipHeader) SETERRQ(comm,PETSC_ERR_USER, "Currently no support for binary files without headers");
130   /* force binary viewer to load .info file if it has not yet done so */
131   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
132 
133   ierr = PetscViewerBinaryRead(viewer,tr,2,NULL,PETSC_INT);CHKERRQ(ierr);
134   if (tr[0] != IS_FILE_CLASSID) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Not an IS next in file");
135 
136   /* Has IS already had its layout defined */
137   /* ierr = ISGetLayout(is,&map);CHKERRQ(ierr); */
138   ierr = PetscLayoutGetSize(is->map,&N);CHKERRQ(ierr);
139   if (N > -1 && N != tr[1]) SETERRQ2(comm,PETSC_ERR_ARG_SIZ,"Size of IS in file %D does not match size of IS provided",tr[1],N);
140   if (N == -1) {
141     N = tr[1];
142     ierr = PetscLayoutSetSize(is->map,N);CHKERRQ(ierr);
143     ierr = PetscLayoutSetUp(is->map);CHKERRQ(ierr);
144   }
145   ierr = PetscLayoutGetLocalSize(is->map,&ln);CHKERRQ(ierr);
146   ierr = PetscMalloc1(ln,&idx);CHKERRQ(ierr);
147 
148   ierr = PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);CHKERRQ(ierr);
149 #if defined(PETSC_HAVE_MPIIO)
150   if (useMPIIO) {
151     MPI_File    mfdes;
152     MPI_Offset  off;
153     PetscMPIInt lsize;
154     PetscInt    rstart;
155 
156     ierr = PetscMPIIntCast(ln,&lsize);CHKERRQ(ierr);
157     ierr = PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);CHKERRQ(ierr);
158     ierr = PetscViewerBinaryGetMPIIOOffset(viewer,&off);CHKERRQ(ierr);
159     ierr = PetscLayoutGetRange(is->map,&rstart,NULL);CHKERRQ(ierr);
160     off += rstart*(MPI_Offset)sizeof(PetscInt);
161     ierr = MPI_File_set_view(mfdes,off,MPIU_INT,MPIU_INT,(char*)"native",MPI_INFO_NULL);CHKERRQ(ierr);
162     ierr = MPIU_File_read_all(mfdes,idx,lsize,MPIU_INT,MPI_STATUS_IGNORE);CHKERRQ(ierr);
163     ierr = PetscViewerBinaryAddMPIIOOffset(viewer,N*(MPI_Offset)sizeof(PetscInt));CHKERRQ(ierr);
164     ierr = ISGeneralSetIndices(is,ln,idx,PETSC_OWN_POINTER);CHKERRQ(ierr);
165     PetscFunctionReturn(0);
166   }
167 #endif
168 
169   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
170   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
171   ierr = PetscObjectGetNewTag((PetscObject)viewer,&tag);CHKERRQ(ierr);
172   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
173 
174   if (!rank) {
175     ierr = PetscBinaryRead(fd,idx,ln,PETSC_INT);CHKERRQ(ierr);
176 
177     if (size > 1) {
178       PetscInt *range,n,i,*idxwork;
179 
180       /* read in other chuncks and send to other processors */
181       /* determine maximum chunck owned by other */
182       range = is->map->range;
183       n = 1;
184       for (i=1; i<size; i++) n = PetscMax(n,range[i+1] - range[i]);
185 
186       ierr = PetscMalloc1(n,&idxwork);CHKERRQ(ierr);
187       for (i=1; i<size; i++) {
188         n    = range[i+1] - range[i];
189         ierr = PetscBinaryRead(fd,idxwork,n,PETSC_INT);CHKERRQ(ierr);
190         ierr = MPI_Isend(idxwork,n,MPIU_INT,i,tag,comm,&request);CHKERRQ(ierr);
191         ierr = MPI_Wait(&request,&status);CHKERRQ(ierr);
192       }
193       ierr = PetscFree(idxwork);CHKERRQ(ierr);
194     }
195   } else {
196     ierr = MPI_Recv(idx,ln,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr);
197   }
198   ierr = ISGeneralSetIndices(is,ln,idx,PETSC_OWN_POINTER);CHKERRQ(ierr);
199   PetscFunctionReturn(0);
200 }
201 
202 PetscErrorCode ISLoad_Default(IS is, PetscViewer viewer)
203 {
204   PetscBool      isbinary;
205 #if defined(PETSC_HAVE_HDF5)
206   PetscBool      ishdf5;
207 #endif
208   PetscErrorCode ierr;
209 
210   PetscFunctionBegin;
211   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
212 #if defined(PETSC_HAVE_HDF5)
213   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
214 #endif
215   if (isbinary) {
216     ierr = ISLoad_Binary(is, viewer);CHKERRQ(ierr);
217 #if defined(PETSC_HAVE_HDF5)
218   } else if (ishdf5) {
219     ierr = ISLoad_HDF5(is, viewer);CHKERRQ(ierr);
220 #endif
221   }
222   PetscFunctionReturn(0);
223 }
224