TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Declarer_bord_perio.cpp
1/****************************************************************************
2* Copyright (c) 2026, 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#include <Reordonner_faces_periodiques.h>
16#include <Declarer_bord_perio.h>
17#include <Format_Post_base.h>
18#include <Synonyme_info.h>
19#include <Octree_Double.h>
20#include <Domaine_bord.h>
21#include <ArrOfBit.h>
22#include <Param.h>
23
24Implemente_instanciable_32_64(Declarer_bord_perio_32_64,"Declarer_bord_perio",Interprete_geometrique_base_32_64<_T_>);
25Add_synonym(Declarer_bord_perio,"Corriger_frontiere_periodique");
26Add_synonym(Declarer_bord_perio_64,"Corriger_frontiere_periodique_64");
27
28// XD declarer_bord_perio interprete corriger_frontiere_periodique BRACE The Declarer_bord_perio keyword is mandatory to
29// XD_CONT first define the periodic boundaries, to reorder the faces and eventually fix unaligned nodes of these
30// XD_CONT boundaries. Faces on one side of the periodic domain are put first, then the faces on the opposite side, in
31// XD_CONT the same order. It must be run in sequential before mesh splitting.
32// XD attr domaine chaine domaine REQ Name of domain.
33// XD attr bord chaine bord REQ the name of the boundary (which must contain two opposite sides of the domain)
34// XD attr direction list direction OPT defines the periodicity direction vector (a vector that points from one node on
35// XD_CONT one side to the opposite node on the other side). This vector must be given if the automatic algorithm fails,
36// XD_CONT that is:NL2 - when the node coordinates are not perfectly periodic NL2 - when the periodic direction is not
37// XD_CONT aligned with the normal vector of the boundary faces
38// XD attr fichier_post chaine fichier_post OPT .
39// XD attr declare_only rien declare_only OPT flag if added will only add the periodic boundary without calling
40// XD_CONT corriger_frontiere_periodique
41
42template <typename _SIZE_>
44{
45 return is;
46}
47
48template <typename _SIZE_>
50{
51 return os;
52}
53
54/*! @brief Main routine recording the periodic boundaries in the domain and performing the appropriate reordering of the faces
55 */
56template <typename _SIZE_>
58{
59 Domaine_t& dom = this->domaine();
60 const int_t dim = dom.coord_sommets().dimension(1);
61 int direction_perio_set;
62 if (direction_perio_.size_array() == 0)
63 {
64 direction_perio_set=0;
65 Cerr << "No direction given, searching periodicity direction automatically:" << finl;
67 }
68 else
69 {
70 direction_perio_set=1;
71 if (direction_perio_.size_array() != dim)
72 {
73 Cerr << "Error in Declarer_bord_perio::interpreter: direction should be of size "
74 << dim << finl;
75 this->exit();
76 }
77 }
78 Cerr << "Searching and moving periodicity nodes for domain " << dom.le_nom() << " boundary " << nom_bord_ << finl;
80 Bord_t& bord = dom.bord(nom_bord_);
81 IntTab_t& faces = bord.faces().les_sommets();
82 const double epsilon = Objet_U::precision_geom;
84 if (!ok)
85 {
86 if (direction_perio_set)
87 Cerr << "May be you give a wrong vector for the DIRECTION option" << finl;
88 else
89 Cerr << "May be you could use the DIRECTION option to specify the vector of periodicity" << finl;
90 Cerr << "for the keyword:" << finl;
91 Cerr << "Declarer_bord_perio { Domaine " << dom.le_nom() << " Bord " << nom_bord_ << " } " << finl;
92 this->exit();
93 }
94}
95
96template <typename _SIZE_>
98{
99 bool declare_only = false;
100
101 Nom nom_dom;
102 Param param(this->que_suis_je());
103 param.ajouter("domaine", &nom_dom, Param::REQUIRED);
104 param.ajouter("bord", &nom_bord_, Param::REQUIRED);
105 param.ajouter("direction", &direction_perio_);
106 param.ajouter("fichier_post", &nom_fichier_post_);
107 param.ajouter_flag("declare_only", &declare_only);
109
110 if (this->nproc() > 1)
111 {
112 Cerr << "Error in Declarer_bord_perio::interpreter():\n"
113 << " this function must be run in sequential before mesh splitting." << finl;
114 this->barrier();
115 this->exit();
116 }
117
118 this->associer_domaine(nom_dom);
119
120 if(!declare_only)
122
123 // Register 'bord' in the list of periodic boundary of the domain:
124 Domaine_t& dom = this->domaine();
125 dom.bords_perio().add(nom_bord_);
126
127 return is;
128}
129
130
131/*! @brief Pour chaque sommet du bord periodique, on cherche son sommet oppose dans la direction + ou - vecteur_perio et dans un rayon search_radius.
132 *
133 * Parmi le couple de sommets forme, on deplace celui qui se trouve en +vecteur_perio
134 * pour le mettre en face de l'autre sommet.
135 * Exit en cas d'erreur (si les sommets sont trop eloignes de leur sommet associe)
136 */
137template <typename _SIZE_>
139{
140 if (Process::nproc() > 1)
141 {
142 Cerr << "Error in Declarer_bord_perio_32_64::corriger_coordonnees_sommets_perio\n"
143 << " this algorithm is sequential (use it before Decouper)" << finl;
146 }
147
148 Domaine_t& dom = this->domaine();
149 Domaine_bord_t domaine_bord;
150 domaine_bord.construire_domaine_bord(dom, nom_bord_);
151 const ArrOfInt_t& renum_som = domaine_bord.get_renum_som();
152 const DoubleTab_t& som_bord = domaine_bord.les_sommets();
153 Octree_Double_t octree;
154 octree.build_nodes(som_bord, 0 /* do not include virtual nodes */);
155
156 const double epsilon_initial = dom.epsilon();
157 if (epsilon_initial == 0.)
158 {
159 Cerr << "Error in Declarer_bord_perio_32_64::corriger_coordonnees_sommets_perio\n"
160 << " dom.epsilon = 0." << finl;
162 }
163
164 int error_flag = 0;
165
166 const int_t nb_som_bord = som_bord.dimension(0);
167 const int dim = static_cast<int>(som_bord.dimension(1));
168 // Un tableau contenant le deplacement applique aux sommets (pour postraitement)
169 DoubleTab_t delta(nb_som_bord, dim);
170 // Un tableau pour detecter les erreurs de periodicite: sommets associes plusieurs fois
171 ArrOfBit_t marker(nb_som_bord);
172 marker = 0;
173 // Tableau temporaire pour l'octree:
174 ArrOfInt_t nodes_list;
175
176 DoubleTab_t& sommets_src = dom.les_sommets();
177 ArrOfDouble coord(dim);
178 for (int_t som = 0; som < nb_som_bord; som++)
179 {
180 if (marker.testsetbit(som))
181 continue; // Sommet deja traite
182
183 // Cherche le sommet oppose dans les deux directions (-1. et +1.)
184 double facteur;
185 int_t som2 = -1;
186 // Recherche du sommet dans un rayon de plus en plus grand en commencant par epsilon:
187 double epsilon = epsilon_initial;
188 do
189 {
190 for (facteur = -1.; facteur < 1.5; facteur += 2.)
191 {
192 for (int i = 0; i < dim; i++)
193 coord[i] = som_bord(som, i) + facteur * direction_perio_[i];
194 octree.search_elements_box(coord, epsilon, nodes_list);
195 som2 = octree.search_nodes_close_to(coord, som_bord, nodes_list, epsilon);
196 if (som2 >= 0)
197 break;
198 }
199 if (som2 >= 0)
200 break;
201 // Sommet non trouve, on recommence avec un rayon de recherche plus grand
202 epsilon *= 4.;
203 }
204 while (1);
205 if (marker.testsetbit(som2))
206 {
207 Cerr << "Error in Declarer_bord_perio_32_64::corriger_coordonnees_sommets_perio\n"
208 << " Coordinate " << coord
209 << " Closest point [ " << som_bord(som2, 0) << " " << som_bord(som2, 0) << " "
210 << ((dim==3)?som_bord(som2, 0):0.) << " ] already used for another point" << finl;
211 error_flag = 1;
212 }
213 else
214 {
215 // On deplace le sommet vers lequel pointe vecteur_perio:
216 const int_t som_ref = som;
217 const int_t som_deplace = som2;
218 // Indice du sommet a deplacer dans le domaine source:
219 const int_t s = renum_som[som_deplace];
220 // Deplacement
221 for (int i = 0; i < dim; i++)
222 {
223 double old_x = som_bord(som_deplace, i);
224 double new_x = som_bord(som_ref, i) + facteur * direction_perio_[i];
225 sommets_src(s, i) = new_x;
226 delta(som_deplace, i) = new_x - old_x;
227 }
228 }
229 }
230
231 if (nom_fichier_post_ != "??")
232 {
233 if (!std::is_same<_SIZE_, int>::value)
234 {
235 Cerr << "Declarer_bord_perio_64 - option 'fichier_post' is not implemented yet for 64b domains!" << finl;
236 Cerr << "Remove the attribute or contact TRUST support." << finl;
237 Process::exit(-1);
238 }
239#if INT_is_64_ != 2
240 //Domaine dom2;
241 Cerr << "Writing node displacement into file: " << nom_fichier_post_ << finl;
242 OWN_PTR(Format_Post_base) fichier_post;
243 fichier_post.typer("FORMAT_POST_LATA");
244 fichier_post->initialize(nom_fichier_post_, 1 /* binaire */, "SIMPLE");
245 Format_Post_base& post = fichier_post.valeur();
246 post.ecrire_entete(0., 0 /*reprise*/, 1 /* premier post */);
247 post.ecrire_domaine(domaine_bord, 1 /* premier_post */);
248 post.ecrire_temps(0.);
249 Noms unites;
250 unites.add("m");
251 unites.add("m");
252 if (dim==3) unites.add("m");
253 Noms compos;
254 compos.add("dx");
255 compos.add("dy");
256 if (dim==3) compos.add("dz");
257 post.ecrire_champ(domaine_bord,
258 unites, compos, -1 /* ecrire toutes les composantes */,
259 0., /* temps */
260 "vitesse", domaine_bord.le_nom(), "SOM","vector", delta);
261 int fin=1;
262 post.finir(fin);
263#endif
264 }
265
266 Cerr << "Max of node displacement (m): " << max_abs_array(delta) << finl;
267 if (error_flag)
268 {
269 Cerr << "Could not correct node coordinates. Aborting." << finl;
271 }
272}
273
274template class Declarer_bord_perio_32_64<int>;
275#if INT_is_64_ == 2
277#endif
int testsetbit(int_t i) const
Renvoie la valeur du bit e, puis met le bit e a 1.
Definition ArrOfBit.h:85
Cet interprete doit etre utilise en sequentiel (avant decoupage) si les sommets opposes d'un bord per...
ArrOfBit_32_64< _SIZE_ > ArrOfBit_t
DoubleTab_T< _SIZE_ > DoubleTab_t
void adapt_som_and_faces()
Main routine recording the periodic boundaries in the domain and performing the appropriate reorderin...
Entree & interpreter_(Entree &is) override
Octree_Double_32_64< _SIZE_ > Octree_Double_t
Domaine_32_64< _SIZE_ > Domaine_t
Domaine_bord_32_64< _SIZE_ > Domaine_bord_t
ArrOfInt_T< _SIZE_ > ArrOfInt_t
void corriger_coordonnees_sommets_perio()
Pour chaque sommet du bord periodique, on cherche son sommet oppose dans la direction + ou - vecteur_...
Bord_32_64< _SIZE_ > Bord_t
DoubleTab_t & les_sommets()
Definition Domaine.h:113
Bord_t & bord(int i)
Definition Domaine.h:193
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
const Noms & bords_perio() const
Definition Domaine.h:278
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
double epsilon() const
virtual void construire_domaine_bord(const Domaine_t &source, const Nom &nom_bord)
construit le domaine en appelant extraire_domaine_bord()
virtual const ArrOfInt_t & get_renum_som() const
renvoie renum_som (pour chaque sommet du domaine_bord, indice du meme sommet dans le domaine)
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
const IntTab_t & les_sommets() const
Renvoie le tableau des sommets de toutes les faces.
Definition Faces.h:74
Classe de base des formats de postraitements pour les champs (lata, med, cgns, lml,...
virtual int finir(const int est_le_dernier_post)
virtual int ecrire_champ(const Domaine &domaine, const Noms &unite_, const Noms &noms_compo, int ncomp, double temps_, const Nom &id_du_champ, const Nom &id_du_domaine, const Nom &localisation, const Nom &nature, const DoubleTab &data)
Ecriture d'un champ dans le fichier de postraitement.
virtual int ecrire_temps(const double temps)
Commence l'ecriture d'un pas de temps.
virtual int ecrire_entete(const double temps_courant, const int reprise, const int est_le_premier_post)
virtual int ecrire_domaine(const Domaine &domaine, const int est_le_premier_post)
Ecriture d'un maillage.
const Faces_t & faces() const
Definition Frontiere.h:54
classe Interprete_geometrique_base .
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
friend class Entree
Definition Objet_U.h:76
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
static double precision_geom
Definition Objet_U.h:86
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
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...
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
int lire_avec_accolades_depuis(Entree &is)
Parse the parameter block { ... } from is.
Definition Param.cpp:32
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static void chercher_direction_perio(ArrOfDouble &direction_perio, const Domaine_32_64< _SIZE_ > &dom, const Nom &bord)
static int reordonner_faces_periodiques(const Domaine_32_64< _SIZE_ > &domaine, IntTab_T< _SIZE_ > &faces, const ArrOfDouble &direction_perio, const double epsilon)
Reordonne le tableau "faces" selon la convention des faces periodiques: D'abord les faces d'une extre...
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133