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