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