TrioCFD 1.9.9_beta
TrioCFD documentation
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) //polyhedron -> volume-weighted interpolation
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 Initializes the array of values at the vertices of domain dom from values read from "input".
168 *
169 * (the array is sized, associated with the parallel structure, and filled with real and virtual values)
170 * The file must have the following format (n is the number of nodal values
171 * stored, x, y, z are the coordinates of the vertices, compo1... are the values
172 * of the components.
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 // Build an octree with the domain vertices:
183 const DoubleTab& coord = dom.coord_sommets();
184 Octree_Double octree;
185 octree.build_nodes(coord, 0 /* do not include virtual nodes */);
186
187 // Read values from 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 // This vertex is not on this processor...
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 Computes the barycentric coordinate of a point (x,y) with respect to the specified vertex of a triangle or rectangle (an element).
234 *
235 * This computation concerns a 2D point.
236 *
237 * @param (IntTab& polys) array containing the indices of the elements with respect to which the barycentric coordinate is to be computed. polys(i,0) is the index of vertex 0 of element i in the coordinate array (coord).
238 * @param (DoubleTab& coord) the coordinates of the vertices for which the barycentric coordinates are to be computed.
239 * @param (double x) the first Cartesian coordinate of the point whose barycentric coordinates are to be computed
240 * @param (double y) the second Cartesian coordinate of the point whose barycentric coordinates are to be computed
241 * @param (int le_poly) the index of the element (in the polys array) with respect to which the barycentric coordinate will be computed.
242 * @param (int i) the index of the vertex with respect to which the barycentric coordinate is wanted.
243 * @return (double) the barycentric coordinate of point (x,y) with respect to the specified vertex (i) in the specified element (le_poly)
244 * @throws arithmetic error, null denominator
245 * @throws computation error, invalid barycentric coordinate
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 //Selection of barycentric coordinate computation depending on element type
251 //Triangle case
252 if (nb_som_elem == 3)
253 return coord_barycentrique_P1_triangle(polys, coord, x, y, le_poly, i);
254 //Rectangle case
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 Computes the barycentric coordinate of a point (x,y,z) with respect to the specified vertex of a tetrahedron or hexahedron (an element).
263 *
264 * This computation concerns a 3D point.
265 *
266 * @param (IntTab& polys) array containing the indices of the elements with respect to which the barycentric coordinate is to be computed. polys(i,0) is the index of vertex 0 of element i in the coordinate array (coord).
267 * @param (DoubleTab& coord) the coordinates of the vertices for which the barycentric coordinates are to be computed.
268 * @param (double x) the first Cartesian coordinate of the point whose barycentric coordinates are to be computed
269 * @param (double y) the second Cartesian coordinate of the point whose barycentric coordinates are to be computed
270 * @param (double z) the third Cartesian coordinate of the point whose barycentric coordinates are to be computed
271 * @param (int le_poly) the index of the element (in the polys array) with respect to which the barycentric coordinate will be computed.
272 * @param (int i) the index of the vertex with respect to which the barycentric coordinate is wanted.
273 * @return (double) the barycentric coordinate of point (x,y,z) with respect to the specified vertex (i) in the specified element (le_poly)
274 * @throws a tetrahedron does not have more than 4 vertices
275 * @throws a hexahedron does not have more than 8 vertices
276 * @throws arithmetic error, null denominator
277 * @throws computation error, invalid barycentric coordinate
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 //Selection of barycentric coordinate computation depending on element type
283 //Tetrahedron case
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)
Initializes the array of values at the vertices of domain dom from values read from "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
Creates an array with one "row" per mesh vertex.
Definition Domaine.cpp:999
int_t nb_som() const
Returns the number of vertices of the domain.
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:94
static double precision_geom
Definition Objet_U.h:81
static int_t search_nodes_close_to(double x, double y, double z, const DoubleTab_t &coords, ArrOfInt_t &node_list, double epsilon)
Non-member method. Searches among the vertices in node_list for those within a distance.
void build_nodes(const DoubleTab_t &coords, const bool include_virtual, const double epsilon=0.)
builds an octree containing the points with coordinates coords.
int_t search_elements_box(double xmin, double ymin, double zmin, double xmax, double ymax, double zmax, ArrOfInt_t &elements) const
searches for all elements or points potentially having a non-empty intersection with the given box.
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
_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")