OGS
CreateDeactivatedSubdomain.cpp
Go to the documentation of this file.
1 
10 
11 #include <Eigen/Dense>
12 
13 #include "BaseLib/ConfigTree.h"
14 #include "BaseLib/Error.h"
15 #include "DeactivatedSubdomain.h"
17 #include "MeshLib/Mesh.h"
19 #include "MeshLib/Node.h"
20 #include "ParameterLib/Parameter.h"
21 #include "ParameterLib/Utils.h"
22 
23 namespace ProcessLib
24 {
25 template <typename IsActive>
26 static std::pair<std::vector<MeshLib::Node*>, std::vector<MeshLib::Node*>>
28  MeshLib::Mesh const& sub_mesh,
29  IsActive is_active)
30 {
31  auto* const bulk_node_ids =
32  sub_mesh.getProperties().template getPropertyVector<std::size_t>(
33  "bulk_node_ids", MeshLib::MeshItemType::Node, 1);
34  if (bulk_node_ids == nullptr)
35  {
36  OGS_FATAL(
37  "Bulk node ids map is not available in the deactivate subdomain "
38  "mesh.");
39  }
40 
41  std::vector<MeshLib::Node*> inner_nodes;
42  // Reserve for more than needed, but not much, because almost all nodes will
43  // be the inner nodes.
44  inner_nodes.reserve(sub_mesh.getNumberOfNodes());
45 
46  std::vector<MeshLib::Node*> outer_nodes;
47 
48  std::partition_copy(
49  begin(sub_mesh.getNodes()), end(sub_mesh.getNodes()),
50  back_inserter(inner_nodes), back_inserter(outer_nodes),
51  [&](MeshLib::Node* const n)
52  {
53  auto const bulk_node = mesh.getNode((*bulk_node_ids)[n->getID()]);
54  const auto& connected_elements =
55  mesh.getElementsConnectedToNode(*bulk_node);
56  // elements. Then it is an inner node, and outer otherwise.
57  return std::all_of(begin(connected_elements),
58  end(connected_elements), is_active);
59  });
60 
61  return {std::move(inner_nodes), std::move(outer_nodes)};
62 }
63 
64 static std::unique_ptr<DeactivatedSubdomainMesh> createDeactivatedSubdomainMesh(
65  MeshLib::Mesh const& mesh, int const material_id)
66 {
67  // An element is active if its material id matches the selected material id.
68  auto is_active = [material_id, material_ids = *materialIDs(mesh)](
69  MeshLib::Element const* const e)
70  { return material_id == material_ids[e->getID()]; };
71 
72  auto const& elements = mesh.getElements();
73  std::vector<MeshLib::Element*> deactivated_elements;
74  std::copy_if(begin(elements), end(elements),
75  back_inserter(deactivated_elements),
76  [&](auto const e) { return is_active(e); });
77 
78  // Subdomain mesh consisting of deactivated elements.
80  "deactivate_subdomain_" + std::to_string(material_id),
81  MeshLib::cloneElements(deactivated_elements));
82 
83  auto [inner_nodes, outer_nodes] =
84  extractInnerAndOuterNodes(mesh, *sub_mesh, is_active);
85  return std::make_unique<DeactivatedSubdomainMesh>(
86  std::move(sub_mesh), std::move(inner_nodes), std::move(outer_nodes));
87 }
88 
90  std::optional<BaseLib::ConfigTree> const& time_interval_config,
91  std::optional<std::string> const& curve_name,
92  std::map<std::string,
93  std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&
94  curves)
95 {
96  // Check for the error case first: only one of the configs must be used.
97  if (time_interval_config && curve_name)
98  {
99  OGS_FATAL(
100  "In the deactivate subdomain either a time interval or a curve "
101  "must be given, not both.");
102  }
103 
104  // Parse time interval and return a curve
105  if (time_interval_config)
106  {
107  DBUG("Constructing time interval");
108  auto const start_time =
110  time_interval_config->getConfigParameter<double>("start");
111 
112  auto const end_time =
114  time_interval_config->getConfigParameter<double>("end");
115 
116  // Using very large value for the curve's value, s.t. for any time from
117  // start to end the whole subdomain is deactivated at once.
118  return {{start_time, end_time},
119  {std::numeric_limits<double>::max(),
120  std::numeric_limits<double>::max()},
121  false};
122  }
123 
124  // Try to find the curve.
125  if (curve_name)
126  {
127  DBUG("Using curve '{:s}'", *curve_name);
128  // Return a copy of the curve because the time interval in the other
129  // branch returns a temporary.
130  return *BaseLib::getOrError(curves, *curve_name,
131  "Could not find curve.");
132  }
133 
134  // If we got so far, there is an error: one of the configs must be
135  // available.
136  OGS_FATAL(
137  "In the deactivate subdomain neither a time interval nor a curve are "
138  "given. One of them must be specified.");
139 }
140 
142 static std::pair<Eigen::Vector3d, Eigen::Vector3d> parseLineSegment(
143  BaseLib::ConfigTree const& config)
144 {
145  DBUG("Constructing line segment");
146  auto const start =
148  config.getConfigParameter<std::vector<double>>("start");
149  if (start.size() != 3)
150  {
151  OGS_FATAL(
152  "For construction of a line segment the start point must be a 3D "
153  "point. Got a vector of size {}.",
154  start.size());
155  }
156 
157  auto const end =
159  config.getConfigParameter<std::vector<double>>("end");
160 
161  if (end.size() != 3)
162  {
163  OGS_FATAL(
164  "For construction of a line segment the end point must be a 3D "
165  "point. Got a vector of size {}.",
166  end.size());
167  }
168  return {Eigen::Vector3d{start[0], start[1], start[2]},
169  Eigen::Vector3d{end[0], end[1], end[2]}};
170 }
171 
172 std::unique_ptr<DeactivatedSubdomain const> createDeactivatedSubdomain(
173  BaseLib::ConfigTree const& config, MeshLib::Mesh const& mesh,
174  std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
175  std::map<std::string,
176  std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&
177  curves)
178 {
179  auto const& time_interval_config =
181  config.getConfigSubtreeOptional("time_interval");
182 
183  auto const& curve_name =
185  config.getConfigParameterOptional<std::string>("time_curve");
186  auto time_interval =
187  parseTimeIntervalOrCurve(time_interval_config, curve_name, curves);
188 
189  auto const line_segment_config =
191  config.getConfigSubtreeOptional("line_segment");
192 
193  if (time_interval_config && line_segment_config)
194  {
195  OGS_FATAL(
196  "When using time interval for subdomain deactivation a line "
197  "segment must not be specified.");
198  }
199 
200  if (curve_name && !line_segment_config)
201  {
202  OGS_FATAL(
203  "When using curve for subdomain deactivation a line segment must "
204  "be specified.");
205  }
206 
207  // If time interval was specified then a dummy line segment is used
208  // *internally* because the whole selected material ids subdomain will be
209  // deactivated.
210  std::pair line_segment{Eigen::Vector3d{0, 0, 0}, Eigen::Vector3d{1, 1, 1}};
211 
212  if (curve_name)
213  {
214  line_segment = parseLineSegment(*line_segment_config);
215  }
216 
217  ParameterLib::Parameter<double>* boundary_value_parameter = nullptr;
218  auto boundary_value_parameter_name =
220  config.getConfigParameterOptional<std::string>("boundary_parameter");
221  if (boundary_value_parameter_name)
222  {
223  DBUG("Using parameter {:s}", *boundary_value_parameter_name);
224  boundary_value_parameter = &ParameterLib::findParameter<double>(
225  *boundary_value_parameter_name, parameters, 1, &mesh);
226  }
227 
228  auto deactivated_subdomain_material_ids =
230  config.getConfigParameter("material_ids", std::vector<int>{});
231 
232  if (deactivated_subdomain_material_ids.empty())
233  {
234  OGS_FATAL(
235  "The material IDs of the deactivated subdomains are not given. The "
236  "program terminates now.");
237  }
238 
239  std::sort(deactivated_subdomain_material_ids.begin(),
240  deactivated_subdomain_material_ids.end());
241 
242  auto const* const material_ids = materialIDs(mesh);
243  if (material_ids == nullptr)
244  {
245  OGS_FATAL(
246  "The mesh doesn't contain materialIDs for subdomain deactivation. "
247  "The program terminates now.");
248  }
249 
250  std::vector<std::unique_ptr<DeactivatedSubdomainMesh>>
251  deactivated_subdomain_meshes;
252  deactivated_subdomain_meshes.reserve(
253  deactivated_subdomain_material_ids.size());
254 
255  std::transform(begin(deactivated_subdomain_material_ids),
256  end(deactivated_subdomain_material_ids),
257  back_inserter(deactivated_subdomain_meshes),
258  [&](std::size_t const id)
259  { return createDeactivatedSubdomainMesh(mesh, id); });
260 
261  return std::make_unique<DeactivatedSubdomain const>(
262  std::move(time_interval),
263  line_segment,
264  std::move(deactivated_subdomain_material_ids),
265  std::move(deactivated_subdomain_meshes),
266  boundary_value_parameter);
267 }
268 
269 std::vector<std::unique_ptr<DeactivatedSubdomain const>>
271  BaseLib::ConfigTree const& config,
272  MeshLib::Mesh const& mesh,
273  std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
274  std::map<std::string,
275  std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&
276  curves)
277 {
278  std::vector<std::unique_ptr<DeactivatedSubdomain const>>
279  deactivated_subdomains;
280  // Deactivated subdomains
281  if (auto subdomains_config =
283  config.getConfigSubtreeOptional("deactivated_subdomains"))
284  {
285  INFO("There are subdomains being deactivated.");
286 
287  auto const deactivated_subdomain_configs =
289  subdomains_config->getConfigSubtreeList("deactivated_subdomain");
290  std::transform(begin(deactivated_subdomain_configs),
291  end(deactivated_subdomain_configs),
292  back_inserter(deactivated_subdomains),
293  [&](auto const& config) {
295  config, mesh, parameters, curves);
296  });
297  }
298  return deactivated_subdomains;
299 }
300 
301 } // namespace ProcessLib
Definition of Duplicate functions.
Definition of the Element class.
#define OGS_FATAL(...)
Definition: Error.h:26
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void DBUG(char const *fmt, Args const &... args)
Definition: Logging.h:27
Definition of the Mesh class.
Definition of the Node class.
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
Definition: ConfigTree.cpp:155
std::optional< T > getConfigParameterOptional(std::string const &param) const
T getConfigParameter(std::string const &param) const
std::size_t getID() const
Definition: Point3dWithID.h:62
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition: Mesh.h:95
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition: Mesh.h:98
Properties & getProperties()
Definition: Mesh.h:123
std::size_t getNumberOfNodes() const
Get the number of nodes.
Definition: Mesh.h:89
std::vector< Element const * > const & getElementsConnectedToNode(std::size_t node_id) const
Definition: Mesh.cpp:232
const Node * getNode(std::size_t idx) const
Get the node with the given index.
Definition: Mesh.h:74
Map::mapped_type & getOrError(Map &map, Key const &key, std::string const &error_message)
Definition: Algorithm.h:147
PropertyVector< int > const * materialIDs(Mesh const &mesh)
Definition: Mesh.cpp:258
std::unique_ptr< MeshLib::Mesh > createMeshFromElementSelection(std::string mesh_name, std::vector< MeshLib::Element * > const &elements)
Definition: Mesh.cpp:268
std::vector< Element * > cloneElements(std::vector< Element * > const &elements)
Clones a vector of elements using the Element::clone() function.
std::vector< std::unique_ptr< DeactivatedSubdomain const > > createDeactivatedSubdomains(BaseLib::ConfigTree const &config, MeshLib::Mesh const &mesh, std::vector< std::unique_ptr< ParameterLib::ParameterBase >> const &parameters, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation >> const &curves)
static std::pair< Eigen::Vector3d, Eigen::Vector3d > parseLineSegment(BaseLib::ConfigTree const &config)
Returns a line segment represented by its begin and end points.
static MathLib::PiecewiseLinearInterpolation parseTimeIntervalOrCurve(std::optional< BaseLib::ConfigTree > const &time_interval_config, std::optional< std::string > const &curve_name, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation >> const &curves)
static std::pair< std::vector< MeshLib::Node * >, std::vector< MeshLib::Node * > > extractInnerAndOuterNodes(MeshLib::Mesh const &mesh, MeshLib::Mesh const &sub_mesh, IsActive is_active)
std::unique_ptr< DeactivatedSubdomain const > createDeactivatedSubdomain(BaseLib::ConfigTree const &config, MeshLib::Mesh const &mesh, std::vector< std::unique_ptr< ParameterLib::ParameterBase >> const &parameters, std::map< std::string, std::unique_ptr< MathLib::PiecewiseLinearInterpolation >> const &curves)
static std::unique_ptr< DeactivatedSubdomainMesh > createDeactivatedSubdomainMesh(MeshLib::Mesh const &mesh, int const material_id)