TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Champ_Fonc_Interp.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
16#include <Discretisation_tools.h>
17#include <Champ_Generique_base.h>
18#include <Option_Interpolation.h>
19#include <Champ_Fonc_Interp.h>
20#include <TRUSTTab_parts.h>
21#include <Comm_Group_MPI.h>
22#include <Param.h>
23#include <MEDLoader.hxx>
24#ifdef MPI_
25#include <ParaFIELD.hxx>
26#endif
27
28Implemente_instanciable(Champ_Fonc_Interp, "Champ_Fonc_Interp", Champ_Fonc_P0_base);
29// XD Champ_Fonc_Interp champ_don_base Champ_Fonc_Interp BRACE Field that is interpolated from a distant domain via
30// XD_CONT MEDCoupling (remapper).
31
33
35{
36#ifdef MEDCOUPLING_
37 using namespace MEDCoupling;
38
39 Param param(que_suis_je());
40 Nom nom_pb_loc, nom_pb_dist, nom_dom_loc, nom_dom_dist, nat;
41 param.ajouter("nom_champ", &nom_, Param::REQUIRED); // XD_ADD_P chaine
42 // XD_CONT Name of the field (for example: temperature).
43 param.ajouter("pb_loc", &nom_pb_loc, Param::REQUIRED); // XD_ADD_P chaine
44 // XD_CONT Name of the local problem.
45 param.ajouter("pb_dist", &nom_pb_dist, Param::REQUIRED); // XD_ADD_P chaine
46 // XD_CONT Name of the distant problem.
47 param.ajouter("dom_loc", &nom_dom_loc); // XD_ADD_P chaine
48 // XD_CONT Name of the local domain.
49 param.ajouter("dom_dist", &nom_dom_dist); // XD_ADD_P chaine
50 // XD_CONT Name of the distant domain.
51 param.ajouter("default_value", &default_value_); // XD_ADD_P chaine
52 // XD_CONT Name of the distant domain.
53 param.ajouter("nature", &nat, Param::REQUIRED); // XD_ADD_P chaine
54 // XD_CONT Nature of the field (knowledge from MEDCoupling is required; IntensiveMaximum, IntensiveConservation, ...).
55 param.ajouter("use_overlapdec", &use_dec_); // XD_ADD_P chaine
56 // XD_CONT Nature of the field (knowledge from MEDCoupling is required; IntensiveMaximum, IntensiveConservation, ...).
57 param.lire_avec_accolades_depuis(is);
58
59 pb_loc_ = ref_cast(Probleme_base, Interprete::objet(nom_pb_loc));
60 pb_dist_ = ref_cast(Probleme_base, Interprete::objet(nom_pb_dist));
61 if (nom_dom_loc == "??") dom_loc_ = pb_loc_->domaine();
62 else dom_loc_ = ref_cast(Domaine, Interprete::objet(nom_dom_loc));
63 if (nom_dom_dist == "??") dom_dist_ = pb_dist_->domaine();
64 else
65 {
66 dom_dist_ = ref_cast(Domaine, Interprete::objet(nom_dom_dist));
68 }
69
70 is_elem_trgt_ = (pb_loc_->domaine_dis().que_suis_je() != "Domaine_VEF");
71
72 if (nat == "IntensiveMaximum") nature_ = IntensiveMaximum;
73 else if (nat == "IntensiveConservation") nature_ = IntensiveConservation;
74 else if (nat == "ExtensiveMaximum") nature_ = ExtensiveMaximum;
75 else if (nat == "ExtensiveConservation") nature_ = ExtensiveConservation;
76 else
77 {
78 Cerr << "Champ_Front_Interp : wrong NatureOfField read : " << nat << finl;
80 }
81
82 if (use_dec_ != -123)
84 else
86
87 return is;
88#else
89 Cerr << "Champ_Fonc_Interp::readOn should not be called since it requires a TRUST version compiled with MEDCoupling !" << finl;
90 throw;
91#endif
92}
93
95{
96 const int ok = Champ_Fonc_P0_base::initialiser(temps);
97 const Champ_base& ch = pb_dist_->has_champ(le_nom()) ? pb_dist_->get_champ(le_nom()) : pb_dist_->get_champ_post(le_nom()).get_champ(espace_stockage_);
98
101
102 nb_compo_ = ch.valeurs().line_size();
103
104 if (is_elem_trgt_)
105 {
106 valeurs_.resize(0, nb_compo_);
107 dom_loc_->creer_tableau_elements(valeurs_);
108 }
109 else
110 {
111 Domaine_VF& dvf = ref_cast(Domaine_VF, pb_loc_->domaine_dis());
112 valeurs_.resize(dvf.nb_faces(), nb_compo_);
114 valeurs_elem_.resize(0, nb_compo_);
115 dom_loc_->creer_tableau_elements(valeurs_elem_);
116 }
117
118 is_initialized_ = true;
119 return ok;
120}
121
123{
124#ifdef MEDCOUPLING_
125 using namespace MEDCoupling;
126
127 local_field_ = MEDCouplingFieldDouble::New(ON_CELLS, ONE_TIME);
128 local_field_->setName(le_nom().getString());
129 local_array_ = DataArrayDouble::New();
130 // XXX Pb with MEDCoupling : OvelapDEC seems to modify the meshes ...
131 if (Process::nproc() > 1 && use_dec_)
132 {
133 MCAuto<MEDCouplingUMesh> msh_cpy = dom_loc_->get_mc_mesh()->deepCopy();
134 local_field_->setMesh(msh_cpy);
135 }
136 else
137 local_field_->setMesh(dom_loc_->get_mc_mesh());
138 local_field_->setNature(nature_);
139
140 distant_field_ = MEDCouplingFieldDouble::New(ON_CELLS, ONE_TIME);
141 distant_array_ = DataArrayDouble::New();
142 distant_field_->setName(le_nom().getString());
143 // XXX Pb with MEDCoupling : OvelapDEC seems to modify the meshes ...
144 if (Process::nproc() > 1 && use_dec_)
145 {
146 MCAuto<MEDCouplingUMesh> msh_cpy = dom_dist_->get_mc_mesh()->deepCopy();
147 distant_field_->setMesh(msh_cpy);
148 }
149 else
150 distant_field_->setMesh(dom_dist_->get_mc_mesh());
151 distant_field_->setNature(nature_);
152#endif
153}
154
156{
157#ifdef MEDCOUPLING_
158 using namespace MEDCoupling;
159
160 const Champ_base& ch = pb_dist_->has_champ(le_nom()) ? pb_dist_->get_champ(le_nom()) : pb_dist_->get_champ_post(le_nom()).get_champ(espace_stockage_);
161
162 const DoubleTab& distant_values = ch.valeurs();
163 const Domaine_dis_base& dom_dist_dis = ch.a_un_domaine_dis_base() ? ch.domaine_dis_base() : pb_dist_->domaine_dis();
164 ConstDoubleTab_parts local_parts(valeurs()), distant_parts(distant_values);
165
166 if (local_field_ == nullptr) init_fields();
167
168 // Target Stuff
169 if (is_elem_trgt_)
170 local_array_->useExternalArrayWithRWAccess(valeurs().addr(), local_parts[0].dimension(0), nb_compo_);
171 else
172 local_array_->useExternalArrayWithRWAccess(valeurs_elem_.addr(), valeurs_elem_.dimension(0), nb_compo_);
173
174 local_field_->setArray(local_array_);
175
176 // Source Stuff
177 if (dom_dist_dis.que_suis_je() == "Domaine_VEF"
178 && dom_dist_dis.nb_elem() > 0
179 && distant_values.dimension_tot(0) == ref_cast(Domaine_VF, dom_dist_dis).nb_faces_tot())
180 {
181 Cerr << finl << "ERROR in Champ_Fonc_Interp : in problem " << pb_loc_->le_nom() << ", the distant field is located at faces!" << finl;
182 Cerr << "Use a postprocessing field located at elements instead of " << le_nom() << finl;
183 Cerr << "In your case, try : " << le_nom() << "_elem_" << dom_dist_dis.domaine().le_nom() << finl;
185 }
186
187 distant_array_->useArray(distant_values.addr(), false, MEDCoupling::DeallocType::CPP_DEALLOC, distant_parts[0].dimension(0), nb_compo_);
188 distant_field_->setArray(distant_array_);
189#endif
190}
191
193{
194#ifdef MEDCOUPLING_
195 using MEDCoupling::WriteField;
197 if (!is_initialized_) return;
198
199 if (Process::nproc() > 1 && use_dec_)
200 {
201#ifdef MPI_
202 if (dom_loc_->get_mc_mesh() == nullptr) dom_loc_->build_mc_mesh();
203 if (dom_dist_->get_mc_mesh() == nullptr) dom_dist_->build_mc_mesh();
204
206 OverlapDEC *dec = dom_loc_->get_dec(dom_dist_.valeur(), distant_field_, local_field_);
207 /* the fields given to OverlapDEC can not be changed without calling synchronize... but we can change where they point to! */
208 dec->setDefaultValue(default_value_);
209 dec->getSourceLocalField()->getField()->setArray(distant_array_);
210 dec->getTargetLocalField()->getField()->setArray(local_array_);
211 dec->sendRecvData(true);
212#endif
213 }
214 else
215 {
216 MEDCouplingRemapper *rmp = dom_loc_->get_remapper(dom_dist_.valeur());
218 rmp->transfer(distant_field_, local_field_, default_value_);
219
220 if (verbose_)
221 {
222 WriteField("/tmp/source" + le_nom().getString() + Nom(Process::me()).getString() + ".med", distant_field_, true);
223 WriteField("/tmp/target" + le_nom().getString() + Nom(Process::me()).getString() + ".med", local_field_, true);
224 }
225 }
226
227 // Put values on faces !
228 if (!is_elem_trgt_)
229 {
230 valeurs_elem_.echange_espace_virtuel();
231 const Domaine_VF& dvf = ref_cast(Domaine_VF, pb_loc_->domaine_dis());
233 }
234#endif
235}
virtual int initialiser(const double temps)
DOES NOTHING.
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
DoubleTab valeurs_
void mettre_a_jour(double) override
Time update of the field.
int initialiser(double) override
DOES NOTHING.
void mettre_a_jour(double) override
Time update of the field.
virtual DoubleTab & valeurs()=0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
virtual int a_un_domaine_dis_base() const
Definition Champ_base.h:69
virtual const Domaine_dis_base & domaine_dis_base() const
static void cells_to_faces(const Champ_base &He, Champ_base &Hf)
class Domaine_VF
Definition Domaine_VF.h:44
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
const Nom & le_nom() const override
Returns the name of the field.
int nb_compo_
Definition Field_base.h:95
Nature_du_champ nature_
Definition Field_base.h:96
static Objet_U & objet(const Nom &)
See Interprete_bloc::objet_global(). BM: the Interprete class is not the best place for this.
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
static int dimension
Definition Objet_U.h:94
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
@ REQUIRED
Definition Param.h:115
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
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
Base class for output streams.
Definition Sortie.h:52
_TYPE_ * addr()
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
int line_size() const
Definition TRUSTVect.tpp:67