TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Convert_ICoCoTrioField.cpp
1/****************************************************************************
2* Copyright (c) 2025, 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 <Convert_ICoCoTrioField.h>
17#include <ICoCoTrioField.h>
18#include <ICoCoMEDDoubleField.hxx>
19#include <Domaine.h>
20#include <Champ_Generique_base.h>
21#include <Domaine_VF.h>
22#include <PE_Groups.h>
23#include <Comm_Group.h>
24#include <Polyedre.h>
25
26void affecte_double_avec_doubletab(double** p, const ArrOfDouble& trio)
27{
28 *p=new double[trio.size_array()];
29 memcpy(*p,trio.addr(),trio.size_array()*sizeof(double));
30}
31
32void affecte_int_avec_inttab(int** p, const ArrOfInt& trio)
33{
34 int sz=trio.size_array();
35 *p=new int[sz];
36 memcpy(*p,trio.addr(),sz*sizeof(int));
37}
38
39void build_triofield(const Champ_Generique_base& ch, ICoCo::TrioField& afield)
40{
41 build_triomesh(ch.get_ref_domaine_dis_base(), afield, ch.get_localisation() == Entity::NODE, ch.get_localisation() == Entity::FACE);
42
43 afield.setName(ch.le_nom().getString());
44 afield._time1 = afield._time2 = ch.get_time(), afield._itnumber = 0;
45
46 /* copie des valeurs du champ */
47 afield._has_field_ownership = true;
48 OWN_PTR(Champ_base) espace_stockage;
49 const Champ_base& champ_ecriture = ch.get_champ(espace_stockage);
50 const DoubleTab& vals = champ_ecriture.valeurs();
51 afield._nb_field_components = vals.nb_dim() > 1 ? vals.dimension(1) : 1;
52 affecte_double_avec_doubletab(&afield._field, vals);
53}
54
55void build_triofield(const Champ_base& ch, const Domaine_dis_base& dom_dis, ICoCo::TrioField& afield)
56{
57 build_triomesh(dom_dis, afield, 0, 0); // XXX seulement elem...
58
59 afield.setName(ch.le_nom().getString());
60 afield._time1 = afield._time2 = 0.0, afield._itnumber = 0;
61
62 /* copie des valeurs du champ */
63 afield._has_field_ownership = true;
64 const DoubleTab& vals = ch.valeurs();
65 afield._nb_field_components = vals.nb_dim() > 1 ? vals.dimension(1) : 1;
66 affecte_double_avec_doubletab(&afield._field, vals);
67}
68
69void build_triomesh(const Domaine_dis_base& dom_dis, ICoCo::TrioField& afield, int type, int loc_faces)
70{
71 const Domaine_VF& zvf = ref_cast(Domaine_VF, dom_dis);
72 const Domaine& dom = dom_dis.domaine();
73 afield.clear();
74 afield._type = type;
75
76 /* tableau des sommets : copie de celui du domaine */
77 const DoubleTab& coord = dom.les_sommets();
78 afield._space_dim = dom.dimension;
79 afield._nbnodes = coord.dimension(0);
80 affecte_double_avec_doubletab(&afield._coords, coord);
81
82 /* dimension des elements du domaine */
83 Motcle type_elem_ = dom_dis.domaine().type_elem()->que_suis_je();
84 Motcle type_elem(type_elem_);
85 type_elem.prefix("_AXI");
86 if (type_elem != Motcle(type_elem_))
87 {
88 if (type_elem == "QUADRILATERE_2D")
89 type_elem = "SEGMENT_2D";
90 if (type_elem == "RECTANGLE_2D")
91 type_elem = "RECTANGLE";
92 }
93 if ((type_elem == "RECTANGLE") || (type_elem == "QUADRANGLE") || (type_elem == "TRIANGLE") || (type_elem == "TRIANGLE_3D") || (type_elem == "QUADRANGLE_3D") || (type_elem == "POLYGONE") || (type_elem == "POLYGONE_3D"))
94 afield._mesh_dim=2;
95 else if ((type_elem == "HEXAEDRE") || (type_elem == "HEXAEDRE_VEF") || (type_elem == "POLYEDRE") || (type_elem == "PRISME") || (type_elem == "TETRAEDRE"))
96 afield._mesh_dim=3;
97 else if ((type_elem == "SEGMENT_2D") || (type_elem == "SEGMENT"))
98 afield._mesh_dim=1;
99 else
100 {
101 Cerr << "build_triofield: " << type_elem<< " not coded" <<finl;
103 }
104
105 /* elements : ceux du domaine si le champ est aux sommets/elements, les faces si le champ est aux faces */
106 if (loc_faces) afield._mesh_dim--;
107 afield._nb_elems = loc_faces ? zvf.nb_faces() : dom_dis.domaine().nb_elem();
108 if (loc_faces || type_elem != "POLYEDRE") //maillage de faces -> connectivity = face_sommets
109 {
110 const IntTab& conn = loc_faces ? dom_dis.face_sommets() : dom_dis.domaine().les_elems();
111 //le seul moyen qu'on a d'eviter que des polygones soient pris pour des quadrilateres est d'avoir un tableau de connectivite de largeur > 4...
112 afield._nodes_per_elem = std::max(conn.dimension(1), type_elem == "POLYGONE" || type_elem == "POLYGONE_3D" || type_elem == "POLYEDRE" ? (int) 5 : 0);
113 afield._connectivity = new int[afield._nb_elems * afield._nodes_per_elem];
114 for (int i = 0; i < afield._nb_elems; i++)
115 for (int j = 0; j < afield._nodes_per_elem; j++)
116 afield._connectivity[afield._nodes_per_elem * i + j] = j < conn.dimension(1) ? conn(i, j) : -1;
117 }
118 else //maillage de polyedres -> connectivite au format MEDCoupling, a faire a la main
119 {
120 const Polyedre& poly = ref_cast(Polyedre, dom.type_elem().valeur());
121 const ArrOfInt& e_fi = poly.getPolyhedronIndex(), &f_si = poly.getFacesIndex(), &sl = poly.getNodes();
122 const IntTab& e_s = dom.les_elems();
123 int e, f, s, nef_max = 0, nfs_max = 0; //nb face/elem et som/face max
124 for (e = 0; e + 1 < e_fi.size_array(); e++) nef_max = std::max(nef_max, e_fi(e + 1) - e_fi(e));
125 for (f = 0; f + 1 < f_si.size_array(); f++) nfs_max = std::max(nfs_max, f_si(f + 1) - f_si(f));
126 afield._nodes_per_elem = std::max(nef_max * (nfs_max + 1), (int) 9); //un -1 apres chaque face : au moins 9 pour eviter un papillonage
127 int *p = afield._connectivity = new int[afield._nb_elems * afield._nodes_per_elem];
128 for (e = 0; e < afield._nb_elems; e++)
129 {
130 /* insertion de la connectivite de chaque face, suivie d'un -1 */
131 for (f = e_fi(e); f < e_fi(e + 1); f++, *p = -1, p++)
132 for (s = f_si(f); s < f_si(f + 1); s++)
133 *p = e_s(e, sl(s)), p++;
134 /* des -1 jusqu'a la ligne suivante */
135 for ( ; p < afield._connectivity + (e + 1) * afield._nodes_per_elem; p++) *p = -1;
136 }
137 }
138}
139
140#ifndef NO_MEDFIELD
141#include <MEDCouplingUMesh.hxx>
142#include <MEDCouplingFieldDouble.hxx>
143#include <MCAuto.hxx>
144#include <string.h>
145#include <vector>
146
147
148using ICoCo::TrioField;
149using ICoCo::MEDDoubleField;
150using std::vector;
151
152
153/*!
154 * This method is non const only due to this->_field that can be modified (to point to the same domaine than returned object).
155 * So \b warning, to access to \a this->_field only when the returned object is alive.
156 */
157MEDDoubleField build_medfield(TrioField& triofield)
158{
159 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingUMesh> mesh(MEDCoupling::MEDCouplingUMesh::New("",triofield._mesh_dim));
160 MEDCoupling::MCAuto<MEDCoupling::DataArrayDouble> coo(MEDCoupling::DataArrayDouble::New());
161 coo->alloc(triofield._nbnodes,triofield._space_dim);
162 mesh->setCoords(coo);
163 double *ptr(coo->getPointer());
164 std::copy(triofield._coords,triofield._coords+triofield._space_dim*triofield._nbnodes,ptr);
165 mesh->allocateCells(triofield._nb_elems);
166 INTERP_KERNEL::NormalizedCellType elemtype;
167 switch(triofield._mesh_dim)
168 {
169 case 0 :
170 {
171 switch (triofield._nodes_per_elem)
172 {
173 case 0: // cas field vide
174 elemtype=INTERP_KERNEL::NORM_SEG2; // pour eviter warning
175 break;
176 default:
177 throw INTERP_KERNEL::Exception("incompatible Trio field - wrong nb of nodes per elem");
178 }
179 break;
180 }
181 case 1:
182 {
183 switch (triofield._nodes_per_elem)
184 {
185 case 2:
186 elemtype=INTERP_KERNEL::NORM_SEG2;
187 break;
188 default:
189 throw INTERP_KERNEL::Exception("incompatible Trio field - wrong nb of nodes per elem");
190 }
191 break;
192 }
193 case 2:
194 {
195 switch (triofield._nodes_per_elem)
196 {
197 case 3:
198 elemtype=INTERP_KERNEL::NORM_TRI3;
199 break;
200 case 4 :
201 elemtype=INTERP_KERNEL::NORM_QUAD4;
202 break;
203 default:
204 elemtype=INTERP_KERNEL::NORM_POLYGON;
205 }
206 break;
207 }
208 case 3:
209 {
210 switch (triofield._nodes_per_elem)
211 {
212 case 4:
213 elemtype=INTERP_KERNEL::NORM_TETRA4;
214 break;
215 case 8 :
216 elemtype=INTERP_KERNEL::NORM_HEXA8;
217 break;
218 default:
219 elemtype=INTERP_KERNEL::NORM_POLYHED;
220 }
221 break;
222 default:
223 throw INTERP_KERNEL::Exception("incompatible Trio field - wrong mesh dimension");
224 }
225 }
226 //creating a connectivity table that complies to MED (1 indexing) <- en fait non
227 //and passing it to _mesh
228 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> field;
229 int *conn(new int[triofield._nodes_per_elem]);
230 for (int i=0; i<triofield._nb_elems; i++)
231 {
232
233 for(int j=0; j<triofield._nodes_per_elem; j++)
234 {
235 conn[j]=triofield._connectivity[i*triofield._nodes_per_elem+j];
236 }
237 if (elemtype==INTERP_KERNEL::NORM_QUAD4)
238 {
239 // dans trio pas la meme numerotation
240 int tmp=conn[3];
241 conn[3]=conn[2];
242 conn[2]=tmp;
243 }
244 if (elemtype==INTERP_KERNEL::NORM_HEXA8)
245 {
246 // dans trio pas la meme numerotation
247 int tmp=conn[3];
248 conn[3]=conn[2];
249 conn[2]=tmp;
250 tmp=conn[7];
251 conn[7]=conn[6];
252 conn[6]=tmp;
253 }
254 int size = triofield._nodes_per_elem;
255 while (conn[size - 1] == -1) size--; //on enleve les -1 a la fin de la connectivite
256#if INT_is_64_ == 2
257 // Convert int into mcIdType
258 std::vector<mcIdType> conn_mc(conn, conn+size);
259 mesh->insertNextCell(elemtype,size,conn_mc.data());
260#else
261 mesh->insertNextCell(elemtype,size,conn);
262#endif
263 }
264 delete [] conn;
265 mesh->finishInsertingCells();
266 //
267
268
269 std::vector<int> cells;
270 // if ((mesh->getSpaceDimension() == 2 || mesh->getSpaceDimension() == 3) && mesh->getMeshDimension() == 2)
271 // mesh->checkButterflyCells(cells);
272 if (!cells.empty())
273 {
274 Cerr<<" cells are butterflyed "<<cells[0]<<finl;
278 }
279 //field on the sending end
280 int nb_case=triofield.nb_values();
281 if (triofield._type==0)
282 {
283 field = MEDCoupling::MEDCouplingFieldDouble::New(MEDCoupling::ON_CELLS,MEDCoupling::ONE_TIME);
284 }
285 else
286 {
287 field = MEDCoupling::MEDCouplingFieldDouble::New(MEDCoupling::ON_NODES,MEDCoupling::ONE_TIME );
288 }
289 field->setMesh(mesh);
290 field->setNature(MEDCoupling::IntensiveMaximum);
291 MEDCoupling::MCAuto<MEDCoupling::DataArrayDouble> fieldArr(MEDCoupling::DataArrayDouble::New());
292 fieldArr->alloc(field->getNumberOfTuplesExpected(),triofield._nb_field_components);
293 field->setName(triofield.getName());
294 std::string meshName("SupportOf_");
295 meshName+=triofield.getName();
296 mesh->setName(meshName);
297 field->setTime(triofield._time1,0,triofield._itnumber);
298 if (triofield._field!=0)
299 {
300 for (int i =0; i<nb_case; i++)
301 for (int j=0; j<triofield._nb_field_components; j++)
302 {
303 fieldArr->setIJ(i,j,triofield._field[i*triofield._nb_field_components+j]);
304 }
305 }
306 //field on the receiving end
307 else
308 {
309 // the trio field points to the pointer inside the MED field
310 triofield._field=fieldArr->getPointer();
311 for (int i=0; i<triofield._nb_field_components*nb_case; i++)
312 triofield._field[i]=0.0;
313 }
314 field->setArray(fieldArr);
315 return MEDDoubleField(field);
316}
317MEDDoubleField build_medfield(const Champ_Generique_base& ch)
318{
319 TrioField fl;
320 build_triofield(ch, fl);
321 return build_medfield(fl);
322}
323
324
325#else
326namespace ICoCo
327{
328class MEDDoubleField
329{
330};
331}
332ICoCo::MEDDoubleField build_medfield(ICoCo::TrioField& ch)
333{
334 Cerr<<"Version compiled without MEDCoupling"<<finl;
336 throw;
337}
338ICoCo::MEDDoubleField build_medfield(const Champ_Generique_base& ch)
339{
340 Cerr<<"Version compiled without MEDCoupling"<<finl;
342 throw;
343}
344#endif
class Champ_Generique_base
virtual const Domaine_dis_base & get_ref_domaine_dis_base() const
Renvoie une ref au domaine_discretisee du domaine sur lequel sera evalue l espace de stockage.
virtual const Champ_base & get_champ(OWN_PTR(Champ_base) &espace_stockage) const =0
virtual double get_time() const
Renvoie le temps du Champ_Generique_base.
virtual Entity get_localisation(const int index=-1) const
Renvoie le type des entites geometriques sur auxquelles les valeurs discretes sont attachees (NODE po...
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual void abort() const =0
virtual void clear()
Reset the Domaine completely except for its name.
Definition Domaine.cpp:108
DoubleTab_t & les_sommets()
Definition Domaine.h:113
IntTab_t & les_elems()
Definition Domaine.h:129
int_t nb_elem() const
Definition Domaine.h:131
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
virtual IntTab & face_sommets()
const Domaine & domaine() const
const Nom & le_nom() const override
Renvoie le nom du champ.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
static const Comm_Group & groupe_TRUST()
Renvoie une reference au groupe de tous les processeurs TRUST.
const ArrOfInt_t & getPolyhedronIndex() const
Definition Polyedre.h:69
const BigArrOfInt_t & getNodes() const
Definition Polyedre.h:67
const ArrOfInt_t & getFacesIndex() const
Definition Polyedre.h:75
static void abort()
Routine de sortie de Trio-U sur une erreur abort().
Definition Process.cpp:570
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
_SIZE_ size_array() const
_TYPE_ * addr()
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133