@@ -16,15 +16,15 @@ using namespace std;
1616class Reader {
1717 public:
1818 // Default constructor
19- Reader ();
19+ Reader () = default ;
2020
2121 // Destructor to free allocated memory
2222 ~Reader ();
2323
2424 // contents of input file:
25- char ms_filename[4096 ]; // Name of Micro-structure hdf5 file
26- char ms_datasetname[4096 ]; // Absolute path of Micro-structure in hdf5 file
27- char results_prefix[4096 ];
25+ char ms_filename[4096 ]{} ; // Name of Micro-structure hdf5 file
26+ char ms_datasetname[4096 ]{} ; // Absolute path of Micro-structure in hdf5 file
27+ char results_prefix[4096 ]{} ;
2828 int n_mat;
2929 json materialProperties;
3030 double TOL;
@@ -35,15 +35,18 @@ class Reader {
3535 string problemType;
3636 string matmodel;
3737 string method;
38- string strain_type; // "small" (default) or "large"
39- string FE_type; // "HEX8" (default), "HEX8R", or "BBAR"
38+ string strain_type{ " small " } ; // "small" (default) or "large"
39+ string FE_type; // "HEX8" (default), "HEX8R", or "BBAR"
4040 vector<string> resultsToWrite;
41+ char results_filename[4096 ]{}; // Output HDF5 filename
42+ char dataset_name[8192 ]{}; // Base path for results in HDF5 file
43+ hid_t results_file_id = -1 ; // Open HDF5 file handle for results
4144
4245 // contents of microstructure file:
4346 vector<int > dims;
4447 vector<double > l_e;
4548 vector<double > L;
46- unsigned short *ms; // Micro-structure
49+ unsigned short *ms{ nullptr } ; // Micro-structure
4750 bool is_zyx = true ;
4851
4952 int world_rank;
@@ -56,30 +59,30 @@ class Reader {
5659 ptrdiff_t local_1_start;
5760
5861 // void Setup(ptrdiff_t howmany);
59- void ReadInputFile (char fn []);
62+ void ReadInputFile (char input_fn []);
6063 void ReadMS (int hm);
6164 void ComputeVolumeFractions ();
6265 // void ReadHDF5(char file_name[], char dset_name[]);
6366 void safe_create_group (hid_t file, const char *const name);
67+ void OpenResultsFile (const char *output_fn); // Open results file once
68+ void CloseResultsFile (); // Explicitly close results file
6469
6570 // Convenience methods to check if a result should be written and write it
6671 template <typename T>
67- void writeData (const char *fieldName, const char *file_name, const char *dataset_name,
68- int load_idx, int time_idx, T *data, hsize_t *dims, int ndims);
72+ void writeData (const char *fieldName, int load_idx, int time_idx, T *data, hsize_t *dims, int ndims);
6973
7074 template <typename T>
71- void writeSlab (const char *fieldName, const char *file_name, const char *dataset_name,
72- int load_idx, int time_idx, T *data, int size);
75+ void writeSlab (const char *fieldName, int load_idx, int time_idx, T *data, int size);
7376
7477 template <typename T>
75- void WriteSlab (T *data, int _howmany, const char *file_name, const char * dset_name);
78+ void WriteSlab (T *data, int _howmany, const char *dset_name);
7679
7780 template <typename T>
78- void WriteData (T *data, const char *file_name, const char * dset_name, hsize_t *dims, int rank);
81+ void WriteData (T *data, const char *dset_name, hsize_t *dims, int rank);
7982};
8083
8184template <typename T>
82- void Reader::WriteData (T *data, const char *file_name, const char * dset_name, hsize_t *dims, int rank)
85+ void Reader::WriteData (T *data, const char *dset_name, hsize_t *dims, int rank)
8386{
8487 hid_t data_type;
8588 if (std::is_same<T, double >::value) {
@@ -90,26 +93,10 @@ void Reader::WriteData(T *data, const char *file_name, const char *dset_name, hs
9093 throw std::invalid_argument (" Conversion of this data type to H5 data type not yet implemented" );
9194 }
9295
93- hid_t plist_id;
94- hid_t file_id;
95- plist_id = H5Pcreate (H5P_FILE_ACCESS);
96-
97- // TODO: refactor this into a general error handling method
98- /* Save old error handler */
99- herr_t (*old_func)(hid_t , void *);
100- void *old_client_data;
101- H5Eget_auto (H5E_DEFAULT, &old_func, &old_client_data);
102- /* Turn off error handling */
103- H5Eset_auto (H5E_DEFAULT, NULL , NULL );
104-
105- file_id = H5Fopen (file_name, H5F_ACC_RDWR, plist_id);
106- /* Restore previous error handler */
107- H5Eset_auto (H5E_DEFAULT, old_func, old_client_data);
108-
96+ hid_t file_id = results_file_id;
10997 if (file_id < 0 ) {
110- file_id = H5Fcreate (file_name, H5F_ACC_EXCL, H5P_DEFAULT, plist_id );
98+ throw std::runtime_error ( " WriteData: results file is not open " );
11199 }
112- H5Pclose (plist_id);
113100
114101 // Ensure all groups in the path are created
115102 safe_create_group (file_id, dset_name);
@@ -135,18 +122,36 @@ void Reader::WriteData(T *data, const char *file_name, const char *dset_name, hs
135122 throw std::runtime_error (" Error creating dataset" );
136123 }
137124
138- // Write the data to the dataset
139- if (H5Dwrite (dataset_id, data_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0 ) {
125+ // Perform the write: only rank 0 has meaningful data; other ranks use an empty memory selection
126+ hid_t memspace = H5Screate_simple (rank, dims, NULL );
127+ if (world_rank == 0 ) {
128+ /* root keeps full memspace */
129+ } else {
130+ /* non-root select none so they participate but write nothing */
131+ H5Sselect_none (memspace);
132+ /* also ensure file selection is none on non-root ranks */
133+ H5Sselect_none (dataspace_id);
134+ }
135+
136+ hid_t dxpl = H5Pcreate (H5P_DATASET_XFER);
137+ H5Pset_dxpl_mpio (dxpl, H5FD_MPIO_INDEPENDENT);
138+
139+ // Use dataspace_id as the FILE selection; on non-root ranks select none so
140+ // the number of elements selected in memspace and filespace match per rank.
141+ if (H5Dwrite (dataset_id, data_type, memspace, dataspace_id, dxpl, (world_rank == 0 ? data : nullptr )) < 0 ) {
142+ H5Pclose (dxpl);
143+ H5Sclose (memspace);
140144 H5Dclose (dataset_id);
141145 H5Sclose (dataspace_id);
142- H5Fclose (file_id);
143146 throw std::runtime_error (" Error writing data to dataset" );
144147 }
145148
146- // Close the dataset and the file
149+ H5Pclose (dxpl);
150+ H5Sclose (memspace);
151+
152+ // Close the dataset and dataspace
147153 H5Dclose (dataset_id);
148154 H5Sclose (dataspace_id);
149- H5Fclose (file_id);
150155}
151156
152157// this function has to be here because of the template
@@ -165,7 +170,6 @@ template <typename T>
165170void Reader::WriteSlab (
166171 T *data, // in: local slab, layout [X][Y][Z][k]
167172 int _howmany, // global size of the 4th axis (k)
168- const char *file_name,
169173 const char *dset_name)
170174{
171175 /* ------------------------------------------------------------------*/
@@ -188,20 +192,13 @@ void Reader::WriteSlab(
188192 /* ------------------------------------------------------------------*/
189193 /* 1. open or create the HDF5 file */
190194 /* ------------------------------------------------------------------*/
191- hid_t plist_id = H5Pcreate (H5P_FILE_ACCESS);
192- H5Pset_fapl_mpio (plist_id, MPI_COMM_WORLD, MPI_INFO_NULL);
193-
194- /* temporarily silence “file not found” during H5Fopen */
195+ hid_t file_id = results_file_id;
196+ hid_t plist_id;
197+ if (file_id < 0 ) {
198+ throw std::runtime_error (" WriteSlab: results file is not open" );
199+ }
195200 herr_t (*old_func)(hid_t , void *);
196201 void *old_client_data;
197- H5Eget_auto (H5E_DEFAULT, &old_func, &old_client_data);
198- H5Eset_auto (H5E_DEFAULT, nullptr , nullptr );
199-
200- hid_t file_id = H5Fopen (file_name, H5F_ACC_RDWR, plist_id);
201- H5Eset_auto (H5E_DEFAULT, old_func, old_client_data); /* restore */
202- if (file_id < 0 ) /* create if absent */
203- file_id = H5Fcreate (file_name, H5F_ACC_EXCL, H5P_DEFAULT, plist_id);
204- H5Pclose (plist_id);
205202
206203 /* ------------------------------------------------------------------*/
207204 /* 2. create the dataset (global dims = Z Y X k ) if necessary */
@@ -298,31 +295,28 @@ void Reader::WriteSlab(
298295 H5Sclose (filespace);
299296 H5Pclose (plist_id);
300297 H5Dclose (dset_id);
301- H5Fclose (file_id);
302298}
303299
304300template <typename T>
305- void Reader::writeData (const char *fieldName, const char *file_name, const char *dataset_name,
306- int load_idx, int time_idx, T *data, hsize_t *dims, int ndims)
301+ void Reader::writeData (const char *fieldName, int load_idx, int time_idx, T *data, hsize_t *dims, int ndims)
307302{
308- if (world_rank != 0 || std::find (resultsToWrite.begin (), resultsToWrite.end (), fieldName) == resultsToWrite.end ()) {
303+ if (std::find (resultsToWrite.begin (), resultsToWrite.end (), fieldName) == resultsToWrite.end ()) {
309304 return ;
310305 }
311306 char name[5096 ];
312307 snprintf (name, sizeof (name), " %s/load%i/time_step%i/%s" , dataset_name, load_idx, time_idx, fieldName);
313- WriteData (data, file_name, name, dims, ndims);
308+ WriteData (data, name, dims, ndims);
314309}
315310
316311template <typename T>
317- void Reader::writeSlab (const char *fieldName, const char *file_name, const char *dataset_name,
318- int load_idx, int time_idx, T *data, int size)
312+ void Reader::writeSlab (const char *fieldName, int load_idx, int time_idx, T *data, int size)
319313{
320314 if (std::find (resultsToWrite.begin (), resultsToWrite.end (), fieldName) == resultsToWrite.end ()) {
321315 return ;
322316 }
323317 char name[5096 ];
324318 snprintf (name, sizeof (name), " %s/load%i/time_step%i/%s" , dataset_name, load_idx, time_idx, fieldName);
325- WriteSlab (data, size, file_name, name);
319+ WriteSlab (data, size, name);
326320}
327321
328322#endif
0 commit comments