MortaringHelpers Namespace Reference

Classes

class  MergedSolidMesh
 
class  PointIntegralScheme
 
class  PointElementWithExternalElement
 

Enumerations

enum  Colour { WHITE , GREY , BLACK }
 

Functions

template<class NodeNodeConstraintClass , class NodeElementConstraintClass , class ELEMENTTYPE >
Vector< ConstraintElement * > setup_constraint_elements_at_nodes (Problem *problem_pt, Vector< Vector< Node * >> node_pt, Vector< SolidMesh * > mesh_pt, const bool &accept_failure=false)
 
template<class NodeNodeConstraintElementType >
void dfs (Node *node_pt, Node *parent_node_pt, std::map< Node *, Vector< std::pair< NodeNodeConstraintElementType *, Node * >>> &tree, std::map< Node *, Colour > &colours, Vector< NodeNodeConstraintElementType * > &pruned_branches)
 
template<class NodeNodeConstraintElementType >
Vector< NodeNodeConstraintElementType * > find_redundant_constraint_elements (Vector< NodeNodeConstraintElementType * > element_pt)
 

Variables

static double Mortaring_Constraints_Distance_Tolerance = 1e-10
 

Enumeration Type Documentation

◆ Colour

Enumerator
WHITE 
GREY 
BLACK 
316 { WHITE, GREY, BLACK };
@ WHITE
Definition: mortaring_helpers.h:316
@ BLACK
Definition: mortaring_helpers.h:316
@ GREY
Definition: mortaring_helpers.h:316

Function Documentation

◆ dfs()

template<class NodeNodeConstraintElementType >
void MortaringHelpers::dfs ( Node node_pt,
Node parent_node_pt,
std::map< Node *, Vector< std::pair< NodeNodeConstraintElementType *, Node * >>> &  tree,
std::map< Node *, Colour > &  colours,
Vector< NodeNodeConstraintElementType * > &  pruned_branches 
)
325 {
326  // Mark the current node as being visited (GREY)
327  colours[node_pt] = GREY;
328 
329  // Get all branches (edges) from the current node
331  for (auto& branch : branches)
332  {
333  Node* next_node = branch.second;
334  NodeNodeConstraintElementType* element = branch.first;
335 
336  // If the branch has already been pruned, skip it
337  if (std::find(pruned_branches.begin(), pruned_branches.end(), element) != pruned_branches.end())
338  {
339  continue;
340  }
341 
342  // If we encounter a GREY node that is not the parent, a cycle is detected
343  if (colours[next_node] == GREY && next_node != parent_node_pt)
344  {
345  pruned_branches.push_back(element);
346  }
347  // If the next node is unvisited (WHITE), continue DFS
348  else if (colours[next_node] == WHITE)
349  {
350  dfs(next_node, node_pt, tree, colours, pruned_branches);
351  }
352  }
353 
354  // Mark the current node as fully processed (BLACK)
355  colours[node_pt] = BLACK;
356 }
Definition: nodes.h:906
Definition: oomph-lib/src/generic/Vector.h:58
void dfs(Node *node_pt, Node *parent_node_pt, std::map< Node *, Vector< std::pair< NodeNodeConstraintElementType *, Node * >>> &tree, std::map< Node *, Colour > &colours, Vector< NodeNodeConstraintElementType * > &pruned_branches)
Definition: mortaring_helpers.h:320

References BLACK, GREY, and WHITE.

Referenced by Eigen::internal::simpl_chol_helper< Scalar, StorageIndex >::calc_post(), and find_redundant_constraint_elements().

◆ find_redundant_constraint_elements()

