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-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// Templated missing masters functions
27
28// Include guards to prevent multiple inclusion of the header
29#ifndef OOMPH_MISSING_MASTERS_TEMPLATE_HEADER
30#define OOMPH_MISSING_MASTERS_TEMPLATE_HEADER
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>
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>
108 Mesh* const& mesh_pt,
109 unsigned& loc_p,
110 unsigned& node_index,
114 unsigned& counter_for_recv_doubles,
116 {
117 for (int i_cont = -1; i_cont < n_cont_inter_values; i_cont++)
118 {
119#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
121 << " Boolean to indicate that continuously interpolated "
122 "variable i_cont "
123 << i_cont << " is hanging "
125#endif
127 {
128#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
130 << " Number of master nodes "
132#endif
134
135 // Setup new HangInfo
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)
144 mesh_pt,
145 loc_p,
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
159 mesh_pt,
160 loc_p,
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>
180 Mesh* const& mesh_pt,
181 unsigned& loc_p,
185 unsigned& counter_for_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 "
195#endif
197 {
198 // Construct a new node based upon sent information
202 loc_p,
203 mesh_pt,
208 }
209 else
210 {
211 // Need to check which storage we should copy this halo node from
212#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
214 << " Existing external halo node was found externally (0) or "
215 "internally (1): "
217#endif
218 unsigned node_found_internally =
221 {
222#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
224 << " index of existing (internal) halo master node "
226#endif
227 // Copy node from received location
230 }
231 else
232 {
233#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
235 << " index of existing external halo master node "
237#endif
238 // Copy node from received location
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>
253 Node*& nod_pt,
254 unsigned& loc_p,
255 Mesh* const& mesh_pt,
258 unsigned& counter_for_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
265 << " ndim for external halo master node "
267#endif
269#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
271 << " nposition type for external halo master node "
273#endif
275#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
277 << " nvalue for external halo master node "
279#endif
281#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
283 << " non-halo processor ID for external halo master node "
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
296 << " nlagrdim for external halo master solid node "
298#endif
300#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
302 << " nlagrtype for external halo master solid node "
304#endif
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);
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
329 << " Boolean for algebraic boundary node "
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
335 {
336 // Create a new BoundaryNode (not attached to an element)
337 if (time_stepper_pt != 0)
338 {
340 time_stepper_pt, n_dim, n_position_type, n_value);
341 }
342 else
343 {
346 }
347
348 // How many boundaries does the algebraic master node live on?
349#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
351 << " Number of boundaries the algebraic master node is on: "
353#endif
355 for (unsigned i = 0; i < nb; i++)
356 {
357 // Boundary number
358#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
360 << " Algebraic master node is on boundary "
362#endif
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 "
374#endif
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,
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",
389 }
390#endif
392 ->index_of_first_value_assigned_by_face_element_pt() == 0)
393 {
395 ->index_of_first_value_assigned_by_face_element_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 =
403 ->index_of_first_value_assigned_by_face_element_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
412 << " Key of map entry for master node"
414 << std::endl;
415#endif
417
418#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
420 << " Value of map entry for master node"
422 << std::endl;
423#endif
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 {
437 new AlgebraicNode(time_stepper_pt, n_dim, n_position_type, n_value);
438 }
439 else
440 {
443 }
444 }
445
446 // Add this as an external halo node BEFORE considering node update!
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
454 << " algebraic node update id for master node "
456#endif
457 /// The first entry of All_unsigned_values is the default node update id
459
460 // Setup algebraic node update info for this new node
461 Vector<double> ref_value;
462
463#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
465 << " algebraic node number of ref values for master node "
467#endif
468 // The size of this vector is in the next entry
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 {
476 }
477
478 // Also require a Vector of geometric objects
479 Vector<GeomObject*> geom_object_pt;
480
481#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
483 << " algebraic node number of geom objects for master node "
485#endif
486
487 // The size of this vector is in the next entry of All_unsigned_values
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
497 << " algebraic node: " << i_geom << "-th out of "
498 << n_geom_obj << "-th geom index "
500#endif
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
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
526 << " Boolean for master algebraic node is boundary node "
528#endif
530 {
531 // Create a new BoundaryNode (not attached to an element)
532 if (time_stepper_pt != 0)
533 {
535 time_stepper_pt, n_dim, n_position_type, n_value);
536 }
537 else
538 {
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: "
550#endif
552 for (unsigned i = 0; i < nb; i++)
553 {
554 // Boundary number
555#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
557 << " Macro element master node is on boundary "
559#endif
562 }
563
564 // Do we have additional values created by face elements?
565#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
567 << " Number of additional values created by face element "
568 << "for macro element master node "
570#endif
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,
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",
585 }
586#endif
588 ->index_of_first_value_assigned_by_face_element_pt() == 0)
589 {
591 ->index_of_first_value_assigned_by_face_element_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 =
599 ->index_of_first_value_assigned_by_face_element_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
608 << " Key of map entry for macro element master node"
610 << std::endl;
611#endif
613
614#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
616 << " Value of map entry for macro element master node"
618 << std::endl;
619#endif
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 {
633 time_stepper_pt, n_dim, n_position_type, n_value);
634 }
635 else
636 {
639 }
640 }
641
642 // Add this as an external halo node
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
650#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
652 << " Bool: need new external halo element "
654#endif
656 {
657 // Issue warning about adding a macro element to the external storage
658 std::ostringstream 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().";
665 "Missing_masters_functions::construct_new_external_"
666 "halo_master_node_helper()",
668
670
671 // Add external halo element to this mesh
673
674 // Cast to finite element
676 dynamic_cast<FiniteElement*>(new_node_update_el_pt);
677
678 // Need number of interpolated values if Refineable
680 if (dynamic_cast<RefineableElement*>(new_node_update_f_el_pt) != 0)
681 {
684 ->ncont_interpolated_values();
685 }
686 else
687 {
689 }
690#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
692 << " Bool: we have a macro element mesh "
694#endif
695 // If we're using macro elements to update,
697 {
698 // Set the macro element
700 dynamic_cast<MacroElementNodeUpdateMesh*>(mesh_pt);
701
702#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
704 << " Number of macro element "
706#endif
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
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) =
722 q_el_pt->s_macro_ur(i_dim) =
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(),
735 }
736 }
737
738 // Check if haloed version was p-refineable
739#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
741 << " Element was p-refineable "
743#endif
744 unsigned el_was_p_refineable =
747 {
748 // Check created element is p-refineable
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: "
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_...()",
778 }
779 }
780
782 for (unsigned j = 0; j < n_node; j++)
783 {
784 Node* new_nod_pt = 0;
787 mesh_pt,
788 loc_p,
789 j,
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
811 << " Found internally? "
813#endif
814 unsigned found_internally =
816#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
818 << " Number of already existing external halo element "
820#endif
821 unsigned halo_element_index =
823 if (found_internally != 0)
824 {
825 new_node_update_f_el_pt = dynamic_cast<FiniteElement*>(
827 // BENFLAG:
828 oomph_info << "Existing node update element: "
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*>(
887 // BENFLAG:
888 oomph_info << "Existing node update element: "
890 << " (nnode_1d = " << new_node_update_f_el_pt->nnode_1d()
891 << ")" << std::endl;
892 oomph_info << "on proc " << loc_p << " at (external) index "
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;
907 dynamic_cast<MacroElementNodeUpdateMesh*>(mesh_pt);
908 geom_object_vector_pt = macro_mesh_pt->geom_object_vector_pt();
909
910 // Cast to MacroElementNodeUpdateNode
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;
937 for (unsigned j = 0; j < n_node; j++)
938 {
940 {
941 // std::cout << "Node " << macro_master_nod_pt << " found at index "
942 // << j << " in update element." << std::endl;
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()",
966 }
967 }
968 // std::cout << "after: " << local_node_index << std::endl;
969
973
974 macro_master_nod_pt->set_node_update_info(new_node_update_f_el_pt,
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
985 << " Bool master is a boundary (solid) node "
987#endif
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,
996 n_dim,
998 n_value);
999 }
1000 else
1001 {
1004 }
1005
1006
1007 // How many boundaries does the macro element master node live on?
1008#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1010 << " Number of boundaries the solid master node is on: "
1012#endif
1014 for (unsigned i = 0; i < nb; i++)
1015 {
1016 // Boundary number
1017#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1019 << " Solid master node is on boundary "
1021#endif
1024 }
1025
1026 // Do we have additional values created by face elements?
1027#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1029 << " Number of additional values created by face element "
1030 << "for solid master node "
1032#endif
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,
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",
1047 }
1048#endif
1050 ->index_of_first_value_assigned_by_face_element_pt() == 0)
1051 {
1053 ->index_of_first_value_assigned_by_face_element_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 =
1061 ->index_of_first_value_assigned_by_face_element_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
1070 << " Key of map entry for solid master node"
1072 << std::endl;
1073#endif
1075
1076#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1078 << " Value of map entry for solid master node"
1080 << std::endl;
1081#endif
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,
1099 n_value);
1100 }
1101 else
1102 {
1105 }
1106 }
1107
1108 // Add this as an external halo node
1110
1111 // Copy across particular info required for SolidNode
1112 // NOTE: Are there any problems with additional values for SolidNodes?
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(
1123 }
1124 }
1125 }
1126 else // Just an ordinary node!
1127 {
1128#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1130 << " Bool node is on boundary "
1132#endif
1133
1134 // If this node was on a boundary then it needs to
1135 // be on the same boundary here
1137 {
1138 // Construct a new boundary node
1139 if (time_stepper_pt != 0)
1140 {
1142 time_stepper_pt, n_dim, n_position_type, n_value);
1143 }
1144 else
1145 {
1148 }
1149
1150 // How many boundaries does the master node live on?
1151#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1153 << " Number of boundaries the master node is on: "
1155#endif
1157 for (unsigned i = 0; i < nb; i++)
1158 {
1159 // Boundary number
1160#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1162 << " Master node is on boundary "
1164#endif
1167 }
1168
1169
1170 // Do we have additional values created by face elements?
1171#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1173 << " Number of additional values created by face element "
1174 << "for master node "
1176#endif
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,
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",
1191 }
1192#endif
1194 ->index_of_first_value_assigned_by_face_element_pt() == 0)
1195 {
1197 ->index_of_first_value_assigned_by_face_element_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 =
1205 ->index_of_first_value_assigned_by_face_element_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
1214 << " Key of map entry for master node"
1216 << std::endl;
1217#endif
1219
1220#ifdef ANNOTATE_MISSING_MASTERS_COMMUNICATION
1222 << " Value of map entry for master node"
1224 << std::endl;
1225#endif
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 {
1239 new Node(time_stepper_pt, n_dim, n_position_type, n_value);
1240 }
1241 else
1242 {
1244 }
1245 }
1246
1247 // Add this as an external halo node
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(
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) =
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
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 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:1876
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
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
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
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:2222
A Generalised Element class.
Definition elements.h:73
void set_halo(const unsigned &non_halo_proc_ID)
Label the element as halo and specify processor that holds non-halo counterpart.
Definition elements.h:1138
unsigned ndim() const
Access function to # of Eulerian 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...
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
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:2259
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:2267
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition mesh.h:477
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:1748
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
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
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....
p-refineable version of RefineableElement
Base class for Qelements.
Definition Qelements.h:91
RefineableElements are FiniteElements that may be subdivided into children to provide a better local ...
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...
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.
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...