Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
LegacyMeshBuilder.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* LegacyMeshBuilder.cc (C) 2000-2024 */
9/* */
10/* Construction du maillage via la méthode "historique". */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/internal/LegacyMeshBuilder.h"
15
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/StringBuilder.h"
18
19#include "arcane/core/MeshKind.h"
20#include "arcane/core/ISubDomain.h"
21#include "arcane/core/CaseNodeNames.h"
22#include "arcane/core/ICaseDocument.h"
23#include "arcane/core/IParallelMng.h"
24#include "arcane/core/ServiceBuilder.h"
25#include "arcane/core/IMainFactory.h"
26#include "arcane/core/IPrimaryMesh.h"
27#include "arcane/core/IGhostLayerMng.h"
28#include "arcane/core/IMeshReader.h"
29#include "arcane/core/IMeshMng.h"
30#include "arcane/core/IMeshUniqueIdMng.h"
31
32/*---------------------------------------------------------------------------*/
33/*---------------------------------------------------------------------------*/
34
35namespace Arcane
36{
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41LegacyMeshBuilder::
42LegacyMeshBuilder(ISubDomain* sd,MeshHandle default_mesh_handle)
43: TraceAccessor(sd->traceMng())
44, m_sub_domain(sd)
45, m_default_mesh_handle(default_mesh_handle)
46, m_internal_partitioner_name(ARCANE_DEFAULT_PARTITIONER_STR)
47{
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53void LegacyMeshBuilder::
54readCaseMeshes()
55{
56 ISubDomain* sd = m_sub_domain;
57 Integer sub_domain_id = sd->subDomainId();
58 ICaseDocument* case_doc = sd->caseDocument();
59 CaseNodeNames* cnn = case_doc->caseNodeNames();
60 XmlNodeList mesh_elems(case_doc->meshElements());
61 bool has_mesh_file = true;
62 if (mesh_elems.empty()){
63 info() << "No mesh in the input data";
64 has_mesh_file = false;
65 }
66 Integer nb_mesh = mesh_elems.size();
67 m_meshes_build_info.resize(nb_mesh);
68 for( Integer i=0; i<nb_mesh; ++i ){
69 MeshBuildInfo& mbi = m_meshes_build_info[i];
70 mbi.m_dir_name = ".";
71 mbi.m_xml_node = mesh_elems[i];
72 XmlNodeList partitioner_elems = mesh_elems[i].children(cnn->mesh_partitioner) ;
73 m_use_partitioner_tester = false;
74 if(partitioner_elems.empty()) {
75 m_use_partitioner_tester = true;
76 m_internal_partitioner_name = ARCANE_DEFAULT_PARTITIONER_STR;
77 }
78 else{
79 m_internal_partitioner_name = partitioner_elems[0].value() ;
80 //check if the partitioner is parallel
81 m_use_partitioner_tester = partitioner_elems[0].attr("need-basic-partition-first").valueAsBoolean();
82 }
83
84 XmlNode meshfile_elem = mesh_elems[i].child(cnn->mesh_file);
85 String smesh_file = meshfile_elem.value();
86 StringBuilder mesh_file = smesh_file;
87 mbi.m_orig_file_name = smesh_file;
88 if (smesh_file.null()){
89 info() << "No mesh in the input data";
90 has_mesh_file = false;
91 }
92
93 String file_format = meshfile_elem.attrValue("format");
94 bool internal_cut = meshfile_elem.attr("internal-partition").valueAsBoolean();
95 String internal_partitioner = meshfile_elem.attr("partitioner").value();
96
97 // Si la variable d'environnement est définie, force le repartitionnement
98 // initial avec le service dont le nom est spécifié dans cette variable.
99 String internal_partitioner_env = platform::getEnvironmentVariable("ARCANE_INTERNAL_PARTITIONER");
100 if (!internal_partitioner_env.null()){
101 info() << "Forcing internal partitioner from environment variable";
102 internal_cut = true;
103 internal_partitioner = internal_partitioner_env;
104 }
105 IParallelMng* pm = sd->parallelMng();
106 // Dans le cas où Arcane est retranché à un coeur, on va pas chercher les CPU*.mli
107 if (pm->isParallel() && (pm->commSize()>1)){
108 m_use_internal_mesh_partitioner = internal_cut;
109
110 if (!internal_partitioner.empty())
111 m_internal_partitioner_name = internal_partitioner;
112 Integer nb_sub_domain = pm->commSize();
113 info() << "Subdomain number is " << sub_domain_id << '/' << nb_sub_domain;
114
115 //check if the file mesh reader need a unique or multi file
116 bool use_unique_file = meshfile_elem.attr("unique").valueAsBoolean();
117 if (!use_unique_file){
118 //Integer nb_sub_domain = m_parallel_mng->commSize();
119 StringBuilder cut_dir_str("cut_");
120 cut_dir_str += nb_sub_domain;
121 String mesh_cut_dir = meshfile_elem.attrValue(cut_dir_str);
122 debug() << "MESH CUT DIR " << mesh_cut_dir << ' ' << cut_dir_str;
123 if (has_mesh_file && !internal_cut){
124 char buf[128];
125 String file_format_str = "mli";
126 if (!file_format.null())
127 file_format_str = file_format;
128 sprintf(buf,"CPU%05d.%s",(int)sub_domain_id,file_format_str.localstr());
129 log() << "The original mesh file is " << mesh_file;
130 if (mesh_cut_dir.empty())
131 mesh_file = String(std::string_view(buf));
132 else{
133 mbi.m_dir_name = mesh_cut_dir;
134 mesh_file = mesh_cut_dir;
135 mesh_file += "/";
136 mesh_file += buf;
137 }
138 }
139 }
140 }
141 log() << "The mesh file is " << mesh_file;
142 mbi.m_file_name = mesh_file;
143 // Cette partie de la configuration doit être lue avant
144 // la création du maillage car elle peut contenir des options
145 // dont le générateur de maillage a besoin.
146 //m_case_config->read();
147 }
148
149 // Créé les MeshHandle pour les maillages.
150 // Cela permettra de les récupérer dans les points d'entrée 'Build'
151 _createMeshesHandle();
152}
153
154/*---------------------------------------------------------------------------*/
155/*---------------------------------------------------------------------------*/
156
157void LegacyMeshBuilder::
158readMeshes()
159{
160 // Construit les services de lecture de maillage. Ce sont
161 // ceux qui implémentent IMeshReader.
162 ServiceBuilder<IMeshReader> builder(m_sub_domain);
163 UniqueArray<Ref<IMeshReader>> mesh_readers(builder.createAllInstances());
164
165 for( const MeshBuildInfo& mbi : m_meshes_build_info ){
166 _readMesh(mesh_readers,mbi);
167 }
168}
169
170/*---------------------------------------------------------------------------*/
171/*---------------------------------------------------------------------------*/
172
173void LegacyMeshBuilder::
174createDefaultMesh()
175{
176 ISubDomain* sd = m_sub_domain;
177 String mesh_name = m_default_mesh_handle.meshName();
178 ICaseDocument* case_doc = sd->caseDocument();
179 if (!case_doc){
180 // Si aucun jeu de données n'est spécifié, créé un maillage
181 m_default_mesh_handle._setMesh(sd->mainFactory()->createMesh(sd,mesh_name));
182 return;
183 }
184
185 CaseNodeNames* cnn = case_doc->caseNodeNames();
186 XmlNodeList mesh_elems(case_doc->meshElements());
187 if (mesh_elems.empty()){
188 info() << "No mesh in the input data";
189 }
190 Integer nb_mesh = mesh_elems.size();
191 for( Integer i=0; i<nb_mesh; ++i ){
192 XmlNode meshfile_elem = mesh_elems[i].child(cnn->mesh_file);
193 String mesh_file = meshfile_elem.value();
194 if (mesh_file.null()){
195 info() << "No mesh in the input data";
196 }
197 }
198 // default_mesh is the mesh described by mesh_elems[0]
199 // Now that amr flag has to be known at mesh creation, check-it for default mesh
200 bool is_amr = mesh_elems[0].attr("amr").valueAsBoolean();
201 eMeshAMRKind amr_type = static_cast<eMeshAMRKind>(mesh_elems[0].attr("amr-type").valueAsInteger());
202 if(is_amr && amr_type == eMeshAMRKind::None) {
203 amr_type = eMeshAMRKind::Cell;
204 }
205
206 m_default_mesh_handle._setMesh(sd->mainFactory()->createMesh(sd,mesh_name, amr_type));
207}
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
211
212void LegacyMeshBuilder::
213_createMeshesHandle()
214{
215 IMeshMng* mesh_mng = m_sub_domain->meshMng();
216
217 // Le premier maillage est toujours celui par défaut
218 Integer nb_build_mesh = m_meshes_build_info.size();
219 if (nb_build_mesh>0){
220 m_meshes_build_info[0].m_mesh_handle = m_default_mesh_handle;
221 }
222
223 // Créé les autres maillages spécifiés dans le jeu de données
224 for( Integer z=1; z<nb_build_mesh; ++z ){
225 String name;
226 if(m_meshes_build_info[z].m_xml_node.attr("dual").valueAsBoolean())
227 name = "DualMesh";
228 else
229 name = "Mesh";
230 name = name + z;
231 MeshHandle handle = mesh_mng->createMeshHandle(name);
232 m_meshes_build_info[z].m_mesh_handle = handle;
233 }
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
238
239void LegacyMeshBuilder::
240allocateMeshes()
241{
242 ISubDomain* sd = m_sub_domain;
243
244 // Le premier maillage est toujours celui par défaut
245 Integer nb_build_mesh = m_meshes_build_info.size();
246 if (nb_build_mesh>0){
247 m_meshes_build_info[0].m_mesh = m_default_mesh_handle.mesh()->toPrimaryMesh();
248 }
249
250 // Créé les autres maillages spécifiés dans le jeu de données
251 for( Integer z=1; z<nb_build_mesh; ++z ){
252 MeshHandle handle = m_meshes_build_info[z].m_mesh_handle;
253 if (handle.isNull())
254 ARCANE_FATAL("Invalid null MeshHandle for mesh index={0}",z);
255 // Depuis la 1.8.0 (modif IFP), cette methode
256 // appelle this->addMesh()
257 bool is_amr = m_meshes_build_info[z].m_xml_node.attr("amr").valueAsBoolean();
258 eMeshAMRKind amr_type = static_cast<eMeshAMRKind>(m_meshes_build_info[z].m_xml_node.attr("amr-type").valueAsInteger());
259 if(is_amr && amr_type == eMeshAMRKind::None) {
260 amr_type = eMeshAMRKind::Cell;
261 }
262
263 IPrimaryMesh* mesh = sd->mainFactory()->createMesh(sd,handle.meshName(),amr_type);
264 m_meshes_build_info[z].m_mesh = mesh;
265 }
266}
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
271void LegacyMeshBuilder::
272initializeMeshVariablesFromCaseFile()
273{
274 info() << "Initialization of the variable from the configuration file";
275 CaseNodeNames* cnn = m_sub_domain->caseDocument()->caseNodeNames();
276 for( const LegacyMeshBuilder::MeshBuildInfo& mbi : m_meshes_build_info ){
277 IMesh* mesh = mbi.m_mesh;
278 XmlNode node = mbi.m_xml_node;
279 XmlNode init_node = node.child(cnn->mesh_initialisation);
280 if (!init_node.null())
281 mesh->initializeVariables(init_node);
282 }
283}
284
285/*---------------------------------------------------------------------------*/
286/*---------------------------------------------------------------------------*/
287
288void LegacyMeshBuilder::
290{
291 IPrimaryMesh* mesh = mbi.m_mesh;
293
294 String mesh_file_name = mbi.m_file_name;
295 // Si un service de partitionnement est spécifié, il faut utiliser le fichier specifié
296 // dans le JDD et pas le nom du fichier éventuellement transformé dans readCaseMeshes()
297 bool use_internal_partitioner = m_use_internal_mesh_partitioner;
298 if (m_initial_partitioner.get()){
299 mesh_file_name = mbi.m_orig_file_name;
301 }
302 // Permet de forcer la dimension au cas ou le format ne peut pas la reconnaitre.
303 Integer wanted_dimension = mbi.m_xml_node.attr("dimension").valueAsInteger();
304 if (wanted_dimension!=0){
305 info() << "Force mesh dimension to " << wanted_dimension;
307 }
308 log() << "Mesh file: " << mesh_file_name;
309
310 Integer nb_ghost_layer = -1;
311 XmlNode nbGhostLayerNode = mbi.m_xml_node.attr("nb-ghostlayer");
312 if (!nbGhostLayerNode.null()){
313 nb_ghost_layer = nbGhostLayerNode.valueAsInteger();
314 if (nb_ghost_layer>=0){
315 info() << "Set number of ghost layers to '" << nb_ghost_layer << "' from caseoption";
316 mesh->ghostLayerMng()->setNbGhostLayer(nb_ghost_layer);
317 }
318 }
319
320 Integer builder_version = mbi.m_xml_node.attr("ghostlayer-builder-version").valueAsInteger();
321 if (nb_ghost_layer>=0 && builder_version>=0){
322 info() << "Set ghostlayer builder version to '" << builder_version << "' from caseoption";
323 mesh->ghostLayerMng()->setBuilderVersion(builder_version);
324 }
325
326 XmlNode face_numbering_version_node = mbi.m_xml_node.attr("face-numbering-version");
327 if (!face_numbering_version_node.null()) {
328 Int32 v = face_numbering_version_node.valueAsInteger();
329 if (v >= 0) {
330 info() << "Set face numbering version to '" << v << "' from caseoption";
331 mesh->meshUniqueIdMng()->setFaceBuilderVersion(v);
332 }
333 }
334 bool is_bad = true;
336 {
337 // Cherche l'extension du fichier et la conserve dans \a case_ext
338 std::string_view fview = mesh_file_name.toStdStringView();
339 debug() << " MF=" << fview;
340 std::size_t extension_pos = fview.find_last_of('.');
341 if (extension_pos!=std::string_view::npos){
342 fview.remove_prefix(extension_pos+1);
344 }
345 }
346
347 for( auto& mesh_reader_ref : mesh_readers ){
349 if (!mesh_reader->allowExtension(extension))
350 continue;
351
352 IMeshReader::eReturnType ret = mesh_reader->readMeshFromFile(mesh,
353 mbi.m_xml_node,
355 mbi.m_dir_name,
357 if (ret==IMeshReader::RTOk){
358 is_bad = false;
359 break;
360 }
361 if (ret==IMeshReader::RTError){
362 ARCANE_FATAL("Error while generating the mesh");
363 }
364 }
365
366 if (is_bad){
367 ARCANE_FATAL("Internal error: no mesh loaded or generated. \n",
368 "The mesh reader or generator required isn't available ",
369 "Recompile with the relevant options");
370 }
371
372 mesh->computeTiedInterfaces(mbi.m_xml_node);
374 //mesh->readAmrActivator(mbi.m_xml_node);
375
376#if 0
377 IMeshWriter* writer = ServiceFinderT<IMeshWriter>::find(serviceMng(),"VtkLegacyMeshWriter");
378 if (writer){
379 writer->writeMeshToFile(mesh,"test.vtk");
380 }
381 if (!parallelMng()->isParallel()){
382 mesh_utils::writeMeshConnectivity(mesh,"mesh-reference.xml");
383 }
384#endif
385}
386
387/*---------------------------------------------------------------------------*/
388/*---------------------------------------------------------------------------*/
389
390} // End namespace Arcane
391
392/*---------------------------------------------------------------------------*/
393/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Interface du service gérant la lecture d'un maillage.
Definition IMeshReader.h:37
eReturnType
Types des codes de retour d'une lecture ou écriture.
Definition IMeshReader.h:42
Interface d'un service d'écriture d'un maillage.
Definition IMeshWriter.h:36
virtual IMeshUniqueIdMng * meshUniqueIdMng() const =0
Gestionnare de la numérotation des identifiants uniques.
virtual IGhostLayerMng * ghostLayerMng() const =0
Gestionnare de couche fantômes associé
virtual void computeTiedInterfaces(const XmlNode &mesh_node)=0
Détermine les interfaces de semi-conformités.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual void setDimension(Integer dim)=0
Positionne la dimension du maillage (1D, 2D ou 3D).
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Noeud d'un arbre DOM.
Definition XmlNode.h:51
Vue constante d'un tableau de type T.
Chaîne de caractères unicode.
ARCCORE_HOST_DEVICE double log(double v)
Logarithme népérien de v.
Definition Math.h:40
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
eMeshAMRKind
Type de maillage AMR.
Definition MeshKind.h:40
Int32 Integer
Type représentant un entier.