template<class NodeNodeConstraintElementType >
Vector<NodeNodeConstraintElementType*> MortaringHelpers::find_redundant_constraint_elements ( Vector< NodeNodeConstraintElementType * >  element_pt)
361 {
362  // Create a tree representation from the constraint elements
363  std::map<Node*, Vector<std::pair<NodeNodeConstraintElementType*, Node*>>> tree;
364  for (auto& element : element_pt)
365  {
366  Node* node1 = element->solid_node_pt(0);
367  Node* node2 = element->solid_node_pt(1);
368  tree[node1].push_back(std::make_pair(element, node2));
369  tree[node2].push_back(std::make_pair(element, node1));
370  }
371 
372  // Vector to store the pruned branches
374  // Map to store the colours of the nodes
375  std::map<Node*, Colour> colours;
376 
377  // Initialize all nodes as unvisited (WHITE)
378  for (auto& node_branches : tree)
379  {
380  Node* root_node = node_branches.first;
381  if (colours[root_node] == WHITE)
382  {
383  // // Perform DFS to detect cycles starting from the root node
384  dfs(root_node, nullptr, tree, colours, pruned_branches);
385  }
386  }
387 
388  return pruned_branches;
389 }

References dfs(), and WHITE.

◆ setup_constraint_elements_at_nodes()

