TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
VDF_to_IJK.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 <VDF_to_IJK.h>
17#include <Schema_Comm_Vecteurs.h>
18#include <Schema_Comm.h>
19#include <communications.h>
20#include <Domaine_VF.h>
21#include <IJK_Field.h>
22#include <TRUSTTabs.h>
23#include <Array_tools.h>
24#include <Domaine.h>
25
26// search non empty lists in src and fills non_empty and dest with non empty lists
27static void pack_lists(const VECT(ArrOfInt) & src, ArrOfInt& non_empty, Static_Int_Lists& dest)
28{
29 // count non empty lists
30 int n = 0;
31 const int nmax = src.size();
32 for (int i = 0; i < nmax; i++)
33 if (src[i].size_array() > 0)
34 n++;
35
36 VECT(ArrOfInt) tmp(n);
37 non_empty.resize_array(n);
38
39 // copy non empty lists into tmp
40 int j = 0;
41 for (int i = 0; i < nmax; i++)
42 {
43 if (src[i].size_array() > 0)
44 {
45 non_empty[j] = i;
46 tmp[j] = src[i];
47 j++;
48 }
49 }
50
51 // Built dest
52 dest.set(tmp);
53}
54
55// Returns 0 if valeur < tab[1],
56// returns tab.size_array() - 1 if valeur >= tab[size_array()-1]
57// returns n if valeur >= tab[n] && valeur < tab[n+1]
58//
59static int bsearch_double(const ArrOfDouble& tab, double valeur)
60{
61 int i = 0;
62 int j = tab.size_array() - 1;
63 if (valeur >= tab[j])
64 return j;
65 while (j > i + 1)
66 {
67 // Le tableau doit etre trie
68 assert(j == tab.size_array() || tab[i] <= tab[j]);
69 const int milieu = (i + j) / 2;
70 const double val = tab[milieu];
71 if (val > valeur)
72 j = milieu;
73 else
74 i = milieu;
75 }
76 return i;
77}
78
79static const DoubleTab& get_items_coords(const Domaine_VF& domaine_vf, Domaine_IJK::Localisation loc, int& nb_items)
80{
81 switch(loc)
82 {
84 nb_items = domaine_vf.domaine().nb_elem();
85 return domaine_vf.xp();
87 nb_items = domaine_vf.domaine().nb_som();
88 return domaine_vf.domaine().les_sommets();
89 default:
90 nb_items = domaine_vf.nb_faces();
91 return domaine_vf.xv();
92 }
93}
94
95void VDF_to_IJK::initialize(const Domaine_VF& domaine_vf, const Domaine_IJK& splitting,
96 Domaine_IJK::Localisation localisation,
97 int direction_for_x,
98 int direction_for_y,
99 int direction_for_z)
100{
101 Cerr << "VDF_to_IJK::initialize localisation=" << (int)localisation << finl;
102 const int np = Process::nproc();
103 const int moi = Process::me();
104
105 const ArrOfDouble& all_coord_i = splitting.get_node_coordinates(0);
106 const ArrOfDouble& all_coord_j = splitting.get_node_coordinates(1);
107 const ArrOfDouble& all_coord_k = splitting.get_node_coordinates(2);
108
109 // For each direction, global position of the first element of each slice
110 VECT(ArrOfInt) slice_offsets(3);
111 VECT(ArrOfInt) slice_size(3);
112 // For each subdomain, on which mpi process is it ?
113 IntTab mapping;
114 splitting.get_processor_mapping(mapping);
115
116 for (int i = 0; i < 3; i++)
117 {
118 splitting.get_slice_offsets(i, slice_offsets[i]);
119 splitting.get_slice_size(i, localisation, slice_size[i]);
120 }
121 Schema_Comm sch;
122 ArrOfInt all_pe;
123
124
125 {
126 // Ajout pour limiter la porte de la variable !!!
127 int pe;
128 for (pe = 0; pe < np; pe++)
129 if (pe != moi)
130 all_pe.append_array(pe);
131 sch.set_send_recv_pe_list(all_pe, all_pe, 1 /* me to me */);
132 }
133
134 VECT(IntTab) all_data(np);
135 for (int pe = 0; pe < np; pe++)
136 {
137
138 all_data[pe].resize(0,2);
139 }
140
141 int srccomponent_for_direction[3];
142 srccomponent_for_direction[direction_for_x] = 0;
143 srccomponent_for_direction[direction_for_y] = 1;
144 srccomponent_for_direction[direction_for_z] = 2;
145
146 // Coordinates of geometric items:
147 int nb_items;
148 // attention, coords.dimension(0) inclut les mailles virtuelles pour le tableau des elements, c'est pas bon,
149 // il faut recuperer nb_elem reels...
150 const DoubleTab& coords = get_items_coords(domaine_vf, localisation, nb_items);
151 const IntVect& orientation = domaine_vf.orientation();
152
153 sch.begin_comm();
154 const double eps = Objet_U::precision_geom;
155 for (int item_index = 0; item_index < nb_items; item_index++)
156 {
157 if (localisation == Domaine_IJK::FACES_I && orientation[item_index] != srccomponent_for_direction[0])
158 continue;
159 else if (localisation == Domaine_IJK::FACES_J && orientation[item_index] != srccomponent_for_direction[1])
160 continue;
161 else if (localisation == Domaine_IJK::FACES_K && orientation[item_index] != srccomponent_for_direction[2])
162 continue;
163
164 double coord[3];
165 coord[direction_for_x] = coords(item_index, 0) + eps;
166 coord[direction_for_y] = coords(item_index, 1) + eps;
167 coord[direction_for_z] = coords(item_index, 2) + eps;
168
169 int ijk[3];
170 ijk[0] = bsearch_double(all_coord_i, coord[0]);
171 ijk[1] = bsearch_double(all_coord_j, coord[1]);
172 ijk[2] = bsearch_double(all_coord_k, coord[2]);
173
174
175 int slice_index[3]; // index of the subdomain than contains the current element, in each direction
176 int local_ijk_size[3]; // size of the ijk subdomain that contains the current element
177 int local_ijk_index[3]; // ijk index of the element in the subdomain
178 for (int i = 0; i < 3; i++)
179 {
180 // Wrap for periodic items:
181 if (ijk[i] >= splitting.get_nb_items_global(localisation, i))
182 ijk[i] = 0;
183 int idx = slice_offsets[i].size_array()-1;
184 while (slice_offsets[i][idx] > ijk[i])
185 idx--;
186 slice_index[i] = idx;
187 local_ijk_size[i] = slice_size[i][idx];
188 local_ijk_index[i] = ijk[i] - slice_offsets[i][idx];
189 }
190 // which pe has this element in the ijk mesh?
191 int pe = mapping(slice_index[0], slice_index[1], slice_index[2]);
192 // local index of this element in the ijk mesh (linear index computed without ghost cells)
193 int local_index = (local_ijk_index[2] * local_ijk_size[1] + local_ijk_index[1]) * local_ijk_size[0] + local_ijk_index[0];
194
195 all_data[pe].append_line(local_index, item_index);
196 }
197
198 VECT(ArrOfInt) to_send(np);
199 for (int pe = 0; pe < np; pe++)
200 {
201 tri_lexicographique_tableau(all_data[pe]);
202 const int n = all_data[pe].dimension(0);
203 if (n > 0)
204 Cerr << "VDF_to_IJK::initialize localisation=" << (int)localisation
205 << " found " << n << " items to send to processor " << pe << finl;
206 Sortie& buf = sch.send_buffer(pe);
207 for (int i = 0; i < n; i++)
208 {
209 buf << all_data[pe](i,0);
210 to_send[pe].append_array(all_data[pe](i,1));
211 }
212 }
214 VECT(ArrOfInt) to_recv(np);
215 for (int pe = 0; pe < np; pe++)
216 {
217
218 }
219
220 for (int pe = 0; pe < np; pe++)
221 {
222
223 Entree& buf = sch.recv_buffer(pe);
224 for (;;)
225 {
226 int val;
227 buf >> val;
228 if (buf.eof())
229 break;
230 to_recv[pe].append_array(val);
231 }
232 if (to_recv[pe].size_array() > 0)
233 Cerr << "VDF_to_IJK::initialize localisation=" << (int)localisation
234 << " found " << to_recv[pe].size_array() << " items to receive from processor " << pe << finl;
235 }
236 sch.end_comm();
237 pack_lists(to_send, pe_send_, pe_send_data_);
238 pack_lists(to_recv, pe_recv_, pe_recv_data_);
239
240 ijk_ni_ = splitting.get_nb_elem_local(0);
241 ijk_nj_ = splitting.get_nb_elem_local(1);
242}
DoubleTab_t & les_sommets()
Definition Domaine.h:113
int_t nb_elem() const
Definition Domaine.h:131
int_t nb_som() const
Renvoie le nombre de sommets du domaine.
Definition Domaine.h:121
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
int get_nb_elem_local(int direction) const
Returns the number of elements owned by this processor in the given direction.
void get_processor_mapping(IntTab &mapping) const
Fills an array containing the mapping of processors.
void get_slice_offsets(int direction, ArrOfInt &tab) const
Returns the indices of the first cell in requested direction of every slices in this direction.
int get_nb_items_global(Localisation loc, int direction) const
Returns the number of local items (on this processor) for the given localisation in the requested dir...
void get_slice_size(int direction, Localisation loc, ArrOfInt &tab) const
Returns the number of items of given location (elements, nodes, faces...) for all slices in the reque...
const ArrOfDouble & get_node_coordinates(int direction) const
Returns an array with the coordinates of all nodes in the mesh in requested direction.
Localisation
Localisation sub class.
Definition Domaine_IJK.h:53
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
virtual const IntVect & orientation() const
Definition Domaine_VF.h:646
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
static double precision_geom
Definition Objet_U.h:86
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
void echange_taille_et_messages() const
Cette methode lance l'echange de donnees entre tous les processeurs.
Sortie & send_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y entasser des donnees a envoyer.
void end_comm() const
Vide les buffers et libere les ressources: on a fini de lire les donnees recues dans les buffers.
Entree & recv_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y lire les donnees recues.
void begin_comm() const
Reserve les buffers de comm pour une nouvelle communication.
void set_send_recv_pe_list(const ArrOfInt &send_pe_list, const ArrOfInt &recv_pe_list, const int me_to_me=0)
Definit la liste des processeurs a qui on va envoyer et de qui on va recevoir des donnees.
Classe de base des flux de sortie.
Definition Sortie.h:52
void set(const ArrsOfInt_t &src)
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
ArrOfInt pe_send_
Definition VDF_to_IJK.h:43
ArrOfInt pe_recv_
Definition VDF_to_IJK.h:45
Static_Int_Lists pe_recv_data_
Definition VDF_to_IJK.h:52
void initialize(const Domaine_VF &domaine_vf, const Domaine_IJK &splitting, Domaine_IJK::Localisation localisation, int direction_for_x, int direction_for_y, int direction_for_z)
Static_Int_Lists pe_send_data_
Definition VDF_to_IJK.h:51