6#include <spdlog/fmt/ranges.h>
16std::vector<std::reference_wrapper<MeshLib::Mesh>>
18 std::vector<std::unique_ptr<MeshLib::Mesh>>
const& meshes,
19 std::vector<std::string>
const& mesh_names_for_output)
21 std::map<std::string, std::reference_wrapper<MeshLib::Mesh>>
22 map_mesh_name_to_mesh;
23 for (
auto const& mesh : meshes)
25 auto const [it, inserted] =
26 map_mesh_name_to_mesh.emplace(mesh->getName(), *mesh);
30 OGS_FATAL(
"Duplicate mesh name '{}' detected.", mesh->getName());
34 std::vector<std::reference_wrapper<MeshLib::Mesh>> meshes_filtered;
36 for (
auto const& mesh_name : mesh_names_for_output)
39 map_mesh_name_to_mesh, mesh_name,
40 "A mesh that has been requested for output is not known to OGS.");
42 meshes_filtered.push_back(mesh);
45 return meshes_filtered;
52 if (!properties.existsPropertyVector<std::size_t>(
57 "The required nodal property '{}' is missing in mesh '{}' or has "
58 "the wrong data type or the wrong number of components",
63 if (!properties.existsPropertyVector<std::size_t>(
68 "The required cell property '{}' is missing in mesh '{}' or has "
69 "the wrong data type or the wrong number of components",
77 std::vector<std::reference_wrapper<MeshLib::Mesh>>
const& submesh_refs)
80 auto const sum_elements_submeshes = [&submesh_refs]()
83 for (
auto const& submesh_ref : submesh_refs)
85 n += submesh_ref.get().getNumberOfElements();
90 if (n_elements_bulk != sum_elements_submeshes)
93 "The number of bulk mesh elements does not match the sum of all "
94 "submesh elements: {} != {}. Hence, the set of all submeshes "
95 "cannot be a non-overlapping cover of the bulk mesh.",
96 n_elements_bulk, sum_elements_submeshes);
102 std::vector<std::reference_wrapper<MeshLib::Mesh>>
const& submesh_refs)
106 std::vector<bool> bulk_element_covered(n_elements_bulk);
108 for (
auto const& submesh_ref : submesh_refs)
110 auto const& submesh = submesh_ref.get();
111 auto const& bulk_element_ids = bulkElementIDs(submesh);
112 if (bulk_element_ids ==
nullptr)
115 "The 'bulk_element_ids' property does not exist on the submesh "
120 if (bulk_element_ids->size() != submesh.getNumberOfElements())
123 "There is something terribly wrong with the mesh '{}'. The "
124 "size of 'bulk_element_ids' does not equal the number of "
125 "elements in the mesh: {} != {}",
126 submesh.getName(), bulk_element_ids->size(),
127 submesh.getNumberOfElements());
130 for (
auto const bulk_element_id : *bulk_element_ids)
134 [[unlikely]]
if (bulk_element_id >= n_elements_bulk)
137 "Saw bulk element id {} in submesh '{}', but the bulk mesh "
138 "('{}') has only {} elements, i.e., the maximum allowed "
139 "bulk element id is {}.",
140 bulk_element_id, submesh.getName(), bulk_mesh.
getName(),
141 n_elements_bulk, n_elements_bulk - 1);
144 [[unlikely]]
if (bulk_element_covered[bulk_element_id])
147 "The bulk element id {} has already been covered by "
148 "another submesh. The second submesh covering this bulk "
150 bulk_element_id, submesh.getName());
153 bulk_element_covered[bulk_element_id] =
true;
157 return bulk_element_covered;
162 std::vector<std::reference_wrapper<MeshLib::Mesh>>
const& submesh_refs)
168 std::vector<bool>
const bulk_element_covered =
171 auto const n_elements_covered =
172 std::accumulate(bulk_element_covered.begin(),
173 bulk_element_covered.end(), std::size_t{0});
175 if (n_elements_covered == n_elements_bulk)
181 auto const non_covered_it = std::find(bulk_element_covered.begin(),
182 bulk_element_covered.end(),
false);
183 auto const non_covered_index =
184 std::distance(bulk_element_covered.begin(), non_covered_it);
187 "The bulk mesh ('{}') is not covered completely by the given "
188 "submeshes. Only {} out of {} elements are covered. The first element "
189 "that is not covered is #{}.",
190 bulk_mesh.
getName(), n_elements_covered, n_elements_bulk,
199 std::vector<std::unique_ptr<MeshLib::Mesh>>& meshes)
203 if (oc.mesh_names_for_output.empty())
206 "You did not specify any meshes for submesh residuum output.");
209 if (
auto const duplicates =
214 "The mesh names for submesh residuum output are not unique. "
215 "Duplicate names: {:s}.",
216 fmt::join(duplicates,
", "));
219 auto const meshes_filtered =
220 filterMeshesForResiduumOutput(meshes, oc.mesh_names_for_output);
222 for (
auto const& mesh : meshes_filtered)
224 checkBulkIDMappingsPresent(mesh.get());
227 auto const& bulk_mesh =
229 checkNonOverlappingCover(bulk_mesh, meshes_filtered);
231 return {
createOutput(std::move(oc), output_directory, meshes),
232 std::move(meshes_filtered)};
Properties & getProperties()
const std::string getName() const
Get name of the mesh.
std::size_t getNumberOfElements() const
Get the number of elements.
std::vector< ranges::range_value_t< Range > > getDuplicates(Range &&range)
OGS_NO_DANGLING Map::mapped_type & getOrError(Map &map, Key const &key, std::string const &error_message)
constexpr std::string_view getBulkIDString(MeshItemType mesh_item_type)
OutputConfig createOutputConfig(const BaseLib::ConfigTree &config, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes)
SubmeshResiduumOutputConfig createSubmeshResiduumOutputConfig(BaseLib::ConfigTree const &config, std::string const &output_directory, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes)
Output createOutput(OutputConfig &&oc, std::string const &output_directory, std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
void checkBulkIDMappingsPresent(MeshLib::Mesh const &mesh)
std::vector< std::reference_wrapper< MeshLib::Mesh > > filterMeshesForResiduumOutput(std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes, std::vector< std::string > const &mesh_names_for_output)
void checkMatchingElementCounts(MeshLib::Mesh const &bulk_mesh, std::vector< std::reference_wrapper< MeshLib::Mesh > > const &submesh_refs)
std::vector< bool > computeNonOverlappingBulkMeshCoverBySubmeshes(MeshLib::Mesh const &bulk_mesh, std::vector< std::reference_wrapper< MeshLib::Mesh > > const &submesh_refs)
void checkNonOverlappingCover(MeshLib::Mesh const &bulk_mesh, std::vector< std::reference_wrapper< MeshLib::Mesh > > const &submesh_refs)