TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
PE_Groups.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Comm_Group.h>
17#include <PE_Groups.h>
18#include <TRUST_Ref.h>
19
20// The following three variables save the group stack
21// (see Comm_Group::enter_group(), Comm_Group::current_group(), Comm_Group::exit_group())
22// The top of the stack is always groupe_TRUST(), provided to initialize().
23// groups[0] points to groupe_trio.
24static OBS_PTR(Comm_Group) groups[100];
25static int ngroups = 0;
26static int max_ngroups = 100;
27const Comm_Group * PE_Groups::current_group_ = 0;
28// node group is an isolated variable from all the other groups as it is only used for IO purposes
29// and might be used throughout the code together with other groups
30static OBS_PTR(Comm_Group) node_group;
31static OBS_PTR(Comm_Group) node_master;
32// For the user that defines his own group ! not done in the main, see the My_Comm_Group class !
33static OBS_PTR(Comm_Group) user_defined_group;
34
35int PE_Groups::check_current_group()
36{
37 assert(ngroups > 0);
38 assert(current_group_ == &(groups[ngroups-1].valeur()));
39 return 1;
40}
41
42/*! @brief Creates a new processor group (can be called anywhere in the code).
43 *
44 * Must be called simultaneously on all processors of current_group() with the same
45 * liste_pe array. liste_pe is the list of ranks within the current group of processors
46 * to include in the new group. The first in the list will be the group master. The list
47 * must not contain duplicates and must include at least one processor.
48 * This method types and initializes the group object.
49 * enter_group() and exit_group() must then be called (as many times as desired).
50 *
51 * @param liste_pe List of PE ranks within current_group().
52 * @param group The group object to initialize.
53 * @param force_Comm_Group_NoParallel If non-zero, force a non-parallel group when possible.
54 */
55void PE_Groups::create_group(const ArrOfInt& liste_pe, OWN_PTR(Comm_Group) & group, int force_Comm_Group_NoParallel)
56{
57 if (liste_pe.size_array()==1 && force_Comm_Group_NoParallel)
58 {
59 // Create a non-parallel group if possible and if required
60 group.typer("Comm_Group_NoParallel");
61 }
62 else
63 {
64 // Create a group of the same type as groupe_TRUST
65 group.typer(groups[0]->que_suis_je());
66 }
67 group->init_group(liste_pe);
68}
69
70/*! @brief Initializes a new processor group that is already instantiated (can be called anywhere in the code).
71 *
72 * Must be called simultaneously on all processors of current_group() with the same
73 * liste_pe array. liste_pe is the list of ranks within the current group of processors
74 * to include in the new group. The first in the list will be the group master. The list
75 * must not contain duplicates and must include at least one processor.
76 * enter_group() and exit_group() must then be called (as many times as desired).
77 *
78 * @param liste_pe List of PE ranks within current_group().
79 * @param group The already-instantiated group object to initialize.
80 */
81void PE_Groups::init_group(const ArrOfInt& liste_pe, OWN_PTR(Comm_Group) & group)
82{
83 assert(group);
84 group->init_group(liste_pe);
85}
86
87/*! @brief If the local processor belongs to the group, the current group for this processor becomes "group" and returns 1; otherwise returns 0.
88 *
89 * A reference to the current group is saved and will be restored when exit_group() is called.
90 * This method must be called simultaneously on all processors of "group".
91 * Each enter_group() must be matched by a corresponding exit_group().
92 * However, it is allowed to enter the same group multiple times in a row, or to enter a
93 * larger group than the current one.
94 * Example: group1 and group2 form a partition of groupe_TRUST().
95 *
96 * int sync_point(int x)
97 * {
98 * PE_Groups::enter_group(groupe_TRUST());
99 * int i = mp_sum(x);
100 * PE_Groups::exit_group();
101 * return i;
102 * }
103 * if (PE_Groups::enter_group(group1)) {
104 * s1 = mp_sum(x); // Sum over group 1
105 * // Sync point with the other group:
106 * s_all = sync_point(x);
107 * } else if (PE_Groups::enter_group(group2)) {
108 * s2 = mp_sum(x);
109 * // Sync point with the other group:
110 * s_all = sync_point(x);
111 * } else {
112 * Cerr << "Error: processor " << me() << " is not within a subgroup.";
113 * exit();
114 * }
115 * PE_Groups::exit_group(); // Exit the subgroup
116 *
117 * @param group The group to enter.
118 * @return 1 if the local processor is in the group, 0 otherwise.
119 */
121{
122 assert(&group != &current_group());
123 if (ngroups >= max_ngroups-1)
124 {
125 Cerr << "Comm_Group::enter_group : fatal, too many groups" << finl;
127 }
128 int my_rank_in_group = rank_translate(current_group().rank(), current_group(), group);
129 if (my_rank_in_group >= 0)
130 {
131 // Save the pointer to the current group and switch current_group():
132 groups[ngroups] = group;
133 current_group_ = &group;
134 ngroups++;
135 // Note: current_group() has changed!
136
137 // Verify that all processors of the new group are present:
140
141 return 1;
142 }
143 else
144 {
145 return 0;
146 }
147}
148
149/*! @brief Returns to the group that was active before the last successful enter_group() call (which returned 1).
150 *
151 * This method must be called simultaneously on all processors of the current current_group() just before exit_group().
152 *
153 */
155{
158
159 if (ngroups <= 1)
160 {
161 Cerr << "Comm_Group::exit_group() error : trying to exit from TRUST main group." << finl;
163 }
164 ngroups--;
165 current_group_ = &(groups[ngroups-1].valeur());
166}
167
168/*! @brief Computes the rank in the current group of the processor with rank "rank" in "group".
169 *
170 * Requires 0 <= rank < group.nproc().
171 * Returns -1 if the processor is not in the current group.
172 *
173 * @param rank Rank in the source group.
174 * @param group The source group.
175 * @param dest_group The destination group.
176 * @return Rank in the destination group, or -1 if not present.
177 */
178int PE_Groups::rank_translate(int rank, const Comm_Group& group,
179 const Comm_Group& dest_group)
180{
181 const int world_rank = group.world_ranks_[rank];
182 const int local_rank = dest_group.local_ranks_[world_rank];
183 return local_rank;
184}
185
186/*! @brief Returns a reference to the group containing all TRUST processors.
187 *
188 * @return Reference to the global TRUST Comm_Group.
189 */
191{
192 assert(ngroups > 0); // Initialized ?
193 return groups[0].valeur();
194}
195
196/*! @brief Returns a reference to the node-level communicator group.
197 *
198 * @return Reference to the node Comm_Group.
199 */
201{
202 assert(node_group);
203 return node_group.valeur();
204}
205
206/*! @brief Returns the group containing the master of my node.
207 *
208 * @return Reference to the node-master Comm_Group.
209 */
211{
212 assert(node_master);
213 return node_master.valeur();
214}
215
216/*! @brief Returns a reference to the user-defined group.
217 *
218 * @return Reference to the user-defined Comm_Group.
219 */
221{
222 assert(user_defined_group);
223 return user_defined_group.valeur();
224}
225
226/*! @brief Method to call at the beginning of execution (MAIN.cpp). Initializes current_group() with groupe_trio_u.
227 *
228 * @param groupe_trio_u The main TRUST communicator group to initialize with.
229 */
230void PE_Groups::initialize(const Comm_Group& groupe_trio_u)
231{
232 assert(ngroups == 0);
233 ngroups = 1;
234 groups[0] = groupe_trio_u;
235 current_group_ = &groupe_trio_u;
236}
237
238/*! @brief Method to call after the initialization of trio_u_world and TRUST's statistical counters.
239 *
240 * @param ngrp The node-level communicator group.
241 */
243{
244 assert(!node_group);
245 node_group = ngrp;
246}
247
249{
250 assert(!user_defined_group);
251 user_defined_group = ngrp;
252}
253
255{
256 return bool(user_defined_group);
257}
258
259/*! @brief Method to call after the initialization of trio_u_world, node_group, and TRUST's statistical counters.
260 *
261 * @param ngrp The node-master communicator group.
262 */
264{
265 assert(!node_master);
266 node_master = ngrp;
267}
268
269/*! @brief Method to call at the end of execution, once back in groupe_TRUST() and just before destroying the main Comm_Group.
270 *
271 */
273{
274 assert(ngroups == 1);
275 groups[0].reset();
276 ngroups = 0;
277 current_group_ = 0;
278 node_group.reset();
279 node_master.reset();
280 user_defined_group.reset();
281}
282
284{
285 return ngroups ;
286}
: This class describes a group of processors on which
Definition Comm_Group.h:37
static int check_enabled()
Definition Comm_Group.h:154
virtual void barrier(int tag) const =0
virtual void init_group(const ArrOfInt &pe_list)
This function must be called simultaneously by all PEs of the current_group with the same parameters.
static void initialize_user_defined_group(const Comm_Group &ngrp)
static int enter_group(const Comm_Group &group)
If the local processor belongs to the group, the current group for this processor becomes "group" and...
static void create_group(const ArrOfInt &liste_pe, OWN_PTR(Comm_Group) &group, int force_Comm_Group_NoParallel=0)
Creates a new processor group (can be called anywhere in the code).
Definition PE_Groups.cpp:55
static void init_group(const ArrOfInt &liste_pe, OWN_PTR(Comm_Group) &group)
Initializes a new processor group that is already instantiated (can be called anywhere in the code).
Definition PE_Groups.cpp:81
static void initialize_node_master(const Comm_Group &ngrp)
Method to call after the initialization of trio_u_world, node_group, and TRUST's statistical counters...
static const int & get_nb_groups()
static void finalize()
Method to call at the end of execution, once back in groupe_TRUST() and just before destroying the ma...
static const Comm_Group & get_node_master()
Returns the group containing the master of my node.
static void initialize(const Comm_Group &groupe_trio_u)
Method to call at the beginning of execution (MAIN.cpp). Initializes current_group() with groupe_trio...
static void initialize_node(const Comm_Group &ngrp)
Method to call after the initialization of trio_u_world and TRUST's statistical counters.
static const Comm_Group & get_user_defined_group()
Returns a reference to the user-defined group.
static const Comm_Group & get_node_group()
Returns a reference to the node-level communicator group.
static bool has_user_defined_group()
static const Comm_Group & current_group()
Returns a reference to the current active processor group.
Definition PE_Groups.h:64
static int rank_translate(int rank, const Comm_Group &group, const Comm_Group &dest_group=current_group())
Computes the rank in the current group of the processor with rank "rank" in "group".
static const Comm_Group & groupe_TRUST()
Returns a reference to the group containing all TRUST processors.
static void exit_group()
Returns to the group that was active before the last successful enter_group() call (which returned 1)...
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
_SIZE_ size_array() const