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