IOSS 2.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Iotm_TextMeshSidesetSplitter.h
Go to the documentation of this file.
1// Copyright(C) 1999-2020, 2022, 2023 National Technology & Engineering Solutions
2// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
3// NTESS, the U.S. Government retains certain rights in this software.
4
5#pragma once
6
7// ####################### Start Clang Header Tool Managed Headers ########################
8// clang-format off
9#include <ctype.h> // for toupper
10#include <stddef.h> // for size_t
11#include <algorithm> // for remove, etc
12#include <iterator> // for insert_iterator
13#include <map>
14#include <set> // for set
15#include <sstream> // for operator<<, etc
16#include <string> // for basic_string, etc
17#include <utility> // for pair
18#include <vector> // for vector
19#include <unordered_map>
20#include <sstream> // for ostringstream
21#include <iostream>
22#include <functional>
23#include <stdexcept>
24#include <numeric>
25#if defined(_WIN32) && !defined(__MINGW32__)
26#include <string.h>
27#define strcasecmp _stricmp
28#define strncasecmp _strnicmp
29#else
30#include <strings.h>
31#endif
32
33#include "Iotm_TextMeshFuncs.h"
36
37// clang-format on
38// ####################### End Clang Header Tool Managed Headers ########################
39namespace Iotm {
40 namespace text_mesh {
41
42 using ErrorHandler = std::function<void(const std::ostringstream &)>;
43
45 {
46 std::string name{};
47 std::string parentName{};
48 std::string sideTopology{};
49 std::string elementTopology{};
50 std::string touchingBlock{};
51 std::vector<size_t> sideIndex{};
52 unsigned numNodesPerSide{0};
53 };
54
56
57 inline std::ostream &operator<<(std::ostream &out, const SplitType &t)
58 {
59 switch (t) {
60 case SplitType::TOPOLOGY: return out << "TOPOLOGY"; break;
61 case SplitType::ELEMENT_BLOCK: return out << "ELEMENT_BLOCK"; break;
62 case SplitType::NO_SPLIT: return out << "NO_SPLIT"; break;
63 default: return out << "INVALID"; break;
64 }
65 return out << "INVALID[" << (unsigned)t << "]";
66 }
67
68 template <typename EntityId> using SidesetDataType = std::pair<EntityId, int>;
69
70 template <typename EntityId, typename Topology> struct SidesetData;
71
72 template <typename EntityId, typename Topology> class SidesetSplitter
73 {
74 public:
75 explicit SidesetSplitter(SplitType splitType) : m_splitType(splitType)
76 {
77 ErrorHandler errorHandler = [](const std::ostringstream &errmsg) {
79 };
80 set_error_handler(errorHandler);
81 }
82
84 {
85 ErrorHandler errorHandler = [](const std::ostringstream &errmsg) {
87 };
88 set_error_handler(errorHandler);
89 }
90
91 void set_error_handler(ErrorHandler errorHandler) { m_errorHandler = errorHandler; }
92
94 const std::vector<ElementData<EntityId, Topology>> &elementData)
95 {
96 m_splitMap.clear();
97 m_sidesetName = sideset.name;
98
99 if (get_split_type() == SplitType::TOPOLOGY) {
100 split_by_topology(sideset, elementData);
101 }
102 else if (get_split_type() == SplitType::ELEMENT_BLOCK) {
103 split_by_element_block(sideset, elementData);
104 }
105 else if (get_split_type() == SplitType::NO_SPLIT) {
106 split_by_no_split(sideset, elementData);
107 }
108 else {
109 std::ostringstream errmsg;
110 errmsg << "Invalid split type: " << get_split_type();
111 m_errorHandler(errmsg);
112 }
113
114 build_index_proc_map(sideset, elementData);
115 }
116
117 std::vector<SideBlockInfo> get_side_block_info() const
118 {
119 std::vector<SideBlockInfo> infoVec;
120 infoVec.reserve(m_splitMap.size());
121
122 for (auto iter = m_splitMap.begin(); iter != m_splitMap.end(); iter++) {
123 const std::string &sideBlockName = iter->first;
124 SideBlockInfo info = get_side_block_info(sideBlockName);
125 infoVec.push_back(info);
126 }
127 return infoVec;
128 }
129
130 std::vector<size_t> get_indices_local_to_proc(const std::vector<size_t> &index,
131 int proc) const
132 {
133 std::vector<size_t> indexForProc;
134 indexForProc.reserve(index.size());
135
136 for (size_t elemPairIndex : index) {
137 if (is_index_local_to_proc(elemPairIndex, proc)) {
138 indexForProc.push_back(elemPairIndex);
139 }
140 }
141
142 indexForProc.resize(indexForProc.size());
143 return indexForProc;
144 }
145
146 SideBlockInfo get_side_block_info(const std::string &name) const
147 {
148 SideBlockInfo info;
149
150 auto iter = m_splitMap.find(name);
151 if (iter != m_splitMap.end()) {
152 const SplitData &splitData = iter->second;
153
154 info.name = name;
155 info.parentName = splitData.sidesetName;
156 info.sideTopology = splitData.sideTopology;
157 info.elementTopology = splitData.elemTopology;
158 info.numNodesPerSide = splitData.sideNodeCount;
159 info.touchingBlock = splitData.touchingBlock;
160 info.sideIndex = splitData.index;
161 }
162 return info;
163 }
164
166 void set_split_type(SplitType inputSplitType) { m_splitType = inputSplitType; }
167
168 private:
170 const std::vector<ElementData<EntityId, Topology>> &elementData)
171 {
172 for (size_t i = 0; i < sideset.data.size(); ++i) {
173 const SidesetDataType<EntityId> &elemSidePair = sideset.data[i];
174 EntityId elemId = elemSidePair.first;
175
176 auto iter = bound_search(elementData.begin(), elementData.end(), elemId,
178 if (iter == elementData.end()) {
179 std::ostringstream errmsg;
180 errmsg << "Error! Sideset with id: " << sideset.id << " and name: " << sideset.name
181 << " has reference to invalid element '" << elemId << "'.";
182 m_errorHandler(errmsg);
183 }
184
185 m_indexProcMap[i] = iter->proc;
186 }
187 }
188
189 bool is_index_local_to_proc(size_t elemPairIndex, int proc) const
190 {
191 auto iter = m_indexProcMap.find(elemPairIndex);
192
193 if (iter == m_indexProcMap.end()) {
194 std::ostringstream errmsg;
195 errmsg << "Sideset with name: " << m_sidesetName << " is referencing an invalid index "
196 << elemPairIndex;
197 m_errorHandler(errmsg);
198 }
199
200 return iter->second == proc;
201 }
202
204 {
205 bool metaDataSet{false};
206 std::string sidesetName{};
207 std::string touchingBlock{};
208 std::string elemTopology{};
209 std::string sideTopology{};
211 std::vector<size_t> index{};
212
214 };
215
216 void fill_split_data(std::string key, size_t index,
217 const ElementData<EntityId, Topology> &elemData, int side)
218 {
220
221 SplitData &splitData = m_splitMap[key];
222
223 splitData.index.push_back(index);
224
225 if (!splitData.metaDataSet) {
226 splitData.sidesetName = m_sidesetName;
227 splitData.elemTopology = elemData.topology.name();
228 splitData.sideTopology = elemData.topology.side_topology_name(side);
229 splitData.sideNodeCount = elemData.topology.side_topology_num_nodes(side);
230
231 if (get_split_type() == ELEMENT_BLOCK) {
232 splitData.touchingBlock = elemData.partName;
233 }
234
235 splitData.metaDataSet = true;
236 }
237 }
238
239 using Criterion =
240 std::function<std::string(const SidesetData<EntityId, Topology> &sideset,
241 const ElementData<EntityId, Topology> &elemData, int side)>;
242
244 const std::vector<ElementData<EntityId, Topology>> &elementData,
245 Criterion criterion)
246 {
247 for (size_t index = 0; index < sideset.data.size(); ++index) {
248 const SidesetDataType<EntityId> &elemSidePair = sideset.data[index];
249 EntityId elemId = elemSidePair.first;
250 int side = elemSidePair.second;
251
252 auto iter = bound_search(elementData.begin(), elementData.end(), elemId,
254 if (iter == elementData.end()) {
255 std::ostringstream errmsg;
256 errmsg << "Error! Sideset with id: " << sideset.id << " and name: " << sideset.name
257 << " has reference to invalid element '" << elemId << "'.";
258 m_errorHandler(errmsg);
259 }
260
261 std::string key = criterion(sideset, *iter, side);
262 fill_split_data(key, index, *iter, side);
263 }
264 }
265
267 const std::vector<ElementData<EntityId, Topology>> &elementData)
268 {
269 Criterion criterion = [](const SidesetData<EntityId, Topology> &sideSet,
270 const ElementData<EntityId, Topology> &elemData, int side) {
271 if (sideSet.has_default_exodus_name()) {
272 return "SURFACE_" + elemData.topology.name() + "_" +
273 elemData.topology.side_topology_name(side) + "_" + std::to_string(sideSet.id);
274 }
275 return sideSet.name + "_" + elemData.topology.name() + "_" +
276 elemData.topology.side_topology_name(side);
277 };
278
279 split_by_criterion(sideset, elementData, criterion);
280 }
281
283 const std::vector<ElementData<EntityId, Topology>> &elementData)
284 {
285 Criterion criterion = [](const SidesetData<EntityId, Topology> &sideSet,
286 const ElementData<EntityId, Topology> &elemData, int side) {
287 if (sideSet.has_default_exodus_name()) {
288 return "SURFACE_" + elemData.partName + "_" +
289 elemData.topology.side_topology_name(side) + "_" + std::to_string(sideSet.id);
290 }
291 return sideSet.name + "_" + elemData.partName + "_" +
292 elemData.topology.side_topology_name(side);
293 };
294
295 split_by_criterion(sideset, elementData, criterion);
296 }
297
299 const std::vector<ElementData<EntityId, Topology>> & /* elementData */)
300 {
301 std::vector<size_t> splitIndex(sideset.data.size());
302 std::iota(std::begin(splitIndex), std::end(splitIndex), 0);
303 SplitData &splitData = m_splitMap[sideset.name];
304
305 splitData.index = splitIndex;
306 splitData.sidesetName = m_sidesetName;
307 splitData.elemTopology = "unknown";
308 splitData.sideTopology = "unknown";
309 splitData.sideNodeCount = -1;
310 splitData.metaDataSet = true;
311 }
312
314 std::string m_sidesetName{};
315
316 std::unordered_map<size_t, int> m_indexProcMap;
317 std::unordered_map<std::string, SplitData> m_splitMap;
319 };
320
321 } // namespace text_mesh
322} // namespace Iotm
unsigned side_topology_num_nodes(unsigned side) const
Definition Iotm_TextMeshTopologyMapping.h:122
const std::string name() const
Definition Iotm_TextMeshTopologyMapping.h:71
std::string side_topology_name(unsigned side) const
Definition Iotm_TextMeshTopologyMapping.h:106
void split_by_no_split(const SidesetData< EntityId, Topology > &sideset, const std::vector< ElementData< EntityId, Topology > > &)
Definition Iotm_TextMeshSidesetSplitter.h:298
std::string m_sidesetName
Definition Iotm_TextMeshSidesetSplitter.h:314
SideBlockInfo get_side_block_info(const std::string &name) const
Definition Iotm_TextMeshSidesetSplitter.h:146
void split(const SidesetData< EntityId, Topology > &sideset, const std::vector< ElementData< EntityId, Topology > > &elementData)
Definition Iotm_TextMeshSidesetSplitter.h:93
SplitType m_splitType
Definition Iotm_TextMeshSidesetSplitter.h:313
SplitType get_split_type() const
Definition Iotm_TextMeshSidesetSplitter.h:165
std::function< std::string(const SidesetData< EntityId, Topology > &sideset, const ElementData< EntityId, Topology > &elemData, int side)> Criterion
Definition Iotm_TextMeshSidesetSplitter.h:239
SidesetSplitter()
Definition Iotm_TextMeshSidesetSplitter.h:83
SidesetSplitter(SplitType splitType)
Definition Iotm_TextMeshSidesetSplitter.h:75
bool is_index_local_to_proc(size_t elemPairIndex, int proc) const
Definition Iotm_TextMeshSidesetSplitter.h:189
ErrorHandler m_errorHandler
Definition Iotm_TextMeshSidesetSplitter.h:318
void set_split_type(SplitType inputSplitType)
Definition Iotm_TextMeshSidesetSplitter.h:166
void split_by_criterion(const SidesetData< EntityId, Topology > &sideset, const std::vector< ElementData< EntityId, Topology > > &elementData, Criterion criterion)
Definition Iotm_TextMeshSidesetSplitter.h:243
void split_by_topology(const SidesetData< EntityId, Topology > &sideset, const std::vector< ElementData< EntityId, Topology > > &elementData)
Definition Iotm_TextMeshSidesetSplitter.h:266
std::vector< size_t > get_indices_local_to_proc(const std::vector< size_t > &index, int proc) const
Definition Iotm_TextMeshSidesetSplitter.h:130
void split_by_element_block(const SidesetData< EntityId, Topology > &sideset, const std::vector< ElementData< EntityId, Topology > > &elementData)
Definition Iotm_TextMeshSidesetSplitter.h:282
std::vector< SideBlockInfo > get_side_block_info() const
Definition Iotm_TextMeshSidesetSplitter.h:117
void build_index_proc_map(const SidesetData< EntityId, Topology > &sideset, const std::vector< ElementData< EntityId, Topology > > &elementData)
Definition Iotm_TextMeshSidesetSplitter.h:169
void set_error_handler(ErrorHandler errorHandler)
Definition Iotm_TextMeshSidesetSplitter.h:91
std::unordered_map< size_t, int > m_indexProcMap
Definition Iotm_TextMeshSidesetSplitter.h:316
std::unordered_map< std::string, SplitData > m_splitMap
Definition Iotm_TextMeshSidesetSplitter.h:317
void fill_split_data(std::string key, size_t index, const ElementData< EntityId, Topology > &elemData, int side)
Definition Iotm_TextMeshSidesetSplitter.h:216
Definition Iotm_TextMeshAdjacencyGraph.h:39
ForwardIt bound_search(ForwardIt first, ForwardIt last, const T &value)
Definition Iotm_TextMeshFuncs.h:46
void convert_to_uppercase(std::string &str)
Definition Iotm_TextMeshFuncs.h:96
std::function< void(const std::ostringstream &)> ErrorHandler
Definition Iotm_TextMeshAdjacencyGraph.h:41
std::ostream & operator<<(std::ostream &out, const AssemblyType &t)
Definition Iotm_TextMeshAssembly.h:40
std::pair< EntityId, int > SidesetDataType
Definition Iotm_TextMeshSideset.h:39
void default_error_handler(const std::ostringstream &message)
Definition Iotm_TextMeshFuncs.h:40
SplitType
Definition Iotm_TextMeshSidesetSplitter.h:55
@ INVALID_SPLIT
Definition Iotm_TextMeshSidesetSplitter.h:55
@ TOPOLOGY
Definition Iotm_TextMeshSidesetSplitter.h:55
@ NO_SPLIT
Definition Iotm_TextMeshSidesetSplitter.h:55
@ ELEMENT_BLOCK
Definition Iotm_TextMeshSidesetSplitter.h:55
A namespace for the textmesh database format.
Definition Iotm_DatabaseIO.C:95
text_mesh::SidesetData< EntityId, Topology > SidesetData
Definition Iotm_TextMesh.h:38
int64_t EntityId
Definition Iotm_TextMesh.h:33
Definition Iotm_TextMeshDataTypes.h:287
Definition Iotm_TextMeshDataTypes.h:276
Topology topology
Definition Iotm_TextMeshDataTypes.h:279
std::string partName
Definition Iotm_TextMeshDataTypes.h:281
std::string name
Definition Iotm_TextMeshEntityGroup.h:49
unsigned id
Definition Iotm_TextMeshEntityGroup.h:48
std::vector< DataType > data
Definition Iotm_TextMeshEntityGroup.h:51
Definition Iotm_TextMeshSidesetSplitter.h:45
unsigned numNodesPerSide
Definition Iotm_TextMeshSidesetSplitter.h:52
std::string elementTopology
Definition Iotm_TextMeshSidesetSplitter.h:49
std::string parentName
Definition Iotm_TextMeshSidesetSplitter.h:47
std::vector< size_t > sideIndex
Definition Iotm_TextMeshSidesetSplitter.h:51
std::string sideTopology
Definition Iotm_TextMeshSidesetSplitter.h:48
std::string touchingBlock
Definition Iotm_TextMeshSidesetSplitter.h:50
std::string name
Definition Iotm_TextMeshSidesetSplitter.h:46
Definition Iotm_TextMeshSideset.h:43
bool has_default_exodus_name() const
Definition Iotm_TextMeshSideset.h:87
Definition Iotm_TextMeshSidesetSplitter.h:204
std::string touchingBlock
Definition Iotm_TextMeshSidesetSplitter.h:207
SplitData()
Definition Iotm_TextMeshSidesetSplitter.h:213
int sideNodeCount
Definition Iotm_TextMeshSidesetSplitter.h:210
std::string sideTopology
Definition Iotm_TextMeshSidesetSplitter.h:209
std::string sidesetName
Definition Iotm_TextMeshSidesetSplitter.h:206
bool metaDataSet
Definition Iotm_TextMeshSidesetSplitter.h:205
std::vector< size_t > index
Definition Iotm_TextMeshSidesetSplitter.h:211
std::string elemTopology
Definition Iotm_TextMeshSidesetSplitter.h:208