TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
FT_Field.cpp
1/****************************************************************************
2* Copyright (c) 2024, 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 <Maillage_FT_IJK.h>
17
18#include <FT_Field.h>
19#include <Maillage_FT_IJK.h>
20#include <Param.h>
21#include <vector>
22#include <cmath>
23#include <algorithm>
24#include <numeric>
25#include <variant>
26#include <IJK_communications.h>
27#include <Process.h>
28using namespace std;
29
30Implemente_instanciable_sans_constructeur( FT_Field, "FT_Field", Objet_U ) ;
31
32double Point3D::tol = 1.e-10;
33double Point2D::tol = 1.e-10;
34
35void FT_Field::initialize(const Maillage_FT_IJK& mesh, const DoubleTab& centre_mass)
36{
37 if (Surfactant_theoric_case_==0. and Concentration_surfactant_init_==0.)
38 {
39 disable_surfactant_ = true;
40 return;
41 }
42 else
43 {
44 disable_surfactant_ = false;
45 }
46 int nbfa7=mesh.nb_facettes();
47 FT_field_Array_.resize(nbfa7);
48 mean_surfactant_= 0.;
49 mean_surface_ = 0.;
50
51 const DoubleTab& sommets=mesh.sommets();
52 const ArrOfDouble& Sfa7 = mesh.get_update_surface_facettes();
53 const IntTab& facettes=mesh.facettes();
54 const ArrOfInt& compo_connex = mesh.compo_connexe_facettes();
55
56
57 if (Surfactant_theoric_case_==1.)
58 {
59 // on initialise un champ pour solution analytique si option activee
60 for (int fa7=0 ; fa7<nbfa7 ; fa7++)
61 {
62 int compo = compo_connex(fa7);
63 Point3D xg_bulle = {centre_mass(compo, 0), centre_mass(compo, 1), centre_mass(compo, 2)};
64 int indice_sommet1 = facettes(fa7,0);
65 int indice_sommet2 = facettes(fa7,1);
66 int indice_sommet3 = facettes(fa7,2);
67 Point3D x0 = {sommets(indice_sommet1,0),sommets(indice_sommet1,1),sommets(indice_sommet1,2)};
68 Point3D x1 = {sommets(indice_sommet2,0),sommets(indice_sommet2,1),sommets(indice_sommet2,2)};
69 Point3D x2 = {sommets(indice_sommet3,0),sommets(indice_sommet3,1),sommets(indice_sommet3,2)};
70 Point3D xg_fa7 = (x0 + x1 + x2)/3.;
71 Point3D AB = xg_fa7-xg_bulle;
72
73 double costheta = AB.x/norme(AB);
74 FT_field_Array_[fa7]= 0.5 * (1.-costheta) ;
75 mean_surfactant_+=FT_field_Array_(fa7)*Sfa7(fa7);
76 mean_surface_+=Sfa7(fa7);
77 }
78
79 }
80 else
81 {
82 // sinon on initialise avec la concentration initiale renseignee dans le jdd
83 for (int fa7=0 ; fa7<nbfa7 ; fa7++)
84 {
85 FT_field_Array_[fa7]= Concentration_surfactant_init_ ;
86 mean_surfactant_+=FT_field_Array_(fa7)*Sfa7(fa7);
87 mean_surface_+=Sfa7(fa7);
88 }
89 }
90 mean_surfactant_=Process::mp_sum(mean_surfactant_);
91 mean_surface_=Process::mp_sum(mean_surface_);
92 mean_surfactant_/=mean_surface_;
93 Concentration_surfactant_init_=mean_surfactant_;
96}
97
101
102
104{
105 // Objet_U::readOn( is );
106 print_debug_surfactant_=0;
107 only_remaillage_=0;
108 patch_conservation_surfactant_locale_=0;
109 patch_conservation_surfactant_globale_=0;
110 check_triangle_duplicata_=0;
111 Diff_coeff_surfactant_=0.;
112 Taylor_test_=0. ;
113 disable_marangoni_source_term_ = 0;
114 sigma0_ = 0.;
115 R_= 8.314; // constante des gaz parfaits
116 T_ = 290 ; // temperature absolue
117 Gamma_inf_ = 0. ;
118 Param param(que_suis_je());
119 param.ajouter("print_debug_surfactant", &print_debug_surfactant_);
120 param.ajouter("only_remaillage", &only_remaillage_);
121 param.ajouter("patch_conservation_surfactant_locale", &patch_conservation_surfactant_locale_);
122 param.ajouter("patch_conservation_surfactant_globale", &patch_conservation_surfactant_globale_);
123 param.ajouter("check_triangle_duplicata", &check_triangle_duplicata_);
124 param.ajouter("Diff_coeff_surfactant", &Diff_coeff_surfactant_);
125 param.ajouter("Surfactant_theoric_case", &Surfactant_theoric_case_);
126 param.ajouter("Concentration_surfactant_init", &Concentration_surfactant_init_);
127 param.ajouter("sigma0", &sigma0_);
128 param.ajouter("Taylor_test", &Taylor_test_);
129 param.ajouter("disable_marangoni_source_term", &disable_marangoni_source_term_);
130 param.ajouter("R", &R_);
131 param.ajouter("T", &T_);
132 param.ajouter("Gamma_inf", &Gamma_inf_);
133 param.lire_avec_accolades(is);
134
135 if (Surfactant_theoric_case_==0. and Concentration_surfactant_init_==0.)
136 {
137 disable_surfactant_ = true;
138 }
139 else
140 {
141 disable_surfactant_ = false;
142 }
143 return is;
144}
145
146Sortie& FT_Field::printOn( Sortie& os ) const
147{
148 //Objet_U::printOn(os);
149 os << "{\n"
150 << " print_debug_surfactant " << print_debug_surfactant_ << "\n"
151 << " only_remaillage " << only_remaillage_ << "\n"
152 << " patch_conservation_surfactant_locale " << patch_conservation_surfactant_locale_ << "\n"
153 << " patch_conservation_surfactant_globale " << patch_conservation_surfactant_globale_ << "\n"
154 << " Diff_coeff_surfactant " << Diff_coeff_surfactant_ << "\n"
155 << " Surfactant_theoric_case " << Surfactant_theoric_case_ << "\n"
156 << " Concentration_surfactant_init " << Concentration_surfactant_init_ << "\n";
157 return os;
158}
159
160
161void FT_Field::avancer_en_temps(const Maillage_FT_IJK& mesh, const double time_step)
162{
163// au pas de temps N+1, je vais calculer S_{n+1}gamma_{n+1}=S_{n}gamma_{n}+DT*Dgamma_{n+1}+DT*Source
164// S_{n}gamma_{n} est la version intensive de la variable de concentration de Surfactant
165
166
167 if (!variable_intensive_)
168 {
169 std::cout << "la variable doit etre intensive a l'appel de cette fonction" << std::endl;
171 }
172 // on met a jour le Laplacien interfacial apres transport
176
177 // ajout du Laplacien
178 for (int fa7=0 ; fa7<FT_field_Array_.size_array() ; fa7++)
179 {
180 if(! mesh.facette_virtuelle(fa7))
181 {
182 FT_field_Array_[fa7]+=time_step*Diff_coeff_surfactant_*Laplacian_FT_field_Array_(fa7);
183 }
184 }
186 // TODO :: ajout du terme source pour les cas surfactant soluble
187
188
189}
190
195
196DoubleTab FT_Field::update_sigma_and_interfacial_source_term_sommet(const Maillage_FT_IJK& mesh, const Domaine_IJK& splitting, bool compute_interfacial_source, bool use_tryggvason_formulation)
197{
198 // on calcule les variations de sigma associees aux variations de FT_field_Array_
199 const int nbsom=mesh.nb_sommets();
200 const int nbfa7=mesh.nb_facettes();
201 sigma_sommets_.resize(nbsom);
202 sigma_facettes_.resize(nbfa7);
203 // on exprime la tension de surface aux facettes, comme pour FT_field_Array_
204 if (Taylor_test_==0.)
205 {
206 for (int fa=0 ; fa<nbfa7 ; fa++)
207 {
208 if(! mesh.facette_virtuelle(fa))
209 {
210 sigma_facettes_[fa]= max(1.e-16,sigma0_ - R_ * T_ * FT_field_Array_[fa]);
211 // max(1.e-5,sigma0_+R_*T_*Gamma_inf_*log(max(1.-FT_field_Array_[fa]/Gamma_inf_, 1.e-5)));
212 }
213 }
214 }
215 else
216 {
217 // on teste le cas analytique de Young (voir Muradoglu & Trygvason 2008)
218 const DoubleTab& sommets=mesh.sommets();
219 const IntTab& facettes=mesh.facettes();
220 const ArrOfInt& compo_connex = mesh.compo_connexe_facettes();
221 ArrOfDouble volume_reel;
222 DoubleTab position;
223 calculer_volume_bulles(volume_reel, position, mesh);
224 double Lx = splitting.get_domain_length(0);
225 for (int fa=0 ; fa<nbfa7 ; fa++)
226 {
227 if(! mesh.facette_virtuelle(fa))
228 {
229 int compo = compo_connex(fa);
230 Point3D xg_bulle = {position(compo, 0), position(compo, 1), position(compo, 2)};
231 int indice_sommet1 = facettes(fa,0);
232 int indice_sommet2 = facettes(fa,1);
233 int indice_sommet3 = facettes(fa,2);
234 Point3D x0 = {sommets(indice_sommet1,0),sommets(indice_sommet1,1),sommets(indice_sommet1,2)};
235 Point3D x1 = {sommets(indice_sommet2,0),sommets(indice_sommet2,1),sommets(indice_sommet2,2)};
236 Point3D x2 = {sommets(indice_sommet3,0),sommets(indice_sommet3,1),sommets(indice_sommet3,2)};
237 Point3D xg_fa7 = (x0 + x1 + x2)/3.;
238 // il faut faire comme si la bulle etait fixe au centre du domaine (voir these kalyani)
239 double x_centre = Lx/2. + (xg_fa7.x-xg_bulle.x);
240 // on prend beta = 1.
241 //double pos = std::fmod(std::fmod(pos_ref + offset - decallage_bulle_reel_ext_domaine_reel, Lx) + Lx, Lx) + decallage_bulle_reel_ext_domaine_reel;
242 sigma_facettes_[fa]= sigma0_ *(1.- Taylor_test_ * x_centre/Lx);
243 }
244 }
245 }
247 // calcule du gradient de sigma
248 //OpFTDisc_.Operator_Gradient_FT_sommets(sigma_facettes_, mesh, Grad_sigma_sommets_, true);
249
250 //OpFTDisc_.Compute_integral_interfaciale_source(sigma_facettes_, mesh, Grad_sigma_sommets_, false);
251 if (compute_interfacial_source)
252 OpFTDisc_.Compute_interfaciale_source(sigma_facettes_, mesh, interfacial_source_term_sommet_, true, use_tryggvason_formulation, !disable_marangoni_source_term_);
253
254 // on extrapole la valeur de la tension de surface aux sommets pour l'algo de IJK_Interfaces_
257}
258
259
260
262{
263 // Le maillage ne doit pas avoir de doublon de facettes a l'appel de cette fonction
264 // Utilisation de nettoyer maillage en amont recommandé
265 if (!variable_intensive_)
266 {
267 const ArrOfDouble& Sfa7 = mesh.get_update_surface_facettes();
268 for (int fa7=0 ; fa7<FT_field_Array_.size_array() ; fa7++)
269 {
270 if(! mesh.facette_virtuelle(fa7))
271 {
272 FT_field_Array_[fa7]*=Sfa7(fa7);
273 }
274 }
276 variable_intensive_=true;
277 }
278}
280{
281 // Le maillage ne doit pas avoir de doublon de facettes a l'appel de cette fonction
282 // Utilisation de nettoyer maillage en amont recommandé
283 if (variable_intensive_)
284 {
285 const ArrOfDouble& Sfa7 = mesh.get_update_surface_facettes();
286 for (int fa7=0 ; fa7<FT_field_Array_.size_array() ; fa7++)
287 {
288 if(! mesh.facette_virtuelle(fa7))
289 {
290 if (Sfa7(fa7)!=0.)
291 {
292 FT_field_Array_[fa7]/=Sfa7(fa7);
293 }
294 else
295 {
296 FT_field_Array_[fa7] = 0.;
297 }
298 }
299 }
301 variable_intensive_=false;
302 }
303}
304
305
307{
308 // On decale toutes les facettes reelles pour remplir lespace libere par les facettes virtuelles
309 {
310 const int nbfacettes = mesh.facettes().dimension(0);
311 int n = 0;
312 int i;
313 for (i = 0; i < nbfacettes; i++)
314 {
315 const int virtuelle = mesh.facette_virtuelle(i);
316 if (!virtuelle)
317 {
319 n++;
320 }
321 }
322 FT_field_Array_.resize(n);
323 }
324}
325
326
327void FT_Field::update_Field_sommets(const Maillage_FT_IJK& FTmesh, const ArrOfDouble& Field_facettes, ArrOfDouble& field_sommet)
328{
329 const int nbfa7=FTmesh.nb_facettes();
330 const int nbsom=FTmesh.nb_sommets();
331 const IntTab& facettes=FTmesh.facettes();
332 const ArrOfDouble& Sfa7 = FTmesh.get_surface_facettes();
333
334 ArrOfDouble Surface_sommet;
335 field_sommet.resize(nbsom);
336 Surface_sommet.resize(nbsom);
337
338 for (int som=0 ; som<nbsom ; som++)
339 {
340 field_sommet[som]=0.;
341 Surface_sommet[som]=0.;
342 }
343
344 // interpolation des valeur de Phi et de la normale aux sommets en moyennant les contributions adjacentes
345
346 for (int fa7=0 ; fa7<nbfa7 ; fa7++)
347 {
348 if(! FTmesh.facette_virtuelle(fa7))
349 {
350 for (int sommet_fa7=0 ; sommet_fa7<3 ; sommet_fa7++)
351 {
352 int indice_sommet = facettes(fa7,sommet_fa7);
353 field_sommet[indice_sommet]+=Field_facettes[fa7]*Sfa7[fa7];
354 Surface_sommet[indice_sommet]+=Sfa7[fa7];
355 }
356 }
357 }
358 // On a calcule la contribution de chaque facette reelle aux differents sommets.
359 // Certaines contributions ont ete ajoutees a des sommets virtuels, il
360 // faut recuperer ces contributions sur le sommet reel.
361 const Desc_Structure_FT& desc_sommets = FTmesh.desc_sommets();
362 desc_sommets.collecter_espace_virtuel(field_sommet, MD_Vector_tools::EV_SOMME);
363 desc_sommets.collecter_espace_virtuel(Surface_sommet, MD_Vector_tools::EV_SOMME);
364
365 for (int som=0 ; som<nbsom ; som++)
366 {
367 if(! FTmesh.sommet_virtuel(som))
368 {
369 field_sommet[som]/= Surface_sommet[som];
370 }
371 Surface_sommet[som] = 0.;
372 }
373 // les sommets reels sont mis a jour
374 // il reste a mettre a jour les sommets virtuels
375 desc_sommets.echange_espace_virtuel(field_sommet);
376}
377
382
383
384
385
386// Toute les fonction qui suivent servent a calculer les intersections entre deux triangles dans un espace 2D.
387// Cela sert a redistribuer de maniere conservative et en diffusant le moins possible la quantite de surfactant
388// lorsque lon supprime les petites cellules.
389
390// Comparator function to sort indices based on the values in the array
391
392bool compare(const std::pair<size_t, double>& a, const std::pair<size_t, double>& b)
393{
394 return a.second < b.second;
395}
396
397void FT_Field::sortAndTrackIndices(const std::vector<double>& arr, std::vector<size_t>& indices)
398{
399 size_t n = arr.size();
400
401 // Create a vector of pairs where the first element is the index and the second is the value
402 std::vector<std::pair<size_t, double>> indexedArray(n);
403 for (size_t i = 0; i < n; ++i)
404 {
405 indexedArray[i] = std::make_pair(i, arr[i]);
406 }
407
408 // Sort the indexedArray using the custom comparator
409 std::sort(indexedArray.begin(), indexedArray.end(), compare);
410
411 // Extract the sorted indices
412 for (size_t i = 0; i < n; ++i)
413 {
414 indices[i] = indexedArray[i].first;
415 }
416}
417
418
419// Function to calculate the determinant
420double FT_Field::det(const Point2D& a, const Point2D& b, const Point2D& c)
421{
422 return a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y);
423}
424
425// Function to check if a point is inside a triangle
426bool FT_Field::isPointInTriangle(const Point2D& pt, const Point2D& v1, const Point2D& v2, const Point2D& v3)
427{
428 double d1 = det(pt, v1, v2);
429 double d2 = det(pt, v2, v3);
430 double d3 = det(pt, v3, v1);
431 bool has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
432 bool has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
433 return !(has_neg && has_pos);
434}
435
436// Function to find the intersection of two lines
437bool FT_Field::lineIntersection(const Point2D& a, const Point2D& b, const Point2D& c, const Point2D& d, Point2D& intersection)
438{
439 double a1 = b.y - a.y;
440 double b1 = a.x - b.x;
441 double c1 = a1 * a.x + b1 * a.y;
442
443 double a2 = d.y - c.y;
444 double b2 = c.x - d.x;
445 double c2 = a2 * c.x + b2 * c.y;
446
447 double determinant = a1 * b2 - a2 * b1;
448
449 if (std::abs(determinant) < 1e-10)
450 {
451 return false; // The lines are parallel
452 }
453
454 intersection.x = (b2 * c1 - b1 * c2) / determinant;
455 intersection.y = (a1 * c2 - a2 * c1) / determinant;
456
457 if (std::min(a.x, b.x) <= intersection.x && intersection.x <= std::max(a.x, b.x) &&
458 std::min(a.y, b.y) <= intersection.y && intersection.y <= std::max(a.y, b.y) &&
459 std::min(c.x, d.x) <= intersection.x && intersection.x <= std::max(c.x, d.x) &&
460 std::min(c.y, d.y) <= intersection.y && intersection.y <= std::max(c.y, d.y))
461 {
462 return true;
463 }
464
465 return false;
466}
467
468// Function to calculate the area using the Shoelace formula
469double FT_Field::polygonArea(const std::vector<Point2D>& vertices)
470{
471 double area = 0;
472 int n = static_cast<int>(vertices.size());
473
474 for (int i = 0; i < n; ++i)
475 {
476 area += (vertices[i].x * vertices[(i + 1) % n].y) - (vertices[(i + 1) % n].x * vertices[i].y);
477 }
478 return std::abs(area) / 2.0;
479}
480
482{
483 vector<Point2D> intersectionPoints;
484
485 // Find intersection points of edges
486 for (int i = 0; i < 3; ++i)
487 {
488 for (int j = 0; j < 3; ++j)
489 {
490 Point2D intersect;
491 if (lineIntersection(t1[i], t1[(i + 1) % 3], t2[j], t2[(j + 1) % 3], intersect))
492 {
493 intersectionPoints.push_back(intersect);
494 }
495 }
496 }
497
498 // Add vertices of t1 that are inside t2
499 for (int i = 0; i < 3; ++i)
500 {
501 if (isPointInTriangle(t1[i], t2[0], t2[1], t2[2]))
502 {
503 intersectionPoints.push_back(t1[i]);
504 }
505 }
506
507 // Add vertices of t2 that are inside t1
508 for (int i = 0; i < 3; ++i)
509 {
510 if (isPointInTriangle(t2[i], t1[0], t1[1], t1[2]))
511 {
512 intersectionPoints.push_back(t2[i]);
513 }
514 }
515
516 // Remove duplicate points
517 sort(intersectionPoints.begin(), intersectionPoints.end(), [](const Point2D &a, const Point2D &b)
518 {
519 return a.x == b.x ? a.y < b.y : a.x < b.x;
520 });
521 intersectionPoints.erase(unique(intersectionPoints.begin(), intersectionPoints.end(), [](const Point2D &a, const Point2D &b)
522 {
523 return std::abs(a.x - b.x) < 1e-10 && std::abs(a.y - b.y) < 1e-10;
524 }), intersectionPoints.end());
525
526 // Sort points to form a closed polygon
527 if (!intersectionPoints.empty())
528 {
529 Point2D centroid = {0, 0};
530 for (const auto &pt : intersectionPoints)
531 {
532 centroid.x += pt.x;
533 centroid.y += pt.y;
534 }
535 centroid.x /= static_cast<double>(intersectionPoints.size());
536 centroid.y /= static_cast<double>(intersectionPoints.size());
537
538 sort(intersectionPoints.begin(), intersectionPoints.end(), [&centroid](const Point2D &a, const Point2D &b)
539 {
540 double angleA = atan2(a.y - centroid.y, a.x - centroid.x);
541 double angleB = atan2(b.y - centroid.y, b.x - centroid.x);
542 return angleA < angleB;
543 });
544 }
545
546 // Calculate the area of the intersection polygon
547 double intersectionArea = polygonArea(intersectionPoints);
548
549 return intersectionArea;
550}
551
552
553double FT_Field::norme(const Point3D& pt)
554{
555 return std::sqrt(pt.x*pt.x + pt.y*pt.y + pt.z*pt.z) ;
556}
557// Function to remove duplicates from a vector of Point3D
558std::vector<Point3D> FT_Field::removeDuplicates(std::vector<Point3D>& points)
559{
560 // Sort the vector of points
561 std::sort(points.begin(), points.end());
562 // Erase duplicates using unique algorithm
563 points.erase(std::unique(points.begin(), points.end()), points.end());
564 return points;
565}
566
567
568
569// Function to compute the centroid of the points
570Point3D FT_Field::computeCentroid(const vector<Point3D>& points)
571{
572 Point3D centroid = {0.0, 0.0, 0.0};
573
574 for (const auto &p : points)
575 {
576 centroid.x += p.x;
577 centroid.y += p.y;
578 centroid.z += p.z;
579 }
580
581 centroid.x /= static_cast<double>(points.size());
582 centroid.y /= static_cast<double>(points.size());
583 centroid.z /= static_cast<double>(points.size());
584
585 return centroid;
586}
587
588// Function to compute the covariance matrix
589void FT_Field::computeCovarianceMatrix(const vector<Point3D>& points, const Point3D& centroid, double cov[3][3])
590{
591 // Initialize covariance matrix to zero
592 for (int i = 0; i < 3; ++i)
593 for (int j = 0; j < 3; ++j)
594 cov[i][j] = 0.0;
595
596 for (const auto &p : points)
597 {
598 double x = p.x - centroid.x;
599 double y = p.y - centroid.y;
600 double z = p.z - centroid.z;
601 cov[0][0] += x * x;
602 cov[0][1] += x * y;
603 cov[0][2] += x * z;
604 cov[1][0] += y * x;
605 cov[1][1] += y * y;
606 cov[1][2] += y * z;
607 cov[2][0] += z * x;
608 cov[2][1] += z * y;
609 cov[2][2] += z * z;
610 }
611
612 for (int i = 0; i < 3; ++i)
613 for (int j = 0; j < 3; ++j)
614 cov[i][j] /= static_cast<double>(points.size());
615}
616
617// Function to compute eigenvalues and eigenvectors of a 3x3 matrix using the power iteration method
618void FT_Field::powerIteration(const double cov[3][3], double eigenVector[3], double& eigenValue)
619{
620 double b_k[3] = {1.0, 1.0, 1.0};
621 double b_k1[3];
622
623 const int maxIterations = 100;
624 const double tolerance = 1e-10;
625
626 for (int iter = 0; iter < maxIterations; ++iter)
627 {
628 // Multiply cov by b_k: b_k1 = cov * b_k
629 for (int i = 0; i < 3; ++i)
630 {
631 b_k1[i] = 0.0;
632 for (int j = 0; j < 3; ++j)
633 {
634 b_k1[i] += cov[i][j] * b_k[j];
635 }
636 }
637
638 // Normalize b_k1
639 double norm = sqrt(b_k1[0] * b_k1[0] + b_k1[1] * b_k1[1] + b_k1[2] * b_k1[2]);
640 for (int i = 0; i < 3; ++i)
641 {
642 b_k1[i] /= norm;
643 }
644
645 // Check for convergence
646 double diff = sqrt((b_k1[0] - b_k[0]) * (b_k1[0] - b_k[0]) +
647 (b_k1[1] - b_k[1]) * (b_k1[1] - b_k[1]) +
648 (b_k1[2] - b_k[2]) * (b_k1[2] - b_k[2]));
649 if (diff < tolerance)
650 {
651 break;
652 }
653
654 // Update b_k
655 for (int i = 0; i < 3; ++i)
656 {
657 b_k[i] = b_k1[i];
658 }
659 }
660
661 // Compute the eigenvalue
662 eigenValue = 0.0;
663 for (int i = 0; i < 3; ++i)
664 {
665 double temp = 0.0;
666 for (int j = 0; j < 3; ++j)
667 {
668 temp += cov[i][j] * b_k1[j];
669 }
670 eigenValue += temp * b_k1[i];
671 }
672
673 // Copy the eigenvector
674 for (int i = 0; i < 3; ++i)
675 {
676 eigenVector[i] = b_k1[i];
677 }
678}
679
680// Function to project a 3D point onto the 2D plane defined by two eigenvectors
681Point2D FT_Field::projectPointToPlane(const Point3D& point, const Point3D& centroid, const array<double, 3>& eigenVector1, const array<double, 3>& eigenVector2)
682{
683 double x = point.x - centroid.x;
684 double y = point.y - centroid.y;
685 double z = point.z - centroid.z;
686
687 Point2D projectedPoint;
688 projectedPoint.x = x * eigenVector1[0] + y * eigenVector1[1] + z * eigenVector1[2];
689 projectedPoint.y = x * eigenVector2[0] + y * eigenVector2[1] + z * eigenVector2[2];
690 return projectedPoint;
691}
692
693
694// Function to project a 3D point onto the 2D plane defined by two eigenvectors
695int FT_Field::orientation_triangle(const Point3D& normale, const array<double, 3>& eigenVector1, const array<double, 3>& eigenVector2)
696{
697 Point3D eigenVector1_pt {eigenVector1[0],eigenVector1[1],eigenVector1[2]};
698 Point3D eigenVector2_pt {eigenVector2[0],eigenVector2[1],eigenVector2[2]};
699 double norm = scalarProduct(crossProduct(normale, eigenVector1_pt), eigenVector2_pt);
700 if (norm >= 0.)
701 return 1 ;
702 else
703 return -1 ;
704}
705
706
707vector<pair<double, array<double, 3>>> FT_Field::Main_2D_plane_eigenvectors(vector<Point3D> points)
708{
709 // Step 1: Compute the centroid
710 Point3D centroid(computeCentroid(points));
711
712 // Step 2: Compute the covariance matrix
713 double cov[3][3];
714 computeCovarianceMatrix(points, centroid, cov);
715
716 // Step 3: Compute the eigenvalues and eigenvectors using power iteration
717 double eigenVector1[3], eigenVector2[3], eigenVector3[3];
718 double eigenValue1, eigenValue2, eigenValue3;
719
720 powerIteration(cov, eigenVector1, eigenValue1);
721
722 // Deflate the covariance matrix by removing the component of the first eigenvector
723 for (int i = 0; i < 3; ++i)
724 {
725 for (int j = 0; j < 3; ++j)
726 {
727 cov[i][j] -= eigenValue1 * eigenVector1[i] * eigenVector1[j];
728 }
729 }
730
731 powerIteration(cov, eigenVector2, eigenValue2);
732
733 // Deflate the covariance matrix by removing the component of the second eigenvector
734 for (int i = 0; i < 3; ++i)
735 {
736 for (int j = 0; j < 3; ++j)
737 {
738 cov[i][j] -= eigenValue2 * eigenVector2[i] * eigenVector2[j];
739 }
740 }
741
742 powerIteration(cov, eigenVector3, eigenValue3);
743
744 // Sort eigenvalues and corresponding eigenvectors in descending order
745 vector<pair<double, array<double, 3>>> eigenPairs =
746 {
747 {eigenValue1, {eigenVector1[0], eigenVector1[1], eigenVector1[2]}},
748 {eigenValue2, {eigenVector2[0], eigenVector2[1], eigenVector2[2]}},
749 {eigenValue3, {eigenVector3[0], eigenVector3[1], eigenVector3[2]}}
750 };
751 sort(eigenPairs.rbegin(), eigenPairs.rend());
752
753 return eigenPairs;
754}
755
756double FT_Field::triangleArea(const Point2D& p1, const Point2D& p2, const Point2D& p3)
757{
758 return 0.5 * std::abs((p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)));
759}
760
761// Function to calculate the cross product of two vectors
763{
764 Point3D cross;
765 cross.x = u.y * v.z - u.z * v.y;
766 cross.y = u.z * v.x - u.x * v.z;
767 cross.z = u.x * v.y - u.y * v.x;
768 return cross;
769}
770// Function to calculate the cross product of two vectors
771double FT_Field::scalarProduct(const Point3D& u, const Point3D& v)
772{
773 return u.x*v.x + u.y*v.y + u.z*v.z;
774}
775
776// Function to calculate the magnitude of a vector
778{
779 return std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
780}
781
782// Function to calculate the area of a triangle given its vertices
783double FT_Field::triangleArea3D(const Point3D& A, const Point3D& B, const Point3D& C)
784{
785 // Create vectors AB and AC
786 Point3D AB = {B.x - A.x, B.y - A.y, B.z - A.z};
787 Point3D AC = {C.x - A.x, C.y - A.y, C.z - A.z};
788
789 // Calculate the cross product of AB and AC
790 Point3D cross = crossProduct(AB, AC);
791
792 // Calculate the magnitude of the cross product
793 double area = magnitude(cross) / 2.0;
794
795 return area;
796}
797
798void FT_Field::Calculate_Facette_Intersection_Area(DoubleTab& Surface_fa7init, DoubleTab& Surface_fa7fin, DoubleTab& Surface_intersection, vector<Point3D> points_fa7_originale, vector<Point3D> points_fa7_finale, IntTab points_triangle_originaux, IntTab points_triangle_finaux, IntTab& normale_triangle_originaux, IntTab& normale_triangle_finaux)
799{
800 // Les grandes lignes de l'algo :
801 // 1 : on calcule les 2 vecteurs propres qui definissent le plan moyen de la structure formee par les triangles initiaux
802 // 2 : on gere le changement eventuel d'orientation des facettes dans certains cas particuliers de repliement
803 // 3 : on projette les points 3D (sommets des facettes) sur le plan 2D defini par les vecteurs propres
804 // 4 : on calcule les intersections de tous les triangles initiaux avec tous les triangles finaux dans ce plan 2D
805
806 if(points_fa7_originale.size()==0 and points_fa7_finale.size()==0)
807 {
808 return;
809 }
810 // Output the initial points
811 int nbtriangle_originaux = points_triangle_originaux.dimension(0);
812 int nbtriangle_finaux = points_triangle_finaux.dimension(0);
813 // Step 1: Compute the centroid and The first two eigenvectors of the mean plane described by points_fa7_originale
814
815 Point3D centroid = computeCentroid(points_fa7_originale);
816 vector<pair<double, array<double, 3>>> eigenPairs = Main_2D_plane_eigenvectors(points_fa7_originale);
817
818 array<double, 3> planeVector1 = eigenPairs[0].second;
819 array<double, 3> planeVector2 = eigenPairs[1].second;
820
821 // Project each 3D point onto the 2D plane
822 vector<Point2D> projectedPoints_fa7_originale;
823 for (const auto &point : points_fa7_originale)
824 {
825 projectedPoints_fa7_originale.push_back(projectPointToPlane(point, centroid, planeVector1, planeVector2));
826 }
827 vector<Point2D> projectedPoints_fa7_finale;
828 for (const auto &point : points_fa7_finale)
829 {
830 projectedPoints_fa7_finale.push_back(projectPointToPlane(point, centroid, planeVector1, planeVector2));
831 }
832
833 // teste des mailles repliee sur elle-même
834 // on calcul l'orientation + ou - de la normale du triangle
835
836 for (int to = 0; to < nbtriangle_originaux; to++)
837 {
838 const Point3D normale = {normale_facette_initiale_(to, 0),normale_facette_initiale_(to, 1),normale_facette_initiale_(to, 2)};
839 normale_triangle_originaux(to) = orientation_triangle(normale, planeVector1, planeVector2);
840 }
841
842 for (int to = 0; to < nbtriangle_finaux; to++)
843 {
844 // Pour les fa7 finale, il faut checker si la normale ne change pas d'orientation pendant le deplacement.
845 // Pour ca, on calcule les deux normale a la fa7 avant et apres
846 // si ça change, on change le signe de la normale de reference
847 Point3D AB = {triangle_initiaux_(to, 1, 0)-triangle_initiaux_(to, 0, 0),
848 triangle_initiaux_(to, 1, 1)-triangle_initiaux_(to, 0, 1),
849 triangle_initiaux_(to, 1, 2)-triangle_initiaux_(to, 0, 2)
850 };
851 Point3D AC = {triangle_initiaux_(to, 2, 0)-triangle_initiaux_(to, 0, 0),
852 triangle_initiaux_(to, 2, 1)-triangle_initiaux_(to, 0, 1),
853 triangle_initiaux_(to, 2, 2)-triangle_initiaux_(to, 0, 2)
854 };
855 Point3D normale = crossProduct(AB, AC);
856 int orientation_normale_avant_deplacement = orientation_triangle(normale, planeVector1, planeVector2);
857 AB = {triangle_finaux_(to, 1, 0)-triangle_finaux_(to, 0, 0),
858 triangle_finaux_(to, 1, 1)-triangle_finaux_(to, 0, 1),
859 triangle_finaux_(to, 1, 2)-triangle_finaux_(to, 0, 2)
860 };
861 AC = {triangle_finaux_(to, 2, 0)-triangle_finaux_(to, 0, 0),
862 triangle_finaux_(to, 2, 1)-triangle_finaux_(to, 0, 1),
863 triangle_finaux_(to, 2, 2)-triangle_finaux_(to, 0, 2)
864 };
865 normale = crossProduct(AB, AC);
866 int orientation_normale_apres_deplacement = orientation_triangle(normale, planeVector1, planeVector2);
867
868 const Point3D normale_ref = {normale_facette_initiale_(to, 0),normale_facette_initiale_(to, 1),normale_facette_initiale_(to, 2)};
869 normale_triangle_finaux(to) = orientation_triangle(normale_ref, planeVector1, planeVector2)*orientation_normale_apres_deplacement*orientation_normale_avant_deplacement;
870 }
871
872 // on projette les points 3D sur le plan 2D defini par les vecteurs propres
873 // Puis on calcule les intersections de tous les triangles initiaux avec tous les triangles finaux
874 for (int tf = 0; tf < nbtriangle_finaux; tf++)
875 {
876 Point2D p1f, p2f, p3f;
877 p1f = projectedPoints_fa7_finale[points_triangle_finaux(tf,0)];
878 p2f = projectedPoints_fa7_finale[points_triangle_finaux(tf,1)];
879 p3f = projectedPoints_fa7_finale[points_triangle_finaux(tf,2)];
880
881 Point2D t1[3] = {{p1f.x, p1f.y},{p2f.x, p2f.y},{p3f.x, p3f.y}};
882 Surface_fa7fin[tf] = triangleArea(t1[0],t1[1],t1[2]);
883
884 for (int to = 0; to < nbtriangle_originaux; to++)
885 {
886 Point2D p1o, p2o, p3o;
887 p1o = projectedPoints_fa7_originale[points_triangle_originaux(to,0)];
888 p2o = projectedPoints_fa7_originale[points_triangle_originaux(to,1)];
889 p3o = projectedPoints_fa7_originale[points_triangle_originaux(to,2)];
890 Point2D t2[3] = {{p1o.x, p1o.y},{p2o.x, p2o.y},{p3o.x, p3o.y}};
891 Surface_fa7init[to] = triangleArea(t2[0],t2[1],t2[2]);
892 Surface_intersection(tf,to) = intersectionArea(t1, t2);
893 }
894 }
895 return;
896}
897
898void FT_Field::sauvegarder_triangle(const Maillage_FT_IJK& mesh, const int i, const int avant_apres_remaillage)
899{
900 bool triangle_already_sauv = false;
901 if (avant_apres_remaillage==0)
902 {
903 /* Normalement pas necessaire de supprimer les duplicata avec la maniere dont est geré le parallelisme
904 * On nest pas sense en avoir a ce stade
905 * Il y en a malgre tout parfois dans les premiere iteration ou le remaillage est violent
906 * Raison non identifiee --> paliatif
907 */
908 if (check_triangle_duplicata_)
909 {
910 for (int triangle = 0; triangle < triangle_initiaux_.dimension(0) ; triangle++)
911 {
912 Point3D p1new = {facettes_sommets_full_compo_(i, 0),facettes_sommets_full_compo_(i, 1),facettes_sommets_full_compo_(i, 2)};
913 Point3D p2new = {facettes_sommets_full_compo_(i, 3),facettes_sommets_full_compo_(i, 4),facettes_sommets_full_compo_(i, 5)};
914 Point3D p3new = {facettes_sommets_full_compo_(i, 6),facettes_sommets_full_compo_(i, 7),facettes_sommets_full_compo_(i, 8)};
915 Point3D p1ref = {triangle_initiaux_(triangle, 0, 0),triangle_initiaux_(triangle, 0, 1),triangle_initiaux_(triangle, 0, 2)};
916 Point3D p2ref = {triangle_initiaux_(triangle, 1, 0),triangle_initiaux_(triangle, 1, 1),triangle_initiaux_(triangle, 1, 2)};
917 Point3D p3ref = {triangle_initiaux_(triangle, 2, 0),triangle_initiaux_(triangle, 2, 1),triangle_initiaux_(triangle, 2, 2)};
918 if (p1new == p1ref and p2new == p2ref and p3new == p3ref)
919 triangle_already_sauv = true;
920 }
921 }
922 if(!triangle_already_sauv)
923 {
924 int index_triangle = triangle_initiaux_.dimension(0);
925 triangle_initiaux_.resize(index_triangle+1, 3, 3);
926 normale_facette_initiale_.resize(index_triangle+1, 3);
927 Surfactant_facette_initiale_.resize(index_triangle+1);
928 Surfactant_facette_initiale_(index_triangle) = facettes_sommets_full_compo_(i, 9);
929 for (int i_som = 0; i_som < 3; i_som++)
930 for (int dir = 0; dir < 3; dir++)
931 {
932 triangle_initiaux_(index_triangle, i_som, dir) = facettes_sommets_full_compo_(i, 3*i_som+dir);
933 }
934 for (int dir = 0; dir < 3; dir++)
935 {
936 normale_facette_initiale_(index_triangle, dir) = facettes_sommets_full_compo_(i, 12+dir);
937 }
938 }
939 }
940 if (avant_apres_remaillage==1)
941 {
942 /* Normalement pas necessaire de supprimer les duplicata avec la maniere dont est geré le parallelisme
943 * On nest pas sense en avoir a ce stade
944 * Il y en a malgre tout parfois dans les premiere iteration ou le remaillage est violent
945 * Raison non identifiee --> paliatif
946 */
947 if (check_triangle_duplicata_)
948 {
949 for (int triangle = 0; triangle < triangle_finaux_.dimension(0) ; triangle++)
950 {
951 Point3D p1new = {facettes_sommets_full_compo_(i, 0),facettes_sommets_full_compo_(i, 1),facettes_sommets_full_compo_(i, 2)};
952 Point3D p2new = {facettes_sommets_full_compo_(i, 3),facettes_sommets_full_compo_(i, 4),facettes_sommets_full_compo_(i, 5)};
953 Point3D p3new = {facettes_sommets_full_compo_(i, 6),facettes_sommets_full_compo_(i, 7),facettes_sommets_full_compo_(i, 8)};
954 Point3D p1ref = {triangle_finaux_(triangle, 0, 0),triangle_finaux_(triangle, 0, 1),triangle_finaux_(triangle, 0, 2)};
955 Point3D p2ref = {triangle_finaux_(triangle, 1, 0),triangle_finaux_(triangle, 1, 1),triangle_finaux_(triangle, 1, 2)};
956 Point3D p3ref = {triangle_finaux_(triangle, 2, 0),triangle_finaux_(triangle, 2, 1),triangle_finaux_(triangle, 2, 2)};
957 if (p1new == p1ref and p2new == p2ref and p3new == p3ref)
958 triangle_already_sauv = true;
959 }
960 }
961 if(!triangle_already_sauv)
962 {
963 int index_triangle = triangle_finaux_.dimension(0);
964 triangle_finaux_.resize(index_triangle+1, 3, 3);
965 normale_facette_finale_.resize(index_triangle+1, 3);
966 indice_facette_finaux_.resize(index_triangle+1);
967 indice_facette_finaux_(index_triangle)=i;
968 for (int i_som = 0; i_som < 3; i_som++)
969 for (int dir = 0; dir < 3; dir++)
970 triangle_finaux_(index_triangle, i_som, dir) = facettes_sommets_full_compo_(i, 3*i_som+dir);
971 for (int dir = 0; dir < 3; dir++)
972 {
973 normale_facette_finale_(index_triangle, dir) = facettes_sommets_full_compo_(i, 12+dir);
974 }
975 }
976 }
977 return;
978}
979
980
982{
983
984 int nb_triangle_fin = triangle_finaux_.dimension(0);
985 int nb_triangle_init = triangle_initiaux_.dimension(0);
986
987 if (nb_triangle_fin == 0 or nb_triangle_init==0)
988 {
989 return;
990 }
991 if ((nb_triangle_fin == 0 or nb_triangle_init==0) and nb_triangle_fin!=nb_triangle_init)
992 {
993 std::cout << "Erreur : nb_triangle_fin = " << nb_triangle_fin << " et triangle_initiaux_= " << nb_triangle_init << std::endl;
995 }
996 if (!variable_intensive_)
997 {
998 std::cout << "Erreur : la variable doit etre intensive ici" ;
1000 }
1001
1002 ArrOfDouble surfactant_copy ;
1003 vector<Point3D> points_fa7_originale((nb_triangle_init)*3);
1004 vector<Point3D> points_fa7_finale((nb_triangle_fin)*3);
1005
1006 //on remplit tous les points, il y a les doublons car sommets communs a plusieurs fa7
1007 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1008 {
1009 int i_sommet ;
1010 for (i_sommet = 0; i_sommet < 3; i_sommet++)
1011 points_fa7_originale[3*ifaforsom+i_sommet]= {triangle_initiaux_(ifaforsom, i_sommet, 0),triangle_initiaux_(ifaforsom, i_sommet, 1),triangle_initiaux_(ifaforsom, i_sommet, 2)};
1012 }
1013 for (int ifaforsom= 0; ifaforsom < nb_triangle_fin; ifaforsom++)
1014 {
1015 int i_sommet ;
1016 for (i_sommet = 0; i_sommet < 3; i_sommet++)
1017 points_fa7_finale[3*ifaforsom+i_sommet]= {triangle_finaux_(ifaforsom, i_sommet, 0),triangle_finaux_(ifaforsom, i_sommet, 1),triangle_finaux_(ifaforsom, i_sommet, 2)};
1018 }
1019
1020 // Supprimer les points dupliques
1021 vector<Point3D> points_fa7_finale_unique = removeDuplicates(points_fa7_finale);
1022 vector<Point3D> points_fa7_originale_unique = removeDuplicates(points_fa7_originale);
1023
1024 // On remplit ensuite les triangles
1025 IntTab points_triangle_originaux(nb_triangle_init,3);
1026 IntTab points_triangle_finaux(nb_triangle_fin,3);
1027
1028 for (int ifaforsom = 0; ifaforsom < nb_triangle_fin; ifaforsom++)
1029 {
1030 int i_sommet ;
1031 int index_point ;
1032 for (i_sommet = 0; i_sommet < 3; i_sommet++)
1033 {
1034 int n = static_cast<int>(points_fa7_finale_unique.size());
1035 for (index_point = 0; index_point < n; index_point++)
1036 {
1037 Point3D point_liste = points_fa7_finale_unique[index_point];
1038 Point3D point_triangle = {triangle_finaux_(ifaforsom, i_sommet, 0),triangle_finaux_(ifaforsom, i_sommet, 1),triangle_finaux_(ifaforsom, i_sommet, 2)};
1039 if(point_liste==point_triangle)
1040 {
1041 points_triangle_finaux(ifaforsom, i_sommet)=index_point;
1042 }
1043 }
1044 }
1045 }
1046
1047 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1048 {
1049 int i_sommet ;
1050 int index_point ;
1051
1052 for (i_sommet = 0; i_sommet < 3; i_sommet++)
1053 {
1054 int n = static_cast<int>(points_fa7_originale_unique.size());
1055 for (index_point = 0; index_point < n; index_point++)
1056 {
1057 Point3D point_liste = points_fa7_originale_unique[index_point];
1058 Point3D point_triangle = {triangle_initiaux_(ifaforsom, i_sommet, 0),triangle_initiaux_(ifaforsom, i_sommet, 1),triangle_initiaux_(ifaforsom, i_sommet, 2)};
1059 if(point_liste==point_triangle)
1060 {
1061 points_triangle_originaux(ifaforsom, i_sommet)=index_point;
1062 }
1063 }
1064 }
1065 }
1066
1067 // Check si la structure initiale de triangle est complete
1068 // Pour ca on verifie que chaque points est partage par au moins 2 triangles
1069 // Sinon cela veut dire quil y a des trous (cela peut arriver en // rarement). La source de lerreur est encore a chercher
1070 // Dans le cas dune structure incomplete, on interpole rien car ca peut donner nimporte quoi.
1071 // On impose la concentration moyenne de la structure partout.
1072 bool structure_complete = true;
1073 int n = static_cast<int>(points_fa7_originale_unique.size());
1074 for (int index_point = 0; index_point < n; index_point++)
1075 {
1076 int nb_triangle = 0;
1077 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1078 {
1079 for (int i_sommet = 0; i_sommet < 3; i_sommet++)
1080 {
1081 if (points_triangle_originaux(ifaforsom, i_sommet)==index_point)
1082 {
1083 nb_triangle+=1;
1084 }
1085 }
1086 }
1087 if (nb_triangle<2)
1088 {
1089 structure_complete=false;
1090 }
1091 }
1092 if(!structure_complete)
1093 {
1094 std::cout << "WARNING : structure incomplete de fa7 pour le remaillage surfactant" << std::endl;
1095 std::cout << "la concentration initiale moyenne est appliquee a toute la structure en question" << std::endl;
1096 std::cout << "Cela peut provoquer des erreurs de conservation" << std::endl;
1097 }
1098
1099 // on calcule ensuite les intersections des triangles
1100 DoubleTab Surface_intersection(nb_triangle_fin, nb_triangle_init);
1101 DoubleTab Surface_fa7init(nb_triangle_init);
1102 DoubleTab Surface_fa7fin(nb_triangle_fin);
1103 IntTab normale_triangle_originaux(nb_triangle_init);
1104 IntTab normale_triangle_finaux(nb_triangle_fin);
1105 Calculate_Facette_Intersection_Area(Surface_fa7init, Surface_fa7fin, Surface_intersection, points_fa7_originale_unique, points_fa7_finale_unique, points_triangle_originaux, points_triangle_finaux,normale_triangle_originaux,normale_triangle_finaux);
1106
1107
1108 // on calcule les surfactants a ajouter au fa7 finale de maniere conservative
1109
1110 surfactant_copy.resize(facettes_sommets_full_compo_.dimension(0));
1111 for (int fa = 0; fa < facettes_sommets_full_compo_.dimension(0); fa++)
1112 surfactant_copy(fa)=0.;
1113
1114
1115 // on calcule l'orientation principale (normale exterieur)
1116
1117 int orientation_principale = 0;
1118 for (int tf = 0; tf < nb_triangle_fin; tf++)
1119 {
1120 orientation_principale+=normale_triangle_finaux(tf);
1121 }
1122 if (orientation_principale>=0)
1123 orientation_principale = 1;
1124 else
1125 orientation_principale = -1;
1126
1127
1128 // on calcule la quantite de surfactant sur la structure finale a partir des intersection calculee
1129 ArrOfDouble surfactant_final(nb_triangle_fin);
1130
1131
1132 if (structure_complete)
1133 {
1134 for (int tf = 0; tf < nb_triangle_fin; tf++)
1135 {
1136 int fa7 = indice_facette_finaux_(tf);
1137
1138 double surfactant_facette_finale=0.;
1139 for (int to = 0; to < nb_triangle_init; to++)
1140 {
1141 if(normale_triangle_finaux(tf) == orientation_principale)
1142 {
1143 surfactant_facette_finale+=Surfactant_facette_initiale_(to)*Surface_intersection(tf, to)/Surface_fa7init[to];
1144 }
1145 }
1146 surfactant_copy(fa7) = surfactant_facette_finale ;
1147 surfactant_final(tf) = surfactant_facette_finale ;
1148 }
1149
1150 double reste_surfactant = 0.;
1151 double tot_surfactant = 0.;
1152 for (int to = 0; to < nb_triangle_init; to++)
1153 {
1154 tot_surfactant+=Surfactant_facette_initiale_(to);
1155 }
1156 reste_surfactant = tot_surfactant;
1157 for (int tf = 0; tf < nb_triangle_fin; tf++)
1158 {
1159 reste_surfactant-=surfactant_final(tf);
1160 }
1161
1162 // on calcule les surfaces pour lesquelles ont a pas trouve dintersection (et qui explique le bilan non conservatif de surfactant)
1163 double surface_finale_manquante = 0. ;
1164 double surface_structure_finale = 0.;
1165 for (int tf = 0; tf < Surface_fa7fin.size_array(); tf++)
1166 {
1167 double conservation = 0. ;
1168 if(normale_triangle_finaux(tf) == orientation_principale)
1169 {
1170 surface_structure_finale+=Surface_fa7fin[tf];
1171 }
1172 for (int to = 0; to < Surface_fa7init.size_array(); to++)
1173 {
1174 if(normale_triangle_finaux(tf) == orientation_principale)
1175 conservation += Surface_intersection(tf,to);
1176 }
1177 conservation/=Surface_fa7fin[tf];
1178 if (abs(conservation-1.)>1.e-8)
1179 {
1180 if(normale_triangle_finaux(tf) == orientation_principale)
1181 surface_finale_manquante += (1.-conservation)*Surface_fa7fin[tf];
1182 }
1183 }
1184
1185
1186 for (int tf = 0; tf < Surface_fa7fin.size_array(); tf++)
1187 {
1188 double conservation = 0. ;
1189 for (int to = 0; to < Surface_fa7init.size_array(); to++)
1190 {
1191 if(normale_triangle_finaux(tf) == orientation_principale)
1192 conservation += Surface_intersection(tf,to);
1193 }
1194 conservation/=Surface_fa7fin[tf];
1195
1196 // si reste_surfactant!= 0. et surface_finale_manquante != 0.
1197 // alors on est dans le cas d'une structure particuliere non parfaitement convexe
1198 // Les intersections peuvent donc ne pas etre complete
1199 // Normalement, la quantite de surfactant qui doit combler les intersections manquantes
1200 // vient de structures voisines (tres complique a mettre en place pour des evenements qui ne se produisent quasiment jamais)
1201 // Pour simplifier, on redistribue ce qui manque sur ces surfaces manquantes
1202 // Cela permet dassurer la conservation
1203 if (surface_finale_manquante!=0.)
1204 {
1205 if(normale_triangle_finaux(tf) == orientation_principale)
1206 {
1207 surfactant_final(tf)+=reste_surfactant * ((1.-conservation) * Surface_fa7fin[tf]/surface_finale_manquante) ;
1208 int fa7 = indice_facette_finaux_(tf);
1209 surfactant_copy(fa7) = surfactant_final(tf);
1210 }
1211 }
1212 else
1213 {
1214 // Il peut encore rester des surfactants non distribues meme si conservation == 1
1215 // Dans le cas d'une maille retournee initiale rebarycentree
1216 // La structure initiale peut alors avoir une surface projetee plus grande que la structure finale (inverse du cas précedent de la structure convexe pour lequel Sfin > Sinit)
1217 // La totalite de la surface des mailles finale trouvent une intersection
1218 // Mais des bouts de surface initiale peuvent disparaitre
1219 // On redistribue ces bouts-là sur les mailles de la structure finale
1220 if(normale_triangle_finaux(tf) == orientation_principale)
1221 {
1222 surfactant_final(tf)+=reste_surfactant * Surface_fa7fin[tf] / surface_structure_finale ;
1223 int fa7 = indice_facette_finaux_(tf);
1224 surfactant_copy(fa7) = surfactant_final(tf);
1225 }
1226 }
1227 }
1228 }
1229 else
1230 {
1231 // Paliatif pour structure incomplete (quil faudrait debug)
1232 // on impose la concentration moyenne de la structure initiale partout
1233 // Cela peut generer des erreurs de conservation
1234 double quantite_surf = 0.;
1235 double surf_tot = 0.;
1236 for (int to = 0; to < nb_triangle_init; to++)
1237 {
1238 if (nb_triangle_init>2)
1239 {
1240 if(normale_triangle_finaux(to) == orientation_principale)
1241 {
1242 quantite_surf += Surfactant_facette_initiale_(to);
1243 surf_tot += Surface_fa7init[to];
1244 }
1245 }
1246 else
1247 {
1248 quantite_surf += Surfactant_facette_initiale_(to);
1249 surf_tot += Surface_fa7init[to];
1250 }
1251 }
1252
1253 for (int tf = 0; tf < nb_triangle_fin; tf++)
1254 {
1255 int fa7 = indice_facette_finaux_(tf);
1256 surfactant_copy(fa7) = (quantite_surf/surf_tot)*Surface_fa7fin[tf] ;
1257 surfactant_final(tf) = (quantite_surf/surf_tot)*Surface_fa7fin[tf] ;
1258 }
1259 }
1260
1261 for (int tf = 0; tf < nb_triangle_fin; tf++)
1262 {
1263 int fa7 = indice_facette_finaux_(tf);
1264 facettes_sommets_full_compo_(fa7,9)=surfactant_copy(fa7);
1265 }
1266
1267 // option d ecriture dans le cout pour debugage si necessaire
1268 if (print_debug_surfactant_)
1269 {
1270 double min_surfactant_init = 1.e+10;
1271 double max_surfactant_init = -1.e+10;
1272 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1273 {
1274 if (normale_triangle_originaux(ifaforsom)==orientation_principale)
1275 {
1276 Point3D p1 = {triangle_initiaux_(ifaforsom, 0, 0), triangle_initiaux_(ifaforsom, 0, 1), triangle_initiaux_(ifaforsom, 0, 2)};
1277 Point3D p2 = {triangle_initiaux_(ifaforsom, 1, 0), triangle_initiaux_(ifaforsom, 1, 1), triangle_initiaux_(ifaforsom, 1, 2)};
1278 Point3D p3 = {triangle_initiaux_(ifaforsom, 2, 0), triangle_initiaux_(ifaforsom, 2, 1), triangle_initiaux_(ifaforsom, 2, 2)};
1279 double S = triangleArea3D( p1, p2, p3);
1280 if (Surfactant_facette_initiale_(ifaforsom)/S > max_surfactant_init)
1281 max_surfactant_init = Surfactant_facette_initiale_(ifaforsom)/S;
1282 if (Surfactant_facette_initiale_(ifaforsom)/S < min_surfactant_init)
1283 min_surfactant_init = Surfactant_facette_initiale_(ifaforsom)/S;
1284 }
1285 }
1286
1287 bool bizarre = false;
1288 for (int ifaforsom = 0; ifaforsom < nb_triangle_fin; ifaforsom++)
1289 {
1290 if (normale_triangle_finaux(ifaforsom)==orientation_principale)
1291 {
1292 Point3D p1 = {triangle_finaux_(ifaforsom, 0, 0), triangle_finaux_(ifaforsom, 0, 1), triangle_finaux_(ifaforsom, 0, 2)};
1293 Point3D p2 = {triangle_finaux_(ifaforsom, 1, 0), triangle_finaux_(ifaforsom, 1, 1), triangle_finaux_(ifaforsom, 1, 2)};
1294 Point3D p3 = {triangle_finaux_(ifaforsom, 2, 0), triangle_finaux_(ifaforsom, 2, 1), triangle_finaux_(ifaforsom, 2, 2)};
1295 double S = triangleArea3D( p1, p2, p3);
1296 if(surfactant_final(ifaforsom)/S > max_surfactant_init*1.5)
1297 bizarre = true;
1298 }
1299 }
1300
1301 if (bizarre)
1302 {
1303 std::cout << " valeur anormale de surfactant " <<std::endl;
1304
1305 std::cout << "normale initiaux : " <<std::endl;
1306 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1307 {
1308 std::cout << normale_triangle_originaux(ifaforsom) << std::endl;
1309 }
1310 std::cout <<std::endl;
1311 std::cout << "normale finale : " <<std::endl;
1312 for (int ifaforsom = 0; ifaforsom < nb_triangle_fin; ifaforsom++)
1313 {
1314 std::cout << normale_triangle_finaux(ifaforsom) << std::endl;
1315 }
1316 std::cout <<std::endl;
1317
1318 std::cout << "triangle initiaux : "<<std::endl;
1319 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1320 {
1321 //indice_facette_initiaux(i, ifaforsom);
1322 int i_sommet ;
1323 std::cout << "[" ;
1324 for (i_sommet = 0; i_sommet < 3; i_sommet++)
1325 std::cout << "[ " << triangle_initiaux_(ifaforsom, i_sommet, 0) << "," << triangle_initiaux_(ifaforsom, i_sommet, 1) << "," << triangle_initiaux_(ifaforsom, i_sommet, 2) << "],";
1326 std::cout << "],"<<std::endl;
1327 }
1328 std::cout << "triangle finaux : " <<std::endl;
1329 for (int ifaforsom = 0; ifaforsom < nb_triangle_fin; ifaforsom++)
1330 {
1331 //indice_facette_initiaux(i, ifaforsom);
1332 int i_sommet ;
1333 std::cout << "[" ;
1334 for (i_sommet = 0; i_sommet < 3; i_sommet++)
1335 std::cout << "[ " << triangle_finaux_(ifaforsom, i_sommet, 0) << "," << triangle_finaux_(ifaforsom, i_sommet, 1) << "," << triangle_finaux_(ifaforsom, i_sommet, 2)<< "],";
1336 std::cout << "],"<<std::endl;
1337 }
1338 std::cout << "Surfactant initiaux : " <<std::endl;
1339 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1340 {
1341 std::cout << Surfactant_facette_initiale_(ifaforsom) << std::endl;
1342 }
1343 std::cout <<std::endl;
1344
1345 std::cout << "Surfactant initiaux / Sfa7: " <<std::endl;
1346 for (int ifaforsom = 0; ifaforsom < nb_triangle_init; ifaforsom++)
1347 {
1348 Point3D p1 = {triangle_initiaux_(ifaforsom, 0, 0), triangle_initiaux_(ifaforsom, 0, 1), triangle_initiaux_(ifaforsom, 0, 2)};
1349 Point3D p2 = {triangle_initiaux_(ifaforsom, 1, 0), triangle_initiaux_(ifaforsom, 1, 1), triangle_initiaux_(ifaforsom, 1, 2)};
1350 Point3D p3 = {triangle_initiaux_(ifaforsom, 2, 0), triangle_initiaux_(ifaforsom, 2, 1), triangle_initiaux_(ifaforsom, 2, 2)};
1351 double S = triangleArea3D( p1, p2, p3);
1352 std::cout << Surfactant_facette_initiale_(ifaforsom)/S << std::endl;
1353 }
1354 std::cout <<std::endl;
1355
1356 std::cout << "Surfactant finaux / Sfa7: " <<std::endl;
1357 for (int ifaforsom = 0; ifaforsom < nb_triangle_fin; ifaforsom++)
1358 {
1359 Point3D p1 = {triangle_finaux_(ifaforsom, 0, 0), triangle_finaux_(ifaforsom, 0, 1), triangle_finaux_(ifaforsom, 0, 2)};
1360 Point3D p2 = {triangle_finaux_(ifaforsom, 1, 0), triangle_finaux_(ifaforsom, 1, 1), triangle_finaux_(ifaforsom, 1, 2)};
1361 Point3D p3 = {triangle_finaux_(ifaforsom, 2, 0), triangle_finaux_(ifaforsom, 2, 1), triangle_finaux_(ifaforsom, 2, 2)};
1362 double S = triangleArea3D( p1, p2, p3);
1363 std::cout << surfactant_final(ifaforsom)/S << std::endl;
1364 }
1365 std::cout <<std::endl;
1366
1367 std::cout << "indice facette finaux : " <<std::endl;
1368 for (int ifaforsom = 0; ifaforsom < nb_triangle_fin; ifaforsom++)
1369 {
1370 std::cout << indice_facette_finaux_(ifaforsom) << std::endl;
1371 }
1372 std::cout <<std::endl;
1373
1374 for (const auto &point : Surface_fa7fin)
1375 {
1376 cout << "Surface fa7 fin = " << point << endl;
1377 }
1378 cout << endl;
1379 for (const auto &point : Surface_fa7init)
1380 {
1381 cout << "Surface fa7 init = " << point << endl;
1382 }
1383 cout << endl;
1384
1385 for (int tf = 0; tf < Surface_fa7fin.size_array(); tf++)
1386 {
1387 for (int to = 0; to < Surface_fa7init.size_array(); to++)
1388 {
1389 cout << "Intersection normalisee " << tf << " / " << to << " = " << Surface_intersection(tf,to)/Surface_fa7fin[tf] << std::endl;
1390 }
1391 }
1392 cout << endl;
1393
1394 for (int tf = 0; tf < Surface_fa7fin.size_array(); tf++)
1395 {
1396 double conservation = 0. ;
1397 for (int to = 0; to < Surface_fa7init.size_array(); to++)
1398 {
1399 if(normale_triangle_finaux(tf) == orientation_principale)
1400 conservation += Surface_intersection(tf,to);
1401 }
1402 conservation/=Surface_fa7fin[tf];
1403 Process::Journal() << "conservation de la surface apres calcul des intersections remaillage pour le triangle final " << tf << " vaut " << conservation << std::endl;
1404 std::cout << "conservation de la surface apres calcul des intersections remaillage pour le triangle final " << tf << " vaut " << conservation << std::endl;
1405
1406
1407 }
1408 }
1409 }
1410}
1411
1413{
1414 // calcule la quantite totale de surfactant pour chaque compo_connexe
1415 const int nbfa7=mesh.nb_facettes();
1416 const ArrOfInt& compo_connex = mesh.compo_connexe_facettes();
1417 const ArrOfDouble& Sfa7 = mesh.get_update_surface_facettes();
1418
1419 int nb_bulles_reelles = 0 ;
1420 if (compo_connex.size_array()!=0)
1421 nb_bulles_reelles = max_array(compo_connex);
1422 nb_bulles_reelles = Process::mp_max(nb_bulles_reelles) + 1;
1423 ArrOfDouble Surfactant_par_compo(nb_bulles_reelles);
1424 for (int fa7=0 ; fa7<nbfa7 ; fa7++)
1425 {
1426 if(! mesh.facette_virtuelle(fa7) and compo_connex(fa7)>=0)
1427 {
1428 Surfactant_par_compo(compo_connex(fa7))+=FT_field_Array_(fa7)*Sfa7(fa7);
1429 }
1430 }
1431 for (int bulle=0 ; bulle<nb_bulles_reelles ; bulle++)
1432 {
1433 Surfactant_par_compo(bulle) = Process::mp_sum(Surfactant_par_compo(bulle));
1434 }
1435 return Surfactant_par_compo;
1436}
1437
1438void FT_Field::correction_conservation_globale(const Maillage_FT_IJK& mesh, const ArrOfDouble& surfactant_avant_remaillage, const ArrOfDouble& surfactant_apres_remaillage)
1439{
1440 // redistribue l'erreur de conservation sur l'ensemble des facettes (par compo)
1441 // A eviter dutiliser. Cela signifie qu'une erreur de conservation locale a ete faite
1442 if(patch_conservation_surfactant_globale_)
1443 {
1444 const int nbfa7=mesh.nb_facettes();
1445 const ArrOfInt& compo_connex = mesh.compo_connexe_facettes();
1446 const ArrOfDouble& Sfa7 = mesh.get_surface_facettes();
1447
1448 int nb_bulles_reelles = 0 ;
1449 if (compo_connex.size_array()!=0)
1450 nb_bulles_reelles = max_array(compo_connex);
1451 nb_bulles_reelles = Process::mp_max(nb_bulles_reelles) + 1;
1452 ArrOfDouble Surface_par_compo(nb_bulles_reelles);
1453
1454 for (int fa7=0 ; fa7<nbfa7 ; fa7++)
1455 {
1456 if(! mesh.facette_virtuelle(fa7) and compo_connex(fa7)>=0)
1457 {
1458 Surface_par_compo(compo_connex(fa7))+=Sfa7(fa7);
1459 }
1460 }
1461 for (int bulle=0 ; bulle<nb_bulles_reelles ; bulle++)
1462 {
1463 Surface_par_compo(bulle) = Process::mp_sum(Surface_par_compo(bulle));
1464 }
1465
1466 for (int fa7=0 ; fa7<nbfa7 ; fa7++)
1467 {
1468 if(! mesh.facette_virtuelle(fa7) and compo_connex(fa7)>=0)
1469 {
1470 FT_field_Array_(fa7) -= (surfactant_apres_remaillage(compo_connex(fa7))-surfactant_avant_remaillage(compo_connex(fa7)))/max(1.e-8,Surface_par_compo(compo_connex(fa7)));
1471 }
1472 }
1473
1474 ArrOfDouble apres_correction = check_conservation(mesh);
1475 std::cout << "Apres correction" << std::endl;
1476 for (int bulle=0 ; bulle<nb_bulles_reelles ; bulle++)
1477 {
1478 double percent_error = 100.*(apres_correction(bulle)-surfactant_avant_remaillage(bulle))/max(1.e-8,apres_correction(bulle)) ;
1479 std::cout << " compo connex " << bulle << " = " << percent_error <<" %" << std::endl;
1480 }
1481 }
1482}
1483
1484bool FT_Field::is_compo_in_proc(const int compo_connexe, const int pe_send)
1485{
1486// renvoie true sur la compo est dans le proc pe_send, false sinon
1487 int index_proc = -1 ;
1488 for (int proc = 0; proc < proc_numero_.size_array(); proc++)
1489 {
1490 if (proc_numero_(proc)==pe_send)
1491 {
1492 index_proc = proc ;
1493 }
1494 }
1495 if (index_proc==-1)
1496 {
1497 std::cout << "ERREUR : ne trouve pas avec quel proc echanger des compo_connexe" << std::endl;
1498 Process::exit();
1499 }
1500
1501 for (int compo = 0; compo < compo_transmises_a_envoyer_.dimension(1); compo++)
1502 {
1503 if(compo_transmises_a_envoyer_(index_proc, compo)-1 == compo_connexe)
1504 return true;
1505 }
1506 return false;
1507}
1508
1509
1510void FT_Field::champ_sommet_from_facettes(const ArrOfInt& compo_connexe_facettes, const Maillage_FT_IJK& mesh)
1511{
1512 compo_connexe_sommets_.resize(mesh.nb_sommets());
1513 const int nbfa = compo_connexe_facettes.size_array();
1514 const IntTab& facettes=mesh.facettes();
1515 for (int fa7=0 ; fa7<nbfa ; fa7++)
1516 {
1517 if(! mesh.facette_virtuelle(fa7))
1518 {
1519 for (int sommet_fa7=0 ; sommet_fa7<3 ; sommet_fa7++)
1520 {
1521 int indice_sommet = facettes(fa7,sommet_fa7);
1522 compo_connexe_sommets_[indice_sommet] = compo_connexe_facettes(fa7);
1523 }
1524 }
1525 }
1526 const Desc_Structure_FT& desc_sommets = mesh.desc_sommets();
1527 desc_sommets.collecter_espace_virtuel(compo_connexe_sommets_, MD_Vector_tools::EV_MAX);
1528}
1529
1530
1532{
1533 for (int proc_deja_sauv = 0; proc_deja_sauv < proc_deja_echange_.size_array(); proc_deja_sauv++)
1534 {
1535 if (proc_deja_echange_(proc_deja_sauv)==pe)
1536 {
1537 return true;
1538 }
1539 }
1540 nb_proc_echange_++;
1541 proc_deja_echange_.resize(nb_proc_echange_);
1542 proc_deja_echange_(nb_proc_echange_-1) = pe;
1543 return false;
1544}
1545
1547{
1548 for (int fa = 0; fa < mesh.nb_facettes(); fa++)
1549 FT_field_Array_(fa) = -123.;
1550
1551 int index_init = index_local_Ft_field_;
1552 for (int fa = 0; fa < mesh.nb_facettes(); fa++)
1553 {
1554 index_init++;
1555 const int indice_fa_locale = int(facettes_sommets_full_compo_(index_init, 10));
1556 FT_field_Array_(indice_fa_locale) = facettes_sommets_full_compo_(index_init, 9);
1557 }
1558}
1559
1560
1561void FT_Field::completer_compo_connexe_partielle(const Maillage_FT_IJK& mesh, const Domaine_IJK& splitting, const DoubleTab& liste_sommets_apres_deplacement, const DoubleTab& liste_sommets_avant_deplacement, const ArrOfInt& compo_connexe_sommets_deplace)
1562{
1563// Version de la methode qui prend en argument :
1564// la liste des coordonnees de sommets avant deplacement
1565// la liste des coordonnees de sommets apres deplacement
1566// la liste contenant la compo_connexe associee
1567// permet de mutualiser la methode pour le remaillage (supprimer petites arretes) et pour le barycentrage.
1568// Cette methode complete les tableaux facettes_sommets_full_compo_ et liste_sommets_et_deplacements_.
1569// Les tableaux contiennent alors la totalite des informations de toutes les composantes connexes qui traversent le proc (position des sommets, deplacement, facette).
1570// Mais il n'y a plus d'information sur l'indexation locale
1571
1572 if (!((liste_sommets_apres_deplacement.dimension(0) == liste_sommets_avant_deplacement.dimension(0)) and (liste_sommets_avant_deplacement.dimension(0) == compo_connexe_sommets_deplace.size_array())))
1573 {
1574 std::cout << "Erreur dans completer_compo_connexe_partielle : les tableaux en arguments ne font pas tous la meme taille" << std::endl;
1575 Process::exit();
1576 }
1577 const ArrOfInt& compo_connex = mesh.compo_connexe_facettes();
1578 champ_sommet_from_facettes(compo_connex, mesh);
1579
1580 IntVect slice_3D(3) ;
1581 IntVect N_3D(3) ;
1582 for (int dir = 0; dir < 3; dir++)
1583 {
1584 slice_3D(dir)= splitting.get_local_slice_index(dir);
1585 N_3D(dir)=splitting.get_nprocessor_per_direction(dir);
1586 }
1587
1588 nb_proc_echange_=0;
1589 nb_compo_a_envoyer_max_=0;
1590 proc_deja_echange_.resize(0);
1591 proc_numero_.resize(0);
1592 compo_transmises_a_envoyer_.resize(0, 0);
1593 // on boucle sur l'ensemble des proc_voisins dans chaque direction (voisin face/arrete/coin)
1594 // compatible tri-periodique
1595 // on echange les compo_connexe concernees
1596 for (int iproc = -1; iproc < 2; iproc++)
1597 {
1598 for (int jproc = -1; jproc < 2; jproc++)
1599 {
1600 for (int kproc = -1; kproc < 2; kproc++)
1601 {
1602 int pe_send = splitting.get_processor_by_ijk(((slice_3D(0)-iproc)%N_3D(0)+N_3D(0))%N_3D(0), ((slice_3D(1)-jproc)%N_3D(1)+N_3D(1))%N_3D(1), ((slice_3D(2)-kproc)%N_3D(2)+N_3D(2))%N_3D(2));
1603 int pe_rcdv = splitting.get_processor_by_ijk(((slice_3D(0)+iproc)%N_3D(0)+N_3D(0))%N_3D(0), ((slice_3D(1)+jproc)%N_3D(1)+N_3D(1))%N_3D(1), ((slice_3D(2)+kproc)%N_3D(2)+N_3D(2))%N_3D(2));
1604 exchange_compo_connexe(pe_send, pe_rcdv, mesh);
1605 }
1606 }
1607 }
1608
1609 // On connait les compo connex a echanger
1610 // On peut maintenant echanger les donnees
1611 // on remet le tableau des echange realises a 0
1612 nb_proc_echange_=0;
1613 proc_deja_echange_.resize(0);
1614 facettes_sommets_full_compo_.resize(0, 0);
1615 liste_sommets_et_deplacements_.resize(0,0);
1616 int moi = splitting.get_processor_by_ijk(slice_3D(0), slice_3D(1), slice_3D(2));
1617 exchange_data(moi, moi, mesh, liste_sommets_avant_deplacement, liste_sommets_apres_deplacement, compo_connexe_sommets_deplace);
1618
1619 for (int iproc = -1; iproc < 2; iproc++)
1620 {
1621 for (int jproc = -1; jproc < 2; jproc++)
1622 {
1623 for (int kproc = -1; kproc < 2; kproc++)
1624 {
1625 int pe_send = splitting.get_processor_by_ijk(((slice_3D(0)-iproc)%N_3D(0)+N_3D(0))%N_3D(0), ((slice_3D(1)-jproc)%N_3D(1)+N_3D(1))%N_3D(1), ((slice_3D(2)-kproc)%N_3D(2)+N_3D(2))%N_3D(2));
1626 int pe_rcdv = splitting.get_processor_by_ijk(((slice_3D(0)+iproc)%N_3D(0)+N_3D(0))%N_3D(0), ((slice_3D(1)+jproc)%N_3D(1)+N_3D(1))%N_3D(1), ((slice_3D(2)+kproc)%N_3D(2)+N_3D(2))%N_3D(2));
1627 if (!(pe_send==moi and pe_rcdv==moi))
1628 exchange_data(pe_send, pe_rcdv, mesh, liste_sommets_avant_deplacement, liste_sommets_apres_deplacement, compo_connexe_sommets_deplace);
1629 }
1630 }
1631 }
1632
1633 // on supprime les eventuels doublons pour que chaque proc ait bien la meme chose
1634 // necessaire car on a echange certaines valeurs virtuelles pour etre sur de perdre personne
1635 // on demarre a partir de nb_facettes() pour etre sûr que les donnes du proc courant ne seront pas supprimees
1636 /* double tol_sauv = get_tolerance_point_identique();
1637 set_tolerance_point_identique(tol_sauv/100.);
1638
1639 std::cout << "avant suppression doublons = " << facettes_sommets_full_compo_.dimension(0) << std::endl;
1640 int size_init = facettes_sommets_full_compo_.dimension(0);
1641 {
1642 for (int index = mesh.nb_facettes() ; index < size_init; index++)
1643 {
1644 for (int index2 = index + 1 ; index2 < size_init; )
1645 {
1646 Point3D p1ref= {facettes_sommets_full_compo_(index, 0),facettes_sommets_full_compo_(index, 1),facettes_sommets_full_compo_(index, 2)};
1647 Point3D p2ref= {facettes_sommets_full_compo_(index, 3),facettes_sommets_full_compo_(index, 4),facettes_sommets_full_compo_(index, 5)};
1648 Point3D p3ref= {facettes_sommets_full_compo_(index, 6),facettes_sommets_full_compo_(index, 7),facettes_sommets_full_compo_(index, 8)};
1649
1650 Point3D p1ref2= {facettes_sommets_full_compo_(index2, 0),facettes_sommets_full_compo_(index2, 1),facettes_sommets_full_compo_(index2, 2)};
1651 Point3D p2ref2= {facettes_sommets_full_compo_(index2, 3),facettes_sommets_full_compo_(index2, 4),facettes_sommets_full_compo_(index2, 5)};
1652 Point3D p3ref2= {facettes_sommets_full_compo_(index2, 6),facettes_sommets_full_compo_(index2, 7),facettes_sommets_full_compo_(index2, 8)};
1653 double faref = facettes_sommets_full_compo_(index, 9);
1654 double faref2 = facettes_sommets_full_compo_(index2, 9);
1655 if(p1ref==p1ref2 and p2ref==p2ref2 and p3ref==p3ref2 and abs(faref-faref2)<1.e-10)
1656 {
1657 std::cout << "triangle sup = " << " " << facettes_sommets_full_compo_(index, 0) << " " << facettes_sommets_full_compo_(index, 1) << " " << facettes_sommets_full_compo_(index, 2) << " " << facettes_sommets_full_compo_(index, 3) << " " << facettes_sommets_full_compo_(index, 4) << facettes_sommets_full_compo_(index, 5) << " " << facettes_sommets_full_compo_(index, 6)<< " " <<facettes_sommets_full_compo_(index, 7)<< " " <<facettes_sommets_full_compo_(index, 8) << " " << facettes_sommets_full_compo_(index, 9) << std::endl ;
1658 for (int k = index2; k < size_init - 1; ++k)
1659 for (int item = 0 ; item < facettes_sommets_full_compo_.dimension(1); item++)
1660 facettes_sommets_full_compo_(k, item)=facettes_sommets_full_compo_(k+1, item);
1661
1662 --size_init;
1663 }
1664 else
1665 {
1666 ++index2;
1667 }
1668 }
1669 }
1670 }
1671 facettes_sommets_full_compo_.resize(size_init, facettes_sommets_full_compo_.dimension(1));
1672 std::cout << "apres suppression doublons = " << facettes_sommets_full_compo_.dimension(0) << std::endl;
1673
1674 size_init = liste_sommets_et_deplacements_.dimension(0);
1675 for (int index = 0 ; index < size_init; index++)
1676 {
1677 for (int index2 = index + 1 ; index2 < size_init; )
1678 {
1679 Point3D p1ref= {liste_sommets_et_deplacements_(index, 0),liste_sommets_et_deplacements_(index, 1),liste_sommets_et_deplacements_(index, 2)};
1680 Point3D p1ref2= {liste_sommets_et_deplacements_(index2, 0),liste_sommets_et_deplacements_(index2, 1),liste_sommets_et_deplacements_(index2, 2)};
1681 if(p1ref==p1ref2)
1682 {
1683 for (int k = index2; k < size_init - 1; ++k)
1684 for (int item = 0 ; item < liste_sommets_et_deplacements_.dimension(1); item++)
1685 liste_sommets_et_deplacements_(k, item)=liste_sommets_et_deplacements_(k+1, item);
1686
1687 --size_init;
1688 }
1689 else
1690 {
1691 ++index2;
1692 }
1693 }
1694 }
1695 liste_sommets_et_deplacements_.resize(size_init, liste_sommets_et_deplacements_.dimension(1));
1696 set_tolerance_point_identique(tol_sauv);
1697
1698 */
1699 // si on veut etre sur que ca marche bien en //, il faut que chaque proc fasse les operations dans le meme ordre !
1700 // on peut trier liste_sommets_et_deplacements_full_compo selon par exemple, les normes des points deplaces
1701
1702 int n = liste_sommets_et_deplacements_.dimension(0);
1703 std::vector<double> arr(n);
1704 sorted_index_.resize(n);
1705 for (int item = 0; item < n; item++)
1706 {
1707 arr[item]=norme({liste_sommets_et_deplacements_(item,0),liste_sommets_et_deplacements_(item,1),liste_sommets_et_deplacements_(item,2)});
1708 }
1709 // Vector to store the sorted indices
1710 std::vector<long unsigned int> indices(n);
1711 // Sort the array and track indices
1712 sortAndTrackIndices(arr, indices);
1713 for (int item = 0; item < n; item++)
1714 {
1715 sorted_index_(item)=int(indices[item]);
1716 }
1717
1718 if (print_debug_surfactant_)
1719 {
1721 int nb_proc = splitting.get_nprocessor_per_direction(0)*splitting.get_nprocessor_per_direction(1)*splitting.get_nprocessor_per_direction(2);
1722 int ny = splitting.get_nprocessor_per_direction(1);
1723 int nz = splitting.get_nprocessor_per_direction(2);
1724 int x = splitting.get_local_slice_index(0);
1725 int y = splitting.get_local_slice_index(1);
1726 int z = splitting.get_local_slice_index(2);
1727 int proc_index = z + y * nz + x * ny * nz ;
1728 int index_global = 0;
1729 for (int proc = 0; proc < nb_proc; proc++)
1730 {
1731 index_global = Process::mp_max(index_global);
1733 if (proc == proc_index)
1734 {
1735 std::cout << "proc = " << proc_index << " total facette connues = " << facettes_sommets_full_compo_.dimension(0) << std::endl;
1736 std::cout << "proc = " << proc_index << " nb facette_local = " << mesh.nb_facettes() << std::endl;
1737 std::cout << "proc = " << proc_index << " total sommets connus = " << liste_sommets_et_deplacements_.dimension(0) << std::endl;
1738 std::cout << "proc = " << proc_index << " nb liste_sommets local = " << liste_sommets_apres_deplacement.dimension(0) << std::endl;
1739 std::cout << "proc = " << proc_index << " nb sommets local = " << mesh.nb_sommets() << std::endl;
1740 }
1741 }
1743 }
1744}
1745
1746Point3D FT_Field::calculer_normale_apres_deplacement(const int fa, const int somfa7, const Vecteur3 pos_apres_dep)
1747{
1748// si n = AB x AC
1749// alors AC' = n x AB doit etre dans la meme direction que AC original, soit AC'.AC > 0
1750// Soit AB le vecteur qui joint les deux premiers sommets
1751 Point3D AB = {facettes_sommets_full_compo_(fa, 3*1+0)-facettes_sommets_full_compo_(fa, 0),
1752 facettes_sommets_full_compo_(fa, 3*1+1)-facettes_sommets_full_compo_(fa, 1),
1753 facettes_sommets_full_compo_(fa, 3*1+2)-facettes_sommets_full_compo_(fa, 2)
1754 };
1755
1756 Point3D AC = {facettes_sommets_full_compo_(fa, 3*2+0)-facettes_sommets_full_compo_(fa, 0),
1757 facettes_sommets_full_compo_(fa, 3*2+1)-facettes_sommets_full_compo_(fa, 1),
1758 facettes_sommets_full_compo_(fa, 3*2+2)-facettes_sommets_full_compo_(fa, 2)
1759 };
1760 Point3D nrecon = crossProduct(AB, AC);
1761 Point3D nreel = {facettes_sommets_full_compo_(fa, 12),facettes_sommets_full_compo_(fa, 13),facettes_sommets_full_compo_(fa, 14)};
1762
1763 int A,B,C ;
1764 if (scalarProduct(nrecon,nreel)>=0.)
1765 {
1766 // alors on a la bonne definition du produit vectoriel qui donne n_reel
1767 A = 0;
1768 B = 1;
1769 C = 2;
1770 }
1771 else
1772 {
1773 // alors on a la definition inverse du produit vectoriel qui donne n_reel
1774 // il suffit d'inverse un vecteur pour obtenir la bonne
1775 A = 0;
1776 B = 2;
1777 C = 1;
1778 }
1779
1780// une fois obtenu, on peut reconstruire la nouvelle normale apres deplacement
1781
1782 if (somfa7==A)// sommet A qui bouge
1783 {
1784 AB = {facettes_sommets_full_compo_(fa, 3*B+0)-pos_apres_dep[0],
1785 facettes_sommets_full_compo_(fa, 3*B+1)-pos_apres_dep[1],
1786 facettes_sommets_full_compo_(fa, 3*B+2)-pos_apres_dep[2]
1787 };
1788 AC = {facettes_sommets_full_compo_(fa, 3*C+0)-pos_apres_dep[0],
1789 facettes_sommets_full_compo_(fa, 3*C+1)-pos_apres_dep[1],
1790 facettes_sommets_full_compo_(fa, 3*C+2)-pos_apres_dep[2]
1791 };
1792 }
1793 else if (somfa7==B)
1794 {
1795 AB = {pos_apres_dep[0]-facettes_sommets_full_compo_(fa, 3*A+0),
1796 pos_apres_dep[1]-facettes_sommets_full_compo_(fa, 3*A+1),
1797 pos_apres_dep[2]-facettes_sommets_full_compo_(fa, 3*A+2)
1798 };
1799 AC = {facettes_sommets_full_compo_(fa, 3*C+0)-facettes_sommets_full_compo_(fa, 3*A+0),
1800 facettes_sommets_full_compo_(fa, 3*C+1)-facettes_sommets_full_compo_(fa, 3*A+1),
1801 facettes_sommets_full_compo_(fa, 3*C+2)-facettes_sommets_full_compo_(fa, 3*A+2)
1802 };
1803 }
1804 else if (somfa7==C)
1805 {
1806 AB = {facettes_sommets_full_compo_(fa, 3*B+0)-facettes_sommets_full_compo_(fa, 3*A+0),
1807 facettes_sommets_full_compo_(fa, 3*B+1)-facettes_sommets_full_compo_(fa, 3*A+1),
1808 facettes_sommets_full_compo_(fa, 3*B+2)-facettes_sommets_full_compo_(fa, 3*A+2)
1809 };
1810 AC = {pos_apres_dep[0]-facettes_sommets_full_compo_(fa, 3*A+0),
1811 pos_apres_dep[1]-facettes_sommets_full_compo_(fa, 3*A+1),
1812 pos_apres_dep[2]-facettes_sommets_full_compo_(fa, 3*A+2)
1813 };
1814 }
1815 return crossProduct(AB, AC);
1816}
1817
1818void FT_Field::exchange_compo_connexe(int pe_send_, /* processor to send data */
1819 int pe_recv_ /* processor to received data */,
1820 const Maillage_FT_IJK& mesh)
1821{
1822 const ArrOfInt& compo_connexe_facettes=mesh.compo_connexe_facettes();
1823 if (pe_send_ == Process::me() && pe_recv_ == Process::me())
1824 {
1825 // Self (periodicity on same processor)
1826 return;
1827 }
1828
1829 bool echange_already_made = sauv_num_pe_echange(pe_send_);
1830 if (echange_already_made)
1831 {
1832 // ATTENTION : Dans le cas de calculs a faible nb de proc, les memes echanges risquent de se realiser plusieurs fois par periodicite des procs
1833 // Il faut s'assurer qu'on ne le fait qu'une seule fois
1834 return;
1835 }
1836
1837 // Le volume de donnees echangees ne sont pas connues a l'avance
1838 // On est oblige de faire l'echange en plusieurs etapes
1839 // 1 - Le proc partage le nb de compo_connexe qui le traverse
1840 // 2 - Le proc partage les valeurs des compo_connexe qui le traverse
1841
1842 const int int_size = sizeof(int);
1843 int *send_buffer_nb_compo_connexe = 0;
1844 int *recv_buffer_nb_compo_connexe = 0;
1845 int *send_buffer_compo_connexe = 0;
1846 int *recv_buffer_compo_connexe = 0;
1847 IntTab compo_to_send(1);
1848 compo_to_send(0)=-1000;
1849 int nb_compo_a_envoyer = 0;
1850 int nb_compo_recu = 0;
1851
1852 ////////////////////////////////// Stockage des compo connexe a envoyer
1853 if (pe_send_ >= 0)
1854 {
1855 for (int fa = 0; fa < mesh.nb_facettes(); fa++)
1856 {
1857 bool new_compo = true ;
1858 if (!mesh.facette_virtuelle(fa))
1859 {
1860 for (int compo_deja_sauv = 0; compo_deja_sauv < compo_to_send.size_array(); compo_deja_sauv++)
1861 {
1862 if(compo_connexe_facettes[fa]==compo_to_send(compo_deja_sauv))
1863 new_compo = false;
1864 break;
1865 }
1866 if(new_compo)
1867 {
1868 nb_compo_a_envoyer++;
1869 compo_to_send.resize(nb_compo_a_envoyer);
1870 compo_to_send(nb_compo_a_envoyer-1) = compo_connexe_facettes[fa];
1871 }
1872 }
1873 }
1874 }
1875
1876 if (pe_send_ >= 0)
1877 {
1878 ////////////////////// envoi du nb de compo connexe /////////////////////
1879 send_buffer_nb_compo_connexe = new int[1];
1880 int *buf_nb_compo_connexe = send_buffer_nb_compo_connexe;
1881 *buf_nb_compo_connexe = nb_compo_a_envoyer ;
1882 ////////////////////// envoi des compo connexe elle-meme /////////////////////
1883 send_buffer_compo_connexe = new int[nb_compo_a_envoyer];
1884 int *buf_compo_connexe = send_buffer_compo_connexe;
1885 for (int compo = 0; compo < nb_compo_a_envoyer; compo++, buf_compo_connexe++)
1886 *buf_compo_connexe = compo_to_send(compo);
1887
1888 }
1889
1890 ////////////////////// reception du nb de compo connexe /////////////////////
1891 if (pe_recv_ >= 0)
1892 {
1893 recv_buffer_nb_compo_connexe = new int[1];
1894 }
1895 ::envoyer_recevoir(send_buffer_nb_compo_connexe, int_size, pe_send_, recv_buffer_nb_compo_connexe, int_size, pe_recv_);
1896
1897 if (pe_recv_ >= 0)
1898 {
1899 int *buf_nb_compo_connexe = recv_buffer_nb_compo_connexe;
1900 nb_compo_recu = *buf_nb_compo_connexe;
1901 if (nb_compo_recu>nb_compo_a_envoyer_max_)
1902 nb_compo_a_envoyer_max_ = nb_compo_recu;
1903 }
1904
1905 ////////////////////// reception des compo connexe elle-memes /////////////////////
1906 if (pe_recv_ >= 0)
1907 {
1908 recv_buffer_compo_connexe = new int[nb_compo_recu];
1909 }
1910 ::envoyer_recevoir(send_buffer_compo_connexe, nb_compo_a_envoyer*int_size, pe_send_, recv_buffer_compo_connexe, nb_compo_recu*int_size, pe_recv_);
1911
1912 if (pe_recv_ >= 0)
1913 {
1914 // on stocke les compo+1 pour que les compo commence a 1 et pas 0
1915 // Les valeurs initalisees non changees reste donc a 0
1916 proc_numero_.resize(nb_proc_echange_);
1917 proc_numero_(nb_proc_echange_-1)=pe_recv_;
1918 compo_transmises_a_envoyer_.resize(nb_proc_echange_, nb_compo_a_envoyer_max_);
1919 int *buf_compo_connexe = recv_buffer_compo_connexe;
1920 for (int compo = 0; compo < nb_compo_recu; compo++, buf_compo_connexe++)
1921 compo_transmises_a_envoyer_(nb_proc_echange_-1, compo) = *buf_compo_connexe+1;
1922 }
1923
1924 delete[] send_buffer_nb_compo_connexe;
1925 delete[] recv_buffer_nb_compo_connexe;
1926 delete[] send_buffer_compo_connexe;
1927 delete[] recv_buffer_compo_connexe;
1928}
1929
1930void FT_Field::exchange_data(int pe_send_, /* processor to send data */
1931 int pe_recv_ /* processor to received data */,
1932 const Maillage_FT_IJK& mesh, const DoubleTab& liste_sommets_avant_deplacement, const DoubleTab& liste_sommets_apres_deplacement, const ArrOfInt& compo_connexe_sommets_deplace)
1933{
1934
1935 const DoubleTab& sommets=mesh.sommets();
1936 const IntTab& facettes=mesh.facettes();
1937 const ArrOfInt& compo_connexe_facettes=mesh.compo_connexe_facettes();
1938 const DoubleTab& normale_facette=mesh.get_update_normale_facettes();
1939 bool echange_already_made = sauv_num_pe_echange(pe_send_);
1940 if (echange_already_made)
1941 {
1942 // ATTENTION : Dans le cas de calculs a faible nb de proc, les memes echanges risquent de se realiser plusieurs fois par periodicite des procs
1943 // Il faut s'assurer qu'on ne le fait qu'une seule fois
1944 return;
1945 }
1946
1947 int dimensions_tab = 15;
1948 if (pe_send_ == Process::me() && pe_recv_ == Process::me())
1949 {
1950 // echange avec soi-meme, je remplis le tableau avec les valeurs locales deja connues
1951 int size_avant_echange = facettes_sommets_full_compo_.dimension(0);
1952 int new_size = size_avant_echange + mesh.nb_facettes() ;
1953 facettes_sommets_full_compo_.resize(new_size, dimensions_tab);
1954 int index = size_avant_echange-1;
1955 index_local_Ft_field_=index;
1956
1957 for (int fa = 0; fa < mesh.nb_facettes(); fa++)
1958 {
1959 //if (!mesh.facette_virtuelle(fa))
1960 {
1961 index++;
1962 facettes_sommets_full_compo_(index, 0) = sommets(facettes(fa, 0), 0) ;
1963 facettes_sommets_full_compo_(index, 1) = sommets(facettes(fa, 0), 1) ;
1964 facettes_sommets_full_compo_(index, 2) = sommets(facettes(fa, 0), 2) ;
1965 facettes_sommets_full_compo_(index, 3) = sommets(facettes(fa, 1), 0) ;
1966 facettes_sommets_full_compo_(index, 4) = sommets(facettes(fa, 1), 1) ;
1967 facettes_sommets_full_compo_(index, 5) = sommets(facettes(fa, 1), 2) ;
1968 facettes_sommets_full_compo_(index, 6) = sommets(facettes(fa, 2), 0) ;
1969 facettes_sommets_full_compo_(index, 7) = sommets(facettes(fa, 2), 1) ;
1970 facettes_sommets_full_compo_(index, 8) = sommets(facettes(fa, 2), 2) ;
1971 facettes_sommets_full_compo_(index, 9) = FT_field_Array_(fa);
1972 facettes_sommets_full_compo_(index, 10) = double(fa);
1973 if (!mesh.facette_virtuelle(fa))
1974 {
1975 facettes_sommets_full_compo_(index, 11) = 0.;
1976 }
1977 else
1978 {
1979 facettes_sommets_full_compo_(index, 11) = 1.;
1980 }
1981 facettes_sommets_full_compo_(index, 12) = normale_facette(fa, 0);
1982 facettes_sommets_full_compo_(index, 13) = normale_facette(fa, 1);
1983 facettes_sommets_full_compo_(index, 14) = normale_facette(fa, 2);
1984 }
1985 }
1986
1987
1988 size_avant_echange = liste_sommets_et_deplacements_.dimension(0);
1989 new_size = size_avant_echange + liste_sommets_avant_deplacement.dimension(0) ;
1990 liste_sommets_et_deplacements_.resize(new_size, 6);
1991 index = size_avant_echange-1;
1992 for (int som = 0; som < liste_sommets_avant_deplacement.dimension(0); som++)
1993 {
1994 index++;
1995 liste_sommets_et_deplacements_(index, 0) = liste_sommets_avant_deplacement(som, 0);
1996 liste_sommets_et_deplacements_(index, 1) = liste_sommets_avant_deplacement(som, 1);
1997 liste_sommets_et_deplacements_(index, 2) = liste_sommets_avant_deplacement(som, 2);
1998 liste_sommets_et_deplacements_(index, 3) = liste_sommets_apres_deplacement(som, 0);
1999 liste_sommets_et_deplacements_(index, 4) = liste_sommets_apres_deplacement(som, 1);
2000 liste_sommets_et_deplacements_(index, 5) = liste_sommets_apres_deplacement(som, 2);
2001 }
2002
2003 return;
2004 }
2005
2006 // Le volume de donnees echangees ne sont pas connues a l'avance
2007 // On est oblige de faire l'echange en plusieurs etapes
2008 // 1 - Une fois ces compo_connexe_connu, on repere les donnes a echanger
2009 // 2 - on transmet au proc le volume de donnees qu'il va recevoir
2010 // 3 - on transmet au proc les donnees elles-même
2011
2012 const int double_size = sizeof(double);
2013 const int int_size = sizeof(int);
2014 int *send_buffer_volume_facette = 0;
2015 int *recv_buffer_volume_facette = 0;
2016 int *send_buffer_volume_sommet = 0;
2017 int *recv_buffer_volume_sommet = 0;
2018 double *send_buffer_data_facette = 0;
2019 double *recv_buffer_data_facette = 0;
2020 double *send_buffer_data_sommet = 0;
2021 double *recv_buffer_data_sommet = 0;
2022 int nb_fa7_a_envoyer = 0;
2023 int nb_som_a_envoyer = 0;
2024
2025
2026 DoubleTab item_to_send_facette;
2027 DoubleTab item_to_send_sommet;
2028 int volume_donnees_facette_envoyees = 0;
2029 int volume_donnees_sommet_envoyees = 0;
2030 int volume_donnees_facette_recue = 0;
2031 int volume_donnees_sommet_recue = 0;
2032
2033 if (pe_send_ >= 0)
2034 {
2035 // A partir des compo_connexe recue, on cherche maintenant les donnes a envoyer
2036 // Cest a dire toute les donnees liees aux facettes dont la compo_connexe est partagee avec le proc a qui on partage
2037 // position des sommets qui compose la fa7 et quantite de surfactant associe a la fa7
2038 for (int fa = 0; fa < mesh.nb_facettes(); fa++)
2039 {
2040 if (!mesh.facette_virtuelle(fa) and is_compo_in_proc(compo_connexe_facettes[fa], pe_send_))
2041 {
2042 // alors il faut envoyer l'info de cette fa7
2043 nb_fa7_a_envoyer++;
2044 item_to_send_facette.resize(nb_fa7_a_envoyer, dimensions_tab);
2045 item_to_send_facette(nb_fa7_a_envoyer-1, 0) = sommets(facettes(fa, 0), 0) ;
2046 item_to_send_facette(nb_fa7_a_envoyer-1, 1) = sommets(facettes(fa, 0), 1) ;
2047 item_to_send_facette(nb_fa7_a_envoyer-1, 2) = sommets(facettes(fa, 0), 2) ;
2048 item_to_send_facette(nb_fa7_a_envoyer-1, 3) = sommets(facettes(fa, 1), 0) ;
2049 item_to_send_facette(nb_fa7_a_envoyer-1, 4) = sommets(facettes(fa, 1), 1) ;
2050 item_to_send_facette(nb_fa7_a_envoyer-1, 5) = sommets(facettes(fa, 1), 2) ;
2051 item_to_send_facette(nb_fa7_a_envoyer-1, 6) = sommets(facettes(fa, 2), 0) ;
2052 item_to_send_facette(nb_fa7_a_envoyer-1, 7) = sommets(facettes(fa, 2), 1) ;
2053 item_to_send_facette(nb_fa7_a_envoyer-1, 8) = sommets(facettes(fa, 2), 2) ;
2054 item_to_send_facette(nb_fa7_a_envoyer-1, 9) = FT_field_Array_(fa);
2055 item_to_send_facette(nb_fa7_a_envoyer-1, 10) = -1.;
2056 item_to_send_facette(nb_fa7_a_envoyer-1, 11) = 0.;
2057 item_to_send_facette(nb_fa7_a_envoyer-1, 12) = normale_facette(fa, 0);
2058 item_to_send_facette(nb_fa7_a_envoyer-1, 13) = normale_facette(fa, 1);
2059 item_to_send_facette(nb_fa7_a_envoyer-1, 14) = normale_facette(fa, 2);
2060
2061 }
2062 }
2063 volume_donnees_facette_envoyees = nb_fa7_a_envoyer;
2064
2065 for (int som = 0; som < liste_sommets_avant_deplacement.dimension(0); som++)
2066 {
2067 if (is_compo_in_proc(compo_connexe_sommets_deplace[som], pe_send_))
2068 {
2069 nb_som_a_envoyer++;
2070 item_to_send_sommet.resize(nb_som_a_envoyer, 6);
2071 item_to_send_sommet(nb_som_a_envoyer-1, 0) = liste_sommets_avant_deplacement(som, 0);
2072 item_to_send_sommet(nb_som_a_envoyer-1, 1) = liste_sommets_avant_deplacement(som, 1);
2073 item_to_send_sommet(nb_som_a_envoyer-1, 2) = liste_sommets_avant_deplacement(som, 2);
2074 item_to_send_sommet(nb_som_a_envoyer-1, 3) = liste_sommets_apres_deplacement(som, 0);
2075 item_to_send_sommet(nb_som_a_envoyer-1, 4) = liste_sommets_apres_deplacement(som, 1);
2076 item_to_send_sommet(nb_som_a_envoyer-1, 5) = liste_sommets_apres_deplacement(som, 2);
2077 }
2078 }
2079 volume_donnees_sommet_envoyees = nb_som_a_envoyer;
2080 }
2081
2082
2083 if (pe_send_ >= 0)
2084 {
2085 ////////////////////// envoi du volume de donnnes /////////////////////
2086 send_buffer_volume_facette = new int[1];
2087 int *buf_volume_facette = send_buffer_volume_facette;
2088 *buf_volume_facette = volume_donnees_facette_envoyees ;
2089
2090 ////////////////////// envoi des donnnes elles-memes /////////////////////
2091 send_buffer_data_facette = new double[volume_donnees_facette_envoyees*dimensions_tab];
2092 double *buf_data_facette = send_buffer_data_facette;
2093
2094 for (int i = 0; i < nb_fa7_a_envoyer; i++)
2095 for (int item = 0; item < dimensions_tab; item++, buf_data_facette++)
2096 *buf_data_facette = item_to_send_facette(i, item);
2097
2098
2099 send_buffer_volume_sommet = new int[1];
2100 int *buf_volume_sommet = send_buffer_volume_sommet;
2101 *buf_volume_sommet = volume_donnees_sommet_envoyees ;
2102
2103 ////////////////////// envoi des donnnes elles-memes /////////////////////
2104 send_buffer_data_sommet = new double[volume_donnees_sommet_envoyees*6];
2105 double *buf_data_sommet = send_buffer_data_sommet;
2106
2107 for (int i = 0; i < nb_som_a_envoyer; i++)
2108 for (int item = 0; item < 6; item++, buf_data_sommet++)
2109 *buf_data_sommet = item_to_send_sommet(i, item);
2110 }
2111
2112 ////////////////////// reception du volume de donnees/////////////////////
2113 if (pe_recv_ >= 0)
2114 {
2115 recv_buffer_volume_facette = new int[1];
2116 recv_buffer_volume_sommet = new int[1];
2117 }
2118 ::envoyer_recevoir(send_buffer_volume_facette, int_size, pe_send_, recv_buffer_volume_facette, int_size, pe_recv_);
2119 ::envoyer_recevoir(send_buffer_volume_sommet, int_size, pe_send_, recv_buffer_volume_sommet, int_size, pe_recv_);
2120 if (pe_recv_ >= 0)
2121 {
2122 int *buf_volume_facette = recv_buffer_volume_facette;
2123 volume_donnees_facette_recue = *buf_volume_facette;
2124
2125 int *buf_volume_sommet = recv_buffer_volume_sommet;
2126 volume_donnees_sommet_recue = *buf_volume_sommet;
2127 }
2128
2129 ////////////////////// reception des donnees elles-memes/////////////////////
2130
2131 if (pe_recv_ >= 0)
2132 {
2133 recv_buffer_data_facette = new double[volume_donnees_facette_recue*dimensions_tab];
2134 recv_buffer_data_sommet = new double[volume_donnees_sommet_recue*6];
2135 }
2136 ::envoyer_recevoir(send_buffer_data_facette, volume_donnees_facette_envoyees*dimensions_tab * double_size, pe_send_, recv_buffer_data_facette, volume_donnees_facette_recue * dimensions_tab * double_size, pe_recv_);
2137 ::envoyer_recevoir(send_buffer_data_sommet, volume_donnees_sommet_envoyees*6 * double_size, pe_send_, recv_buffer_data_sommet, volume_donnees_sommet_recue * 6 * double_size, pe_recv_);
2138
2139 if (pe_recv_ >= 0)
2140 {
2141 int size_avant_echange = facettes_sommets_full_compo_.dimension(0);
2142 int new_size = size_avant_echange + volume_donnees_facette_recue ;
2143 facettes_sommets_full_compo_.resize(new_size, dimensions_tab);
2144 double *buf_data_facette = recv_buffer_data_facette;
2145 for (int i = size_avant_echange; i < new_size; i++)
2146 for (int item = 0; item < dimensions_tab; item++, buf_data_facette++)
2147 facettes_sommets_full_compo_(i, item) = *buf_data_facette;
2148
2149 size_avant_echange = liste_sommets_et_deplacements_.dimension(0);
2150 new_size = size_avant_echange + volume_donnees_sommet_recue ;
2151 liste_sommets_et_deplacements_.resize(new_size, 6);
2152 double *buf_data_sommet = recv_buffer_data_sommet;
2153 for (int i = size_avant_echange; i < new_size; i++)
2154 for (int item = 0; item < 6; item++, buf_data_sommet++)
2155 liste_sommets_et_deplacements_(i, item) = *buf_data_sommet;
2156 }
2157
2158 delete[] send_buffer_volume_facette;
2159 delete[] recv_buffer_volume_facette;
2160 delete[] send_buffer_data_facette;
2161 delete[] recv_buffer_data_facette;
2162 delete[] send_buffer_volume_sommet;
2163 delete[] recv_buffer_volume_sommet;
2164 delete[] send_buffer_data_sommet;
2165 delete[] recv_buffer_data_sommet;
2166}
2167
2168
2169void FT_Field::calculer_volume_bulles(ArrOfDouble& volumes, DoubleTab& centre_gravite, const Maillage_FT_IJK& mesh) const
2170{
2171 const int n = mesh.nb_facettes();
2172 const ArrOfInt& compo_connex = mesh.compo_connexe_facettes();
2173 int nb_bulles_reelles = 0 ;
2174 if (compo_connex.size_array()!=0)
2175 nb_bulles_reelles = max_array(compo_connex);
2176 nb_bulles_reelles = Process::mp_max(nb_bulles_reelles) + 1;
2177
2178 const int nbulles_tot = nb_bulles_reelles ;
2179 volumes.resize_array(nbulles_tot, RESIZE_OPTIONS::NOCOPY_NOINIT);
2180 volumes = 0.;
2181 centre_gravite.resize(nbulles_tot, 3, RESIZE_OPTIONS::NOCOPY_NOINIT);
2182 centre_gravite = 0.;
2183 const ArrOfDouble& surfaces_facettes = mesh.get_update_surface_facettes();
2184 const DoubleTab& normales_facettes = mesh.get_update_normale_facettes();
2185 const IntTab& facettes = mesh.facettes();
2186 const DoubleTab& sommets = mesh.sommets();
2187 const ArrOfInt& compo_facettes = mesh.compo_connexe_facettes();
2188 for (int i = 0; i < n; i++)
2189 {
2190 if (mesh.facette_virtuelle(i))
2191 continue;
2192 int compo = compo_facettes[i];
2193 // les bulles dupliquees a la fin :
2194 const double s = surfaces_facettes[i];
2195 const double normale_scalaire_direction = normales_facettes(i, 0); // On projette sur x
2196 // Coordonnee du centre de gravite de la facette
2197 const int i0 = facettes(i, 0);
2198 const int i1 = facettes(i, 1);
2199 const int i2 = facettes(i, 2);
2200 const double coord_centre_gravite_i = (sommets(i0, 0) + sommets(i1, 0) + sommets(i2, 0)) / 3.;
2201 const double coord_centre_gravite_j = (sommets(i0, 1) + sommets(i1, 1) + sommets(i2, 1)) / 3.;
2202 const double coord_centre_gravite_k = (sommets(i0, 2) + sommets(i1, 2) + sommets(i2, 2)) / 3.;
2203 const double volume_prisme = coord_centre_gravite_i * s * normale_scalaire_direction;
2204 // centre de gravite du prisme pondere par son volume avec signe
2205 centre_gravite(compo, 0) += volume_prisme * (coord_centre_gravite_i * 0.5);
2206 centre_gravite(compo, 1) += volume_prisme * coord_centre_gravite_j;
2207 centre_gravite(compo, 2) += volume_prisme * coord_centre_gravite_k;
2208 volumes[compo] += volume_prisme;
2209 }
2210 mp_sum_for_each_item(volumes);
2211 mp_sum_for_each_item(centre_gravite);
2212 //Cerr << "volumes : " << volumes << finl;
2213 for (int i = 0; i < nbulles_tot; i++)
2214 {
2215 // const double x = 1./volumes[i];
2216 const double x = (volumes[i] == 0.) ? 0. : 1. / volumes[i];
2217 centre_gravite(i, 0) *= x;
2218 centre_gravite(i, 1) *= x;
2219 centre_gravite(i, 2) *= x;
2220 }
2221}
: class Desc_Structure_FT
void collecter_espace_virtuel(ArrOfDouble &tab, MD_Vector_tools::Operations_echange op) const
void echange_espace_virtuel(ArrOfDouble &tab) const
This class encapsulates all the information related to the eulerian mesh for TrioIJK.
Definition Domaine_IJK.h:47
int get_processor_by_ijk(const FixedVector< int, 3 > &slice) const
Return the global index of the processor according to its position.
double get_domain_length(int direction) const
Returns the length of the entire domain in requested direction.
int get_nprocessor_per_direction(int direction) const
Returns the number of slices in the given direction.
int get_local_slice_index(int direction) const
Returns the position of the local subdomain in the requested direction.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
void update_gradient_laplacien_FT(const Maillage_FT_IJK &mesh)
Definition FT_Field.cpp:191
double intersectionArea(Point2D t1[3], Point2D t2[3])
Definition FT_Field.cpp:481
Point2D projectPointToPlane(const Point3D &point, const Point3D &centroid, const array< double, 3 > &eigenVector1, const array< double, 3 > &eigenVector2)
Definition FT_Field.cpp:681
void exchange_data(int pe_send_, int pe_recv_, const Maillage_FT_IJK &mesh, const DoubleTab &liste_sommets_avant_deplacement, const DoubleTab &liste_sommets_apres_deplacement, const ArrOfInt &compo_connexe_sommets_deplace)
Operator_FT_Disc OpFTDisc_
Definition FT_Field.h:219
void passer_variable_intensive(const Maillage_FT_IJK &mesh)
Definition FT_Field.cpp:261
void completer_compo_connexe_partielle(const Maillage_FT_IJK &mesh, const Domaine_IJK &splitting, const DoubleTab &liste_sommets_apres_deplacement, const DoubleTab &liste_sommets_avant_deplacement, const ArrOfInt &compo_connexe_sommets_deplace)
double polygonArea(const std::vector< Point2D > &vertices)
Definition FT_Field.cpp:469
Point3D crossProduct(const Point3D &u, const Point3D &v)
Definition FT_Field.cpp:762
void remailler_FT_Field(Maillage_FT_IJK &mesh)
Definition FT_Field.cpp:981
ArrOfDouble FT_field_Array_
Definition FT_Field.h:215
double norme(const Point3D &pt)
Definition FT_Field.cpp:553
void sortAndTrackIndices(const std::vector< double > &arr, std::vector< size_t > &indices)
Definition FT_Field.cpp:397
void powerIteration(const double cov[3][3], double eigenVector[3], double &eigenValue)
Definition FT_Field.cpp:618
int orientation_triangle(const Point3D &normale, const array< double, 3 > &eigenVector1, const array< double, 3 > &eigenVector2)
Definition FT_Field.cpp:695
ArrOfDouble sigma_sommets_
Definition FT_Field.h:224
ArrOfDouble FT_field_Array_sommets_
Definition FT_Field.h:216
DoubleTab update_sigma_and_interfacial_source_term_sommet(const Maillage_FT_IJK &mesh, const Domaine_IJK &splitting, bool compute_interfacial_source, bool use_tryggvason_formulation)
Definition FT_Field.cpp:196
void initialize(const Maillage_FT_IJK &mesh, const DoubleTab &centre_mass)
Definition FT_Field.cpp:35
double det(const Point2D &a, const Point2D &b, const Point2D &c)
Definition FT_Field.cpp:420
ArrOfDouble check_conservation(const Maillage_FT_IJK &mesh)
double magnitude(const Point3D &v)
Definition FT_Field.cpp:777
void correction_conservation_globale(const Maillage_FT_IJK &mesh, const ArrOfDouble &surfactant_avant_remaillage, const ArrOfDouble &surfactant_apres_remaillage)
std::vector< Point3D > removeDuplicates(std::vector< Point3D > &points)
Definition FT_Field.cpp:558
void exchange_compo_connexe(int pe_send_, int pe_recv_, const Maillage_FT_IJK &mesh)
void Calculate_Facette_Intersection_Area(DoubleTab &Surface_fa7init, DoubleTab &Surface_fa7fin, DoubleTab &Surface_intersection, vector< Point3D > points_fa7_originale, vector< Point3D > points_fa7_finale, IntTab points_triangle_originaux, IntTab points_triangle_finaux, IntTab &normale_triangle_originaux, IntTab &normale_triangle_finaux)
Definition FT_Field.cpp:798
double Gamma_inf_
Definition FT_Field.h:223
void echange_espace_virtuel(const Maillage_FT_Disc &mesh)
Definition FT_Field.cpp:378
ArrOfDouble sigma_facettes_
Definition FT_Field.h:225
DoubleTab Grad_FT_field_Array_
Definition FT_Field.h:217
void passer_variable_extensive(const Maillage_FT_IJK &mesh)
Definition FT_Field.cpp:279
void nettoyer_espace_virtuel_facette(const Maillage_FT_IJK &mesh)
Definition FT_Field.cpp:306
double sigma0_
Definition FT_Field.h:220
DoubleTab interfacial_source_term_sommet_
Definition FT_Field.h:226
vector< pair< double, array< double, 3 > > > Main_2D_plane_eigenvectors(vector< Point3D > points)
Definition FT_Field.cpp:707
void computeCovarianceMatrix(const vector< Point3D > &points, const Point3D &centroid, double cov[3][3])
Definition FT_Field.cpp:589
bool isPointInTriangle(const Point2D &pt, const Point2D &v1, const Point2D &v2, const Point2D &v3)
Definition FT_Field.cpp:426
double R_
Definition FT_Field.h:221
void champ_sommet_from_facettes(const ArrOfInt &compo_connexe_facettes, const Maillage_FT_IJK &mesh)
Point3D calculer_normale_apres_deplacement(const int fa, const int somfa7, const Vecteur3 pos_apres_dep)
Point3D computeCentroid(const vector< Point3D > &points)
Definition FT_Field.cpp:570
void update_Field_sommets(const Maillage_FT_IJK &FTmesh, const ArrOfDouble &Field_facettes, ArrOfDouble &field_sommet)
Definition FT_Field.cpp:327
double scalarProduct(const Point3D &u, const Point3D &v)
Definition FT_Field.cpp:771
bool lineIntersection(const Point2D &a, const Point2D &b, const Point2D &c, const Point2D &d, Point2D &intersection)
Definition FT_Field.cpp:437
void sauvegarder_triangle(const Maillage_FT_IJK &mesh, const int i, const int avant_apres_remaillage)
Definition FT_Field.cpp:898
void update_FT_Field_local_from_full_compo(const Maillage_FT_IJK &mesh)
void calculer_volume_bulles(ArrOfDouble &volumes, DoubleTab &centre_gravite, const Maillage_FT_IJK &mesh) const
double triangleArea3D(const Point3D &A, const Point3D &B, const Point3D &C)
Definition FT_Field.cpp:783
double T_
Definition FT_Field.h:222
double triangleArea(const Point2D &p1, const Point2D &p2, const Point2D &p3)
Definition FT_Field.cpp:756
bool is_compo_in_proc(const int compo_connexe, const int pe_send)
bool sauv_num_pe_echange(int pe)
ArrOfDouble Laplacian_FT_field_Array_
Definition FT_Field.h:218
void avancer_en_temps(const Maillage_FT_IJK &mesh, const double time_step)
Definition FT_Field.cpp:161
: class Maillage_FT_Disc Cette classe decrit un maillage:
int nb_sommets() const
renvoie le nombre de sommets (reels et virtuels) (egal a sommets().
const DoubleTab & sommets() const
renvoie le tableau des sommets (reels et virtuels) dimension(0) = nombre de sommets,
virtual const ArrOfDouble & get_surface_facettes() const
int nb_facettes() const
renvoie le nombre de facettes (reelles et virtuelles) (egal a facettes().
int facette_virtuelle(int i) const
Renvoie 0 si la facette m'appartient, 1 sinon.
const Desc_Structure_FT & desc_sommets() const
renvoie le descripteur des sommets (espace_distant/virtuel)
virtual const DoubleTab & get_update_normale_facettes() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
const Desc_Structure_FT & desc_facettes() const
renvoie le descripteur des facettes (espace_distant/virtuel)
int sommet_virtuel(int i) const
virtual const ArrOfDouble & get_update_surface_facettes() const
Calcule la grandeur demandee, stocke le resultat dans un tableau interne a la classe et renvoie le re...
const IntTab & facettes() const
renvoie le tableau des facettes (reelles et virtuelles) dimension(0) = nombre de facettes,
: class Maillage_FT_IJK
const ArrOfInt & compo_connexe_facettes() const
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
double x
Definition FT_Field.h:41
double y
Definition FT_Field.h:41
static double tol
Definition FT_Field.h:42
double z
Definition FT_Field.h:80
static double tol
Definition FT_Field.h:79
double y
Definition FT_Field.h:80
double x
Definition FT_Field.h:80
static double mp_max(double)
Definition Process.cpp:376
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTArray.h:156
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133