missing_masters.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 // Non-templated missing masters functions which help to reconcile the hanging
27 // status of nodes in the halo layer of distributed meshes
28 
29 // oomph-lib header
30 #include "missing_masters.h"
32 #include "mesh.h"
33 #include "algebraic_elements.h"
35 #include "Qelements.h"
36 
37 namespace oomph
38 {
39  //======================================================================
40  // Namespace for "global" missing-master-locating functions
41  //======================================================================
42  namespace Missing_masters_functions
43  {
44  // Workspace for locate zeta methods
45  //----------------------------------
46 
47 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
48 
49  // Temporary vector of strings to enable full annotation of multi domain
50  // comms (but keep alive because it would be such a bloody pain to
51  // rewrite it if things ever go wrong again...)
52  // This is left over from the multi-domain stuff and should work
53  // in the same way, but it has not been tested.
55 
56 #endif
57 
58  /// Boolean to indicate whether to doc timings or not.
59  bool Doc_timings = false;
60 
61  /// Boolean to indicate whether to output basic info during
62  /// setup_multi_domain_interaction() routines
63  bool Doc_stats = false;
64 
65  /// Boolean to indicate whether to output further info during
66  /// setup_multi_domain_interaction() routines
67  bool Doc_full_stats = false;
68 
69 #ifdef OOMPH_HAS_MPI
70 
71 
72  // Functions for location method in multi-domain problems
73 
74  //========start of add_external_haloed_node_to_storage====================
75  /// Helper function to add external haloed nodes, including any masters
76  //========================================================================
78  Node* nod_pt,
79  Mesh* const& mesh_pt,
80  int& n_cont_inter_values,
81  Vector<unsigned>& send_unsigneds,
82  Vector<double>& send_doubles)
83  {
84  // Add the node if required
86  nod_pt,
87  mesh_pt,
88  n_cont_inter_values,
89  send_unsigneds,
90  send_doubles);
91 
92  // Recursively add any master nodes (and their master nodes etc)
94  nod_pt,
95  mesh_pt,
96  n_cont_inter_values,
97  send_unsigneds,
98  send_doubles);
99  }
100 
101 
102  //========================================================================
103  /// Recursively add any master nodes (and their master nodes etc) of
104  /// external nodes
105  //========================================================================
107  int& iproc,
108  Node* nod_pt,
109  Mesh* const& mesh_pt,
110  int& n_cont_inter_values,
111  Vector<unsigned>& send_unsigneds,
112  Vector<double>& send_doubles)
113  {
114  // Loop over continuously interpolated values and add masters
115  for (int i_cont = -1; i_cont < n_cont_inter_values; i_cont++)
116  {
117  if (nod_pt->is_hanging(i_cont))
118  {
119  // Indicate that this node is a hanging node so the other
120  // process knows to create HangInfo and masters, etc.
121  send_unsigneds.push_back(1);
122 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
123  Flat_packed_unsigneds_string.push_back("Is hanging");
124 #endif
125  // If this is a hanging node then add all its masters as
126  // external halo nodes if they have not yet been added
127  HangInfo* hang_pt = nod_pt->hanging_pt(i_cont);
128  // Loop over masters
129  unsigned n_master = hang_pt->nmaster();
130 
131  // Indicate number of master nodes to add on other process
132  send_unsigneds.push_back(n_master);
133 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
134  Flat_packed_unsigneds_string.push_back("nmaster");
135 #endif
136  for (unsigned m = 0; m < n_master; m++)
137  {
138  Node* master_nod_pt = hang_pt->master_node_pt(m);
139 
140  // Call the helper function for master nodes
142  master_nod_pt,
143  mesh_pt,
144  n_cont_inter_values,
145  send_unsigneds,
146  send_doubles);
147 
148  // Indicate the weight of this master
149  send_doubles.push_back(hang_pt->master_weight(m));
150 
151  // Recursively add any master nodes (and their master nodes etc)
153  master_nod_pt,
154  mesh_pt,
155  n_cont_inter_values,
156  send_unsigneds,
157  send_doubles);
158  }
159  }
160  else
161  {
162  // Indicate that it's not a hanging node in this variable
163  send_unsigneds.push_back(0);
164 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
165  Flat_packed_unsigneds_string.push_back("Not hanging");
166 #endif
167  }
168  } // end loop over continously interpolated values
169  }
170 
171  //==========start of add_external_haloed_node_helper======================
172  /// Helper to add external haloed node that is not a master
173  //========================================================================
175  Node* nod_pt,
176  Mesh* const& mesh_pt,
177  int& n_cont_inter_values,
178  Vector<unsigned>& send_unsigneds,
179  Vector<double>& send_doubles)
180  {
181  // Check to see if this haloed node already exists in (internal)
182  // haloed node storage with any processor
183  bool found_internally = false;
184  unsigned shared_node_index = 0;
185 
186  // Get vector of all shared nodes with processor iproc
187  Vector<Node*> shared_node_pt;
188  mesh_pt->get_shared_node_pt(iproc, shared_node_pt);
189 
190  // Search the internal haloed storage for this node
192  std::find(shared_node_pt.begin(), shared_node_pt.end(), nod_pt);
193 
194  // Check if the node was found in shared storage
195  if (it != shared_node_pt.end())
196  {
197  // Node found in (internal) haloed storage
198  found_internally = true;
199  // Store the index in this storage
200  shared_node_index = it - shared_node_pt.begin();
201  }
202 
203  /// / Slow search version without additional access function in Mesh class
204  /// /Search the internal shared node storage for this node
205  // for(unsigned i=0; i<mesh_pt->nshared_node(iproc); i++)
206  // {
207  // if(nod_pt == mesh_pt->shared_node_pt(iproc,i))
208  // {
209  // //Node found in (internal) shared storage
210  // found_internally = true;
211  // shared_node_index = i;
212  // break;
213  // }
214  // }
215 
216  // If we've found the node internally
217  if (found_internally)
218  {
219  // Indicate that this node doesn not need to be constructed on
220  // the other process
221  send_unsigneds.push_back(0);
222 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
223  std::stringstream junk;
224  junk << "Node was already added [size=" << send_unsigneds.size()
225  << "]; last entry: " << send_unsigneds[send_unsigneds.size() - 1];
226 
227  Flat_packed_unsigneds_string.push_back(junk.str());
228 #endif
229 
230  // This node is already shared with processor iproc, so tell the other
231  // processor its index in the shared node storage
232  send_unsigneds.push_back(1);
233 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
234  Flat_packed_unsigneds_string.push_back("haloed node found internally");
235 #endif
236  send_unsigneds.push_back(shared_node_index);
237 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
238  Flat_packed_unsigneds_string.push_back("(internal) haloed node index");
239 #endif
240  }
241  else
242  {
243  // Attempt to add this node as an external haloed node
244  unsigned n_ext_haloed_nod = mesh_pt->nexternal_haloed_node(iproc);
245  unsigned external_haloed_node_index;
246  external_haloed_node_index =
247  mesh_pt->add_external_haloed_node_pt(iproc, nod_pt);
248 
249  // If it was added then the new index should match the size of the
250  // storage
251  if (external_haloed_node_index == n_ext_haloed_nod)
252  {
253  // Indicate that this node needs to be constructed on
254  // the other process
255  send_unsigneds.push_back(1);
256 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
257  std::stringstream junk;
258  junk << "Node needs to be constructed [size=" << send_unsigneds.size()
259  << "]; last entry: "
260  << send_unsigneds[send_unsigneds.size() - 1];
261  Flat_packed_unsigneds_string.push_back(junk.str());
262 #endif
263 
264  // This helper function gets all the required information for the
265  // specified node and stores it into MPI-sendable information
266  // so that a halo copy can be made on the receiving process
268  nod_pt,
269  mesh_pt,
270  n_cont_inter_values,
271  send_unsigneds,
272  send_doubles);
273  }
274  else // It was already added
275  {
276  // Indicate that this node doesn not need to be constructed on
277  // the other process
278  send_unsigneds.push_back(0);
279 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
280  std::stringstream junk;
281  junk << "Node was already added [size=" << send_unsigneds.size()
282  << "]; last entry: "
283  << send_unsigneds[send_unsigneds.size() - 1];
284 
285  Flat_packed_unsigneds_string.push_back(junk.str());
286 #endif
287 
288  // This node is already an external haloed node, so tell
289  // the other process its index in the equivalent external halo storage
290  send_unsigneds.push_back(0);
291 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
293  "haloed node found externally");
294 #endif
295  send_unsigneds.push_back(external_haloed_node_index);
296 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
297  Flat_packed_unsigneds_string.push_back("external haloed node index");
298 #endif
299  }
300  }
301  }
302 
303 
304  //==========start of add_external_haloed_master_node_helper===============
305  /// Helper function to add external haloed node that is a master
306  //========================================================================
308  int& iproc,
309  Node* master_nod_pt,
310  Mesh* const& mesh_pt,
311  int& n_cont_inter_values,
312  Vector<unsigned>& send_unsigneds,
313  Vector<double>& send_doubles)
314  {
315  // Check to see if this haloed node already exists in (internal)
316  // haloed node storage with any processor
317  bool found_internally = false;
318  unsigned shared_node_index = 0;
319 
320  // Get vector of all shared nodes with processor iproc
321  Vector<Node*> shared_node_pt;
322  mesh_pt->get_shared_node_pt(iproc, shared_node_pt);
323 
324  // Search the internal haloed storage for this node
326  std::find(shared_node_pt.begin(), shared_node_pt.end(), master_nod_pt);
327 
328  // Check if the node was found in shared storage
329  if (it != shared_node_pt.end())
330  {
331  // Node found in (internal) haloed storage
332  found_internally = true;
333  // Store the index in this storage
334  shared_node_index = it - shared_node_pt.begin();
335  }
336 
337  /// / Slow search version without additional access function in Mesh class
338  /// /Search the internal shared node storage for this node
339  // for(unsigned i=0; i<mesh_pt->nshared_node(iproc); i++)
340  // {
341  // if(master_nod_pt == mesh_pt->shared_node_pt(iproc,i))
342  // {
343  // //Node found in (internal) shared storage
344  // found_internally = true;
345  // shared_node_index = i;
346  // break;
347  // }
348  // }
349 
350  // If we've found the node internally
351  if (found_internally)
352  {
353  // Indicate that this node doesn not need to be constructed on
354  // the other process
355  send_unsigneds.push_back(0);
356 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
357  std::stringstream junk;
358  junk << "Node was already added [size=" << send_unsigneds.size()
359  << "]; last entry: " << send_unsigneds[send_unsigneds.size() - 1];
360 
361  Flat_packed_unsigneds_string.push_back(junk.str());
362 #endif
363 
364  // This node is already shared with processor iproc, so tell the other
365  // processor its index in the shared node storage
366  send_unsigneds.push_back(1);
367 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
368  Flat_packed_unsigneds_string.push_back("haloed node found internally");
369 #endif
370  send_unsigneds.push_back(shared_node_index);
371 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
372  Flat_packed_unsigneds_string.push_back("(internal) haloed node index");
373 #endif
374  }
375  else
376  {
377  // Attempt to add node as an external haloed node
378  unsigned n_ext_haloed_nod = mesh_pt->nexternal_haloed_node(iproc);
379  unsigned external_haloed_node_index;
380  external_haloed_node_index =
381  mesh_pt->add_external_haloed_node_pt(iproc, master_nod_pt);
382 
383  // If it was added the returned index is the same as current storage
384  // size
385  if (external_haloed_node_index == n_ext_haloed_nod)
386  {
387  // Indicate that this node needs to be constructed on
388  // the other process
389  send_unsigneds.push_back(1);
390 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
392  "Node needs to be constructed[2]");
393 #endif
394 
395  // This gets all the required information for the specified
396  // master node and stores it into MPI-sendable information
397  // so that a halo copy can be made on the receiving process
399  master_nod_pt,
400  mesh_pt,
401  n_cont_inter_values,
402  send_unsigneds,
403  send_doubles);
404  }
405  else // It was already added
406  {
407  // Indicate that this node doesn not need to be constructed on
408  // the other process
409  send_unsigneds.push_back(0);
410 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
411  Flat_packed_unsigneds_string.push_back("Node was already added[2]");
412 #endif
413 
414  // This node is already an external haloed node, so tell
415  // the other process its index in the equivalent external halo storage
416  send_unsigneds.push_back(0);
417 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
419  "haloed node found externally");
420 #endif
421  send_unsigneds.push_back(external_haloed_node_index);
422 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
424  "external haloed node index[2]");
425 #endif
426  }
427  }
428  }
429 
430 
431  //========start of get_required_nodal_information_helper==================
432  /// Helper function to get the required nodal information from an
433  /// external haloed node so that a fully-functional external halo
434  /// node (and therefore element) can be created on the receiving process
435  //========================================================================
437  Node* nod_pt,
438  Mesh* const& mesh_pt,
439  int& n_cont_inter_values,
440  Vector<unsigned>& send_unsigneds,
441  Vector<double>& send_doubles)
442  {
443  // Tell the halo copy of this node how many values there are
444  // [NB this may be different for nodes within the same element, e.g.
445  // when using Lagrange multipliers]
446  unsigned n_val = nod_pt->nvalue();
447  send_unsigneds.push_back(n_val);
448 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
449  Flat_packed_unsigneds_string.push_back("Number of values");
450 #endif
451 
452  unsigned n_dim = nod_pt->ndim();
453  TimeStepper* time_stepper_pt = nod_pt->time_stepper_pt();
454 
455  // Default number of previous values to 1
456  unsigned n_prev = 1;
457  if (time_stepper_pt != 0)
458  {
459  // Add number of history values to n_prev
460  n_prev = time_stepper_pt->ntstorage();
461  }
462 
463  // Is the node on any boundaries?
464  if (nod_pt->is_on_boundary())
465  {
466  send_unsigneds.push_back(1);
467 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
468  Flat_packed_unsigneds_string.push_back("Node is on boundary");
469 #endif
470 
471  // Loop over the boundaries of the external mesh
472  Vector<unsigned> boundaries;
473  unsigned n_bnd = mesh_pt->nboundary();
474  for (unsigned i_bnd = 0; i_bnd < n_bnd; i_bnd++)
475  {
476  // Which boundaries (could be more than one) is it on?
477  if (nod_pt->is_on_boundary(i_bnd))
478  {
479  boundaries.push_back(i_bnd);
480  }
481  }
482  unsigned nb = boundaries.size();
483  send_unsigneds.push_back(nb);
484 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
485  std::stringstream junk;
486  junk << "Node is on " << nb << " boundaries";
487  Flat_packed_unsigneds_string.push_back(junk.str());
488 #endif
489  for (unsigned i = 0; i < nb; i++)
490  {
491  send_unsigneds.push_back(boundaries[i]);
492 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
493  std::stringstream junk;
494  junk << "Node is on boundary " << boundaries[i] << " of " << n_bnd;
495  Flat_packed_unsigneds_string.push_back(junk.str());
496 #endif
497  }
498 
499  // Get pointer to the map of indices associated with
500  // additional values created by face elements
501  BoundaryNodeBase* bnod_pt = dynamic_cast<BoundaryNodeBase*>(nod_pt);
502 #ifdef PARANOID
503  if (bnod_pt == 0)
504  {
505  throw OomphLibError("Failed to cast new node to boundary node\n",
506  OOMPH_CURRENT_FUNCTION,
507  OOMPH_EXCEPTION_LOCATION);
508  }
509 #endif
510  std::map<unsigned, unsigned>* map_pt =
512 
513  // No additional values created
514  if (map_pt == 0)
515  {
516  send_unsigneds.push_back(0);
517 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
518  std::stringstream junk;
520  "No additional values were created by face element");
521 #endif
522  }
523  // Created additional values
524  else
525  {
526  // How many?
527  send_unsigneds.push_back(map_pt->size());
528 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
529  std::stringstream junk;
530  junk << "Map size " << map_pt->size() << n_bnd;
531  Flat_packed_unsigneds_string.push_back(junk.str());
532 #endif
533  // Loop over entries in map and add to send data
534  for (std::map<unsigned, unsigned>::iterator p = map_pt->begin();
535  p != map_pt->end();
536  p++)
537  {
538  send_unsigneds.push_back((*p).first);
539 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
540  std::stringstream junk;
541  Flat_packed_unsigneds_string.push_back("Key of map entry");
542 #endif
543  send_unsigneds.push_back((*p).second);
544 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
545  Flat_packed_unsigneds_string.push_back("Value of map entry");
546 #endif
547  }
548  }
549  }
550  else
551  {
552  // Not on any boundary
553  send_unsigneds.push_back(0);
554 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
555  Flat_packed_unsigneds_string.push_back("Node is not on any boundary");
556 #endif
557  }
558 
559  // Is the Node algebraic? If so, send its ref values and
560  // an indication of its geometric objects if they are stored
561  // in the algebraic mesh
562  AlgebraicNode* alg_nod_pt = dynamic_cast<AlgebraicNode*>(nod_pt);
563  if (alg_nod_pt != 0)
564  {
565  // The external mesh should be algebraic
566  AlgebraicMesh* alg_mesh_pt = dynamic_cast<AlgebraicMesh*>(mesh_pt);
567 
568  // Get default node update function ID
569  unsigned update_id = alg_nod_pt->node_update_fct_id();
570  send_unsigneds.push_back(update_id);
571 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
572  Flat_packed_unsigneds_string.push_back("Alg Node update id");
573 #endif
574 
575  // Get reference values at default...
576  unsigned n_ref_val = alg_nod_pt->nref_value();
577  send_unsigneds.push_back(n_ref_val);
578 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
579  Flat_packed_unsigneds_string.push_back("Alg Node n ref values");
580 #endif
581  for (unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
582  {
583  send_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
584  }
585 
586  // Access geometric objects at default...
587  unsigned n_geom_obj = alg_nod_pt->ngeom_object();
588  send_unsigneds.push_back(n_geom_obj);
589 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
590  Flat_packed_unsigneds_string.push_back("Alg Node n geom objects");
591 #endif
592  for (unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
593  {
594  GeomObject* geom_obj_pt = alg_nod_pt->geom_object_pt(i_geom);
595 
596  // Check this against the stored geometric objects in mesh
597  unsigned n_geom_list = alg_mesh_pt->ngeom_object_list_pt();
598 
599  // Default found index to zero
600  unsigned found_geom_object = 0;
601  for (unsigned i_list = 0; i_list < n_geom_list; i_list++)
602  {
603  if (geom_obj_pt == alg_mesh_pt->geom_object_list_pt(i_list))
604  {
605  found_geom_object = i_list;
606  }
607  }
608  send_unsigneds.push_back(found_geom_object);
609 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
610  Flat_packed_unsigneds_string.push_back("Found geom object");
611 #endif
612  }
613  }
614 
615  // If it is a MacroElementNodeUpdateNode, everything has been
616  // dealt with by the new element already
617 
618  // Is it a SolidNode?
619  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(nod_pt);
620  if (solid_nod_pt != 0)
621  {
622  unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
623  for (unsigned i_val = 0; i_val < n_solid_val; i_val++)
624  {
625  for (unsigned t = 0; t < n_prev; t++)
626  {
627  send_doubles.push_back(
628  solid_nod_pt->variable_position_pt()->value(t, i_val));
629  }
630  }
631  }
632 
633  // Finally copy info required for all node types
634  for (unsigned i_val = 0; i_val < n_val; i_val++)
635  {
636  for (unsigned t = 0; t < n_prev; t++)
637  {
638  send_doubles.push_back(nod_pt->value(t, i_val));
639  }
640  }
641 
642  // Now do positions
643  for (unsigned idim = 0; idim < n_dim; idim++)
644  {
645  for (unsigned t = 0; t < n_prev; t++)
646  {
647  send_doubles.push_back(nod_pt->x(t, idim));
648  }
649  }
650  }
651 
652  //=========start of get_required_master_nodal_information_helper==========
653  /// Helper function to get the required master nodal information from an
654  /// external haloed master node so that a fully-functional external halo
655  /// master node (and possible element) can be created on the receiving
656  /// process
657  //========================================================================
659  int& iproc,
660  Node* master_nod_pt,
661  Mesh* const& mesh_pt,
662  int& n_cont_inter_values,
663  Vector<unsigned>& send_unsigneds,
664  Vector<double>& send_doubles)
665  {
666  // Need to send over dimension, position type and number of values
667  send_unsigneds.push_back(master_nod_pt->ndim());
668 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
669  Flat_packed_unsigneds_string.push_back("Master node ndim");
670 #endif
671  send_unsigneds.push_back(master_nod_pt->nposition_type());
672 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
673  Flat_packed_unsigneds_string.push_back("Master node npos_type");
674 #endif
675  send_unsigneds.push_back(master_nod_pt->nvalue());
676 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
677  Flat_packed_unsigneds_string.push_back("Master node nvalue");
678 #endif
679  if (master_nod_pt->is_halo())
680  {
681  send_unsigneds.push_back(master_nod_pt->non_halo_proc_ID());
682  }
683  else
684  {
685  send_unsigneds.push_back(mesh_pt->communicator_pt()->my_rank());
686  }
687 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
689  "Master node non-halo processor ID");
690 #endif
691 
692  // If it's a solid node, also need to send lagrangian dim and type
693  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(master_nod_pt);
694  if (solid_nod_pt != 0)
695  {
696  send_unsigneds.push_back(solid_nod_pt->nlagrangian());
697 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
698  Flat_packed_unsigneds_string.push_back("Master solid node nlagr");
699 #endif
700  send_unsigneds.push_back(solid_nod_pt->nlagrangian_type());
701 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
702  Flat_packed_unsigneds_string.push_back("Master solid node nlagr_type");
703 #endif
704  }
705 
706  unsigned n_dim = master_nod_pt->ndim();
707  TimeStepper* time_stepper_pt = master_nod_pt->time_stepper_pt();
708 
709  // Default number of previous values to 1
710  unsigned n_prev = 1;
711  if (time_stepper_pt != 0)
712  {
713  // Add number of history values to n_prev
714  n_prev = time_stepper_pt->ntstorage();
715  }
716 
717  // Is the node on any boundaries?
718  if (master_nod_pt->is_on_boundary())
719  {
720  send_unsigneds.push_back(1);
721 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
722  Flat_packed_unsigneds_string.push_back("Master node is on boundary");
723 #endif
724  // Loop over the boundaries of the external mesh
725  Vector<unsigned> boundaries;
726  unsigned n_bnd = mesh_pt->nboundary();
727  for (unsigned i_bnd = 0; i_bnd < n_bnd; i_bnd++)
728  {
729  // Which boundaries (could be more than one) is it on?
730  if (master_nod_pt->is_on_boundary(i_bnd))
731  {
732  boundaries.push_back(i_bnd);
733  }
734  }
735  unsigned nb = boundaries.size();
736  send_unsigneds.push_back(nb);
737 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
738  std::stringstream junk;
739  junk << "Master node is on " << nb << " boundaries";
740  Flat_packed_unsigneds_string.push_back(junk.str());
741 #endif
742  for (unsigned i = 0; i < nb; i++)
743  {
744  send_unsigneds.push_back(boundaries[i]);
745 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
746  std::stringstream junk;
747  junk << "Master noode is on boundary " << boundaries[i] << " of "
748  << n_bnd;
749  Flat_packed_unsigneds_string.push_back(junk.str());
750 #endif
751  }
752 
753  // Get pointer to the map of indices associated with
754  // additional values created by face elements
755  BoundaryNodeBase* bnod_pt =
756  dynamic_cast<BoundaryNodeBase*>(master_nod_pt);
757 #ifdef PARANOID
758  if (bnod_pt == 0)
759  {
760  throw OomphLibError("Failed to cast new node to boundary node\n",
761  OOMPH_CURRENT_FUNCTION,
762  OOMPH_EXCEPTION_LOCATION);
763  }
764 #endif
765  std::map<unsigned, unsigned>* map_pt =
767 
768  // No additional values created
769  if (map_pt == 0)
770  {
771  send_unsigneds.push_back(0);
772 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
773  std::stringstream junk;
775  "No additional values were created by face element for this master "
776  "node");
777 #endif
778  }
779  // Created additional values
780  else
781  {
782  // How many?
783  send_unsigneds.push_back(map_pt->size());
784 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
785  std::stringstream junk;
786  junk << "Map size for master node " << map_pt->size() << n_bnd;
787  Flat_packed_unsigneds_string.push_back(junk.str());
788 #endif
789  // Loop over entries in map and add to send data
790  for (std::map<unsigned, unsigned>::iterator p = map_pt->begin();
791  p != map_pt->end();
792  p++)
793  {
794  send_unsigneds.push_back((*p).first);
795 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
796  std::stringstream junk;
798  "Key of map entry for master node");
799 #endif
800  send_unsigneds.push_back((*p).second);
801 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
803  "Value of map entry for master node");
804 #endif
805  }
806  }
807  }
808  else
809  {
810  // Not on any boundary
811  send_unsigneds.push_back(0);
812 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
814  "Master node is not on any boundary");
815 #endif
816  }
817 
818  // Is the Node algebraic? If so, send its ref values and
819  // an indication of its geometric objects if they are stored
820  // in the algebraic mesh
821  AlgebraicNode* alg_nod_pt = dynamic_cast<AlgebraicNode*>(master_nod_pt);
822  if (alg_nod_pt != 0)
823  {
824  // The external mesh should be algebraic
825  AlgebraicMesh* alg_mesh_pt = dynamic_cast<AlgebraicMesh*>(mesh_pt);
826 
827  // Get default node update function ID
828  unsigned update_id = alg_nod_pt->node_update_fct_id();
829  send_unsigneds.push_back(update_id);
830 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
831  Flat_packed_unsigneds_string.push_back("Master Alg Node update id");
832 #endif
833 
834  // Get reference values at default...
835  unsigned n_ref_val = alg_nod_pt->nref_value();
836  send_unsigneds.push_back(n_ref_val);
837 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
838  Flat_packed_unsigneds_string.push_back("Master Alg Node n ref values");
839 #endif
840  for (unsigned i_ref_val = 0; i_ref_val < n_ref_val; i_ref_val++)
841  {
842  send_doubles.push_back(alg_nod_pt->ref_value(i_ref_val));
843  }
844 
845  // Access geometric objects at default...
846  unsigned n_geom_obj = alg_nod_pt->ngeom_object();
847  send_unsigneds.push_back(n_geom_obj);
848 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
850  "Master Alg Node n geom objects");
851 #endif
852  for (unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
853  {
854  GeomObject* geom_obj_pt = alg_nod_pt->geom_object_pt(i_geom);
855  // Check this against the stored geometric objects in mesh
856  unsigned n_geom_list = alg_mesh_pt->ngeom_object_list_pt();
857  // Default found index to zero
858  unsigned found_geom_object = 0;
859  for (unsigned i_list = 0; i_list < n_geom_list; i_list++)
860  {
861  if (geom_obj_pt == alg_mesh_pt->geom_object_list_pt(i_list))
862  {
863  found_geom_object = i_list;
864  }
865  }
866  send_unsigneds.push_back(found_geom_object);
867 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
869  "Master node Found geom object");
870 #endif
871  }
872  } // end AlgebraicNode check
873 
874  // Is it a MacroElementNodeUpdateNode?
875  MacroElementNodeUpdateNode* macro_nod_pt =
876  dynamic_cast<MacroElementNodeUpdateNode*>(master_nod_pt);
877  if (macro_nod_pt != 0)
878  {
879  oomph_info << "Adding external haloed master node: " << master_nod_pt
880  << " at " << master_nod_pt->x(0) << ", "
881  << master_nod_pt->x(1) << " ]" << std::endl;
882  // Loop over current external haloed elements - has the element which
883  // controls the node update for this node been added yet?
884  GeneralisedElement* macro_node_update_el_pt =
885  macro_nod_pt->node_update_element_pt();
886 
887  // BENFLAG: Check that the node's macro element node update element
888  // actually contains the node
889  oomph_info << "Master node's macro update element:" << std::endl;
890  bool really_bad = true;
891  FiniteElement* mac_el_pt =
892  dynamic_cast<FiniteElement*>(macro_node_update_el_pt);
893  for (unsigned j = 0; j < mac_el_pt->nnode(); j++)
894  {
895  oomph_info << mac_el_pt->node_pt(j) << ": [ "
896  << mac_el_pt->node_pt(j)->x(0) << ", "
897  << mac_el_pt->node_pt(j)->x(1) << " ] " << std::endl;
898  if (mac_el_pt->node_pt(j) == master_nod_pt)
899  {
900  really_bad = false;
901  // oomph_info << "Found it!" << std::endl;
902  }
903  }
904  if (really_bad == true)
905  {
906  oomph_info << "This is REALLY BAD! The master node is not part of "
907  "its own update element..."
908  << std::endl;
909  }
910 
911  // BENFLAG: Search internal storage for node update element
912  Vector<GeneralisedElement*> int_haloed_el_pt(
913  mesh_pt->haloed_element_pt(iproc));
914  // unsigned n_int_haloed_el=int_haloed_el_pt.size();
916  std::find(int_haloed_el_pt.begin(),
917  int_haloed_el_pt.end(),
918  macro_node_update_el_pt);
919  if (it != int_haloed_el_pt.end())
920  {
921  // Found in internal haloed storage
922  unsigned int_haloed_el_index = it - int_haloed_el_pt.begin();
923  oomph_info << "Found internally at index " << int_haloed_el_index
924  << std::endl;
925  // BENFLAG: Check index corresponds to correct element
926  if ((mesh_pt->haloed_element_pt(iproc))[int_haloed_el_index] !=
927  macro_node_update_el_pt)
928  {
929  oomph_info << "Found wrong index!!!" << std::endl;
930  throw;
931  }
932  else
933  {
934  oomph_info << "index and proc are correct in internal storage."
935  << std::endl;
936  oomph_info << "i.e. "
937  << (mesh_pt->haloed_element_pt(
938  iproc))[int_haloed_el_index]
939  << "==" << macro_node_update_el_pt << std::endl;
940  }
941 
942 
943  // Say haloed element already exists
944  send_unsigneds.push_back(0);
945 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
947  "External haloed element already exists");
948 #endif
949  // Say found internally
950  send_unsigneds.push_back(1);
951 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
953  "Haloed element found internally");
954 #endif
955  // Say what the index is
956  send_unsigneds.push_back(int_haloed_el_index);
957 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
959  "Index of existing internal haloed element");
960 #endif
961  // BENFLAG:
962  FiniteElement* tmp_el_pt = dynamic_cast<FiniteElement*>(
963  (mesh_pt->haloed_element_pt(iproc))[int_haloed_el_index]);
964  oomph_info << "Internal haloed element (" << tmp_el_pt
965  << ") already exists..." << std::endl;
966  oomph_info << "on proc " << iproc << " at index "
967  << int_haloed_el_index << std::endl;
968  for (unsigned j = 0; j < tmp_el_pt->nnode(); j++)
969  {
970  oomph_info << tmp_el_pt->node_pt(j) << "=="
971  << dynamic_cast<FiniteElement*>(
972  (mesh_pt->haloed_element_pt(
973  iproc))[int_haloed_el_index])
974  ->node_pt(j)
975  << " at [ " << tmp_el_pt->node_pt(j)->x(0) << ", "
976  << tmp_el_pt->node_pt(j)->x(1) << " ]" << std::endl;
977  }
978 
979  // oomph_info << "now " << tmp_el_pt << "==" <<
980  // (mesh_pt->haloed_element_pt(iproc))[int_haloed_el_index] << "==" <<
981  // macro_node_update_el_pt << std::endl;
982 
983  // //BENFLAG: Add to external storage too
984  // unsigned n_ext_haloed_el=mesh_pt->
985  // nexternal_haloed_element(iproc);
986  // unsigned external_haloed_el_index;
987  // external_haloed_el_index=mesh_pt->
988  // add_external_haloed_element_pt(iproc,macro_node_update_el_pt);
989  //
990  // // If it was already added, say
991  // if (external_haloed_el_index!=n_ext_haloed_el)
992  // {
993  // oomph_info << "Element (" << tmp_el_pt << "==" <<
994  // macro_node_update_el_pt << "==" <<
995  // mesh_pt->external_haloed_element_pt(iproc,external_haloed_el_index)
996  // << ") also exists in external storage with proc " << iproc
997  // << " at index " << external_haloed_el_index << " of " <<
998  // n_ext_haloed_el << "..." << std::endl;
999  // // Say also exists in external storage
1000  // send_unsigneds.push_back(1234);
1001  //#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1002  // Flat_packed_unsigneds_string.push_back("Haloed element also
1003  // found externally");
1004  //#endif
1005  // // Say what the index is
1006  // send_unsigneds.push_back(external_haloed_el_index);
1007  //#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1008  // Flat_packed_unsigneds_string.push_back("Index of existing
1009  // internal haloed element");
1010  //#endif
1011  // oomph_info << "sent external_haloed_el_index = " <<
1012  // external_haloed_el_index << std::endl;
1013  //
1014  // }
1015  // else
1016  // {
1017  // oomph_info << "Element didn't exist in external storage
1018  // with proc " << iproc << "..." << std::endl;
1019  // // Say doesn't exists in external storage
1020  // send_unsigneds.push_back(0);
1021  //#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1022  // Flat_packed_unsigneds_string.push_back("Haloed element not
1023  // also found externally");
1024  //#endif
1025  // }
1026  }
1027  else
1028  {
1029  unsigned n_ext_haloed_el = mesh_pt->nexternal_haloed_element(iproc);
1030  unsigned external_haloed_el_index;
1031  external_haloed_el_index = mesh_pt->add_external_haloed_element_pt(
1032  iproc, macro_node_update_el_pt);
1033 
1034  // If it wasn't already added, we need to create a halo copy
1035  if (external_haloed_el_index == n_ext_haloed_el)
1036  {
1037  send_unsigneds.push_back(1);
1038 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1039  Flat_packed_unsigneds_string.push_back(
1040  "Master Node needs to be constructed");
1041 #endif
1042  // Cast to a finite elemnet
1043  FiniteElement* macro_node_update_finite_el_pt =
1044  dynamic_cast<FiniteElement*>(macro_node_update_el_pt);
1045 
1046  // We're using macro elements to update...
1047  MacroElementNodeUpdateMesh* macro_mesh_pt =
1048  dynamic_cast<MacroElementNodeUpdateMesh*>(mesh_pt);
1049  if (macro_mesh_pt != 0)
1050  {
1051  send_unsigneds.push_back(1);
1052 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1053  Flat_packed_unsigneds_string.push_back(
1054  "Mesh is macro element mesh");
1055 #endif
1056  // Need to send the macro element number in the mesh across
1057  MacroElement* macro_el_pt =
1058  macro_node_update_finite_el_pt->macro_elem_pt();
1059  unsigned macro_el_num = macro_el_pt->macro_element_number();
1060  send_unsigneds.push_back(macro_el_num);
1061 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1062  Flat_packed_unsigneds_string.push_back("Number of macro element");
1063 #endif
1064  // Also need to send
1065  // the lower left and upper right coordinates of the macro element
1066  QElementBase* q_el_pt =
1067  dynamic_cast<QElementBase*>(macro_node_update_el_pt);
1068  if (q_el_pt != 0)
1069  {
1070  // The macro element needs to be set first before
1071  // its lower left and upper right coordinates can be accessed
1072  // Now send the lower left and upper right coordinates
1073  unsigned el_dim = q_el_pt->dim();
1074  for (unsigned i_dim = 0; i_dim < el_dim; i_dim++)
1075  {
1076  send_doubles.push_back(q_el_pt->s_macro_ll(i_dim));
1077  send_doubles.push_back(q_el_pt->s_macro_ur(i_dim));
1078  }
1079  }
1080  else // Throw an error
1081  {
1082  std::ostringstream error_stream;
1083  error_stream << "You are using a MacroElement node update\n"
1084  << "in a case with non-QElements. This has not\n"
1085  << "yet been implemented.\n";
1086  throw OomphLibError(error_stream.str(),
1087  OOMPH_CURRENT_FUNCTION,
1088  OOMPH_EXCEPTION_LOCATION);
1089  }
1090  }
1091  else // Not using macro elements for node update... umm, we're
1092  // already inside a loop over macro elements, so this
1093  // should never get here... an error should be thrown I suppose
1094  {
1095  send_unsigneds.push_back(0);
1096 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1097  Flat_packed_unsigneds_string.push_back(
1098  "Mesh is not a macro element mesh");
1099 #endif
1100  }
1101 
1102  // If the element is p-refineable we need to send the p-order so
1103  // that the halo version can be constructed correctly
1104  PRefineableElement* p_refineable_el_pt =
1105  dynamic_cast<PRefineableElement*>(macro_node_update_finite_el_pt);
1106  if (p_refineable_el_pt != 0)
1107  {
1108  send_unsigneds.push_back(1);
1109 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1110  Flat_packed_unsigneds_string.push_back("Element is p-refineable");
1111 #endif
1112  // Send p-order of macro element node update element
1113  unsigned p_order = p_refineable_el_pt->p_order();
1114  send_unsigneds.push_back(p_order);
1115 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1116  Flat_packed_unsigneds_string.push_back("p-order of element");
1117 #endif
1118  }
1119  else
1120  {
1121  send_unsigneds.push_back(0);
1122 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1123  Flat_packed_unsigneds_string.push_back(
1124  "Element is not p-refineable");
1125 #endif
1126  }
1127 
1128  // This element needs to be fully functioning on the other
1129  // process, so send all the information required to create it
1130  unsigned n_node = macro_node_update_finite_el_pt->nnode();
1131  for (unsigned j = 0; j < n_node; j++)
1132  {
1133  Node* new_nod_pt = macro_node_update_finite_el_pt->node_pt(j);
1135  new_nod_pt,
1136  mesh_pt,
1137  n_cont_inter_values,
1138  send_unsigneds,
1139  send_doubles);
1140  }
1141  }
1142  else // The external haloed element already exists
1143  {
1144  // Say haloed element already exists
1145  send_unsigneds.push_back(0);
1146 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1147  Flat_packed_unsigneds_string.push_back(
1148  "External haloed element already exists");
1149 #endif
1150  // Say found externally
1151  send_unsigneds.push_back(0);
1152 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1153  Flat_packed_unsigneds_string.push_back(
1154  "Haloed element found externally");
1155 #endif
1156  send_unsigneds.push_back(external_haloed_el_index);
1157 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1158  Flat_packed_unsigneds_string.push_back(
1159  "Index of existing external haloed element");
1160 #endif
1161  // BENFLAG:
1162  oomph_info << "External haloed element already exists..."
1163  << std::endl;
1164  FiniteElement* tmp_el_pt =
1165  dynamic_cast<FiniteElement*>(mesh_pt->external_haloed_element_pt(
1166  iproc, external_haloed_el_index));
1167  oomph_info << "on proc " << iproc << " at index "
1168  << external_haloed_el_index << std::endl;
1169  for (unsigned j = 0; j < tmp_el_pt->nnode(); j++)
1170  {
1171  oomph_info << tmp_el_pt->node_pt(j) << " at [ "
1172  << tmp_el_pt->node_pt(j)->x(0) << ", "
1173  << tmp_el_pt->node_pt(j)->x(1) << " ]" << std::endl;
1174  }
1175  }
1176  } // End of case where not found internally
1177 
1178  } // end of MacroElementNodeUpdateNode check
1179 
1180  // Is it a SolidNode?
1181  if (solid_nod_pt != 0)
1182  {
1183  unsigned n_val = solid_nod_pt->variable_position_pt()->nvalue();
1184  for (unsigned i_val = 0; i_val < n_val; i_val++)
1185  {
1186  for (unsigned t = 0; t < n_prev; t++)
1187  {
1188  send_doubles.push_back(
1189  solid_nod_pt->variable_position_pt()->value(t, i_val));
1190  }
1191  }
1192  }
1193 
1194  // Finally copy info required for all node types
1195 
1196  // Halo copy needs to know all the history values
1197  unsigned n_val = master_nod_pt->nvalue();
1198  for (unsigned i_val = 0; i_val < n_val; i_val++)
1199  {
1200  for (unsigned t = 0; t < n_prev; t++)
1201  {
1202  send_doubles.push_back(master_nod_pt->value(t, i_val));
1203  }
1204  }
1205 
1206  // Now do positions
1207  for (unsigned idim = 0; idim < n_dim; idim++)
1208  {
1209  for (unsigned t = 0; t < n_prev; t++)
1210  {
1211  send_doubles.push_back(master_nod_pt->x(t, idim));
1212  }
1213  }
1214  }
1215 
1216 
1217  //=======start of add_external_halo_node_helper===========================
1218  /// Helper functiono to add external halo node that is not a master
1219  //========================================================================
1221  Mesh* const& mesh_pt,
1222  unsigned& loc_p,
1223  unsigned& node_index,
1224  FiniteElement* const& new_el_pt,
1225  int& n_cont_inter_values,
1226  unsigned& counter_for_recv_unsigneds,
1227  Vector<unsigned>& recv_unsigneds,
1228  unsigned& counter_for_recv_doubles,
1229  Vector<double>& recv_doubles)
1230  {
1231  // Given the node and the external mesh, and received information
1232  // about them from process loc_p, construct them on the current process
1233 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1234  oomph_info << "Rec:" << counter_for_recv_unsigneds
1235  << " Bool: New node needs to be constructed "
1236  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1237 #endif
1238  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
1239  {
1240  // Construct a new node based upon sent information
1242  loc_p,
1243  node_index,
1244  new_el_pt,
1245  mesh_pt,
1246  counter_for_recv_unsigneds,
1247  recv_unsigneds,
1248  counter_for_recv_doubles,
1249  recv_doubles);
1250  }
1251  else
1252  {
1253  // Need to check which storage we should copy this halo node from
1254 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1255  oomph_info << "Rec:" << counter_for_recv_unsigneds
1256  << " Existing external halo node was found externally (0) "
1257  "or internally (1): "
1258  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1259 #endif
1260  unsigned node_found_internally =
1261  recv_unsigneds[counter_for_recv_unsigneds++];
1262  if (node_found_internally)
1263  {
1264 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1265  oomph_info << "Rec:" << counter_for_recv_unsigneds
1266  << " index of existing (internal) halo master node "
1267  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1268 #endif
1269 
1270  // Copy node from received location
1271  new_nod_pt = mesh_pt->shared_node_pt(
1272  loc_p, recv_unsigneds[counter_for_recv_unsigneds++]);
1273 
1274  new_el_pt->node_pt(node_index) = new_nod_pt;
1275  }
1276  else
1277  {
1278 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1279  oomph_info << "Rec:" << counter_for_recv_unsigneds
1280  << " Index of existing external halo node "
1281  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1282 #endif
1283 
1284  // Copy node from received location
1285  new_nod_pt = mesh_pt->external_halo_node_pt(
1286  loc_p, recv_unsigneds[counter_for_recv_unsigneds++]);
1287 
1288  new_el_pt->node_pt(node_index) = new_nod_pt;
1289  }
1290  }
1291  }
1292 
1293 
1294  //========start of construct_new_external_halo_node_helper=================
1295  /// Helper function which constructs a new external halo node (on new
1296  /// element) with the required information sent from the haloed process
1297  //========================================================================
1299  Node*& new_nod_pt,
1300  unsigned& loc_p,
1301  unsigned& node_index,
1302  FiniteElement* const& new_el_pt,
1303  Mesh* const& mesh_pt,
1304  unsigned& counter_for_recv_unsigneds,
1305  Vector<unsigned>& recv_unsigneds,
1306  unsigned& counter_for_recv_doubles,
1307  Vector<double>& recv_doubles)
1308  {
1309  // The first entry indicates the number of values at this new Node
1310  // (which may be different across the same element e.g. Lagrange
1311  // multipliers)
1312 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1313  oomph_info << "Rec:" << counter_for_recv_unsigneds
1314  << " Number of values of external halo node "
1315  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1316 #endif
1317  unsigned n_val = recv_unsigneds[counter_for_recv_unsigneds++];
1318 
1319  // Null TimeStepper for now
1320  TimeStepper* time_stepper_pt = 0;
1321  // Default number of previous values to 1
1322  unsigned n_prev = 1;
1323 
1324  // Just take timestepper from a node
1325  // Let's use first node of first element since this must exist
1326  time_stepper_pt =
1327  mesh_pt->finite_element_pt(0)->node_pt(0)->time_stepper_pt();
1328 
1329  // If this node was on a boundary then it needs to
1330  // be on the same boundary here
1331 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1332  oomph_info << "Rec:" << counter_for_recv_unsigneds
1333  << " Is node on boundary? "
1334  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1335 #endif
1336  if (recv_unsigneds[counter_for_recv_unsigneds++] == 1)
1337  {
1338  // Construct a new boundary node
1339  if (time_stepper_pt != 0)
1340  {
1341  new_nod_pt =
1342  new_el_pt->construct_boundary_node(node_index, time_stepper_pt);
1343  }
1344  else
1345  {
1346  new_nod_pt = new_el_pt->construct_boundary_node(node_index);
1347  }
1348 
1349  // How many boundaries does the node live on?
1350 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1351  oomph_info << "Rec:" << counter_for_recv_unsigneds
1352  << " Number of boundaries the node is on: "
1353  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1354 #endif
1355  unsigned nb = recv_unsigneds[counter_for_recv_unsigneds++];
1356  for (unsigned i = 0; i < nb; i++)
1357  {
1358  // Boundary number
1359 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1360  oomph_info << "Rec:" << counter_for_recv_unsigneds
1361  << " Node is on boundary "
1362  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1363 #endif
1364  unsigned i_bnd = recv_unsigneds[counter_for_recv_unsigneds++];
1365  mesh_pt->add_boundary_node(i_bnd, new_nod_pt);
1366  }
1367 
1368  // Do we have additional values created by face elements?
1369 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1370  oomph_info << "Rec:" << counter_for_recv_unsigneds
1371  << " Number of additional values created by face element "
1372  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1373 #endif
1374  unsigned n_entry = recv_unsigneds[counter_for_recv_unsigneds++];
1375  if (n_entry > 0)
1376  {
1377  // Create storage, if it doesn't already exist, for the map
1378  // that will contain the position of the first entry of
1379  // this face element's additional values,
1380  BoundaryNodeBase* bnew_nod_pt =
1381  dynamic_cast<BoundaryNodeBase*>(new_nod_pt);
1382 #ifdef PARANOID
1383  if (bnew_nod_pt == 0)
1384  {
1385  throw OomphLibError("Failed to cast new node to boundary node\n",
1386  OOMPH_CURRENT_FUNCTION,
1387  OOMPH_EXCEPTION_LOCATION);
1388  }
1389 #endif
1391  0)
1392  {
1394  new std::map<unsigned, unsigned>;
1395  }
1396 
1397  // Get pointer to the map of indices associated with
1398  // additional values created by face elements
1399  std::map<unsigned, unsigned>* map_pt =
1401 
1402  // Loop over number of entries in map
1403  for (unsigned i = 0; i < n_entry; i++)
1404  {
1405  // Read out pairs...
1406 
1407 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1408  oomph_info << "Rec:" << counter_for_recv_unsigneds
1409  << " Key of map entry"
1410  << recv_unsigneds[counter_for_recv_unsigneds]
1411  << std::endl;
1412 #endif
1413  unsigned first = recv_unsigneds[counter_for_recv_unsigneds++];
1414 
1415 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1416  oomph_info << "Rec:" << counter_for_recv_unsigneds
1417  << " Value of map entry"
1418  << recv_unsigneds[counter_for_recv_unsigneds]
1419  << std::endl;
1420 #endif
1421  unsigned second = recv_unsigneds[counter_for_recv_unsigneds++];
1422 
1423  // ...and assign
1424  (*map_pt)[first] = second;
1425  }
1426  }
1427  }
1428  else
1429  {
1430  // Construct an ordinary (non-boundary) node
1431  if (time_stepper_pt != 0)
1432  {
1433  new_nod_pt = new_el_pt->construct_node(node_index, time_stepper_pt);
1434  }
1435  else
1436  {
1437  new_nod_pt = new_el_pt->construct_node(node_index);
1438  }
1439  }
1440 
1441  // Node constructed: add to external halo nodes
1442  mesh_pt->add_external_halo_node_pt(loc_p, new_nod_pt);
1443 
1444  // Is the new constructed node Algebraic?
1445  AlgebraicNode* new_alg_nod_pt = dynamic_cast<AlgebraicNode*>(new_nod_pt);
1446 
1447  // If it is algebraic, its node update functions will
1448  // not yet have been set up properly
1449  if (new_alg_nod_pt != 0)
1450  {
1451  // The AlgebraicMesh is the external mesh
1452  AlgebraicMesh* alg_mesh_pt = dynamic_cast<AlgebraicMesh*>(mesh_pt);
1453 
1454  /// The first entry of All_alg_nodal_info contains
1455  /// the default node update id
1456  /// e.g. for the quarter circle there are
1457  /// "Upper_left_box", "Lower right box" etc...
1458 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1459  oomph_info << "Rec:" << counter_for_recv_unsigneds
1460  << " Alg node update id "
1461  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1462 #endif
1463 
1464  unsigned update_id = recv_unsigneds[counter_for_recv_unsigneds++];
1465 
1466  Vector<double> ref_value;
1467 
1468  // The size of this vector is in the next entry
1469  // of All_alg_nodal_info
1470 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1471  oomph_info << "Rec:" << counter_for_recv_unsigneds
1472  << " Alg node # of ref values "
1473  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1474 #endif
1475  unsigned n_ref_val = recv_unsigneds[counter_for_recv_unsigneds++];
1476 
1477  // The reference values themselves are in
1478  // All_alg_ref_value
1479  ref_value.resize(n_ref_val);
1480  for (unsigned i_ref = 0; i_ref < n_ref_val; i_ref++)
1481  {
1482  ref_value[i_ref] = recv_doubles[counter_for_recv_doubles++];
1483  }
1484 
1485  Vector<GeomObject*> geom_object_pt;
1486  /// again we need the size of this vector as it varies
1487  /// between meshes; we also need some indication
1488  /// as to which geometric object should be used...
1489 
1490  // The size of this vector is in the next entry
1491  // of All_alg_nodal_info
1492 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1493  oomph_info << "Rec:" << counter_for_recv_unsigneds
1494  << " Alg node # of geom objects "
1495  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1496 #endif
1497  unsigned n_geom_obj = recv_unsigneds[counter_for_recv_unsigneds++];
1498 
1499  // The remaining indices are in the rest of
1500  // All_alg_nodal_info
1501  geom_object_pt.resize(n_geom_obj);
1502  for (unsigned i_geom = 0; i_geom < n_geom_obj; i_geom++)
1503  {
1504 #ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1505  oomph_info << "Rec:" << counter_for_recv_unsigneds
1506  << " Alg node: geom object index "
1507  << recv_unsigneds[counter_for_recv_unsigneds] << std::endl;
1508 #endif
1509  unsigned geom_index = recv_unsigneds[counter_for_recv_unsigneds++];
1510  // This index indicates which of the AlgebraicMesh's
1511  // stored geometric objects should be used
1512  // (0 is a null pointer; everything else should have
1513  // been filled in by the specific Mesh). If it
1514  // hasn't been filled in then the update_node_update
1515  // call should fix it
1516  geom_object_pt[i_geom] = alg_mesh_pt->geom_object_list_pt(geom_index);
1517  }
1518 
1519  /// For the received update_id, ref_value, geom_object
1520  /// call add_node_update_info
1521  new_alg_nod_pt->add_node_update_info(
1522  update_id, alg_mesh_pt, geom_object_pt, ref_value);
1523 
1524  /// Now call update_node_update
1525  alg_mesh_pt->update_node_update(new_alg_nod_pt);
1526  }
1527 
1528  // Is the node a MacroElementNodeUpdateNode?
1529  MacroElementNodeUpdateNode* macro_nod_pt =
1530  dynamic_cast<MacroElementNodeUpdateNode*>(new_nod_pt);
1531 
1532  if (macro_nod_pt != 0)
1533  {
1534  // Need to call set_node_update_info; this requires
1535  // a Vector<GeomObject*> (taken from the mesh)
1536  Vector<GeomObject*> geom_object_vector_pt;
1537 
1538  // Access the required geom objects from the
1539  // MacroElementNodeUpdateMesh
1540  MacroElementNodeUpdateMesh* macro_mesh_pt =
1541  dynamic_cast<MacroElementNodeUpdateMesh*>(mesh_pt);
1542  geom_object_vector_pt = macro_mesh_pt->geom_object_vector_pt();
1543 
1544  // Get local coordinate of node in new element
1545  Vector<double> s_in_macro_node_update_element;
1546  new_el_pt->local_coordinate_of_node(node_index,
1547  s_in_macro_node_update_element);
1548 
1549  // Set node update info for this node
1550  macro_nod_pt->set_node_update_info(
1551  new_el_pt, s_in_macro_node_update_element, geom_object_vector_pt);
1552  }
1553 
1554  // Is the new node a SolidNode?
1555  SolidNode* solid_nod_pt = dynamic_cast<SolidNode*>(new_nod_pt);
1556  if (solid_nod_pt != 0)
1557  {
1558  unsigned n_solid_val = solid_nod_pt->variable_position_pt()->nvalue();
1559  for (unsigned i_val = 0; i_val < n_solid_val; i_val++)
1560  {
1561  for (unsigned t = 0; t < n_prev; t++)
1562  {
1563  solid_nod_pt->variable_position_pt()->set_value(
1564  t, i_val, recv_doubles[counter_for_recv_doubles++]);
1565  }
1566  }
1567  }
1568 
1569  // If there are additional values, resize the node
1570  unsigned n_new_val = new_nod_pt->nvalue();
1571  if (n_val > n_new_val)
1572  {
1573  new_nod_pt->resize(n_val);
1574  }
1575 
1576  // Get copied history values
1577  // unsigned n_val=new_nod_pt->nvalue();
1578  for (unsigned i_val = 0; i_val < n_val; i_val++)
1579  {
1580  for (unsigned t = 0; t < n_prev; t++)
1581  {
1582  new_nod_pt->set_value(
1583  t, i_val, recv_doubles[counter_for_recv_doubles++]);
1584  }
1585  }
1586 
1587  // Get copied history values for positions
1588  unsigned n_dim = new_nod_pt->ndim();
1589  for (unsigned idim = 0; idim < n_dim; idim++)
1590  {
1591  for (unsigned t = 0; t < n_prev; t++)
1592  {
1593  // Copy to coordinate
1594  new_nod_pt->x(t, idim) = recv_doubles[counter_for_recv_doubles++];
1595  }
1596  }
1597  }
1598 
1599 
1600 #endif
1601 
1602  } // namespace Missing_masters_functions
1603 
1604 } // namespace oomph
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.
unsigned ngeom_object_list_pt()
Return number of geometric objects associated with AlgebraicMesh.
////////////////////////////////////////////////////////////////////
unsigned ngeom_object(const int &id)
Number of geometric objects involved in id-th update function.
unsigned nref_value(const int &id)
Number of reference values involved in id-th update function.
GeomObject * geom_object_pt(const unsigned &i)
Return pointer to i-th geometric object involved in default (usually first) update function.
int node_update_fct_id()
Default (usually first if there are multiple ones) node update fct id.
double ref_value(const unsigned &i)
Return i-th reference value involved in default (usually first) update function.
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
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:238
bool is_halo() const
Is this Data a halo?
Definition: nodes.h:532
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
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
Definition: nodes.h:293
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo node; negative if not a halo.
Definition: nodes.h:539
A general Finite Element class.
Definition: elements.h:1313
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
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Definition: elements.h:2509
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
MacroElement * macro_elem_pt()
Access function to pointer to macro element.
Definition: elements.h:1878
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
Definition: elements.h:2538
A Generalised Element class.
Definition: elements.h:73
/////////////////////////////////////////////////////////////////////
Definition: geom_objects.h:101
Class that contains data for hanging nodes.
Definition: nodes.h:742
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Definition: nodes.h:808
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:791
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:785
MacroElementNodeUpdateMeshes contain MacroElementNodeUpdateNodes which have their own node update fun...
Vector< GeomObject * > geom_object_vector_pt()
Access function to the vector of GeomObject.
////////////////////////////////////////////////////////////////////
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...
Base class for MacroElement s that are used during mesh refinement in domains with curvlinear and/or ...
Definition: macro_element.h:73
unsigned & macro_element_number()
Access function to the Macro_element_number.
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
unsigned nexternal_haloed_element()
Total number of external haloed elements in this Mesh.
Definition: mesh.h:2267
unsigned add_external_haloed_node_pt(const unsigned &p, Node *&nod_pt)
Add external haloed node whose halo (external) counterpart is held on processor p to the storage sche...
Definition: mesh.cc:9516
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
OomphCommunicator * communicator_pt() const
Read-only access fct to communicator (Null if mesh is not distributed, i.e. if we don't have mpi).
Definition: mesh.h:1600
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
Vector< GeneralisedElement * > haloed_element_pt(const unsigned &p)
Return vector of haloed elements in this Mesh whose haloing counterpart is held on processor p.
Definition: mesh.h:1779
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:827
unsigned add_external_haloed_element_pt(const unsigned &p, GeneralisedElement *&el_pt)
Add external haloed element whose non-halo counterpart is held on processor p to the storage scheme f...
Definition: mesh.cc:9475
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
void get_shared_node_pt(const unsigned &p, Vector< Node * > &shared_node_pt)
Get vector of pointers to shared nodes with processor p. Required for faster search in Missing_master...
Definition: mesh.h:2119
unsigned nexternal_haloed_node()
Total number of external haloed nodes in this Mesh.
Definition: mesh.h:2412
GeneralisedElement *& external_haloed_element_pt(const unsigned &p, const unsigned &e)
Access fct to the e-th external haloed element in this Mesh whose non-halo counterpart is held on pro...
Definition: mesh.h:2296
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
HangInfo *const & hanging_pt() const
Return pointer to hanging node data (this refers to the geometric hanging node status) (const version...
Definition: nodes.h:1228
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary,...
Definition: nodes.h:1373
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
void resize(const unsigned &n_value)
Resize the number of equations.
Definition: nodes.cc:2167
unsigned nposition_type() const
Number of coordinate types needed in the mapping between local and global coordinates.
Definition: nodes.h:1016
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1285
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation....
Definition: nodes.cc:2408
An OomphLibError object which should be thrown when an run-time error is encountered....
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
unsigned & p_order()
Access function to P_order.
/////////////////////////////////////////////////////////////////// /////////////////////////////////...
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
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
Definition: nodes.h:1686
unsigned nlagrangian_type() const
Number of types of Lagrangian coordinates used to interpolate the Lagrangian coordinates within the e...
Definition: nodes.h:1877
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1765
unsigned nlagrangian() const
Return number of lagrangian coordinates.
Definition: nodes.h:1870
////////////////////////////////////////////////////////////////////// //////////////////////////////...
Definition: timesteppers.h:231
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
Definition: timesteppers.h:601
bool Doc_full_stats
Boolean to indicate whether to output further info during setup_multi_domain_interaction() routines.
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 get_required_master_nodal_information_helper(int &iproc, Node *master_nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Helper function to get the required master nodal information from an external haloed master node so t...
void add_external_haloed_node_helper(int &iproc, Node *nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Helper to add external haloed node that is not a master.
bool Doc_stats
Boolean to indicate whether to output basic info during setup_multi_domain_interaction() routines.
void add_external_haloed_node_to_storage(int &iproc, Node *nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Helper function to add external haloed nodes, including any masters.
void recursively_add_masters_of_external_haloed_node(int &iproc, Node *nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Recursively add any master nodes (and their master nodes etc) of external nodes.
void get_required_nodal_information_helper(int &iproc, Node *nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Helper function to get the required nodal information from an external haloed node so that a fully-fu...
void add_external_haloed_master_node_helper(int &iproc, Node *master_nod_pt, Mesh *const &mesh_pt, int &n_cont_inter_values, Vector< unsigned > &send_unsigneds, Vector< double > &send_doubles)
Helper function to add external haloed node that is a master.
bool Doc_timings
Boolean to indicate whether to doc timings or not.
void construct_new_external_halo_node_helper(Node *&new_nod_pt, unsigned &loc_p, unsigned &node_index, FiniteElement *const &new_el_pt, 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 node (on new element) with the required informat...
Vector< std::string > Flat_packed_unsigneds_string
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...