OGS
ipDataToPointCloud.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include <tclap/CmdLine.h>
5
6#include <unordered_map>
7
8#include "BaseLib/Logging.h"
9#include "BaseLib/MPI.h"
11#include "InfoLib/GitInfo.h"
14#include "MeshLib/Mesh.h"
18
19template <typename MeshElement>
20std::vector<std::array<double, 3>> interpolateElementCoords(
21 MeshLib::Element const& e, NumLib::ShapeMatrixCache const& sm_cache)
22{
23 constexpr int dim = MeshElement::dimension;
24 using ShapeFunction =
27
28 auto const& Ns = sm_cache.NsHigherOrder<MeshElement>();
29 std::vector<std::array<double, 3>> coords;
30 coords.reserve(Ns.size());
31
32 for (auto const& N : Ns)
33 {
34 coords.push_back(
36 }
37
38 return coords;
39}
40
41// A template metafunction "returning" the cell type of a mesh element
42template <typename Element>
44
45template <typename ElementRule>
46struct CellTypeOfTemplateElement<MeshLib::TemplateElement<ElementRule>>
47{
48 static constexpr MeshLib::CellType value = ElementRule::cell_type;
49};
50
51std::unordered_map<MeshLib::CellType, std::vector<std::array<double, 3>> (*)(
52 MeshLib::Element const&,
55{
56 std::unordered_map<MeshLib::CellType,
57 std::vector<std::array<double, 3>> (*)(
58 MeshLib::Element const&,
60 map_cell_type_to_element_coords_interpolator;
61
62 map_cell_type_to_element_coords_interpolator.reserve(
63 boost::mp11::mp_size<NumLib::AllElementTraitsLagrange>::value);
64
65 boost::mp11::mp_for_each<NumLib::AllElementTraitsLagrange>(
66 [&map_cell_type_to_element_coords_interpolator]<typename ETL>(ETL)
67 {
68 using MeshElement = typename ETL::Element;
69 auto constexpr cell_type =
71
72 auto const [it, newly_inserted] =
73 map_cell_type_to_element_coords_interpolator.emplace(
75
76 if (!newly_inserted)
77 {
79 "Coordinate interpolator for cell type {} is already "
80 "present",
81 MeshLib::CellType2String(cell_type));
82 }
83 });
84
85 return map_cell_type_to_element_coords_interpolator;
86}
87
88std::vector<MeshLib::Node*> computePointCloudNodes(
89 MeshLib::Mesh const& mesh, unsigned const integration_order)
90{
91 NumLib::ShapeMatrixCache sm_cache{integration_order};
92 auto const map_cell_type_to_element_coords_interpolator =
94
95 std::vector<MeshLib::Node*> nodes;
96
97 for (auto const* element : mesh.getElements())
98 {
99 auto const cell_type = element->getCellType();
100
101 auto const it =
102 map_cell_type_to_element_coords_interpolator.find(cell_type);
103 if (it == map_cell_type_to_element_coords_interpolator.end())
104 {
105 OGS_FATAL("Unsupported cell type {} for element #{}",
106 MeshLib::CellType2String(cell_type), element->getID());
107 }
108
109 auto const& element_coords_interpolator = it->second;
110 auto const coords = element_coords_interpolator(*element, sm_cache);
111
112 for (auto& cs : coords)
113 {
114 nodes.push_back(new MeshLib::Node(cs, nodes.size()));
115 }
116 }
117
118 return nodes;
119}
120
122{
123 auto const& properties = mesh.getProperties();
124 auto const ip_meta_data = MeshLib::getIntegrationPointMetaData(properties);
125
126 std::optional<unsigned> integration_order;
127
128 for (auto const& [name, property] : properties)
129 {
130 if (property->getMeshItemType() !=
132 {
133 continue;
134 }
135
136 if (name == "IntegrationPointMetaData" || name == "OGS_VERSION")
137 {
138 continue;
139 }
140
141 auto const order =
144
145 if (!integration_order)
146 {
147 integration_order = order;
148 }
149 else if (integration_order != order)
150 {
151 OGS_FATAL("Integration orders differ: {} != {}", *integration_order,
152 order);
153 }
154 }
155
156 if (!integration_order)
157 {
158 OGS_FATAL("Integration order could not be determined.");
159 }
160
161 return *integration_order;
162}
163
165 MeshLib::Properties& props_out,
166 std::size_t const num_ips)
167{
168 for (auto const& [prop_name, prop_in] : props_in)
169 {
170 auto const mesh_item_type = prop_in->getMeshItemType();
171
172 if (mesh_item_type != MeshLib::MeshItemType::IntegrationPoint)
173 {
174 continue;
175 }
176
177 auto const num_comp = prop_in->getNumberOfGlobalComponents();
178 auto const* prop_in_double =
179 dynamic_cast<MeshLib::PropertyVector<double> const*>(prop_in);
180
181 if (prop_in_double == nullptr)
182 {
183 INFO(
184 "Ignoring non-double-valued property '{}' with {} components "
185 "on {}",
186 prop_name, num_comp, toString(mesh_item_type));
187 continue;
188 }
189
190 DBUG("Converting property '{}' with {} components on {}", prop_name,
191 num_comp, toString(mesh_item_type));
192
193 if (props_out.existsPropertyVector<double>(prop_name))
194 {
195 OGS_FATAL(
196 "A property vector with name '{}' already exists. Not "
197 "adding it again",
198 prop_name);
199 }
200
201 if (auto const num_ips_actual = prop_in_double->getNumberOfTuples();
202 num_ips_actual != num_ips)
203 {
204 WARN(
205 "Property vector '{}' has {} tuples, which differs from "
206 "the number of integration points ({}). Skipping this "
207 "property.",
208 prop_name, num_ips_actual, num_ips);
209 }
210
211 auto* prop_out = props_out.createNewPropertyVector<double>(
212 prop_name, MeshLib::MeshItemType::Node, num_comp);
213
214 prop_out->assign(*prop_in_double);
215 }
216}
217
218int main(int argc, char** argv)
219{
220 // TODO future additions to this tool might include:
221 // -C --copy-cell-data
222 // -N --interpolate-node-data
223 // -I --add-cell-ids
224 // -O --integration-order
225 // --natural-coords add natural coordinates of integration points, or better
226 // not?
227 // --no-data
228 // --linear-shape-functions={pressure, ...} for the interpolation of nodal
229 // data
230 // PVD support
231 // handle other data than only double data
232
233 TCLAP::CmdLine cmd(
234 "Creates a point cloud mesh for the integration point data existing on "
235 "a given input mesh.\n\n"
236 "OpenGeoSys-6 software, version " +
238 ".\n"
239 "Copyright (c) 2012-2026, OpenGeoSys Community "
240 "(http://www.opengeosys.org)",
242 TCLAP::ValueArg<std::string> arg_out_file(
243 "o", "output-file", "Output (.vtu). The output mesh (point cloud)",
244 true, "", "OUTPUT_FILE");
245 cmd.add(arg_out_file);
246 TCLAP::ValueArg<std::string> arg_in_file("i", "input-file",
247 "Input (.vtu). The input mesh",
248 true, "", "INPUT_FILE");
249 cmd.add(arg_in_file);
250
251 auto log_level_arg = BaseLib::makeLogLevelArg();
252 cmd.add(log_level_arg);
253 cmd.parse(argc, argv);
254
255 BaseLib::MPI::Setup mpi_setup(argc, argv);
256 BaseLib::initOGSLogger(log_level_arg.getValue());
257
258 std::unique_ptr<MeshLib::Mesh const> mesh_in(
259 MeshLib::IO::readMeshFromFile(arg_in_file.getValue()));
260
261 auto const integration_order = determineIntegrationOrder(*mesh_in);
262 auto nodes = computePointCloudNodes(*mesh_in, integration_order);
263
264 MeshLib::Mesh point_cloud("point_cloud", std::move(nodes), {});
265
266 copyDoubleValuedFieldDataToPointCloud(mesh_in->getProperties(),
267 point_cloud.getProperties(),
268 point_cloud.getNumberOfNodes());
269
270 MeshLib::IO::writeMeshToFile(point_cloud, arg_out_file.getValue());
271
272 return EXIT_SUCCESS;
273}
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition Mesh.h:100
Properties & getProperties()
Definition Mesh.h:125
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
bool existsPropertyVector(std::string_view name) const
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
constexpr void assign(R &&r)
boost::mp11::mp_at< ShapeFunctionsHigherOrder, boost::mp11::mp_find< MeshElements, MeshElement > > ShapeFunctionHigherOrder
auto const & NsHigherOrder() const
unsigned determineIntegrationOrder(MeshLib::Mesh const &mesh)
int main(int argc, char **argv)
std::vector< MeshLib::Node * > computePointCloudNodes(MeshLib::Mesh const &mesh, unsigned const integration_order)
void copyDoubleValuedFieldDataToPointCloud(MeshLib::Properties const &props_in, MeshLib::Properties &props_out, std::size_t const num_ips)
std::vector< std::array< double, 3 > > interpolateElementCoords(MeshLib::Element const &e, NumLib::ShapeMatrixCache const &sm_cache)
std::unordered_map< MeshLib::CellType, std::vector< std::array< double, 3 > >(*)(MeshLib::Element const &, NumLib::ShapeMatrixCache const &)> createElementCoordInterpolatorsForAllElementTypes()
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
Definition Logging.cpp:56
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)
int writeMeshToFile(const MeshLib::Mesh &mesh, std::filesystem::path const &file_path, std::set< std::string > variable_output_names)
CellType
Types of mesh elements supported by OpenGeoSys.
Definition MeshEnums.h:53
std::optional< IntegrationPointMetaData > getIntegrationPointMetaData(MeshLib::Properties const &properties)
std::string CellType2String(const CellType t)
Given a MeshElemType this returns the appropriate string.
IntegrationPointMetaDataSingleField getIntegrationPointMetaDataSingleField(std::optional< IntegrationPointMetaData > const &ip_meta_data, std::string const &field_name)
std::array< double, 3 > interpolateCoordinates(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)