Welcome to the NetCologne GmbH open source mirroring service!

This machine mirrors various open-source projects. 20 Gbit/s uplink.

If there are any issues or you want another project mirrored, please contact mirror-service -=AT=- netcologne DOT de !

GetFEM: src/getfem_enumeration_dof_para.cc Source File
GetFEM  5.5
getfem_enumeration_dof_para.cc
1 /*===========================================================================
2 
3  Copyright (C) 2012-2026 Yves Renard, Julien Pommier.
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 #include <queue>
21 #include <queue>
22 #include "getfem/dal_singleton.h"
23 #include "getfem/getfem_mesh_fem.h"
24 
25 
26 namespace getfem {
27 
28 #if GETFEM_PARA_LEVEL > 1
29 
30  struct fem_dof {
31  size_type ind_node;
32  pdof_description pnd;
33  size_type part;
34  };
35 
36 /* Fonction de renumérotation des degrés de libertés */
37 
38 /// Parallel Enumeration of dofs
39 void mesh_fem::enumerate_dof_para(void) const {
40 
41 #if 0
42 
43  GMM_TRACE2("Enumeration dof para !!!!!!!!!!!!!!!!");
44  GMM_ASSERT1(linked_mesh_ != 0, "Uninitialized mesh_fem");
45  context_check();
46  if (fe_convex.card() == 0) {
47  dof_enumeration_made = true;
48  nb_total_dof = 0;
49  return;
50  }
51 
52  dof_structure.clear();
53  MPI_Status mstatus;
54  fem_dof fd;
55 
56 /* Récupération du nombre total de régions (procs)!!!!*/
57  int num_rg, nb_rg;
58  MPI_Comm_rank(MPI_COMM_WORLD, &num_rg);
59  MPI_Comm_size(MPI_COMM_WORLD, &nb_rg);
60 
61 
62  cout<<"nb total region : "<<nb_rg<<" et nb_points = "<<linked_mesh().nb_points()<<endl;
63 
64 /* Récupération du num de la région */
65  //size_type num_rg;
66  //num_rg = linked_mesh.mpi_region.id();
67 
68 /* Création de la liste des ddl */
69 /// list_of_dof[1:nb_total_dof_mesh, 1:2]
70  std::vector<size_type> list_of_dof_numeration;
71  std::vector<size_type> list_of_dof_num_rg;
72  dal::bit_vector enumeration_of_dof_made;
73 
74  list_of_dof_numeration.resize(100000);
75  list_of_dof_num_rg.resize(100000);
76  // enumeration_of_dof_made(100000);
77 
78 /* Création de la liste des ddl interface */
79  std::vector<size_type> list_of_dof_linkable_index;
80  std::vector<size_type> list_of_dof_linkable_to;
81 
82  list_of_dof_linkable_index.resize(10000);
83  list_of_dof_linkable_to.resize(10000);
84 
85 /* Création de la liste des ddl globaux */
86  std::vector<size_type> list_of_global_dof_index;
87  std::vector<size_type> list_of_global_dof_local_index;
88 
89  list_of_global_dof_index.resize(10000);
90  list_of_global_dof_local_index.resize(10000);
91 
92 /* Initialisation de l'itérateur sur list_of_dof */
93  size_type iter_dof = 0;
94 
95 /* Construction de la liste des cv à la charge de chaque proc en fonction de la région */
96 /// list_of_cv[1:nb_cv_total_mesh, 1:2]
97  std::vector<size_type> list_of_cv_num_rg;
98  //list_of_cv_num_rg = size_type(0);
99  std::vector<size_type> list_of_cv_first_index;
100 
101  std::vector<size_type> list_of_icv;
102  std::vector<size_type> icv_in_list;
103 
104  list_of_cv_num_rg.resize(10000);
105  list_of_cv_first_index.resize(10000);
106  list_of_icv.resize(1000);
107  icv_in_list.resize(1000);
108 
109 /// En parallèle sur les régions on récupère les indices des cv de chaque proc
110  //dal::bit_vector index_tab;
111  const std::vector<size_type> &cmk = linked_mesh().cuthill_mckee_ordering();
112  //index_tab = linked_mesh().region(num_rg).index();
113 
114  cout<<"cmk.size = "<<cmk.size()<<endl;
115  cout<<"cmk[0] = "<<cmk[0]<<endl;
116  cout<<"cml[10] = "<<cmk[10]<<endl;
117  cout<<"nb_cv = "<<linked_mesh().convex_index().card()<<endl;
118 
119  size_type nb_cv = 0;
120  std::vector<size_type> neighbors;
121  bgeot::pgeotrans_precomp pgp = 0;
122  base_node P;
123  bgeot::pgeotrans_precomp pgpj = 0;
124  base_node Pj;
125 
126 // Boucle i pour remplir la liste des cv:
127  GMM_TRACE2("Initialisation of lists cv");
128  // for(dal::bv_visitor i(index_tab); !i.finished(); ++i)
129  cout<<"me = "<<num_rg<<endl;
130 
131  bool entre = false;
132 
133  cout<<"bool avant : "<<entre<<endl;
134 
135  for(size_type i = cmk[0]; i<cmk.size(); i++)
136  {
137  size_type icv = cmk[i];
138  if(linked_mesh().region(num_rg).is_in(icv))
139  {
140  GMM_TRACE2("ICI 0");
141  // cout<<"i = "<<i<<endl;
142  //cout<<"me "<<num_rg<<" et icv = "<<icv<<endl;
143  list_of_cv_num_rg[nb_cv] = num_rg;
144  GMM_TRACE2("ICI 1");
145  list_of_cv_first_index[nb_cv] = iter_dof;
146  GMM_TRACE2("ICI 2");
147  list_of_icv[nb_cv] = icv;
148  icv_in_list[icv] = nb_cv;
149 
150  pfem pf = fem_of_element(icv);
151  size_type nbd = pf->nb_dof(icv);
152  iter_dof += nbd;
153  nb_cv += 1;
154  //cout<<"la!!!!!!"<<nb_cv<<endl;
155  entre = true;
156  }
157  else
158  {
159  list_of_cv_num_rg[nb_cv] = 0;
160  list_of_cv_first_index[nb_cv] = 0;
161  list_of_icv[nb_cv]=0;
162  icv_in_list[icv]=0;
163 
164  pfem pf = fem_of_element(icv);
165  size_type nbd = pf->nb_dof(icv);
166  iter_dof += nbd;
167  nb_cv += 1;
168  //cout<<"ou la !!!!!!!!!"<<nb_cv<<endl;
169 
170  }
171  //cout<<"me = "<<num_rg<<"iteration i : "<<i<<endl;
172  }
173 
174  cout<<"bool : "<<entre<<endl;
175 
176  //int nb_cv_tot;
177 // Mise en commun par échange MPI_AllReduce du nombre totale de cv sur le mesh
178  //GMM_TRACE2("Echange MPI 1");
179  // MPI_Allreduce(&nb_cv, &nb_cv_tot, 1, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD);
180 
181  cout<<"nb_cv_tot = "<<nb_cv<<endl;
182 
183 
184 
185 
186  std::vector<size_type> list_of_cv_num_rg_Recv;
187  std::vector<size_type> list_of_cv_first_index_Recv;
188  std::vector<size_type> list_of_icv_Recv;
189  std::vector<size_type> icv_in_list_Recv;
190 
191  cout<<"size(cv_num_rg) = "<<list_of_cv_num_rg.size()<<endl;
192 
193  list_of_cv_num_rg.resize(nb_cv);
194  list_of_cv_num_rg_Recv.resize(nb_cv);
195  list_of_cv_first_index_Recv.resize(nb_cv);
196  list_of_icv_Recv.resize(nb_cv);
197  icv_in_list_Recv.resize(nb_cv);
198 
199  MPI_Barrier(MPI_COMM_WORLD);
200 
201 // Mise en commun par échange MPI_AllReduce de la liste list_of_cv_num_rg
202  GMM_TRACE2("Echange MPI 2");
203  MPI_Allreduce (&list_of_cv_num_rg[0], &list_of_cv_num_rg_Recv, nb_cv,
204  MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
205 
206  cout<<"num_rg[10] = "<<list_of_cv_num_rg[10]<<endl;
207  cout<<"num_rg_Recv[10] = "<<list_of_cv_num_rg_Recv[10]<<endl;
208 
209  GMM_TRACE2("Echange 3");
210 // Mise en commun par échange MPI_AllReduce de la liste list_of_cv_num_rg
211  MPI_Allreduce (&list_of_cv_first_index[0], &list_of_cv_first_index_Recv, nb_cv,
212  MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
213 
214  GMM_TRACE2("Echange 4");
215  MPI_Allreduce (&list_of_icv[0], &list_of_icv_Recv, nb_cv,
216  MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
217 
218  GMM_TRACE2("Echange 5");
219 
220  MPI_Allreduce (&icv_in_list[0], &icv_in_list_Recv, nb_cv,
221  MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
222 
223 /* Construction de la liste des ddl à la charge de chaque proc */
224  size_type nb_dof_rg = 0;
225  size_type nb_dof_tot;
226  //size_type nb_dof_inter = 0;
227  size_type nb_global_dof = 0;
228  size_type nb_global_dof_tot;
229  size_type nb_dof_linkable = 0;
230 
231 // Pour chaque cv dont ce proc a la charge :
232  GMM_TRACE2("Attributions des ddl aux rg");
233  for(size_type cv = 0; cv < list_of_cv_num_rg_Recv.size(); ++cv)
234  {
235  size_type icv = list_of_icv_Recv[cv];
236  if (list_of_cv_num_rg_Recv[cv] == num_rg)
237  {
238  pfem pf = fem_of_element(icv);
239  size_type nbd = pf->nb_dof(icv);
240  nb_dof_rg += nbd;
241  pdof_description andof = global_dof(pf->dim());
242 
243 // pour chaque ddl associé à ce cv :
244  for (size_type i = list_of_cv_first_index_Recv[cv];
245  i <= list_of_cv_first_index_Recv[cv] + nbd; i++)
246  {
247  fd.pnd = pf->dof_types()[i];
248  fd.part = get_dof_partition(icv);
249 
250 // Test si le ddl est raccordable
251  if (dof_linkable(fd.pnd))
252  {
253  size_type bool_rg = 0;
254  size_type bool_inter = 0;
255  P.resize(linked_mesh().dim());
256  pgp->transform(linked_mesh().points_of_convex(icv), i, P);
257 
258 // Récupération des voisins qui possèdent ce même ddl :
259  neighbors = linked_mesh().convex_to_point(i);
260  for (size_type jcv = neighbors[0]; jcv < neighbors.size(); ++jcv)
261  {
262 // Si le voisin appartient à la même région (ie pas ddl interface)
263  if (list_of_cv_num_rg_Recv[icv_in_list_Recv[jcv]] == num_rg)
264  {
265  bool_rg++;
266  }
267 // Sinon si c'est un dof interface "et" qui doit être à la charge de cette région
268  else if (list_of_cv_num_rg_Recv[icv_in_list_Recv[jcv]] > num_rg)
269  {
270  bool_inter++;
271  }
272  }
273 // Test si pas ddl interface
274  if (bool_rg == neighbors.size() || bool_inter+bool_rg == neighbors.size())
275  // ie tout les voisins raccordable sont dans cette même region
276  {
277  /* for(size_type jcv = neighbors[0]; jcv < neighbors.size(); ++jcv)
278  {
279  list_of_dof_linkable_index[nb_dof_linkable] = list_of_cv_first_index_Recv[jcv]+j;
280  list_of_dof_linkable_to[nb_dof_linkable] = i;
281  nb_dof_linkable ++;
282  }
283  list_of_dof_num_rg[i] = num_rg;
284  }
285  else if ((bool_inter + bool_rg)==neighbors.size())
286  // ie tout les voisins raccordable doivent être associé à cette region
287  {*/
288  list_of_dof_num_rg[i] = num_rg;
289  for (size_type jcv = neighbors[0]; jcv < neighbors.size(); ++jcv)
290  {
291 /// on associe le ddl correspondant au proc
292  pfem pfj = fem_of_element(jcv);
293  size_type nbdj = pfj->nb_dof(jcv);
294  for(size_type j = 0; j < nbdj; j++)
295  {
296  Pj.resize(linked_mesh().dim());
297  pgpj->transform(linked_mesh().points_of_convex(jcv), j, Pj);
298  if (&P == &Pj)
299  {
300  list_of_dof_linkable_index[nb_dof_linkable] =
301  list_of_cv_first_index_Recv[icv_in_list_Recv[jcv]]+j;
302  list_of_dof_linkable_to[nb_dof_linkable] = i;
303  nb_dof_linkable++;
304  list_of_dof_num_rg[list_of_cv_first_index_Recv
305  [icv_in_list_Recv[jcv]]+j] = num_rg;
306  }
307  }
308  }
309  }
310 
311  }
312 // Si ddl global
313  else if(fd.pnd == andof)
314  {
315 /// on recupère son numéro global : encountered_global_dof[1:3, num_region] = [num_global, icv, i]
316  size_type num = pf->index_of_global_dof(icv, i);
317  list_of_global_dof_index[nb_global_dof] = num;
318  list_of_global_dof_local_index [nb_global_dof] = i;
319  list_of_dof_num_rg[i] = num_rg;
320  nb_global_dof++;
321  }
322 // Si le ddl est non raccordable
323  else
324  {
325 /// on associe ce ddl au proc => list_of_dof[i, 1] = num_region (ou qqch de remarquable!!!!)
326  list_of_dof_num_rg[i] = num_rg;
327  } //end if
328  } // end for
329  } // end if
330  } // end for
331 
332 
333 
334 // Mise en commun par échange MPI_AllReduce de la liste list_of _dof
335 
336 // Mise en commun par échange MPI_AllReduce du nombre totale de dof sur le mesh
337 
338  MPI_Allreduce (&nb_dof_rg, &nb_dof_tot, 1, MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
339  size_type nbd_p;
340  size_type numerot = 0;
341  for (int p = 0; p < nb_rg; p++)
342  {
343  // Si il a des proc plus petit que num_rg, il recoit le nb de dof des autres plus petit pour mettre à jour son indice de début de numérotation
344  if (p < num_rg)
345  {
346  MPI_Recv(&nbd_p, 1, MPI_UNSIGNED, p, 100, MPI_COMM_WORLD, &mstatus);
347  numerot += nbd_p;
348  }
349  // Sinon il envoi le nombre de dof qu'il a à sa charge au autre qui lui sont supérieur
350  else if (p > num_rg)
351  {
352  MPI_Send(&nb_dof_rg, 1, MPI_UNSIGNED, p, 100, MPI_COMM_WORLD);
353  }
354  }
355 
356 
357  std::vector<size_type> list_of_dof_num_rg_Recv;
358  list_of_dof_num_rg_Recv.resize(nb_dof_tot);
359 
360 // Mise en commun par échange MPI_AllReduce de la liste list_of_cv_num_rg
361  MPI_Allreduce(&list_of_dof_num_rg[0], &list_of_dof_num_rg_Recv, nb_dof_tot,
362  MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
363 
364 
365  std::vector<size_type> list_of_global_dof_index_Recv;
366  std::vector<size_type> list_of_global_dof_local_index_Recv;
367  size_type nb_global_dof_Recv;
368 
369 // Mise en commun des information sur les global_dof
370  MPI_Allreduce (&nb_global_dof, &nb_global_dof_tot, 1, MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
371 
372  list_of_global_dof_index_Recv.resize(nb_global_dof_tot);
373  list_of_global_dof_local_index_Recv.resize(nb_global_dof_tot);
374 
375  for (int p = 0; p<nb_rg; p++)
376  {
377  MPI_Send (&nb_global_dof, 1, MPI_UNSIGNED, p, 200, MPI_COMM_WORLD);
378  MPI_Recv (&nb_global_dof_Recv, 1, MPI_UNSIGNED, p, 200, MPI_COMM_WORLD, &mstatus);
379 
380  MPI_Send(&list_of_global_dof_index[0], nb_global_dof, MPI_UNSIGNED, p, 300, MPI_COMM_WORLD);
381 
382  MPI_Recv (&list_of_global_dof_index_Recv[0], nb_global_dof_Recv,
383  MPI_UNSIGNED, p, 300, MPI_COMM_WORLD, &mstatus);
384 
385  MPI_Send(&list_of_global_dof_local_index[0], nb_global_dof, MPI_UNSIGNED, p, 400, MPI_COMM_WORLD);
386 
387  MPI_Recv (&list_of_global_dof_local_index_Recv[0], nb_global_dof_Recv,
388  MPI_UNSIGNED, p, 400, MPI_COMM_WORLD, &mstatus);
389  }
390 
391 
392 
393 /* Numérotation des ddl en charge de chaque processeur */
394 // Pour chaque cv dont ce proc a la charge :
395  GMM_TRACE2("Numerotation des ddl");
396  size_type ind_linkable = 0;
397  for(size_type icv = 0; icv < list_of_cv_num_rg_Recv.size(); ++icv)
398  {
399  pfem pf = fem_of_element(icv);
400  size_type nbd = pf->nb_dof(icv);
401 
402 // pour chaque ddl associé à ce cv :
403  for (size_type i = list_of_cv_first_index_Recv[icv];
404  i <= list_of_cv_first_index_Recv[icv] + nbd; i++)
405  {
406  if (list_of_dof_num_rg_Recv[i] == num_rg && !enumeration_of_dof_made[i])
407  {
408  if (!dof_linkable(fd.pnd))
409  {
410  list_of_dof_numeration[i] = numerot;
411  numerot += Qdim / pf->target_dim();
412  }
413 // Test si ddl raccordable
414  else if (dof_linkable(fd.pnd))
415  {
416 /// Recherche des cv ayant ce même point et dont le proc à la charge
417  while (list_of_dof_linkable_to[ind_linkable] == i)
418  {
419 /// Récupération des indices correspondants dans list_of_dof et Numérotation dans list_of_dof(indices)
420  list_of_dof_numeration[list_of_dof_linkable_index[ind_linkable]] = numerot;
421  enumeration_of_dof_made[list_of_dof_linkable_index[ind_linkable]] = true;
422  ind_linkable++;
423  }
424  list_of_dof_numeration[i] = numerot;
425  enumeration_of_dof_made[i] = true;
426  numerot += Qdim / pf->target_dim();
427  } // Fin Si
428  } // Fin boucle
429  } // Fin Boucle
430  }// Fin Boucle
431 
432 // Traitement des ddl globaux
433 // Boucle sur list_of_global_dof_in_charge
434 /* if(num_rg == 0)// temporairement
435  {
436  for (size_type i=0; i < list_of_global_dof_index_Recv.size(); i++)
437  {
438  pfem pf = fem_of_element(icv);
439 
440  if(!enumeration_of_dof_made[i])
441  {
442 /// Récupère les indices ayant le même num_global
443  for (size_type j = i; j < list_of_global_dof_index_Recv.size(); j++)
444  {
445 /// Numérotation
446  if (list_of_global_dof_index_Recv[j] == list_of_global_dof_index_Recv[i]
447  && !enumeration_of_dof_made[j])
448  {
449  list_of_dof_numeration[list_of_global_dof_local_index_Recv[j]] = numerot;
450  enumeration_of_dof_made[list_of_gloabl_dof_local_index_Recv[j]] = true;
451  }
452  }
453  list_of_dof_numeration[list_of_global_dof_local_index[i]] = numerot;
454  enumeration_of_dof_made[list_of_global_dof_local_index[i]] = true;
455  numerot += Qdim / pf->target_dim();
456  }
457  }
458  }*/
459 // Fin boucle
460 
461 // Mise en commun de list_of_dof par échange avec MPI_AllReduce
462  std::vector<size_type> list_of_dof_numeration_Recv;
463  list_of_dof_numeration_Recv.resize(nb_dof_tot);
464 
465  MPI_Allreduce(&list_of_dof_numeration[0], &list_of_dof_numeration_Recv, numerot,
466  MPI_UNSIGNED, MPI_SUM, MPI_COMM_WORLD);
467 
468 // Envoi de la structure numérotée
469  GMM_TRACE2("Envoi de la numerotation");
470  std::vector<size_type> tab;
471  size_type ind_tab = 0;
472  for(size_type icv = 0; icv < list_of_cv_num_rg.size(); ++icv)
473  {
474  pfem pf = fem_of_element(icv);
475  if (list_of_cv_num_rg[icv] == num_rg)
476  {
477  size_type nbd = pf->nb_dof(icv);
478  tab.resize(nbd);
479  for (size_type i = list_of_cv_first_index_Recv[icv]; i < list_of_cv_first_index_Recv[icv] + nbd; i++)
480  {
481  tab[ind_tab] = list_of_dof_numeration[i];
482  ind_tab++;
483  }
484  }
485  dof_structure.add_convex_noverif(pf->structure(icv), tab.begin(), icv);
486  }
487 
488  nb_total_dof = nb_dof_tot;
489 
490 
491 #endif
492 }
493 
494 #endif
495 
496 
497 } // end of getfem namespace
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
void clear()
erase the mesh
const ind_cv_ct & convex_to_point(size_type ip) const
Return a container of the convexes attached to point ip.
bool context_check() const
return true if update_from_context was called
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
virtual pfem fem_of_element(size_type cv) const
Return the basic fem associated with an element (if no fem is associated, the function will crash!...
const std::vector< size_type > & cuthill_mckee_ordering() const
Return the list of convex IDs for a Cuthill-McKee ordering.
size_type nb_points() const
Give the number of geometrical nodes in the mesh.
Definition: getfem_mesh.h:193
A simple singleton implementation.
Define the getfem::mesh_fem class.
bool dof_linkable(pdof_description)
Says if the dof is linkable.
Definition: getfem_fem.cc:615
pdof_description global_dof(dim_type d)
Description of a global dof, i.e.
Definition: getfem_fem.cc:542
dof_description * pdof_description
Type representing a pointer on a dof_description.
Definition: getfem_fem.h:159
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:243
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
GEneric Tool for Finite Element Methods.