@@ -55,10 +55,10 @@ namespace libmpdataxx
5555 H5::PredType::NATIVE_FLOAT,
5656 flttype_output = H5::PredType::NATIVE_FLOAT; // using floats not to waste disk space
5757
58- blitz::TinyVector<hsize_t , parent_t ::n_dims> cshape, shape, chunk, srfcshape, srfcchunk, offst;
58+ blitz::TinyVector<hsize_t , parent_t ::n_dims> cshape, shape, chunk, srfcshape, srfcchunk, offst, shape_h, chunk_h, offst_h, shape_mem_h, offst_mem_h ;
5959 H5::DSetCreatPropList params;
6060
61- H5::DataSpace sspace, cspace, srfcspace;
61+ H5::DataSpace sspace, cspace, srfcspace, sspace_h, sspace_mem_h ;
6262#if defined(USE_MPI)
6363 hid_t fapl_id;
6464#endif
@@ -95,36 +95,56 @@ namespace libmpdataxx
9595 {
9696 // creating the dimensions
9797 // x,y,z
98- offst = 0 ;
98+ offst = 0 ;
99+ offst_h = 0 ;
100+ offst_mem_h = 0 ;
99101
100102 for (int d = 0 ; d < parent_t ::n_dims; ++d)
101- shape[d] = this ->mem ->distmem .grid_size [d];
103+ {
104+ shape[d] = this ->mem ->distmem .grid_size [d]; // shape of arrays stored in file
105+ shape_h[d] = this ->mem ->distmem .grid_size [d] + 2 * this ->halo ; // shape of arrays with halos stored in files
106+ shape_mem_h[d] = this ->mem ->grid_size [d].length () + 2 * this ->halo ; // shape of the array with halo stored in memory of given MPI rank
107+ }
102108
103- chunk = shape;
109+ chunk = shape;
110+ chunk_h = shape_h;
104111
105112 // there is one more coordinate than cell index in each dimension
106113 cshape = shape + 1 ;
107114
108115 srfcshape = shape;
109116 *(srfcshape.end ()-1 ) = 1 ;
110- sspace = H5::DataSpace (parent_t ::n_dims, shape.data ());
111- srfcspace = H5::DataSpace (parent_t ::n_dims, srfcshape.data ());
112- cspace = H5::DataSpace (parent_t ::n_dims, cshape.data ());
117+
118+ sspace = H5::DataSpace (parent_t ::n_dims, shape.data ());
119+ sspace_h = H5::DataSpace (parent_t ::n_dims, shape_h.data ());
120+ sspace_mem_h = H5::DataSpace (parent_t ::n_dims, shape_mem_h.data ());
121+ srfcspace = H5::DataSpace (parent_t ::n_dims, srfcshape.data ());
122+ cspace = H5::DataSpace (parent_t ::n_dims, cshape.data ());
113123
114124#if defined(USE_MPI)
115125 if (this ->mem ->distmem .size () > 1 )
116126 {
117127 shape[0 ] = this ->mem ->grid_size [0 ].length ();
118128 cshape[0 ] = this ->mem ->grid_size [0 ].length ();
119129
130+ shape_h[0 ] =
131+ this ->mem ->distmem .rank () == 0 || this ->mem ->distmem .rank () == this ->mem ->distmem .size ()-1 ?
132+ this ->mem ->grid_size [0 ].length () + this ->halo :
133+ this ->mem ->grid_size [0 ].length ();
134+
135+
120136 if (this ->mem ->distmem .rank () == this ->mem ->distmem .size () - 1 )
121137 cshape[0 ] += 1 ;
122138
123- offst[0 ] = this ->mem ->grid_size [0 ].first ();
139+ offst[0 ] = this ->mem ->grid_size [0 ].first ();
140+ offst_h[0 ] = this ->mem ->distmem .rank () == 0 ? 0 : this ->mem ->grid_size [0 ].first () + this ->halo ;
141+ if (this ->mem ->distmem .rank () > 0 )
142+ offst_mem_h[0 ] = this ->halo ;
124143
125144 // chunk size has to be common to all processes !
126- // TODO: something better ?
127- chunk[0 ] = ( (typename solver_t ::real_t ) (this ->mem ->distmem .grid_size [0 ])) / this ->mem ->distmem .size () + 0.5 ;
145+ // TODO: set to 1? Test performance...
146+ chunk[0 ] = ( (typename solver_t ::real_t ) (this ->mem ->distmem .grid_size [0 ])) / this ->mem ->distmem .size () + 0.5 ;
147+ chunk_h[0 ] = 1 ;// chunk[0];
128148 }
129149#endif
130150
@@ -135,8 +155,10 @@ namespace libmpdataxx
135155 *(srfcchunk.end ()-1 ) = 1 ;
136156
137157 params.setChunk (parent_t ::n_dims, chunk.data ());
158+
138159#if !defined(USE_MPI)
139- params.setDeflate (5 ); // TODO: move such constant to the header
160+ params.setDeflate (5 ); // TODO: move such constant to the header
161+ // TODO2: why not deflate without MPI?
140162#endif
141163
142164 // creating variables
@@ -203,10 +225,10 @@ namespace libmpdataxx
203225 }
204226 }
205227
206- std::string base_name ()
228+ std::string base_name (const std::string &name = " timestep " )
207229 {
208230 std::stringstream ss;
209- ss << " timestep " << std::setw (10 ) << std::setfill (' 0' ) << this ->timestep ;
231+ ss << name << std::setw (10 ) << std::setfill (' 0' ) << this ->timestep ;
210232 return ss.str ();
211233 }
212234
@@ -216,6 +238,12 @@ namespace libmpdataxx
216238 return base_name () + " .h5" ;
217239 }
218240
241+ std::string hdf_name (const std::string &base_name)
242+ {
243+ // TODO: add option of .nc extension for Paraview sake ?
244+ return base_name + " .h5" ;
245+ }
246+
219247 void record_all ()
220248 {
221249 // in concurrent setup only the first solver does output
@@ -362,6 +390,30 @@ namespace libmpdataxx
362390 record_dsc_helper (aux, arr);
363391 }
364392
393+ // for array + halo
394+ void record_aux_halo_hlpr (const std::string &name, const typename solver_t ::arr_t &arr, H5::H5File hdf)
395+ {
396+ assert (this ->rank == 0 );
397+
398+ params.setChunk (parent_t ::n_dims, chunk_h.data ());
399+
400+ auto aux = hdf.createDataSet (
401+ name,
402+ flttype_output,
403+ sspace_h,
404+ params
405+ );
406+
407+ // revert to default chunk
408+ params.setChunk (parent_t ::n_dims, chunk.data ());
409+
410+ auto space = aux.getSpace ();
411+ space.selectHyperslab (H5S_SELECT_SET, shape_h.data (), offst_h.data ());
412+ sspace_mem_h.selectHyperslab (H5S_SELECT_SET, shape_h.data (), offst_mem_h.data ());
413+
414+ aux.write (arr.data (), flttype_solver, sspace_mem_h, space, dxpl_id);
415+ }
416+
365417 void record_scalar_hlpr (const std::string &name, const std::string &group_name, typename solver_t ::real_t data, H5::H5File hdf)
366418 {
367419 assert (this ->rank == 0 );
0 commit comments