Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AlephVector.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* AlephVector.cc (C) 2000-2024 */
9/* */
10/*---------------------------------------------------------------------------*/
11/*---------------------------------------------------------------------------*/
12
13#include "arcane/aleph/AlephArcane.h"
14#include "arcane/IMesh.h"
15
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19namespace Arcane
20{
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25/******************************************************************************
26 *****************************************************************************/
27AlephVector::
28AlephVector(AlephKernel* kernel)
29: TraceAccessor(kernel->parallel()->traceMng())
30, m_kernel(kernel)
31, m_index(kernel->index())
32, m_bkp_num_values(0)
33{
34 ItacFunction(AlephVector);
35
36 if (kernel->isInitialized() == false) {
37 debug() << "\33[1;36m[AlephVector::AlephVector] New Aleph vector, but kernel is not initialized!\33[0m";
38 return;
39 }
40 m_ranks = kernel->solverRanks(m_index);
41 m_participating_in_solver = kernel->subParallelMng(m_index) != NULL;
42 debug() << "\33[1;36m[AlephVector::AlephVector] New Aleph Vector\33[0m";
43 if (m_kernel->subParallelMng(m_index) == NULL) {
44 debug() << "\33[1;36m[AlephVector::AlephVector] Not concerned with this one!\33[0m";
45 return;
46 }
47 debug() << "\33[1;36m[AlephVector::AlephVector] site size="
48 << m_kernel->subParallelMng(m_index)->commSize()
49 << " @"
50 << m_kernel->subParallelMng(m_index)->commRank() << "\33[0m";
51 m_implementation = m_kernel->factory()->GetVector(m_kernel, m_index);
52}
53
54/******************************************************************************
55 *****************************************************************************/
56AlephVector::
57~AlephVector()
58{
59 ItacFunction(AlephVector);
60 debug() << "\33[1;36m\t\t[~AlephVector]\33[0m";
61}
62
63/******************************************************************************
64 * 6bdba30a
65 *****************************************************************************/
66void AlephVector::
67create(void)
68{
69 ItacFunction(AlephVector);
70 if (m_kernel->isInitialized() == false)
71 return;
72 if (m_kernel->configured()) {
73 debug() << "\33[1;36m[AlephVector::create] kernel is configured, returning"
74 << "\33[0m";
75 return;
76 }
77 if (m_kernel->thereIsOthers() && !m_kernel->isAnOther()) {
78 m_kernel->world()->broadcast(UniqueArray<unsigned long>(1, 0x6bdba30al).view(), 0);
79 }
80 // Si nous sommes dans le cas parallèle, mais que nous ne sommes pas le solver, on se dimensionne localement
81 if (m_kernel->isParallel()) { // && (!m_participating_in_solver)){
82 debug() << "\33[1;36m[AlephVector::create] // resizing idx & val to " << m_kernel->topology()->nb_row_rank() << "\33[0m";
83 m_aleph_vector_buffer_idx.resize(m_kernel->topology()->nb_row_rank());
84 m_aleph_vector_buffer_val.resize(m_kernel->topology()->nb_row_rank());
85 }
86 if (m_participating_in_solver) {
87 debug() << "\33[1;36m[AlephVector::create] Participating in solver!"
88 << "\33[0m";
89 // Initialisation des buffers du solver
90 // On en profite pour initialiser en même temps les indices
91 for (Integer iCpu = 0, idx = 0; iCpu < m_kernel->size(); ++iCpu) {
92 debug() << "\33[1;36m[AlephVector::create] m_kernel->rank()=" << m_kernel->rank() << ", m_ranks[" << iCpu << "]=" << m_ranks[iCpu] << "\33[0m";
93 if (m_kernel->rank() != m_ranks[iCpu])
94 continue;
95 AlephInt nbRowsInCpu = m_kernel->topology()->gathered_nb_row(iCpu + 1) - m_kernel->topology()->gathered_nb_row(iCpu);
96 debug() << "\33[1;36m[AlephVector::create] Adding nb_row[iCpu=" << iCpu << "]=" << nbRowsInCpu << "\33[0m";
97 for (Integer i = 0; i < nbRowsInCpu; ++i, idx += 1) {
98 m_aleph_vector_buffer_idxs.add(m_kernel->ordering()->swap(m_kernel->topology()->gathered_nb_row(iCpu) + i));
99 //debug()<<"\33[1;36m[AlephVector::create] idxs:"<<idx<<"="<<m_aleph_vector_buffer_idxs[idx]<<"\33[0m";
100 }
101 }
102 m_aleph_vector_buffer_vals.resize(m_aleph_vector_buffer_idxs.size());
103 //m_aleph_vector_buffer_vals.fill(0.);
104 debug() << "\33[1;36m[AlephVector::create] resizing m_aleph_vector_buffer_[vals&idxs] to " << m_aleph_vector_buffer_vals.size() << "\33[0m";
105 }
106 else {
107 // En parallèle, sans solveur, on a pas besoin de vecteur
108 debug() << "\33[1;36m[AlephVector::create] not participating, returning before 'create_really'"
109 << "\33[0m";
110 return;
111 }
112 // Dans les autres cas, oui
113 create_really();
114 debug() << "\33[1;36m[AlephVector::create] done"
115 << "\33[0m";
116}
117
118// ****************************************************************************
119// * setLocalComponents - without global indices
120// ****************************************************************************
121void AlephVector::
122setLocalComponents(ConstArrayView<double> values)
123{
124 UniqueArray<AlephInt> indexs;
125 if (m_bkp_num_values == 0) {
126 AlephInt row_offset = 0;
127 if (m_kernel->isInitialized())
128 row_offset = m_kernel->topology()->part()[m_kernel->rank()];
129 debug() << "\33[1;36m[AlephVector::setLocalComponents] m_bkp_num_values==0"
130 << "\33[0m";
131 indexs.resize(0);
132 for (Integer i = 0, iMx = values.size(); i < iMx; i += 1)
133 indexs.add(i + row_offset);
134 }
135 setLocalComponents(values.size(), indexs, values);
136}
137
138// ****************************************************************************
139// * reSetLocalComponents
140// ****************************************************************************
141void AlephVector::
142reSetLocalComponents(AlephVector* from)
143{
144 const AlephInt row_offset = m_kernel->topology()->part()[m_kernel->rank()];
145 debug() << "\33[1;36m[AlephVector::reSetLocalComponents] Patching with row_offset=" << row_offset << "\33[0m";
146 for (Int32 i = 0, mx = from->m_bkp_num_values; i < mx; i += 1)
147 from->m_bkp_indexs[i] += row_offset;
148 setLocalComponents(from->m_bkp_num_values, from->m_bkp_indexs, from->m_bkp_values);
149}
150
151// ****************************************************************************
152// * setLocalComponents - standard
153// ****************************************************************************
154void AlephVector::
155setLocalComponents(Integer num_values,
156 ConstArrayView<AlephInt> indexs,
157 ConstArrayView<double> values)
158{
159 ItacFunction(AlephVector);
160 if (!m_kernel->isInitialized()) {
161 debug() << "\33[1;36m[AlephVector::setLocalComponents] Trying to setLocalComponents from an uninitialized kernel!\33[0m";
162 m_bkp_num_values = num_values;
163 debug() << "\33[1;36m[AlephVector::setLocalComponents] Backuping " << num_values << " values and indexes!\33[0m";
164 m_bkp_indexs.copy(indexs);
165 m_bkp_values.copy(values);
166 return;
167 }
168 if (!m_kernel->isParallel()) {
169 debug() << "\33[1;36m[AlephVector::setLocalComponents] implementation AlephVectorSet, num_values=" << num_values << "\33[0m";
170 m_implementation->AlephVectorSet(values.data(),
171 indexs.data(),
172 num_values);
173 return;
174 }
175 debug() << "\33[1;36m[AlephVector::setLocalComponents]\33[0m";
176 for (Integer i = 0, is = num_values; i < is; ++i) {
177 // Si je suis sur le site de résolution, je place les values dans les 'vals'
178 if (m_participating_in_solver && (m_kernel->rank() == m_ranks[m_kernel->rank()])) {
179 if (!m_kernel->isCellOrdering()) {
180 // Dans le cas multi-site de résolution, on shift avec la base m_aleph_vector_buffer_idxs[0]
181 //debug() << "\33[1;36m[AlephVector::setLocalComponents] multi-site de résolution"<<", indexs["<<i<<"]="<<indexs[i]<<", m_aleph_vector_buffer_idxs[0]="<<m_aleph_vector_buffer_idxs[0]<<"\33[0m";
182 m_aleph_vector_buffer_vals[indexs[i] - m_aleph_vector_buffer_idxs[0]] = values[i];
183 }
184 else {
185 // Dans le cas de l'ordering, on est mono site, on veut pas de shift
186 m_aleph_vector_buffer_vals[indexs[i]] = values[i];
187 }
188 }
189 else {
190 m_aleph_vector_buffer_idx[i] = m_kernel->ordering()->swap(indexs[i]);
191 m_aleph_vector_buffer_val[i] = values[i];
192 }
193 }
194}
195
196/******************************************************************************
197 *****************************************************************************/
198void AlephVector::
199create_really(void)
200{
201 ItacFunction(AlephVector);
202 debug() << "\33[1;36m[AlephVector::create_really] New UNconfigured vector"
203 << "\33[0m";
204 m_implementation->AlephVectorCreate();
205}
206
207/******************************************************************************
208 * ec7a979f
209 *****************************************************************************/
210void AlephVector::
211assemble(void)
212{
213 ItacFunction(AlephVector);
214
215 if (!m_kernel->isInitialized()) {
216 debug() << "\33[1;36m[AlephVector::AlephVector] Trying to assemble a vector from an uninitialized kernel!\33[0m";
217 return;
218 }
219 if (m_kernel->thereIsOthers() && !m_kernel->isAnOther())
220 m_kernel->world()->broadcast(UniqueArray<unsigned long>(1, 0xec7a979fl).view(), 0);
221 // Si on est en mode seq, on a rien à faire
222 if (!m_kernel->isParallel())
223 return;
224 if (m_participating_in_solver) {
225 // Si je suis le solveur, je recv le reste des vecteurs provenant d'autres coeurs
226 debug() << "\33[1;36m[AlephVector::assemble] m_participating_in_solver"
227 << "\33[0m";
228 AlephInt nbRows = 0;
229 for (Integer iCpu = 0, iRows = 0; iCpu < m_kernel->size(); ++iCpu, iRows += nbRows) {
230 nbRows = 0;
231 if (m_kernel->rank() != m_ranks[iCpu])
232 continue;
233 // Dans les autres cas, il faut décaler l'offset iRows
234 nbRows = m_kernel->topology()->gathered_nb_row(iCpu + 1) - m_kernel->topology()->gathered_nb_row(iCpu);
235 if (iCpu == m_kernel->rank())
236 continue;
237 debug() << "\33[1;36m[AlephVector::assemble]"
238 << " recv " << m_kernel->rank()
239 << " <= " << iCpu
240 << ", offset=" << iRows
241 << " for " << nbRows << "\33[0m";
242 m_parallel_requests.add(m_kernel->world()->recv(m_aleph_vector_buffer_vals.subView(iRows, nbRows),
243 iCpu,
244 false));
245 }
246 }
247 if (m_kernel->rank() != m_ranks[m_kernel->rank()] && !m_kernel->isAnOther()) { // Dans ce cas, il faut envoyer ses données
248 debug() << "\33[1;36m[AlephVector::assemble]"
249 << " send " << m_kernel->rank()
250 << " => " << m_ranks[m_kernel->rank()]
251 << " for " << m_aleph_vector_buffer_val.size() << "\33[0m";
252 m_parallel_requests.add(m_kernel->world()->send(m_aleph_vector_buffer_val,
253 m_ranks[m_kernel->rank()],
254 false));
255 }
256 debug() << "\33[1;36m[AlephVector::assemble] done"
257 << "\33[0m";
258}
259
260/******************************************************************************
261 *****************************************************************************/
262void AlephVector::
263assemble_waitAndFill(void)
264{
265 ItacFunction(AlephVector);
266 if (!m_kernel->isParallel())
267 return;
268 debug() << "\33[1;36m[AlephVector::assemble_waitAndFill] wait for "
269 << m_parallel_requests.size()
270 << " Requests for solver "
271 << m_index << "\33[0m";
272 m_kernel->world()->waitAllRequests(m_parallel_requests);
273 m_parallel_requests.clear();
274 if (!m_participating_in_solver) {
275 debug() << "\33[1;36m[AlephVector::assemble_waitAndFill] Not participating in solver, returning"
276 << "\33[0m";
277 return;
278 }
279 debug() << "\33[1;36m[AlephVector::assemble_waitAndFill] " << m_index << " locfill"
280 << "\33[0m";
281 m_implementation->AlephVectorSet(m_aleph_vector_buffer_vals.data(),
282 m_aleph_vector_buffer_idxs.data(),
283 m_aleph_vector_buffer_idxs.size());
284 debug() << "\33[1;36m[AlephVector::assemble_waitAndFill] " << m_index << " VECTOR ASSEMBLE"
285 << "\33[0m";
286 m_implementation->AlephVectorAssemble();
287 debug() << "\33[1;36m[AlephVector::assemble_waitAndFill] done"
288 << "\33[0m";
289}
290
291/******************************************************************************
292 *****************************************************************************/
293void AlephVector::
294reassemble(void)
295{
296 ItacFunction(AlephVector);
297 if (!m_kernel->isParallel())
298 return;
299 // Cas où le site de résolution n'est pas le notre, on pousse les données dans le 'val'
300 if (m_kernel->rank() != m_ranks[m_kernel->rank()] && !m_kernel->isAnOther()) {
301 debug() << "\33[1;36m[AlephVector::REassemble] "
302 << m_kernel->rank()
303 << "<="
304 << m_ranks[m_kernel->rank()] << "\33[0m";
305 m_parallel_reassemble_requests.add(m_kernel->world()->recv(m_aleph_vector_buffer_val, m_ranks[m_kernel->rank()], false));
306 }
307 // Si je suis un site de résolution, je résupère les résultats
308 if (m_participating_in_solver) {
309 // Je récupère déjà les valeurs depuis le vecteur
310 debug() << "\33[1;36m[AlephVector::REassemble] J'ai participé, je récupère les résultats depuis l'implémentation"
311 << "\33[0m";
312 m_implementation->AlephVectorGet(m_aleph_vector_buffer_vals.unguardedBasePointer(),
313 m_aleph_vector_buffer_idxs.unguardedBasePointer(),
314 m_aleph_vector_buffer_idxs.size());
315 // Puis je send les parties des vecteurs aux autres sites
316 AlephInt nbRows = 0;
317 for (Integer iCpu = 0, iRows = 0; iCpu < m_kernel->size(); ++iCpu, iRows += nbRows) {
318 nbRows = 0;
319 if (m_kernel->rank() != m_ranks[iCpu])
320 continue;
321 nbRows = m_kernel->topology()->gathered_nb_row(iCpu + 1) - m_kernel->topology()->gathered_nb_row(iCpu);
322 if (iCpu == m_kernel->rank())
323 continue;
324 debug() << "\33[1;36m[AlephVector::REassemble] send "
325 << m_kernel->rank()
326 << " => " << iCpu
327 << ", offset=" << iRows
328 << " for " << nbRows << "\33[0m";
329 m_parallel_reassemble_requests.add(m_kernel->world()->send(m_aleph_vector_buffer_vals.view().subView(iRows, nbRows), iCpu, false));
330 }
331 }
332}
333
334/******************************************************************************
335 *****************************************************************************/
336void AlephVector::
337reassemble_waitAndFill(void)
338{
339 ItacFunction(AlephVector);
340 if (!m_kernel->isParallel())
341 return;
342 m_kernel->world()->waitAllRequests(m_parallel_reassemble_requests);
343 m_parallel_reassemble_requests.clear();
344 debug() << "\33[1;36m[AlephVector::REassemble_waitAndFill]"
345 << "\33[0m";
346}
347
348/******************************************************************************
349 *****************************************************************************/
350void AlephVector::
351getLocalComponents(Integer vector_size,
352 ConstArrayView<AlephInt> global_indice,
353 ArrayView<double> vector_values)
354{
355 ItacFunction(AlephVector);
356 debug() << "\33[1;36m[AlephVector::getLocalComponents] vector_size=" << vector_size << "\33[0m";
357 if (!m_kernel->isParallel()) {
358 // En séquentiel, on va piocher les résultats directement
359 m_implementation->AlephVectorGet(vector_values.data(),
360 global_indice.data(),
361 vector_size);
362 debug() << "\33[1;36m[AlephVector::getLocalComponents] seq done!\33[0m";
363 return;
364 }
365 // En parallèle, on va piocher dans nos buffers qui devraient être à jour
366 for (int i = 0; i < vector_size; ++i) {
367 // Dans le cas où nous sommes sur notre site de résolution, les 'vals' sont nos cibles
368 if (m_participating_in_solver && (m_kernel->rank() == m_ranks[m_kernel->rank()])) {
369 if (!m_kernel->isCellOrdering()) {
370 vector_values[i] = m_aleph_vector_buffer_vals[global_indice[i] - m_aleph_vector_buffer_idxs[0]];
371 }
372 else {
373 vector_values[i] = m_aleph_vector_buffer_vals[global_indice[i]];
374 }
375 }
376 // Dans le cas où le site de résolution est distant, on vient dans les 'val'
377 else {
378 vector_values[i] = m_aleph_vector_buffer_val[i];
379 }
380 }
381 debug() << "\33[1;36m[AlephVector::getLocalComponents] parallel done!\33[0m";
382}
383
384// ****************************************************************************
385// * getLocalComponents
386// ****************************************************************************
387void AlephVector::
388getLocalComponents(Array<double>& vector_values)
389{
390 const Integer vector_size = m_kernel->topology()->nb_row_rank();
391 vector_values.resize(vector_size);
392 m_aleph_vector_buffer_idx.resize(vector_size);
393 ItacFunction(AlephVector);
394 debug() << "\33[1;36m[getLocalComponents(vector_values)] vector_size=" << vector_size << "\33[0m";
395 if (!m_kernel->isParallel()) {
396 for (Integer i = 0; i < vector_size; i += 1) {
397 m_aleph_vector_buffer_idx[i] = i;
398 //debug()<<"\33[1;36mm_aleph_vector_buffer_idx["<<i<<"]="<<m_aleph_vector_buffer_idx[i]<<"\33[0m";
399 }
400 ARCANE_CHECK_POINTER(m_implementation);
401 // En séquentiel, on va piocher les résultats directement
402 m_implementation->AlephVectorGet(vector_values.data(), m_aleph_vector_buffer_idx.data(), vector_size);
403 debug() << "\33[1;36m[getLocalComponents(vector_values)] seq done!\33[0m";
404 return;
405 }
406 // En parallèle, on va piocher dans nos buffers qui devraient être à jour
407 for (int i = 0; i < vector_size; ++i) {
408 // Dans le cas où nous sommes sur notre site de résolution, les 'vals' sont nos cibles
409 if (m_participating_in_solver && (m_kernel->rank() == m_ranks[m_kernel->rank()])) {
410 vector_values[i] = m_aleph_vector_buffer_vals[i];
411 }
412 else { // Dans le cas où le site de résolution est distant, on vient dans les 'val'
413 vector_values[i] = m_aleph_vector_buffer_val[i];
414 }
415 }
416 debug() << "\33[1;36m[getLocalComponents(vector_values)] parallel done!\33[0m";
417}
418
419/******************************************************************************
420 *****************************************************************************/
421void AlephVector::
422startFilling()
423{
424 ItacFunction(AlephVector);
425 debug() << "\33[1;36m[AlephVector::startFilling]"
426 << "\33[0m";
427}
428
429/******************************************************************************
430 *****************************************************************************/
431void AlephVector::
432writeToFile(const String base_file_name)
433{
434 ItacFunction(AlephVector);
435 debug() << "\33[1;36m[AlephVector::writeToFile]"
436 << "\33[0m";
437 m_implementation->writeToFile(base_file_name);
438}
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442
443} // End namespace Arcane
444
445/*---------------------------------------------------------------------------*/
446/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
int AlephInt
Type par défaut pour indexer les lignes et les colonnes des matrices et vecteurs.
Definition AlephGlobal.h:50
Int32 Integer
Type représentant un entier.