TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Champ_implementation_P1.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 <Champ_implementation_P1.h>
17#include <Domaine_Poly_base.h>
18#include <Octree_Double.h>
19#include <Domaine.h>
20
21double Champ_implementation_P1::form_function(const ArrOfDouble& position, const IntTab& les_elems, const DoubleTab& nodes, ArrOfInt& index, int cell, int ddl) const
22{
23 int nb_nodes_per_cell = les_elems.dimension(1);
24 assert(ddl < nb_nodes_per_cell);
25
26 for (int i = 0; i < nb_nodes_per_cell; i++)
27 index[i] = les_elems(cell, (i + ddl) % nb_nodes_per_cell);
28
29 if (nb_nodes_per_cell == 2)
30 {
31 double num = 0.;
32 double den = 0.;
33 for (int d = 0; d < Objet_U::dimension; d++)
34 {
35 num += (position[d] - nodes(index[0], d)) * (position[d] - nodes(index[0], d));
36 den += (nodes(index[1], d) - nodes(index[0], d)) * (nodes(index[1], d) - nodes(index[0], d));
37 }
38 double res = 1. - sqrt(num / den);
39 // Cerr<<"ii "<<res<<" "<<index[0]<<" "<<ddl<<" "<<(ddl)%nb_nodes_per_cell<<finl;
40 return res;
41 }
42 double num = 0.;
43 double den = 0.;
44
45 if (Objet_U::dimension == 2)
46 {
47 den = (nodes(index[2], 0) - nodes(index[1], 0)) * (nodes(index[0], 1) - nodes(index[1], 1)) - (nodes(index[2], 1) - nodes(index[1], 1)) * (nodes(index[0], 0) - nodes(index[1], 0));
48
49 num = (nodes(index[2], 0) - nodes(index[1], 0)) * (position[1] - nodes(index[1], 1)) - (nodes(index[2], 1) - nodes(index[1], 1)) * (position[0] - nodes(index[1], 0));
50 }
51 else if (Objet_U::dimension == 3)
52 {
53 double xp = (nodes(index[2], 1) - nodes(index[1], 1)) * (nodes(index[0], 2) - nodes(index[1], 2)) - (nodes(index[2], 2) - nodes(index[1], 2)) * (nodes(index[0], 1) - nodes(index[1], 1));
54
55 double yp = (nodes(index[2], 2) - nodes(index[1], 2)) * (nodes(index[0], 0) - nodes(index[1], 0)) - (nodes(index[2], 0) - nodes(index[1], 0)) * (nodes(index[0], 2) - nodes(index[1], 2));
56
57 double zp = (nodes(index[2], 0) - nodes(index[1], 0)) * (nodes(index[0], 1) - nodes(index[1], 1)) - (nodes(index[2], 1) - nodes(index[1], 1)) * (nodes(index[0], 0) - nodes(index[1], 0));
58
59 den = xp * (nodes(index[3], 0) - nodes(index[1], 0)) + yp * (nodes(index[3], 1) - nodes(index[1], 1)) + zp * (nodes(index[3], 2) - nodes(index[1], 2));
60
61 xp = (nodes(index[2], 1) - nodes(index[1], 1)) * (position[2] - nodes(index[1], 2)) - (nodes(index[2], 2) - nodes(index[1], 2)) * (position[1] - nodes(index[1], 1));
62
63 yp = (nodes(index[2], 2) - nodes(index[1], 2)) * (position[0] - nodes(index[1], 0)) - (nodes(index[2], 0) - nodes(index[1], 0)) * (position[2] - nodes(index[1], 2));
64
65 zp = (nodes(index[2], 0) - nodes(index[1], 0)) * (position[1] - nodes(index[1], 1)) - (nodes(index[2], 1) - nodes(index[1], 1)) * (position[0] - nodes(index[1], 0));
66
67 num = xp * (nodes(index[3], 0) - nodes(index[1], 0)) + yp * (nodes(index[3], 1) - nodes(index[1], 1)) + zp * (nodes(index[3], 2) - nodes(index[1], 2));
68 }
69 else
70 {
71 Cerr << "Error in Champ_implementation_P1::form_function : Invalid dimension" << finl;
73 }
74
75 assert(den != 0.);
76 double result = num / den;
77
78 if ((result < -Objet_U::precision_geom) || (result > 1. + Objet_U::precision_geom))
79 {
80 Cerr << "WARNING: The barycentric coordinate of point :" << finl;
81 Cerr << "x= " << position[0] << " y=" << position[1];
82 if (Objet_U::dimension == 3)
83 {
84 Cerr << " z=" << position[3];
85 }
86 Cerr << finl;
87 Cerr << "is not between 0 and 1 : " << result << finl;
88 Cerr << "On the element " << cell << " of the processor " << Process::me() << finl;
89
90#ifndef NDEBUG
92#endif
93
94 }
95
96 return result;
97}
98void Champ_implementation_P1::value_interpolation(const DoubleTab& positions, const ArrOfInt& cells, const DoubleTab& values, DoubleTab& resu, int ncomp) const
99{
100 const Domaine& domaine = get_domaine_geom();
101 const Domaine_Poly_base *zpoly = sub_type(Domaine_Poly_base, get_domaine_dis()) ? &ref_cast(Domaine_Poly_base, get_domaine_dis()) : nullptr;
102 const IntTab& les_elems = domaine.les_elems();
103 const DoubleTab& nodes = domaine.les_sommets();
104 const int nb_nodes_per_cell = domaine.nb_som_elem(), N = resu.line_size();
105 ArrOfInt index(nb_nodes_per_cell);
106 ArrOfDouble position(Objet_U::dimension);
107 resu = 0;
108 if (zpoly) //polyedred -> interpolation ponderee par les volumes
109 {
110 const DoubleTab& v_es = zpoly->vol_elem_som();
111 const DoubleVect& ve = zpoly->volumes();
112 const IntTab& es_d = zpoly->elem_som_d();
113 for (int ic = 0; ic < cells.size_array(); ic++)
114 {
115 int cell = cells[ic];
116 if (cell < 0)
117 continue;
118 assert(cell >= 0);
119 assert(cell < les_elems.dimension_tot(0));
120 if (ncomp != -1)
121 for (int j = 0, k = es_d(cell); k < es_d(cell + 1); j++, k++)
122 resu(ic) += values(les_elems(cell, j), ncomp) * v_es(k) / ve(cell);
123 else
124 {
125 assert(values.line_size() == N);
126 for (int j = 0, k = es_d(cell); k < es_d(cell + 1); k++)
127 for (int n = 0, s = les_elems(cell, j); n < N; n++)
128 resu(ic, n) += values(s, n) * v_es(k) / ve(cell);
129 }
130
131 }
132 }
133 else
134 for (int ic = 0; ic < cells.size_array(); ic++)
135 {
136 int cell = cells[ic];
137 if (cell < 0)
138 continue;
139 for (int k = 0; k < Objet_U::dimension; k++)
140 position[k] = positions(ic, k);
141
142 assert(cell >= 0);
143 assert(cell < les_elems.dimension_tot(0));
144 if (ncomp != -1)
145 {
146 for (int j = 0; j < nb_nodes_per_cell; j++)
147 {
148 int node = les_elems(cell, j);
149 resu(ic) += values(node, ncomp) * form_function(position, les_elems, nodes, index, cell, j);
150 }
151 }
152 else
153 {
154
155 assert(values.line_size() == N);
156 for (int j = 0; j < nb_nodes_per_cell; j++)
157 {
158 double weight = form_function(position, les_elems, nodes, index, cell, j);
159 int node = les_elems(cell, j);
160 for (int k = 0; k < N; k++)
161 resu(ic, k) += values(node, k) * weight;
162 }
163 }
164 }
165}
166
167/*! @brief Initialise le tableau de valeurs aux sommets du domaine dom a partir de valeurs lues dans "input".
168 *
169 * (on dimensionne, associe la structure parallele et remplit les valeurs reelles et virtuelles)
170 * Le fichier doit avoir le format suivant (n est le nombre de valeurs nodales
171 * stockees, x, y, z sont les coordonnees des sommets, compo1... sont les valeurs
172 * des composantes.
173 * n (int)
174 * x y [z] compo1 [compo2 [compo3 ... ]] (type double)
175 *
176 */
177void Champ_implementation_P1::init_from_file(DoubleTab& val, const Domaine& dom, int nb_comp, double tolerance, Entree& input)
178{
179 val.resize(0, nb_comp);
180 dom.creer_tableau_sommets(val, RESIZE_OPTIONS::NOCOPY_NOINIT);
181
182 // Construction d'un octree avec les sommets du domaine:
183 const DoubleTab& coord = dom.coord_sommets();
184 Octree_Double octree;
185 octree.build_nodes(coord, 0 /* do not include virtual nodes */);
186
187 // Lecture des valeurs dans input
188 int nb_val_lues;
189 input >> nb_val_lues;
190 const int dim = coord.dimension(1);
191 const int tmp_size = dim + nb_comp;
192 ArrOfDouble tmp(tmp_size);
193 ArrOfDouble node_coord; // points to the dim first elements of "tmp" (coordinates of the node)
194 node_coord.ref_array(tmp, 0 /* start index */, dim /* size */);
195 ArrOfInt node_list;
196
197
198 ArrOfInt count(dom.nb_som()); // number of times this coordinate has been found
199
200 for (int i_val = 0; i_val < nb_val_lues; i_val++)
201 {
202 input.get(tmp.addr(), tmp_size);
203 // first call returns more points (some might be at a larger distance)
204 octree.search_elements_box(node_coord, tolerance, node_list);
205 octree.search_nodes_close_to(node_coord, coord, node_list, tolerance);
206 const int n = node_list.size_array();
207 if (n > 1)
208 {
209 Cerr << "Error in Champ_som_lu::readOn: point " << node_coord << " corresponds to " << node_list.size_array() << " nodes in the geometry within the specified tolerance" << finl;
211 }
212 if (n == 1)
213 {
214 const int node_index = node_list[0];
215 count[node_index]++;
216 for (int i = 0; i < nb_comp; i++)
217 val(node_index, i) = tmp[dim + i];
218 }
219 else
220 {
221 // Ce sommet n'est pas sur ce processeur...
222 }
223 }
224
225 if (dom.nb_som() > 0 && min_array(count) == 0)
226 {
227 Cerr << "Error in Champ_som_lu::readOn: some coordinates were not found in the file" << finl;
229 }
231}
232
233/*! @brief Calcule la coordonnee barycentrique d'un point (x,y) par rapport au sommet specifie d'un triangle ou d'un rectange (un element)
234 *
235 * Ce calcul concerne un point 2D.
236 *
237 * @param (IntTab& polys) tableau contenant les numeros des elements par rapport auxquels on veut calculer une coordonnee barycentrique. polys(i,0) est l'indice du sommet 0 de l'element i dans le tableau des coordonnees (coord).
238 * @param (DoubleTab& coord) les coordonnees des sommets par auxquels on veut calculer les coordonnees barycentriques.
239 * @param (double x) la premiere coordonnee cartesienne du point dont on veut calculer les coordonnees barycentriques
240 * @param (double y) la deuxieme coordonnee cartesienne du point dont on veut calculer les coordonnees barycentriques
241 * @param (int le_poly) le numero de l'element (dans le tableau polys) par rapport auquel on calculera la coordonnee barycentrique.
242 * @param (int i) le numero du sommet par rapport auquel on veut la coordonnee barycentrique.
243 * @return (double) la coordonnee barycentrique du point (x,y) par rapport au sommet specifie (i) dans l'element specifie (le_poly)
244 * @throws erreur arithmetique, denominateur nul
245 * @throws erreur de calcul, coordonnee barycentrique invalide
246 */
247double coord_barycentrique_P1(const IntTab& polys, const DoubleTab& coord, double x, double y, int le_poly, int i)
248{
249 int nb_som_elem = polys.dimension(1);
250 //Distinction du calcul de la coordonnee barycentrique en fonction du type de l element
251 //Cas Triangle
252 if (nb_som_elem == 3)
253 return coord_barycentrique_P1_triangle(polys, coord, x, y, le_poly, i);
254 //Cas Rectangle
255 else if (nb_som_elem == 4)
256 return coord_barycentrique_P1_rectangle(polys, coord, x, y, le_poly, i);
257 Cerr << "The number of nodes by element " << nb_som_elem << " does not correspond to a treated situation in the coord_barycentrique_P1 function." << finl;
259 return 0.;
260}
261
262/*! @brief Calcule la coordonnee barycentrique d'un point (x,y,z) par rapport au sommet specifie d'un tetraedre ou d'un hexaedre (un element)
263 *
264 * Ce calcul concerne un point 3D.
265 *
266 * @param (IntTab& polys) tableau contenant les numeros des elements par rapport auxquels on veut calculer une coordonnee barycentrique. polys(i,0) est l'indice du sommet 0 de l'element i dans le tableau des coordonnees (coord).
267 * @param (DoubleTab& coord) les coordonnees des sommets par auxquels on veut calculer les coordonnees barycentriques.
268 * @param (double x) la premiere coordonnee cartesienne du point dont on veut calculer les coordonnees barycentriques
269 * @param (double y) la deuxieme coordonnee cartesienne du point dont on veut calculer les coordonnees barycentriques
270 * @param (double z) la troisieme coordonnee cartesienne du point dont on veut calculer les coordonnees barycentriques
271 * @param (int le_poly) le numero de l'element (dans le tableau polys) par rapport auquel on calculera la coordonnee barycentrique.
272 * @param (int i) le numero du sommet par rapport auquel on veut la coordonnee barycentrique.
273 * @return (double) la coordonnee barycentrique du point (x,y,z) par rapport au sommet specifie (i) dans l'element specifie (le_poly)
274 * @throws un tetraedre n'a pas plus de 4 sommets
275 * @throws un hexaedre n'a pas plus de 8 sommets
276 * @throws erreur arithmetique, denominateur nul
277 * @throws erreur de calcul, coordonnee barycentrique invalide
278 */
279double coord_barycentrique_P1(const IntTab& polys, const DoubleTab& coord, double x, double y, double z, int le_poly, int i)
280{
281 int nb_som_elem = polys.dimension(1);
282 //Distinction du calcul de la coordonnee barycentrique en fonction du type de l element
283 //Cas Tetraedre
284 if (nb_som_elem == 4)
285 return coord_barycentrique_P1_tetraedre(polys, coord, x, y, z, le_poly, i);
286 else if (nb_som_elem == 8)
287 return coord_barycentrique_P1_hexaedre(polys, coord, x, y, z, le_poly, i);
288 Cerr << "The number of nodes by element " << nb_som_elem << " does not correspond to a treated situation in the coord_barycentrique_P1 function." << finl;
290 return 0.;
291}
static void init_from_file(DoubleTab &val, const Domaine &dom, int nb_comp, double tolerance, Entree &input)
Initialise le tableau de valeurs aux sommets du domaine dom a partir de valeurs lues dans "input".
void value_interpolation(const DoubleTab &positions, const ArrOfInt &cells, const DoubleTab &values, DoubleTab &resu, int ncomp=-1) const override
const Domaine & get_domaine_geom() const
const Domaine_VF & get_domaine_dis() const
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
virtual void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Cree un tableau ayant une "ligne" par sommet du maillage.
Definition Domaine.cpp:1000
int_t nb_som() const
Renvoie le nombre de sommets du domaine.
Definition Domaine.h:121
class Domaine_Poly_base
const DoubleTab & vol_elem_som() const
const IntTab & elem_som_d() const
double volumes(int i) const
Definition Domaine_VF.h:113
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int get(int *ob, std::streamsize n)
Definition Entree.cpp:222
static int dimension
Definition Objet_U.h:99
static double precision_geom
Definition Objet_U.h:86
static int_t search_nodes_close_to(double x, double y, double z, const DoubleTab_t &coords, ArrOfInt_t &node_list, double epsilon)
Methode hors classe Cherche parmi les sommets de la liste node_list ceux qui sont a une.
void build_nodes(const DoubleTab_t &coords, const bool include_virtual, const double epsilon=0.)
construit un octree contenant les points de coordonnees coords.
int_t search_elements_box(double xmin, double ymin, double zmin, double xmax, double ymax, double zmax, ArrOfInt_t &elements) const
cherche tous les elements ou points ayant potentiellement une intersection non vide avec la boite don...
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
_SIZE_ size_array() const
virtual void ref_array(TRUSTArray &, _SIZE_ start=0, _SIZE_ sz=-1)
_TYPE_ * addr()
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")