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