823 const std::string & groupname)
825#ifndef LIBMESH_HAVE_HDF5
827 libmesh_error_msg(
"ERROR: need HDF5 support to handle .h5 files!!!");
829 LOG_SCOPE(
"read_coreform_hdf5()",
"SparseMatrix");
831 std::size_t num_rows = 0, num_cols = 0;
834 hid_t group = H5I_INVALID_HID;
835 hid_t file = H5I_INVALID_HID;
837 if (this->processor_id() == 0)
839 file = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
841 if (file == H5I_INVALID_HID)
842 libmesh_file_error(filename);
844 group = H5Gopen(file, groupname.c_str(), H5P_DEFAULT);
845 check_open(filename, group, groupname);
847 auto read_size_attribute = [&filename, &group]
848 (
const std::string & attribute_name)
850 unsigned long long returnval = 0;
852 const hid_t attr = H5Aopen(group, attribute_name.c_str(), H5P_DEFAULT);
853 check_open(filename, attr, attribute_name);
855 const hid_t attr_type = H5Aget_type(attr);
856 check_hdf5(filename, attr_type, attribute_name +
" type");
860 if (H5Tget_class(attr_type) != H5T_INTEGER)
861 libmesh_error_msg(
"Non-integer type for " + attribute_name +
" in " + filename);
867 const herr_t errval = H5Aread(attr, H5T_NATIVE_ULLONG, &returnval);
868 check_hdf5(filename, errval, attribute_name +
" read");
875 num_cols = read_size_attribute(
"num_cols");
876 num_rows = read_size_attribute(
"num_rows");
878 this->comm().broadcast(num_cols);
879 this->comm().broadcast(num_rows);
883 this->comm().broadcast(num_cols);
884 this->comm().broadcast(num_rows);
888 new_col_start, new_col_stop;
892 std::vector<numeric_index_type> new_row_starts, new_row_stops,
893 new_col_starts, new_col_stops;
896 num_cols == this->n() &&
897 num_rows == this->m())
899 new_row_start = this->row_start(),
900 new_row_stop = this->row_stop();
902 new_col_start = this->col_start(),
903 new_col_stop = this->col_stop();
908 new_row_start = this->processor_id() * num_rows / this->n_processors(),
909 new_row_stop = (this->processor_id()+1) * num_rows / this->n_processors();
911 new_col_start = this->processor_id() * num_cols / this->n_processors(),
912 new_col_stop = (this->processor_id()+1) * num_cols / this->n_processors();
915 this->comm().gather(0, new_row_start, new_row_starts);
916 this->comm().gather(0, new_row_stop, new_row_stops);
917 this->comm().gather(0, new_col_start, new_col_starts);
918 this->comm().gather(0, new_col_stop, new_col_stops);
921 off_diagonal_nonzeros = 0;
923 std::vector<std::size_t> cols, row_offsets;
924 std::vector<double> vals;
926 if (this->processor_id() == 0)
928 auto read_vector = [&filename, &group]
929 (
const std::string & dataname,
auto hdf5_class,
930 auto hdf5_type,
auto & datavec)
932 const hid_t data = H5Dopen1(group, dataname.c_str());
933 check_open(filename, data, dataname.c_str());
935 const hid_t data_type = H5Dget_type(data);
936 check_hdf5(filename, data_type, dataname +
" type");
940 if (H5Tget_class(data_type) != hdf5_class)
941 libmesh_error_msg(
"Unexpected type for " + dataname +
" in " + filename);
945 const hid_t dataspace = H5Dget_space(data);
946 check_hdf5(filename, dataspace, dataname +
" space");
948 int ndims = H5Sget_simple_extent_ndims(dataspace);
950 libmesh_error_msg(
"Non-vector space for " + dataname +
" in " + filename);
953 herr_t errval = H5Sget_simple_extent_dims(dataspace, &len, &maxlen);
954 check_hdf5(filename, errval, dataname +
" dims");
958 errval = H5Dread(data, hdf5_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, datavec.data());
959 check_hdf5(filename, errval, dataname +
" read");
964 read_vector(
"cols", H5T_INTEGER, H5T_NATIVE_ULLONG, cols);
965 read_vector(
"row_offsets", H5T_INTEGER, H5T_NATIVE_ULLONG, row_offsets);
966 read_vector(
"vals", H5T_FLOAT, H5T_NATIVE_DOUBLE, vals);
968 if (cols.size() != vals.size())
969 libmesh_error_msg(
"Inconsistent cols/vals sizes in " + filename);
971 if (row_offsets.size() != num_rows + 1)
972 libmesh_error_msg(
"Inconsistent row_offsets size in " + filename);
979 if (row_offsets[0] != 0)
980 libmesh_error_msg(
"Unexpected row_offsets[0] in " + filename);
984 while (row_offsets[current_row+1] <= i)
987 if (row_offsets[current_row] < row_offsets[current_row-1])
988 libmesh_error_msg(
"Non-monotonic row_offsets in " + filename);
989 current_on_diagonal_nonzeros = 0;
990 current_off_diagonal_nonzeros = 0;
993 while (current_row >= new_row_stops[current_proc])
997 if (cols[i] >= new_col_starts[current_proc] &&
998 cols[i] < new_col_stops[current_proc])
1000 ++current_on_diagonal_nonzeros;
1001 on_diagonal_nonzeros =
1002 std::max(on_diagonal_nonzeros,
1003 current_on_diagonal_nonzeros);
1007 ++current_off_diagonal_nonzeros;
1008 off_diagonal_nonzeros =
1009 std::max(off_diagonal_nonzeros,
1010 current_off_diagonal_nonzeros);
1015 this->comm().broadcast(on_diagonal_nonzeros);
1016 this->comm().broadcast(off_diagonal_nonzeros);
1018 this->init(num_rows, num_cols,
1019 new_row_stop-new_row_start,
1020 new_col_stop-new_col_start,
1021 on_diagonal_nonzeros,
1022 off_diagonal_nonzeros);
1025 if (this->processor_id() == 0)
1030 while (row_offsets[current_row+1] <= i)
1033 libmesh_assert_greater_equal (row_offsets[current_row],
1034 row_offsets[current_row-1]);
1036 this->set(current_row, cols[i], vals[i]);
1052 LOG_SCOPE(
"read_matlab()",
"SparseMatrix");
1054#ifndef LIBMESH_HAVE_CXX11_REGEX
1055 libmesh_not_implemented();
1058 parallel_object_only();
1068 std::vector<numeric_index_type> new_row_starts, new_row_stops,
1069 new_col_starts, new_col_stops;
1072 new_col_start, new_col_stop;
1083 std::unique_ptr<std::istream> file;
1092 std::vector<std::tuple<numeric_index_type, numeric_index_type, T>> entries;
1098 if (this->processor_id() == 0)
1102 const std::regex start_regex
1103 (
"\\s*\\w+\\s*=\\s*\\[");
1104 const std::regex end_regex
1109#ifdef LIBMESH_HAVE_GZSTREAM
1110 auto inf = std::make_unique<igzstream>();
1112 inf->open(filename.c_str(), std::ios::in);
1113 file = std::move(inf);
1115 libmesh_error_msg(
"ERROR: need gzstream to handle .gz files!!!");
1120 auto inf = std::make_unique<std::ifstream>();
1125 inf->open(new_name.c_str(), std::ios::in);
1126 file = std::move(inf);
1131 const std::regex size_regex
1132 (
"%\\s*[Ss][Ii][Zz][Ee]\\s*=\\s*(\\d+)\\s+(\\d+)");
1133 const std::string whitespace =
" \t";
1135 bool have_started =
false;
1136 bool have_ended =
false;
1137 std::size_t largest_i_seen = 0, largest_j_seen = 0;
1141 std::size_t current_row = 1;
1143 for (std::string line; std::getline(*file, line);)
1153 std::istringstream l(line);
1158 l >> i >> j >>
value;
1162 libmesh_error_msg_if
1163 (!have_started,
"Confused by premature entries in matrix file " << filename);
1165 entries.emplace_back(cast_int<numeric_index_type>(i),
1166 cast_int<numeric_index_type>(j),
1169 libmesh_error_msg_if
1170 (!i || !j,
"Expected 1-based indexing in matrix file "
1173 current_row = std::max(current_row, i);
1175 libmesh_error_msg_if
1177 "Can't handle out-of-order entries in matrix file "
1180 largest_i_seen = std::max(i, largest_i_seen);
1181 largest_j_seen = std::max(j, largest_j_seen);
1184 else if (std::regex_search(line, sm, size_regex))
1186 const std::string msize = sm[1];
1187 const std::string nsize = sm[2];
1188 m = std::stoull(msize);
1189 n = std::stoull(nsize);
1192 else if (std::regex_search(line, start_regex))
1193 have_started =
true;
1195 else if (std::regex_search(line, end_regex))
1202 libmesh_error_msg_if
1203 (!have_started,
"Confused by missing assignment beginning in matrix file " << filename);
1205 libmesh_error_msg_if
1206 (!have_ended,
"Confused by missing assignment ending in matrix file " << filename);
1208 libmesh_error_msg_if
1209 (m > largest_i_seen,
"Confused by missing final row(s) in matrix file " << filename);
1211 libmesh_error_msg_if
1212 (m > 0 && m < largest_i_seen,
"Confused by extra final row(s) in matrix file " << filename);
1217 libmesh_error_msg_if
1218 (n > largest_j_seen,
"Confused by missing final column(s) in matrix file " << filename);
1220 libmesh_error_msg_if
1221 (n > 0 && n < largest_j_seen,
"Confused by extra final column(s) in matrix file " << filename);
1226 this->comm().broadcast(m);
1227 this->comm().broadcast(n);
1231 this->comm().broadcast(m);
1232 this->comm().broadcast(n);
1239 new_row_start = this->row_start(),
1240 new_row_stop = this->row_stop();
1242 new_col_start = this->col_start(),
1243 new_col_stop = this->col_stop();
1248 new_row_start = this->processor_id() * m / this->n_processors(),
1249 new_row_stop = (this->processor_id()+1) * m / this->n_processors();
1251 new_col_start = this->processor_id() * n / this->n_processors(),
1252 new_col_stop = (this->processor_id()+1) * n / this->n_processors();
1255 this->comm().gather(0, new_row_start, new_row_starts);
1256 this->comm().gather(0, new_row_stop, new_row_stops);
1257 this->comm().gather(0, new_col_start, new_col_starts);
1258 this->comm().gather(0, new_col_stop, new_col_stops);
1267 off_diagonal_nonzeros =0;
1269 if (this->processor_id() == 0)
1278 for (
auto [i, j,
value] : entries)
1280 if (i > current_row)
1284 while (current_row >= (new_row_stops[current_proc]+1))
1286 current_on_diagonal_nonzeros = 0;
1287 current_off_diagonal_nonzeros = 0;
1291 if (j >= (new_col_starts[current_proc]+1) &&
1292 j < (new_col_stops[current_proc]+1))
1294 ++current_on_diagonal_nonzeros;
1295 on_diagonal_nonzeros =
1296 std::max(on_diagonal_nonzeros,
1297 current_on_diagonal_nonzeros);
1301 ++current_off_diagonal_nonzeros;
1302 off_diagonal_nonzeros =
1303 std::max(off_diagonal_nonzeros,
1304 current_off_diagonal_nonzeros);
1309 this->comm().broadcast(on_diagonal_nonzeros);
1310 this->comm().broadcast(off_diagonal_nonzeros);
1313 new_row_stop-new_row_start,
1314 new_col_stop-new_col_start,
1315 on_diagonal_nonzeros,
1316 off_diagonal_nonzeros);
1321 if (this->processor_id() == 0)
1322 for (
auto [i, j,
value] : entries)
1323 this->set(i-1, j-1,
value);