template<class NodeNodeConstraintClass , class NodeElementConstraintClass , class ELEMENTTYPE >
Vector<ConstraintElement*> MortaringHelpers::setup_constraint_elements_at_nodes ( Problem problem_pt,
Vector< Vector< Node * >>  node_pt,
Vector< SolidMesh * >  mesh_pt,
const bool accept_failure = false 
)
173 {
174  // Vector of constraint elements built
175  Vector<ConstraintElement*> constraint_element_pt;
176 
177  // Assume all the nodes/elements are the same dimension
178  const unsigned dim = node_pt[0][0]->ndim();
179 
180  // The number of nodes from each mesh
181  const Vector<long unsigned> n_node = {node_pt[0].size(), node_pt[1].size()};
182 
183  // Allocate for nodes which were not matched to other nodes
184  Vector<Vector<unsigned>> node_was_matched(2);
185  node_was_matched[0].resize(n_node[0], 0);
186  node_was_matched[1].resize(n_node[1], 0);
187 
188  // First attempt to match each node to another in the other mesh
189  unsigned n_matched_nodes = 0;
190  for(unsigned i=0; i<n_node[0]; i++)
191  {
192  SolidNode* node_0_pt = dynamic_cast<SolidNode*>(node_pt[0][i]);
193  for(unsigned j=0; j<n_node[1]; j++)
194  {
195  // If the node has already been matched to another node
196  if(node_was_matched[1][j]) continue;
197 
198  SolidNode* node_1_pt = dynamic_cast<SolidNode*>(node_pt[1][j]);
199 
200  // get the distance between the nodes TODO is it faster to just check absolute distance in each spatial direction?
201  double distance = 0.0;
202  for(unsigned d=0; d<dim; d++)
203  {
204  distance += (node_0_pt->xi(d) - node_1_pt->xi(d))*
205  (node_0_pt->xi(d) - node_1_pt->xi(d));
206  }
207  // if co-located build constraint element
209  {
210  // If the nodes are the same then skip this, we can't mortar a node to itself
211  // This check is useful because it will allow a mesh to be mortared to itself
212  if(node_0_pt == node_1_pt) continue;
213  // Record that these nodes were matched
214  node_was_matched[0][i] = 1;
215  node_was_matched[1][j] = 1;
216  n_matched_nodes++;
217  // Build the node-node constraint element
218  constraint_element_pt.push_back(new NodeNodeConstraintClass(node_0_pt, node_1_pt));
219 
220  // stop checking for this node in the first mesh
221  break;
222  }
223  }
224  }
225 
226  // If we have matched all nodes then return
227  if((n_node[0] - n_matched_nodes) == 0 && (n_node[1] - n_matched_nodes) == 0 ) return constraint_element_pt;
228 
229  // If we get to here then we know that some nodes have not been mortared.
230  // If the mesh pointers are the same then we know we have failed. We can't perform the following procedure
231  // if the meshes are the same.
232  if(mesh_pt[0] == mesh_pt[1])
233  {
234  throw OomphLibError("Mortaring failed - meshes are the same and node-node mortaring has not captured all nodes",
237  }
238 
239  const bool Previous_Accept_failed_locate_zeta_in_setup_multi_domain_interaction
242 
243 
244  // Figure out how many nodes are left to be matched from each mesh
245  Vector<long unsigned> n_unmatched_nodes{n_node[0] - n_matched_nodes,
246  n_node[1] - n_matched_nodes};
247 
248  for(unsigned m : {0,1})
249  {
250  if(n_unmatched_nodes[m] == 0) continue;
251 
252  // Get the nodes which were not matched
253  Vector<Node*> unmatched_node_pt(n_unmatched_nodes[m]);
254  unsigned count = 0;
255  for(unsigned i=0; i<n_node[m]; i++)
256  {
257  if(!node_was_matched[m][i])
258  {
259  unmatched_node_pt[count++] = node_pt[m][i];
260  }
261  }
262 
263  // Create a mesh for locating the zetas in the other mesh
264  Mesh* Locating_mesh_pt = new Mesh;
265 
266  Vector<PointElementWithExternalElement*> locating_elements_pt(n_unmatched_nodes[m]);
267  for(unsigned i=0; i<n_unmatched_nodes[m]; i++)
268  {
269  Vector<double> x(dim);
270  for(unsigned d=0; d<dim; d++)
271  {
272  x[d] = dynamic_cast<SolidNode*>(unmatched_node_pt[i])->xi(d);
273  }
274 
275  locating_elements_pt[i] = new PointElementWithExternalElement(x);
276  Locating_mesh_pt->add_element_pt(locating_elements_pt[i]);
277  }
278 
279  // Setup multi domain interactions with the second mesh
280  Multi_domain_functions::setup_multi_domain_interaction<ELEMENTTYPE>(problem_pt,
281  Locating_mesh_pt,
282  mesh_pt[unsigned(1-m)],
283  0);
284 
285  // Loop over the locating elements
286  for(unsigned i=0; i<n_unmatched_nodes[m]; i++)
287  {
288  // If the external element was not found skip this element - no need to crash out, that would have happened
289  // earlier if this was an issue (if accept_failure == false)
290  if(locating_elements_pt[i]->external_element_pt(0,0) == nullptr) continue;
291  constraint_element_pt.push_back(new NodeElementConstraintClass(dynamic_cast<SolidNode*>(unmatched_node_pt[i]),
292  locating_elements_pt[i]->external_element_pt(0,0),
293  locating_elements_pt[i]->external_element_local_coord(0,0)));
294  }
295  }
296  Multi_domain_functions::Accept_failed_locate_zeta_in_setup_multi_domain_interaction = Previous_Accept_failed_locate_zeta_in_setup_multi_domain_interaction;
297 
298  return constraint_element_pt;
299 }
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Definition: mesh.h:67
void add_element_pt(GeneralisedElement *const &element_pt)
Add a (pointer to) an element to the mesh.
Definition: mesh.h:617
Definition: oomph_definitions.h:222
Definition: nodes.h:1686
double & xi(const unsigned &i)
Reference to i-th Lagrangian position.
Definition: nodes.h:1883
int * m
Definition: level2_cplx_impl.h:294
static double Mortaring_Constraints_Distance_Tolerance
Definition: mortaring_helpers.h:162
bool Accept_failed_locate_zeta_in_setup_multi_domain_interaction
Definition: multi_domain.cc:56
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References oomph::Multi_domain_functions::Accept_failed_locate_zeta_in_setup_multi_domain_interaction, oomph::Mesh::add_element_pt(), i, j, m, Mortaring_Constraints_Distance_Tolerance, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, sqrt(), plotDoE::x, and oomph::SolidNode::xi().

Referenced by MortaringValidationProblem< ELEMENT, NON_MORTAR_ELEMENT >::build_constraint_elements(), and MortaringValidationProblem< ELEMENT, NON_MORTAR_ELEMENT >::build_mortaring_elements().

Variable Documentation

◆ Mortaring_Constraints_Distance_Tolerance

double MortaringHelpers::Mortaring_Constraints_Distance_Tolerance = 1e-10
static