missing_masters.template.cc
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 // Templated missing masters functions
27 
28 // Include guards to prevent multiple inclusion of the header
29 #ifndef OOMPH_MISSING_MASTERS_CC
30 #define OOMPH_MISSING_MASTERS_CC
31 
32 // Config header generated by autoconfig
33 #ifdef HAVE_CONFIG_H
34 #include <oomph-lib-config.h>
35 #endif
36 
37 // Oomph-lib headers
38 #include "geom_objects.h"
39 #include "problem.h"
40 #include "shape.h"
41 
42 #include "mesh.h"
44 #include "algebraic_elements.h"
46 #include "Qelements.h"
48 #include "missing_masters.h"
49 
50 namespace oomph
51 {
52  /// / Templated helper functions for missing master methods,
53 
54 #ifdef OOMPH_HAS_MPI
55 
56 
57  //============start of add_external_halo_node_to_storage===============
58  /// Helper function to add external halo nodes, including any masters,
59  /// based on information received from the haloed process
60  //=========================================================================
61  template<class EXT_ELEMENT>
63  Node*& new_nod_pt,
64  Mesh* const& mesh_pt,
65  unsigned& loc_p,
66  unsigned& node_index,
67  FiniteElement* const& new_el_pt,
68  int& n_cont_inter_values,
69  unsigned& counter_for_recv_unsigneds,
70  Vector<unsigned>& recv_unsigneds,
71  unsigned& counter_for_recv_doubles,
72  Vector<double>& recv_doubles)
73  {
74  // Add the external halo node if required
76  mesh_pt,
77  loc_p,
78  node_index,
79  new_el_pt,
80  n_cont_inter_values,
81  counter_for_recv_unsigneds,
82  recv_unsigneds,
83  counter_for_recv_doubles,
84  recv_doubles);
85 
86  // Recursively add masters
87  recursively_add_masters_of_external_halo_node_to_storage<EXT_ELEMENT>(
88  new_nod_pt,
89  mesh_pt,
90  loc_p,
91  node_index,
92  n_cont_inter_values,
93  counter_for_recv_unsigneds,
94  recv_unsigneds,
95  counter_for_recv_doubles,
96  recv_doubles);
97  }
98 
99 
100  //========================================================================
101  /// Recursively add masters of external halo nodes (and their masters, etc)
102  /// based on information received from the haloed process
103  //=========================================================================
104  template<class EXT_ELEMENT>
107  Node*& new_nod_pt,
108  Mesh* const& mesh_pt,
109  unsigned& loc_p,
110  unsigned& node_index,
111  int& n_cont_inter_values,
112  unsigned& counter_for_recv_unsigneds,
113  Vector<unsigned>& recv_unsigneds,
114  unsigned& counter_for_recv_doubles,
115  Vector<double>& recv_doubles)
116  {
117  for (int i_cont = -1; i_cont < n_cont_inter_values; i_cont++)
118  {
119 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
120  oomph_info << "Rec:" << counter_for_recv_unsigneds
121  << " Boolean to indicate that continuously interpolated "
122  "variable i_cont "
123  << i_cont << " is hanging "
124  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
125 #endif
126  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
127  {
128 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
129  oomph_info << "Rec:" << counter_for_recv_unsigneds
130  << " Number of master nodes "
131  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
132 #endif
133  unsigned n_master = recv_unsigneds[counter_for_recv_unsigneds++];
134 
135  // Setup new HangInfo
136  HangInfo* hang_pt = new HangInfo(n_master);
137  for (unsigned m = 0; m < n_master; m++)
138  {
139  Node* master_nod_pt = 0;
140  // Get the master node (creating and adding it if required)
141  add_external_halo_master_node_helper<EXT_ELEMENT>(
142  master_nod_pt,
143  new_nod_pt,
144  mesh_pt,
145  loc_p,
146  n_cont_inter_values,
147  counter_for_recv_unsigneds,
148  recv_unsigneds,
149  counter_for_recv_doubles,
150  recv_doubles);
151 
152  // Get the weight and set the HangInfo
153  double master_weight = recv_doubles[counter_for_recv_doubles++];
154  hang_pt->set_master_node_pt(m, master_nod_pt, master_weight);
155 
156  // Recursively add masters of master
157  recursively_add_masters_of_external_halo_node_to_storage<EXT_ELEMENT>(
158  master_nod_pt,
159  mesh_pt,
160  loc_p,
161  node_index,
162  n_cont_inter_values,
163  counter_for_recv_unsigneds,
164  recv_unsigneds,
165  counter_for_recv_doubles,
166  recv_doubles);
167  }
168  new_nod_pt->set_hanging_pt(hang_pt, i_cont);
169  }
170  } // end loop over continous interpolated values
171  }
172 
173  //========================================================================
174  /// Helper function to add external halo node that is a master
175  //========================================================================
176  template<class EXT_ELEMENT>
178  Node*& new_master_nod_pt,
179  Node*& new_nod_pt,
180  Mesh* const& mesh_pt,
181  unsigned& loc_p,
182  int& ncont_inter_values,
183  unsigned& counter_for_recv_unsigneds,
184  Vector<unsigned>& recv_unsigneds,
185  unsigned& counter_for_recv_doubles,
186  Vector<double>& recv_doubles)
187  {
188  // Given the node and the external mesh, and received information
189  // about them from process loc_p, construct them on the current process
190 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
191  oomph_info
192  << "Rec:" << counter_for_recv_unsigneds
193  << " Boolean to trigger construction of new external halo master node "
194  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
195 #endif
196  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
197  {
198  // Construct a new node based upon sent information
199  construct_new_external_halo_master_node_helper<EXT_ELEMENT>(
200  new_master_nod_pt,
201  new_nod_pt,
202  loc_p,
203  mesh_pt,
204  counter_for_recv_unsigneds,
205  recv_unsigneds,
206  counter_for_recv_doubles,
207  recv_doubles);
208  }
209  else
210  {
211  // Need to check which storage we should copy this halo node from
212 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
213  oomph_info << "Rec:" << counter_for_recv_unsigneds
214  << " Existing external halo node was found externally (0) or "
215  "internally (1): "
216  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
217 #endif
218  unsigned node_found_internally =
219  recv_unsigneds[counter_for_recv_unsigneds++];
220  if (node_found_internally)
221  {
222 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
223  oomph_info << "Rec:" << counter_for_recv_unsigneds
224  << " index of existing (internal) halo master node "
225  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
226 #endif
227  // Copy node from received location
228  new_master_nod_pt = mesh_pt->shared_node_pt(
229  loc_p, recv_unsigneds[counter_for_recv_unsigneds++]);
230  }
231  else
232  {
233 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
234  oomph_info << "Rec:" << counter_for_recv_unsigneds
235  << " index of existing external halo master node "
236  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
237 #endif
238  // Copy node from received location
239  new_master_nod_pt = mesh_pt->external_halo_node_pt(
240  loc_p, recv_unsigneds[counter_for_recv_unsigneds++]);
241  }
242  }
243  }
244 
245  //======start of construct_new_external_halo_master_node_helper===========
246  /// Helper function which constructs a new external halo master node
247  /// with the required information sent from the haloed process
248  //========================================================================
249  template<class EXT_ELEMENT>
252  Node*& new_master_nod_pt,
253  Node*& nod_pt,
254  unsigned& loc_p,
255  Mesh* const& mesh_pt,
256  unsigned& counter_for_recv_unsigneds,
257  Vector<unsigned>& recv_unsigneds,
258  unsigned& counter_for_recv_doubles,
259  Vector<double>& recv_doubles)
260  {
261  // First three sent numbers are dimension, position type and nvalue
262  // (to be used in Node constructors)
263 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
264  oomph_info << "Rec:" << counter_for_recv_unsigneds
265  << " ndim for external halo master node "
266  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
267 #endif
268  unsigned n_dim = recv_unsigneds[counter_for_recv_unsigneds++];
269 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
270  oomph_info << "Rec:" << counter_for_recv_unsigneds
271  << " nposition type for external halo master node "
272  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
273 #endif
274  unsigned n_position_type = recv_unsigneds[counter_for_recv_unsigneds++];
275 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
276  oomph_info << "Rec:" << counter_for_recv_unsigneds
277  << " nvalue for external halo master node "
278  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
279 #endif
280  unsigned n_value = recv_unsigneds[counter_for_recv_unsigneds++];
281 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
282  oomph_info << "Rec:" << counter_for_recv_unsigneds
283  << " non-halo processor ID for external halo master node "
284  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
285 #endif
286  unsigned non_halo_proc_ID = recv_unsigneds[counter_for_recv_unsigneds++];
287 
288  // If it's a solid node also receive the lagrangian dimension and pos type
289  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
290  unsigned n_lag_dim;
291  unsigned n_lag_type;
292  if (solid_nod_pt != 0)
293  {
294 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
295  oomph_info << "Rec:" << counter_for_recv_unsigneds
296  << " nlagrdim for external halo master solid node "
297  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
298 #endif
299  n_lag_dim = recv_unsigneds[counter_for_recv_unsigneds++];
300 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
301  oomph_info << "Rec:" << counter_for_recv_unsigneds
302  << " nlagrtype for external halo master solid node "
303  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
304 #endif
305  n_lag_type = recv_unsigneds[counter_for_recv_unsigneds++];
306  }
307 
308  // Null TimeStepper for now
309  TimeStepper* time_stepper_pt = 0;
310  // Default number of previous values to 1
311  unsigned n_prev = 1;
312 
313  // Just take timestepper from a node
314  // Let's use first node of first element since this must exist
315  time_stepper_pt =
316  mesh_pt->finite_element_pt(0)->node_pt(0)->time_stepper_pt();
317 
318  // Is the node for which the master is required Algebraic, Macro or Solid?
319  AlgebraicNode* alg_nod_pt = dynamic_cast<AlgebraicNode*>(nod_pt);
320  MacroElementNodeUpdateNode* macro_nod_pt =
321  dynamic_cast<MacroElementNodeUpdateNode*>(nod_pt);
322 
323  // What type of node was the node for which we are constructing a master?
324  if (alg_nod_pt != 0)
325  {
326  // The master node should also be algebraic
327 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
328  oomph_info << "Rec:" << counter_for_recv_unsigneds
329  << " Boolean for algebraic boundary node "
330  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
331 #endif
332  // If this master node's haloed copy is on a boundary then
333  // it needs to be on the same boundary here
334  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
335  {
336  // Create a new BoundaryNode (not attached to an element)
337  if (time_stepper_pt != 0)
338  {
339  new_master_nod_pt = new BoundaryNode<AlgebraicNode>(
340  time_stepper_pt, n_dim, n_position_type, n_value);
341  }
342  else
343  {
344  new_master_nod_pt =
345  new BoundaryNode<AlgebraicNode>(n_dim, n_position_type, n_value);
346  }
347 
348  // How many boundaries does the algebraic master node live on?
349 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
350  oomph_info << "Rec:" << counter_for_recv_unsigneds
351  << " Number of boundaries the algebraic master node is on: "
352  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
353 #endif
354  unsigned nb = recv_unsigneds[counter_for_recv_unsigneds++];
355  for (unsigned i = 0; i < nb; i++)
356  {
357  // Boundary number
358 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
359  oomph_info << "Rec:" << counter_for_recv_unsigneds
360  << " Algebraic master node is on boundary "
361  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
362 #endif
363  unsigned i_bnd = recv_unsigneds[counter_for_recv_unsigneds++];
364  mesh_pt->add_boundary_node(i_bnd, new_master_nod_pt);
365  }
366 
367 
368  // Do we have additional values created by face elements?
369 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
370  oomph_info << "Rec:" << counter_for_recv_unsigneds << " "
371  << "Number of additional values created by face element "
372  << "for master node "
373  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
374 #endif
375  unsigned n_entry = recv_unsigneds[counter_for_recv_unsigneds++];
376  if (n_entry > 0)
377  {
378  // Create storage, if it doesn't already exist, for the map
379  // that will contain the position of the first entry of
380  // this face element's additional values,
381  BoundaryNodeBase* bnew_master_nod_pt =
382  dynamic_cast<BoundaryNodeBase*>(new_master_nod_pt);
383 #ifdef PARANOID
384  if (bnew_master_nod_pt == 0)
385  {
386  throw OomphLibError("Failed to cast new node to boundary node\n",
387  OOMPH_CURRENT_FUNCTION,
388  OOMPH_EXCEPTION_LOCATION);
389  }
390 #endif
391  if (bnew_master_nod_pt
392  ->index_of_first_value_assigned_by_face_element_pt() == 0)
393  {
394  bnew_master_nod_pt
396  new std::map<unsigned, unsigned>;
397  }
398 
399  // Get pointer to the map of indices associated with
400  // additional values created by face elements
401  std::map<unsigned, unsigned>* map_pt =
402  bnew_master_nod_pt
404 
405  // Loop over number of entries in map
406  for (unsigned i = 0; i < n_entry; i++)
407  {
408  // Read out pairs...
409 
410 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
411  oomph_info << "Rec:" << counter_for_recv_unsigneds
412  << " Key of map entry for master node"
413  << recv_unsigneds[counter_for_recv_unsigneds]
414  << std::endl;
415 #endif
416  unsigned first = recv_unsigneds[counter_for_recv_unsigneds++];
417 
418 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
419  oomph_info << "Rec:" << counter_for_recv_unsigneds
420  << " Value of map entry for master node"
421  << recv_unsigneds[counter_for_recv_unsigneds]
422  << std::endl;
423 #endif
424  unsigned second = recv_unsigneds[counter_for_recv_unsigneds++];
425 
426  // ...and assign
427  (*map_pt)[first] = second;
428  }
429  }
430  }
431  else
432  {
433  // Create node (not attached to any element)
434  if (time_stepper_pt != 0)
435  {
436  new_master_nod_pt =
437  new AlgebraicNode(time_stepper_pt, n_dim, n_position_type, n_value);
438  }
439  else
440  {
441  new_master_nod_pt =
442  new AlgebraicNode(n_dim, n_position_type, n_value);
443  }
444  }
445 
446  // Add this as an external halo node BEFORE considering node update!
447  mesh_pt->add_external_halo_node_pt(loc_p, new_master_nod_pt);
448 
449  // The external mesh is itself Algebraic...
450  AlgebraicMesh* alg_mesh_pt = dynamic_cast<AlgebraicMesh*>(mesh_pt);
451 
452 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
453  oomph_info << "Rec:" << counter_for_recv_unsigneds
454  << " algebraic node update id for master node "
455  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
456 #endif
457  /// The first entry of All_unsigned_values is the default node update id
458  unsigned update_id = recv_unsigneds[counter_for_recv_unsigneds++];
459 
460  // Setup algebraic node update info for this new node
461  Vector<double> ref_value;
462 
463 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
464  oomph_info << "Rec:" << counter_for_recv_unsigneds
465  << " algebraic node number of ref values for master node "
466  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
467 #endif
468  // The size of this vector is in the next entry
469  unsigned n_ref_val = recv_unsigneds[counter_for_recv_unsigneds++];
470 
471  // The reference values are in the subsequent entries of All_double_values
472  ref_value.resize(n_ref_val);
473  for (unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
474  {
475  ref_value[i_ref] = recv_doubles[counter_for_recv_doubles++];
476  }
477 
478  // Also require a Vector of geometric objects
479  Vector<GeomObject*> geom_object_pt;
480 
481 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
482  oomph_info << "Rec:" << counter_for_recv_unsigneds
483  << " algebraic node number of geom objects for master node "
484  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
485 #endif
486 
487  // The size of this vector is in the next entry of All_unsigned_values
488  unsigned n_geom_obj = recv_unsigneds[counter_for_recv_unsigneds++];
489 
490  // The remaining indices are in the rest of
491  // All_alg_nodal_info
492  geom_object_pt.resize(n_geom_obj);
493  for (unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
494  {
495 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
496  oomph_info << "Rec:" << counter_for_recv_unsigneds
497  << " algebraic node: " << i_geom << "-th out of "
498  << n_geom_obj << "-th geom index "
499  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
500 #endif
501  unsigned geom_index = recv_unsigneds[counter_for_recv_unsigneds++];
502 
503  // This index indicates which (if any) of the AlgebraicMesh's
504  // stored geometric objects should be used
505  geom_object_pt[i_geom] = alg_mesh_pt->geom_object_list_pt(geom_index);
506  }
507 
508  AlgebraicNode* alg_master_nod_pt =
509  dynamic_cast<AlgebraicNode*>(new_master_nod_pt);
510 
511  /// ... so for the specified update_id, call
512  /// add_node_update_info
513  alg_master_nod_pt->add_node_update_info(
514  update_id, alg_mesh_pt, geom_object_pt, ref_value);
515 
516  /// Now call update_node_update
517  alg_mesh_pt->update_node_update(alg_master_nod_pt);
518  }
519  else if (macro_nod_pt != 0)
520  {
521  // The master node should also be a macro node
522  // If this master node's haloed copy is on a boundary then
523  // it needs to be on the same boundary here
524 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
525  oomph_info << "Rec:" << counter_for_recv_unsigneds
526  << " Boolean for master algebraic node is boundary node "
527  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
528 #endif
529  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
530  {
531  // Create a new BoundaryNode (not attached to an element)
532  if (time_stepper_pt != 0)
533  {
534  new_master_nod_pt = new BoundaryNode<MacroElementNodeUpdateNode>(
535  time_stepper_pt, n_dim, n_position_type, n_value);
536  }
537  else
538  {
539  new_master_nod_pt = new BoundaryNode<MacroElementNodeUpdateNode>(
540  n_dim, n_position_type, n_value);
541  }
542 
543 
544  // How many boundaries does the macro element master node live on?
545 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
546  oomph_info
547  << "Rec:" << counter_for_recv_unsigneds
548  << " Number of boundaries the macro element master node is on: "
549  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
550 #endif
551  unsigned nb = recv_unsigneds[counter_for_recv_unsigneds++];
552  for (unsigned i = 0; i < nb; i++)
553  {
554  // Boundary number
555 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
556  oomph_info << "Rec:" << counter_for_recv_unsigneds
557  << " Macro element master node is on boundary "
558  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
559 #endif
560  unsigned i_bnd = recv_unsigneds[counter_for_recv_unsigneds++];
561  mesh_pt->add_boundary_node(i_bnd, new_master_nod_pt);
562  }
563 
564  // Do we have additional values created by face elements?
565 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
566  oomph_info << "Rec:" << counter_for_recv_unsigneds
567  << " Number of additional values created by face element "
568  << "for macro element master node "
569  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
570 #endif
571  unsigned n_entry = recv_unsigneds[counter_for_recv_unsigneds++];
572  if (n_entry > 0)
573  {
574  // Create storage, if it doesn't already exist, for the map
575  // that will contain the position of the first entry of
576  // this face element's additional values,
577  BoundaryNodeBase* bnew_master_nod_pt =
578  dynamic_cast<BoundaryNodeBase*>(new_master_nod_pt);
579 #ifdef PARANOID
580  if (bnew_master_nod_pt == 0)
581  {
582  throw OomphLibError("Failed to cast new node to boundary node\n",
583  OOMPH_CURRENT_FUNCTION,
584  OOMPH_EXCEPTION_LOCATION);
585  }
586 #endif
587  if (bnew_master_nod_pt
588  ->index_of_first_value_assigned_by_face_element_pt() == 0)
589  {
590  bnew_master_nod_pt
592  new std::map<unsigned, unsigned>;
593  }
594 
595  // Get pointer to the map of indices associated with
596  // additional values created by face elements
597  std::map<unsigned, unsigned>* map_pt =
598  bnew_master_nod_pt
600 
601  // Loop over number of entries in map
602  for (unsigned i = 0; i < n_entry; i++)
603  {
604  // Read out pairs...
605 
606 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
607  oomph_info << "Rec:" << counter_for_recv_unsigneds
608  << " Key of map entry for macro element master node"
609  << recv_unsigneds[counter_for_recv_unsigneds]
610  << std::endl;
611 #endif
612  unsigned first = recv_unsigneds[counter_for_recv_unsigneds++];
613 
614 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
615  oomph_info << "Rec:" << counter_for_recv_unsigneds
616  << " Value of map entry for macro element master node"
617  << recv_unsigneds[counter_for_recv_unsigneds]
618  << std::endl;
619 #endif
620  unsigned second = recv_unsigneds[counter_for_recv_unsigneds++];
621 
622  // ...and assign
623  (*map_pt)[first] = second;
624  }
625  }
626  }
627  else
628  {
629  // Create node (not attached to any element)
630  if (time_stepper_pt != 0)
631  {
632  new_master_nod_pt = new MacroElementNodeUpdateNode(
633  time_stepper_pt, n_dim, n_position_type, n_value);
634  }
635  else
636  {
637  new_master_nod_pt =
638  new MacroElementNodeUpdateNode(n_dim, n_position_type, n_value);
639  }
640  }
641 
642  // Add this as an external halo node
643  mesh_pt->add_external_halo_node_pt(loc_p, new_master_nod_pt);
644  oomph_info << "Added external halo master node:" << new_master_nod_pt
645  << " at [ " << new_master_nod_pt->x(0) << ", "
646  << new_master_nod_pt->x(1) << " ]" << std::endl;
647 
648  // Create a new node update element for this master node if required
649  FiniteElement* new_node_update_f_el_pt = 0;
650 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
651  oomph_info << "Rec:" << counter_for_recv_unsigneds
652  << " Bool: need new external halo element "
653  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
654 #endif
655  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
656  {
657  // Issue warning about adding a macro element to the external storage
658  std::ostringstream warn_stream;
659  warn_stream
660  << "You are adding a MacroElementNodeUpdate element to the\n"
661  << "external storage. This functionality is still being\n"
662  << "developed and may cause problems later on, say during\n"
663  << "Problem::remove_duplicate_data().";
664  OomphLibWarning(warn_stream.str(),
665  "Missing_masters_functions::construct_new_external_"
666  "halo_master_node_helper()",
667  OOMPH_EXCEPTION_LOCATION);
668 
669  GeneralisedElement* new_node_update_el_pt = new EXT_ELEMENT;
670 
671  // Add external halo element to this mesh
672  mesh_pt->add_external_halo_element_pt(loc_p, new_node_update_el_pt);
673 
674  // Cast to finite element
675  new_node_update_f_el_pt =
676  dynamic_cast<FiniteElement*>(new_node_update_el_pt);
677 
678  // Need number of interpolated values if Refineable
679  int n_cont_inter_values;
680  if (dynamic_cast<RefineableElement*>(new_node_update_f_el_pt) != 0)
681  {
682  n_cont_inter_values =
683  dynamic_cast<RefineableElement*>(new_node_update_f_el_pt)
684  ->ncont_interpolated_values();
685  }
686  else
687  {
688  n_cont_inter_values = -1;
689  }
690 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
691  oomph_info << "Rec:" << counter_for_recv_unsigneds
692  << " Bool: we have a macro element mesh "
693  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
694 #endif
695  // If we're using macro elements to update,
696  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
697  {
698  // Set the macro element
699  MacroElementNodeUpdateMesh* macro_mesh_pt =
700  dynamic_cast<MacroElementNodeUpdateMesh*>(mesh_pt);
701 
702 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
703  oomph_info << "Rec:" << counter_for_recv_unsigneds
704  << " Number of macro element "
705  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
706 #endif
707  unsigned macro_el_num = recv_unsigneds[counter_for_recv_unsigneds++];
708  new_node_update_f_el_pt->set_macro_elem_pt(
709  macro_mesh_pt->macro_domain_pt()->macro_element_pt(macro_el_num));
710 
711  // we need to receive
712  // the lower left and upper right coordinates of the macro
713  QElementBase* q_el_pt =
714  dynamic_cast<QElementBase*>(new_node_update_f_el_pt);
715  if (q_el_pt != 0)
716  {
717  unsigned el_dim = q_el_pt->dim();
718  for (unsigned i_dim = 0; i_dim < el_dim; i_dim++)
719  {
720  q_el_pt->s_macro_ll(i_dim) =
721  recv_doubles[counter_for_recv_doubles++];
722  q_el_pt->s_macro_ur(i_dim) =
723  recv_doubles[counter_for_recv_doubles++];
724  }
725  }
726  else // Throw an error
727  {
728  std::ostringstream error_stream;
729  error_stream << "You are using a MacroElement node update\n"
730  << "in a case with non-QElements. This has not\n"
731  << "yet been implemented.\n";
732  throw OomphLibError(error_stream.str(),
733  OOMPH_CURRENT_FUNCTION,
734  OOMPH_EXCEPTION_LOCATION);
735  }
736  }
737 
738  // Check if haloed version was p-refineable
739 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
740  oomph_info << "Rec:" << counter_for_recv_unsigneds
741  << " Element was p-refineable "
742  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
743 #endif
744  unsigned el_was_p_refineable =
745  recv_unsigneds[counter_for_recv_unsigneds++];
746  if (el_was_p_refineable)
747  {
748  // Check created element is p-refineable
749  PRefineableElement* p_refineable_el_pt =
750  dynamic_cast<PRefineableElement*>(new_node_update_f_el_pt);
751  if (p_refineable_el_pt != 0)
752  {
753  // Recieve p-order
754 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
755  oomph_info << "Rec:" << counter_for_recv_unsigneds << " p-order: "
756  << recv_unsigneds[counter_for_recv_unsigneds]
757  << std::endl;
758 #endif
759  unsigned p_order = recv_unsigneds[counter_for_recv_unsigneds++];
760 
761  // Do initial setup with original element as the clone's adopted
762  // father
763  p_refineable_el_pt->initial_setup(0, p_order);
764  // BENFLAG:
765  oomph_info << "New node update element: " << new_node_update_el_pt
766  << " (p-order = " << p_order << ")" << std::endl;
767  }
768  else
769  {
770  std::ostringstream error_stream;
771  error_stream << "Created MacroElement node update element is not "
772  "p-refineable\n"
773  << "but the haloed version is.\n";
774  throw OomphLibError(error_stream.str(),
775  "Missing_masters_functions::construct_new_"
776  "external_halo_master_...()",
777  OOMPH_EXCEPTION_LOCATION);
778  }
779  }
780 
781  unsigned n_node = new_node_update_f_el_pt->nnode();
782  for (unsigned j = 0; j < n_node; j++)
783  {
784  Node* new_nod_pt = 0;
785  add_external_halo_node_to_storage<EXT_ELEMENT>(
786  new_nod_pt,
787  mesh_pt,
788  loc_p,
789  j,
790  new_node_update_f_el_pt,
791  n_cont_inter_values,
792  counter_for_recv_unsigneds,
793  recv_unsigneds,
794  counter_for_recv_doubles,
795  recv_doubles);
796  // BENFLAG:
797  oomph_info << "Added node " << new_nod_pt << " at [ "
798  << new_nod_pt->x(0) << ", " << new_nod_pt->x(1) << " ]"
799  << std::endl;
800  }
801 
802  // BENFLAG:
803  oomph_info << "New node update element: " << new_node_update_f_el_pt
804  << " (nnode_1d = " << new_node_update_f_el_pt->nnode_1d()
805  << ")" << std::endl;
806  }
807  else // The node update element exists already
808  {
809 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
810  oomph_info << "Rec:" << counter_for_recv_unsigneds
811  << " Found internally? "
812  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
813 #endif
814  unsigned found_internally =
815  recv_unsigneds[counter_for_recv_unsigneds++];
816 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
817  oomph_info << "Rec:" << counter_for_recv_unsigneds
818  << " Number of already existing external halo element "
819  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
820 #endif
821  unsigned halo_element_index =
822  recv_unsigneds[counter_for_recv_unsigneds++];
823  if (found_internally != 0)
824  {
825  new_node_update_f_el_pt = dynamic_cast<FiniteElement*>(
826  (mesh_pt->halo_element_pt(loc_p))[halo_element_index]);
827  // BENFLAG:
828  oomph_info << "Existing node update element: "
829  << new_node_update_f_el_pt
830  << " (nnode_1d = " << new_node_update_f_el_pt->nnode_1d()
831  << ")" << std::endl;
832  oomph_info << "on proc " << loc_p << " at (internal) index "
833  << halo_element_index << std::endl;
834 
835  // //BENFLAG: Also add halo element to external storage
836  // oomph_info << "Adding to external halo storage..." <<
837  // std::endl; GeneralisedElement* g_el_pt =
838  // dynamic_cast<GeneralisedElement*>(new_node_update_f_el_pt);
839  // mesh_pt->add_external_halo_element_pt(
840  // loc_p,g_el_pt);
841  //
842  // // Check if also found externally
843  //#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
844  // oomph_info << "Rec:" << counter_for_recv_unsigneds
845  // << " Found externally too? "
846  // << recv_unsigneds[counter_for_recv_unsigneds]
847  // << std::endl;
848  //#endif
849  // unsigned found_externally_too =
850  // recv_unsigneds[counter_for_recv_unsigneds++]; std::cout <<
851  // "received found_externally_too = " << found_externally_too
852  // << std::endl; if(found_externally_too==1234)
853  // {
854  //#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
855  // oomph_info << "Rec:" << counter_for_recv_unsigneds
856  // << " Number of already existing external halo
857  // element "
858  // << recv_unsigneds[counter_for_recv_unsigneds]
859  // << std::endl;
860  //#endif
861  // unsigned ext_version_halo_element_index =
862  // recv_unsigneds[counter_for_recv_unsigneds++]; std::cout <<
863  // "received ext_version_halo_element_index = " <<
864  // ext_version_halo_element_index << std::endl;
865  //
866  // FiniteElement* ext_version_pt =
867  // dynamic_cast<FiniteElement*>(
868  // (mesh_pt->halo_element_pt(loc_p))[ext_version_halo_element_index]);
869  // //BENFLAG:
870  // oomph_info << "Existing node update element: " <<
871  // ext_version_pt << " (nnode_1d = " <<
872  // ext_version_pt->nnode_1d() << ")" << std::endl; oomph_info
873  // << "on proc " << loc_p << " is also at (external) index "
874  // << ext_version_halo_element_index << std::endl;
875  // for(unsigned j=0; j<ext_version_pt->nnode(); j++)
876  // {
877  // oomph_info << ext_version_pt->node_pt(j) << " at [ " <<
878  // ext_version_pt->node_pt(j)->x(0) << ", " <<
879  // ext_version_pt->node_pt(j)->x(1) << " ]" << std::endl;
880  // }
881  // }
882  }
883  else
884  {
885  new_node_update_f_el_pt = dynamic_cast<FiniteElement*>(
886  mesh_pt->external_halo_element_pt(loc_p, halo_element_index));
887  // BENFLAG:
888  oomph_info << "Existing node update element: "
889  << new_node_update_f_el_pt
890  << " (nnode_1d = " << new_node_update_f_el_pt->nnode_1d()
891  << ")" << std::endl;
892  oomph_info << "on proc " << loc_p << " at (external) index "
893  << recv_unsigneds[counter_for_recv_unsigneds - 1]
894  << std::endl;
895  // oomph_info << "...and doesn't exist in the external storage." <<
896  // std::endl;
897  }
898  }
899 
900  // Remaining required information to create functioning
901  // MacroElementNodeUpdateNode...
902 
903  // Get the required geom objects for the node update
904  // from the mesh
905  Vector<GeomObject*> geom_object_vector_pt;
906  MacroElementNodeUpdateMesh* macro_mesh_pt =
907  dynamic_cast<MacroElementNodeUpdateMesh*>(mesh_pt);
908  geom_object_vector_pt = macro_mesh_pt->geom_object_vector_pt();
909 
910  // Cast to MacroElementNodeUpdateNode
911  MacroElementNodeUpdateNode* macro_master_nod_pt =
912  dynamic_cast<MacroElementNodeUpdateNode*>(new_master_nod_pt);
913 
914  // Set all required information - node update element,
915  // local coordinate in this element, and then set node update info
916  macro_master_nod_pt->node_update_element_pt() = new_node_update_f_el_pt;
917 
918 
919  /// /print out nodes
920  // std::cout << "nodes are:" << std::endl;
921  // for(unsigned j=0; j<new_node_update_f_el_pt->nnode(); j++)
922  // {
923  // std::cout << new_node_update_f_el_pt->node_pt(j) << " at [ " <<
924  // new_node_update_f_el_pt->node_pt(j)->x(0) << ", " <<
925  // new_node_update_f_el_pt->node_pt(j)->x(1) << " ]" << std::endl;
926  // //std::cout << new_node_update_f_el_pt->node_pt(j) << std::endl;
927  // }
928  // std::cout << "should include: " << macro_master_nod_pt << " at [ " <<
929  // macro_master_nod_pt->x(0) << ", " << macro_master_nod_pt->x(1) << " ]"
930  // << std::endl;
931 
932 
933  // Need to get the local node index of the macro_master_nod_pt
934  unsigned local_node_index = 0;
935  // std::cout << "before: " << local_node_index << std::endl;
936  unsigned n_node = new_node_update_f_el_pt->nnode();
937  for (unsigned j = 0; j < n_node; j++)
938  {
939  if (macro_master_nod_pt == new_node_update_f_el_pt->node_pt(j))
940  {
941  // std::cout << "Node " << macro_master_nod_pt << " found at index "
942  // << j << " in update element." << std::endl;
943  local_node_index = j;
944  break;
945  }
946  // BENFLAG:
947  if (j == n_node - 1)
948  {
949  /// / Check if sons...
950  // RefineableElement* ref_el_pt =
951  // dynamic_cast<RefineableElement*>(new_node_update_f_el_pt);
952  // if(ref_el_pt->tree_pt()->nsons()!=0)
953  // {
954  // std::cout << "update el has sons!" << std::endl;
955  // }
956  // else
957  // {
958  // std::cout << "No sons." << std::endl;
959  // }
960 
961  // oomph_info << "Node not found in update element!" << std::endl;
962  throw OomphLibError("Node not found in update element!",
963  "Missing_masters_functions::construct_new_"
964  "external_halo_master_node_helper()",
965  OOMPH_EXCEPTION_LOCATION);
966  }
967  }
968  // std::cout << "after: " << local_node_index << std::endl;
969 
970  Vector<double> s_in_macro_node_update_element;
971  new_node_update_f_el_pt->local_coordinate_of_node(
972  local_node_index, s_in_macro_node_update_element);
973 
974  macro_master_nod_pt->set_node_update_info(new_node_update_f_el_pt,
975  s_in_macro_node_update_element,
976  geom_object_vector_pt);
977  }
978  else if (solid_nod_pt != 0)
979  {
980  // The master node should also be a SolidNode
981  // If this node was on a boundary then it needs to
982  // be on the same boundary here
983 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
984  oomph_info << "Rec:" << counter_for_recv_unsigneds
985  << " Bool master is a boundary (solid) node "
986  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
987 #endif
988  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
989  {
990  // Construct a new boundary node
991  if (time_stepper_pt != 0)
992  {
993  new_master_nod_pt = new BoundaryNode<SolidNode>(time_stepper_pt,
994  n_lag_dim,
995  n_lag_type,
996  n_dim,
997  n_position_type,
998  n_value);
999  }
1000  else
1001  {
1002  new_master_nod_pt = new BoundaryNode<SolidNode>(
1003  n_lag_dim, n_lag_type, n_dim, n_position_type, n_value);
1004  }
1005 
1006 
1007  // How many boundaries does the macro element master node live on?
1008 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1009  oomph_info << "Rec:" << counter_for_recv_unsigneds
1010  << " Number of boundaries the solid master node is on: "
1011  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1012 #endif
1013  unsigned nb = recv_unsigneds[counter_for_recv_unsigneds++];
1014  for (unsigned i = 0; i < nb; i++)
1015  {
1016  // Boundary number
1017 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1018  oomph_info << "Rec:" << counter_for_recv_unsigneds
1019  << " Solid master node is on boundary "
1020  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1021 #endif
1022  unsigned i_bnd = recv_unsigneds[counter_for_recv_unsigneds++];
1023  mesh_pt->add_boundary_node(i_bnd, new_master_nod_pt);
1024  }
1025 
1026  // Do we have additional values created by face elements?
1027 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1028  oomph_info << "Rec:" << counter_for_recv_unsigneds
1029  << " Number of additional values created by face element "
1030  << "for solid master node "
1031  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1032 #endif
1033  unsigned n_entry = recv_unsigneds[counter_for_recv_unsigneds++];
1034  if (n_entry > 0)
1035  {
1036  // Create storage, if it doesn't already exist, for the map
1037  // that will contain the position of the first entry of
1038  // this face element's additional values,
1039  BoundaryNodeBase* bnew_master_nod_pt =
1040  dynamic_cast<BoundaryNodeBase*>(new_master_nod_pt);
1041 #ifdef PARANOID
1042  if (bnew_master_nod_pt == 0)
1043  {
1044  throw OomphLibError("Failed to cast new node to boundary node\n",
1045  OOMPH_CURRENT_FUNCTION,
1046  OOMPH_EXCEPTION_LOCATION);
1047  }
1048 #endif
1049  if (bnew_master_nod_pt
1050  ->index_of_first_value_assigned_by_face_element_pt() == 0)
1051  {
1052  bnew_master_nod_pt
1054  new std::map<unsigned, unsigned>;
1055  }
1056 
1057  // Get pointer to the map of indices associated with
1058  // additional values created by face elements
1059  std::map<unsigned, unsigned>* map_pt =
1060  bnew_master_nod_pt
1062 
1063  // Loop over number of entries in map
1064  for (unsigned i = 0; i < n_entry; i++)
1065  {
1066  // Read out pairs...
1067 
1068 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1069  oomph_info << "Rec:" << counter_for_recv_unsigneds
1070  << " Key of map entry for solid master node"
1071  << recv_unsigneds[counter_for_recv_unsigneds]
1072  << std::endl;
1073 #endif
1074  unsigned first = recv_unsigneds[counter_for_recv_unsigneds++];
1075 
1076 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1077  oomph_info << "Rec:" << counter_for_recv_unsigneds
1078  << " Value of map entry for solid master node"
1079  << recv_unsigneds[counter_for_recv_unsigneds]
1080  << std::endl;
1081 #endif
1082  unsigned second = recv_unsigneds[counter_for_recv_unsigneds++];
1083 
1084  // ...and assign
1085  (*map_pt)[first] = second;
1086  }
1087  }
1088  }
1089  else
1090  {
1091  // Construct an ordinary (non-boundary) node
1092  if (time_stepper_pt != 0)
1093  {
1094  new_master_nod_pt = new SolidNode(time_stepper_pt,
1095  n_lag_dim,
1096  n_lag_type,
1097  n_dim,
1098  n_position_type,
1099  n_value);
1100  }
1101  else
1102  {
1103  new_master_nod_pt = new SolidNode(
1104  n_lag_dim, n_lag_type, n_dim, n_position_type, n_value);
1105  }
1106  }
1107 
1108  // Add this as an external halo node
1109  mesh_pt->add_external_halo_node_pt(loc_p, new_master_nod_pt);
1110 
1111  // Copy across particular info required for SolidNode
1112  // NOTE: Are there any problems with additional values for SolidNodes?
1113  SolidNode* solid_master_nod_pt =
1114  dynamic_cast<SolidNode*>(new_master_nod_pt);
1115  unsigned n_solid_val =
1116  solid_master_nod_pt->variable_position_pt()->nvalue();
1117  for (unsigned i_val = 0; i_val < n_solid_val; i_val++)
1118  {
1119  for (unsigned t = 0; t < n_prev; t++)
1120  {
1121  solid_master_nod_pt->variable_position_pt()->set_value(
1122  t, i_val, recv_doubles[counter_for_recv_doubles++]);
1123  }
1124  }
1125  }
1126  else // Just an ordinary node!
1127  {
1128 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1129  oomph_info << "Rec:" << counter_for_recv_unsigneds
1130  << " Bool node is on boundary "
1131  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1132 #endif
1133 
1134  // If this node was on a boundary then it needs to
1135  // be on the same boundary here
1136  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
1137  {
1138  // Construct a new boundary node
1139  if (time_stepper_pt != 0)
1140  {
1141  new_master_nod_pt = new BoundaryNode<Node>(
1142  time_stepper_pt, n_dim, n_position_type, n_value);
1143  }
1144  else
1145  {
1146  new_master_nod_pt =
1147  new BoundaryNode<Node>(n_dim, n_position_type, n_value);
1148  }
1149 
1150  // How many boundaries does the master node live on?
1151 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1152  oomph_info << "Rec:" << counter_for_recv_unsigneds
1153  << " Number of boundaries the master node is on: "
1154  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1155 #endif
1156  unsigned nb = recv_unsigneds[counter_for_recv_unsigneds++];
1157  for (unsigned i = 0; i < nb; i++)
1158  {
1159  // Boundary number
1160 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1161  oomph_info << "Rec:" << counter_for_recv_unsigneds
1162  << " Master node is on boundary "
1163  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1164 #endif
1165  unsigned i_bnd = recv_unsigneds[counter_for_recv_unsigneds++];
1166  mesh_pt->add_boundary_node(i_bnd, new_master_nod_pt);
1167  }
1168 
1169 
1170  // Do we have additional values created by face elements?
1171 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1172  oomph_info << "Rec:" << counter_for_recv_unsigneds
1173  << " Number of additional values created by face element "
1174  << "for master node "
1175  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1176 #endif
1177  unsigned n_entry = recv_unsigneds[counter_for_recv_unsigneds++];
1178  if (n_entry > 0)
1179  {
1180  // Create storage, if it doesn't already exist, for the map
1181  // that will contain the position of the first entry of
1182  // this face element's additional values,
1183  BoundaryNodeBase* bnew_master_nod_pt =
1184  dynamic_cast<BoundaryNodeBase*>(new_master_nod_pt);
1185 #ifdef PARANOID
1186  if (bnew_master_nod_pt == 0)
1187  {
1188  throw OomphLibError("Failed to cast new node to boundary node\n",
1189  OOMPH_CURRENT_FUNCTION,
1190  OOMPH_EXCEPTION_LOCATION);
1191  }
1192 #endif
1193  if (bnew_master_nod_pt
1194  ->index_of_first_value_assigned_by_face_element_pt() == 0)
1195  {
1196  bnew_master_nod_pt
1198  new std::map<unsigned, unsigned>;
1199  }
1200 
1201  // Get pointer to the map of indices associated with
1202  // additional values created by face elements
1203  std::map<unsigned, unsigned>* map_pt =
1204  bnew_master_nod_pt
1206 
1207  // Loop over number of entries in map
1208  for (unsigned i = 0; i < n_entry; i++)
1209  {
1210  // Read out pairs...
1211 
1212 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1213  oomph_info << "Rec:" << counter_for_recv_unsigneds
1214  << " Key of map entry for master node"
1215  << recv_unsigneds[counter_for_recv_unsigneds]
1216  << std::endl;
1217 #endif
1218  unsigned first = recv_unsigneds[counter_for_recv_unsigneds++];
1219 
1220 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1221  oomph_info << "Rec:" << counter_for_recv_unsigneds
1222  << " Value of map entry for master node"
1223  << recv_unsigneds[counter_for_recv_unsigneds]
1224  << std::endl;
1225 #endif
1226  unsigned second = recv_unsigneds[counter_for_recv_unsigneds++];
1227 
1228  // ...and assign
1229  (*map_pt)[first] = second;
1230  }
1231  }
1232  }
1233  else
1234  {
1235  // Construct an ordinary (non-boundary) node
1236  if (time_stepper_pt != 0)
1237  {
1238  new_master_nod_pt =
1239  new Node(time_stepper_pt, n_dim, n_position_type, n_value);
1240  }
1241  else
1242  {
1243  new_master_nod_pt = new Node(n_dim, n_position_type, n_value);
1244  }
1245  }
1246 
1247  // Add this as an external halo node
1248  mesh_pt->add_external_halo_node_pt(loc_p, new_master_nod_pt);
1249  }
1250 
1251  // Remaining info received for all node types
1252  // Get copied history values
1253  // unsigned n_val=new_master_nod_pt->nvalue();
1254  for (unsigned i_val = 0; i_val < n_value; i_val++)
1255  {
1256  for (unsigned t = 0; t < n_prev; t++)
1257  {
1258  new_master_nod_pt->set_value(
1259  t, i_val, recv_doubles[counter_for_recv_doubles++]);
1260  }
1261  }
1262 
1263  // Get copied history values for positions
1264  unsigned n_nod_dim = new_master_nod_pt->ndim();
1265  for (unsigned idim = 0; idim < n_nod_dim; idim++)
1266  {
1267  for (unsigned t = 0; t < n_prev; t++)
1268  {
1269  // Copy to coordinate
1270  new_master_nod_pt->x(t, idim) =
1271  recv_doubles[counter_for_recv_doubles++];
1272  }
1273  }
1274 
1275  // Assign correct non-halo processor ID
1276  new_master_nod_pt->set_halo(non_halo_proc_ID);
1277  }
1278 
1279 
1280 #endif
1281 
1282 
1283 } // namespace oomph
1284 
1285 #endif
cstr elem_len * i
Definition: cfortran.h:603
char t
Definition: cfortran.h:568
////////////////////////////////////////////////////////////////////
virtual void update_node_update(AlgebraicNode *&node_pt)=0
Update the node update info for given node, following mesh adaptation. Must be implemented for every ...
GeomObject * geom_object_list_pt(const unsigned &i)
Access function to the ith GeomObject.
////////////////////////////////////////////////////////////////////
void add_node_update_info(const int &id, AlgebraicMesh *mesh_pt, const Vector< GeomObject * > &geom_object_pt, const Vector< double > &ref_value, const bool &called_from_constructor=false)
Add algebraic update information for node: What's the ID of the mesh update function (typically used ...
A class that contains the information required by Nodes that are located on Mesh boundaries....
Definition: nodes.h:1996
std::map< unsigned, unsigned > *& index_of_first_value_assigned_by_face_element_pt()
Return pointer to the map giving the index of the first face element value.
Definition: nodes.h:2046
A template Class for BoundaryNodes; that is Nodes that MAY live on the boundary of a Mesh....
Definition: nodes.h:2242
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:238
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
Definition: nodes.h:271
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
void set_halo(const unsigned &non_halo_proc_ID)
Label the node as halo and specify processor that holds non-halo counterpart.
Definition: nodes.h:520
MacroElement * macro_element_pt(const unsigned &i)
Access to i-th macro element.
Definition: domain.h:116
A general Finite Element class.
Definition: elements.h:1313
virtual void set_macro_elem_pt(MacroElement *macro_elem_pt)
Set pointer to macro element – can be overloaded in derived elements to perform additional tasks.
Definition: elements.h:1872
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual)
Definition: elements.h:1842
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2611
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
Definition: elements.h:2218
A Generalised Element class.
Definition: elements.h:73
Class that contains data for hanging nodes.
Definition: nodes.h:742
void set_master_node_pt(const unsigned &i, Node *const &master_node_pt, const double &weight)
Set the pointer to the i-th master node and its weight.
Definition: nodes.cc:1474
MacroElementNodeUpdateMeshes contain MacroElementNodeUpdateNodes which have their own node update fun...
Vector< GeomObject * > geom_object_vector_pt()
Access function to the vector of GeomObject.
Domain *& macro_domain_pt()
Broken assignment operator.
////////////////////////////////////////////////////////////////////
FiniteElement *& node_update_element_pt()
Pointer to finite element that performs the update by referring to its macro-element representation (...
void set_node_update_info(FiniteElement *node_update_element_pt, const Vector< double > &s_in_node_update_element, const Vector< GeomObject * > &geom_object_pt)
Set node update information for node: Pass the pointer to the element that performs the update operat...
A general mesh class.
Definition: mesh.h:67
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
Definition: mesh.cc:243
void add_external_halo_element_pt(const unsigned &p, GeneralisedElement *&el_pt)
Add external halo element whose non-halo counterpart is held on processor p to this Mesh.
Definition: mesh.h:2259
Node * shared_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th shared node in this Mesh who has a counterpart on processor p.
Definition: mesh.h:2110
Node *& external_halo_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th external halo node in this Mesh whose non-halo external counterpart is held on...
Definition: mesh.h:2377
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:473
GeneralisedElement *& external_halo_element_pt(const unsigned &p, const unsigned &e)
Access fct to the e-th external halo element in this Mesh whose non-halo counterpart is held on proce...
Definition: mesh.h:2251
void add_external_halo_node_pt(const unsigned &p, Node *&nod_pt)
Add external halo node whose non-halo (external) counterpart is held on processor p to the storage sc...
Definition: mesh.h:2368
Vector< GeneralisedElement * > halo_element_pt(const unsigned &p)
Return vector of halo elements in this Mesh whose non-halo counterpart is held on processor p.
Definition: mesh.h:1740
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:906
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
void set_hanging_pt(HangInfo *const &hang_pt, const int &i)
Set the hanging data for the i-th value. (hang_pt=0 to make non-hanging)
Definition: nodes.cc:2068
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
Definition: Qelements.h:91
double & s_macro_ll(const unsigned &i)
Access fct to the i-th coordinate of the element's "lower left" vertex in the associated MacroElement...
Definition: Qelements.h:186
double & s_macro_ur(const unsigned &i)
Access fct to the i-th coordinate of the element's "upper right" vertex in the associated MacroElemen...
Definition: Qelements.h:202
RefineableElements are FiniteElements that may be subdivided into children to provide a better local ...
virtual void initial_setup(Tree *const &adopted_father_pt=0, const unsigned &initial_p_order=0)
Initial setup of the element: e.g. set the appropriate internal p-order. If an adopted father is spec...
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
Definition: nodes.h:1686
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1765
////////////////////////////////////////////////////////////////////// //////////////////////////////...
Definition: timesteppers.h:231
void add_external_halo_node_helper(Node *&new_nod_pt, Mesh *const &mesh_pt, unsigned &loc_p, unsigned &node_index, FiniteElement *const &new_el_pt, int &n_cont_inter_values, unsigned &counter_for_recv_unsigneds, Vector< unsigned > &recv_unsigneds, unsigned &counter_for_recv_doubles, Vector< double > &recv_doubles)
Helper functiono to add external halo node that is not a master.
void recursively_add_masters_of_external_halo_node_to_storage(Node *&new_nod_pt, Mesh *const &mesh_pt, unsigned &loc_p, unsigned &node_index, int &n_cont_inter_values, unsigned &counter_for_recv_unsigneds, Vector< unsigned > &recv_unsigneds, unsigned &counter_for_recv_doubles, Vector< double > &recv_doubles)
Recursively add masters of external halo nodes (and their masters, etc) based on information received...
void add_external_halo_node_to_storage(Node *&new_nod_pt, Mesh *const &mesh_pt, unsigned &loc_p, unsigned &node_index, FiniteElement *const &new_el_pt, int &n_cont_inter_values, unsigned &counter_for_recv_unsigneds, Vector< unsigned > &recv_unsigneds, unsigned &counter_for_recv_doubles, Vector< double > &recv_doubles)
Helper function to add external halo nodes, including any masters, based on information received from...
void construct_new_external_halo_master_node_helper(Node *&new_master_nod_pt, Node *&nod_pt, unsigned &loc_p, Mesh *const &mesh_pt, unsigned &counter_for_recv_unsigneds, Vector< unsigned > &recv_unsigneds, unsigned &counter_for_recv_doubles, Vector< double > &recv_doubles)
Helper function which constructs a new external halo master node with the information sent from the h...
void add_external_halo_master_node_helper(Node *&new_master_nod_pt, Node *&new_nod_pt, Mesh *const &mesh_pt, unsigned &loc_p, int &n_cont_inter_values, unsigned &counter_for_recv_unsigneds, Vector< unsigned > &recv_unsigneds, unsigned &counter_for_recv_doubles, Vector< double > &recv_doubles)
Helper function to add external halo node that is a master.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...