Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
Lima.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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/* Lima.cc (C) 2000-2023 */
9/* */
10/* Lecture/Ecriture d'un fichier au format Lima. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Iostream.h"
15#include "arcane/utils/StdHeader.h"
16#include "arcane/utils/HashTableMap.h"
17#include "arcane/utils/ValueConvert.h"
18#include "arcane/utils/ScopedPtr.h"
19#include "arcane/utils/ArcanePrecomp.h"
20#include "arcane/utils/ITraceMng.h"
21#include "arcane/utils/Collection.h"
22#include "arcane/utils/Enumerator.h"
23#include "arcane/utils/PlatformUtils.h"
24#include "arcane/utils/Real3.h"
25#include "arcane/utils/OStringStream.h"
26#include "arcane/utils/CheckedConvert.h"
27#include "arcane/utils/StringBuilder.h"
28
29#include "arcane/IMeshReader.h"
30#include "arcane/IGhostLayerMng.h"
31#include "arcane/ISubDomain.h"
32#include "arcane/IIOMng.h"
33#include "arcane/IParallelMng.h"
34#include "arcane/IPrimaryMesh.h"
35#include "arcane/Item.h"
36#include "arcane/ItemTypeMng.h"
37#include "arcane/ItemGroup.h"
38#include "arcane/ArcaneException.h"
39#include "arcane/Service.h"
40#include "arcane/Timer.h"
41#include "arcane/ServiceFactory.h"
42#include "arcane/ServiceInfo.h"
43#include "arcane/CaseOptionsMain.h"
44#include "arcane/MeshUtils.h"
45#include "arcane/ItemEnumerator.h"
46#include "arcane/VariableTypes.h"
47#include "arcane/ServiceBuildInfo.h"
48#include "arcane/XmlNodeList.h"
49#include "arcane/IXmlDocumentHolder.h"
50#include "arcane/IItemFamily.h"
51#include "arcane/FactoryService.h"
52#include "arcane/IMeshWriter.h"
53#include "arcane/AbstractService.h"
54#include "arcane/ICaseDocument.h"
55#include "arcane/ICaseMeshReader.h"
56#include "arcane/IMeshBuilder.h"
57
58#include "arcane/cea/LimaCutInfosReader.h"
59
60#include <Lima/lima++.h>
61
62#include <memory>
63#include <algorithm>
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68namespace Arcane
69{
70
71/*---------------------------------------------------------------------------*/
72/*---------------------------------------------------------------------------*/
73
74namespace LimaUtils
75{
76void createGroup(IItemFamily* family,const String& name,Int32ArrayView local_ids);
77}
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81/*!
82 * \brief Lecteur des fichiers de maillage via la bibliothèque LIMA.
83 */
85: public TraceAccessor
86{
87 public:
88
89 LimaMeshBase(ISubDomain* sub_domain)
90 : TraceAccessor(sub_domain->traceMng()), m_sub_domain(sub_domain) {}
91 virtual ~LimaMeshBase() {}
92
93 public:
94
95 virtual bool readMesh(Lima::Maillage& lima,IPrimaryMesh* mesh,const String& filename,
96 const String& dir_name,bool use_internal_partition,Real length_multiplier) =0;
97
98 ISubDomain* subDomain() const { return m_sub_domain; }
99
100 protected:
101
102 private:
103
104 ISubDomain* m_sub_domain;
105
106 private:
107};
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111/*!
112 * \brief Lecteur des fichiers de maillage via la bibliothèque LIMA.
113 *
114 * Le paramètre 'template' permet de spécifier un wrapper pour lire les
115 * maillages 2D ou 3D.
116 */
117template<typename ReaderWrapper>
119: public LimaMeshBase
120{
121 public:
122
123 LimaWrapper(ISubDomain* sub_domain)
124 : LimaMeshBase(sub_domain), m_cut_infos_reader(new LimaCutInfosReader(sub_domain->parallelMng())) {}
125
127 {
128 delete m_cut_infos_reader;
129 }
130
131 public:
132
133 virtual bool readMesh(Lima::Maillage& lima,IPrimaryMesh* mesh,const String& filename,
134 const String& dir_name,bool use_internal_partition,Real length_multiplier);
135
136 private:
137
138 LimaCutInfosReader* m_cut_infos_reader;
139 ReaderWrapper m_wrapper;
140
141 bool _readMesh(Lima::Maillage& lima,IPrimaryMesh* mesh,const String& filename,
142 const String& dir_name,bool use_internal_partition,Real length_multiplier);
143
144 void _getProcList(UniqueArray<Integer>& proc_list,const String& dir_name);
145};
146
147/*---------------------------------------------------------------------------*/
148/*---------------------------------------------------------------------------*/
149
151{
152 public:
153
154 void setLima(const Lima::Maillage& lima_mesh)
155 {
156 m_lima_mesh = lima_mesh;
157 }
158
159 protected:
160
161 Lima::Maillage m_lima_mesh;
162};
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
169{
170 public:
171 typedef Lima::Surface LimaCellGroup;
172 typedef Lima::Polygone LimaCell;
173 typedef Lima::Ligne LimaFaceGroup;
174 typedef Lima::Bras LimaFace;
175 public:
176 Integer nbCellGroup()
177 {
178 return CheckedConvert::toInteger(m_lima_mesh.nb_surfaces());
179 }
180 Integer nbFaceGroup()
181 {
182 return CheckedConvert::toInteger(m_lima_mesh.nb_lignes());
183 }
184 LimaCellGroup cellGroup(Integer i)
185 {
186 return m_lima_mesh.surface(i);
187 }
188 LimaFaceGroup faceGroup(Integer i)
189 {
190 return m_lima_mesh.ligne(i);
191 }
192 Integer faceGroupNbFace(const LimaFaceGroup& group)
193 {
194 return CheckedConvert::toInteger(group.nb_bras());
195 }
196 LimaFace faceFaceGroup(const LimaFaceGroup& group,Integer i)
197 {
198 return group.bras(i);
199 }
200 Integer cellGroupNbCell(const LimaCellGroup& group)
201 {
202 return CheckedConvert::toInteger(group.nb_polygones());
203 }
204 LimaCell cellCellGroup(const LimaCellGroup& group,Integer i)
205 {
206 return group.polygone(i);
207 }
208 LimaCell cell(Integer i)
209 {
210 return m_lima_mesh.polygone(i);
211 }
212 LimaFace face(Integer i)
213 {
214 return m_lima_mesh.bras(i);
215 }
216 Integer nbCell()
217 {
218 return CheckedConvert::toInteger(m_lima_mesh.nb_polygones());
219 }
220 Integer nbFace()
221 {
222 return CheckedConvert::toInteger(m_lima_mesh.nb_bras());
223 }
224 int limaDimension()
225 {
226 return Lima::D2;
227 }
228 const char* strDimension()
229 {
230 return "2D";
231 }
232 static Integer cellToType(Integer nb_node)
233 {
234 switch(nb_node){
235 case 3: return IT_Triangle3;
236 case 4: return IT_Quad4;
237 case 5: return IT_Pentagon5;
238 case 6: return IT_Hexagon6;
239 default:
240 break;
241 }
242 return IT_NullType;
243 }
244};
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
251{
252 public:
253 typedef Lima::Volume LimaCellGroup;
254 typedef Lima::Polyedre LimaCell;
255 typedef Lima::Surface LimaFaceGroup;
256 typedef Lima::Polygone LimaFace;
257
258 Integer nbCellGroup()
259 {
260 return CheckedConvert::toInteger(m_lima_mesh.nb_volumes());
261 }
262 Integer nbFaceGroup()
263 {
264 return CheckedConvert::toInteger(m_lima_mesh.nb_surfaces());
265 }
266 LimaCellGroup cellGroup(Integer i)
267 {
268 return m_lima_mesh.volume(i);
269 }
270 LimaFaceGroup faceGroup(Integer i)
271 {
272 return m_lima_mesh.surface(i);
273 }
274 Integer faceGroupNbFace(const LimaFaceGroup& group)
275 {
276 return CheckedConvert::toInteger(group.nb_polygones());
277 }
278 LimaFace faceFaceGroup(const LimaFaceGroup& group,Integer i)
279 {
280 return group.polygone(i);
281 }
282 Integer cellGroupNbCell(const LimaCellGroup& group)
283 {
284 return CheckedConvert::toInteger(group.nb_polyedres());
285 }
286 LimaCell cellCellGroup(const LimaCellGroup& group,Integer i)
287 {
288 return group.polyedre(i);
289 }
290 LimaCell cell(Integer i)
291 {
292 return m_lima_mesh.polyedre(i);
293 }
294 LimaFace face(Integer i)
295 {
296 return m_lima_mesh.polygone(i);
297 }
298 Integer nbCell()
299 {
300 return CheckedConvert::toInteger(m_lima_mesh.nb_polyedres());
301 }
302 Integer nbFace()
303 {
304 return CheckedConvert::toInteger(m_lima_mesh.nb_polygones());
305 }
306 int limaDimension()
307 {
308 return Lima::D3;
309 }
310 const char* strDimension()
311 {
312 return "3D";
313 }
314 static Integer cellToType(Integer nb_node)
315 {
316 switch(nb_node){
317 case 4: return IT_Tetraedron4;
318 case 5: return IT_Pyramid5;
319 case 6: return IT_Pentaedron6;
320 case 8: return IT_Hexaedron8;
321 case 10: return IT_Heptaedron10;
322 case 12: return IT_Octaedron12;
323 default:
324 break;
325 }
326 return IT_NullType;
327 }
328};
329
330/*---------------------------------------------------------------------------*/
331/*---------------------------------------------------------------------------*/
332/*!
333 * \brief Lecteur des fichiers de maillage via la bibliothèque LIMA.
334 */
336: public TraceAccessor
337{
338 public:
339
341 : TraceAccessor(sd->traceMng()), m_sub_domain(sd){}
342
343 public:
344
345 auto readMesh(IPrimaryMesh* mesh, const String& file_name,
346 const String& dir_name,bool use_internal_partition,
347 bool use_length_unit) -> IMeshReader::eReturnType;
348
349 private:
350
351 ISubDomain* m_sub_domain;
352};
353
354/*---------------------------------------------------------------------------*/
355/*---------------------------------------------------------------------------*/
356/*!
357 * \brief Lecteur des fichiers de maillage via la bibliothèque LIMA.
358 */
360: public AbstractService
361, public IMeshReader
362{
363 public:
364
365 explicit LimaMeshReaderService(const ServiceBuildInfo& sbi);
366
367 public:
368
369 void build() {}
370
371 public:
372
373 bool allowExtension(const String& str) override
374 {
375 return str=="unf" || str=="mli" || str=="mli2" || str=="ice" || str=="uns" || str=="unv";
376 }
377
378 eReturnType readMeshFromFile(IPrimaryMesh* mesh,const XmlNode& mesh_node,
379 const String& file_name,
380 const String& dir_name,bool use_internal_partition) override;
381 ISubDomain* subDomain() { return m_sub_domain; }
382
383 private:
384
385 ISubDomain* m_sub_domain;
386
387 private:
388};
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
393ARCANE_REGISTER_SERVICE(LimaMeshReaderService,
394 ServiceProperty("Lima",ST_SubDomain),
395 ARCANE_SERVICE_INTERFACE(IMeshReader));
396
397/*---------------------------------------------------------------------------*/
398/*---------------------------------------------------------------------------*/
399
400LimaMeshReaderService::
401LimaMeshReaderService(const ServiceBuildInfo& sbi)
402: AbstractService(sbi)
403, m_sub_domain(sbi.subDomain())
404{
405}
406
407/*---------------------------------------------------------------------------*/
408/*---------------------------------------------------------------------------*/
409
410#ifdef ARCANE_LIMA_HAS_MLI
411extern "C++" IMeshReader::eReturnType
412_directLimaPartitionMalipp(ITimerMng* timer_mng,IPrimaryMesh* mesh,
413 const String& filename,Real length_multiplier);
414#endif
415
416#ifdef ARCANE_LIMA_HAS_MLI2
417extern "C++" IMeshReader::eReturnType
418_directLimaPartitionMalipp2(ITimerMng* timer_mng,IPrimaryMesh* mesh,
419 const String& filename,Real length_multiplier);
420#endif
421
422/*---------------------------------------------------------------------------*/
423/*---------------------------------------------------------------------------*/
424
426readMeshFromFile(IPrimaryMesh* mesh,const XmlNode& mesh_node,
427 const String& filename,const String& dir_name,
428 bool use_internal_partition)
429{
430 ISubDomain* sd = subDomain();
431
432 String case_doc_lang = "en";
433 ICaseDocument* case_doc = sd->caseDocument();
434 if (case_doc)
435 case_doc_lang = case_doc->language();
436
437 // Regarde si on souhaite utiliser l'unité de longueur dans le fichier de maillage.
438 String use_unit_attr_name = "utilise-unite";
439 String use_unit_str = mesh_node.attrValue(use_unit_attr_name);
440 if (case_doc_lang=="en"){
441 // Pour des raisons de compatiblité, regarde si 'utilise-unite' est présent
442 // auquel cas on le prend. Sinon, on prend le terme anglais.
443 if (!use_unit_str.empty()){
444 warning() << "'utilise-unite' ne doit être utilisé que pour les JDD en francais."
445 << "Utilisez 'use-unit' à la place";
446 }
447 use_unit_attr_name = "use-unit";
448 }
449 else{
450 // Si non anglais et que 'utilise-unite' n'est pas trouvé,
451 // essaie d'utiliser 'use-unit'. Cela est nécessaire pour prendre en compte
452 // MeshReaderMng::isUseMeshUnit().
453 if (use_unit_str.null()){
454 info() << "Attribute '" << use_unit_attr_name << "' is not found. Trying with 'use-unit'";
455 use_unit_attr_name = "use-unit";
456 }
457 }
458
459 // Depuis la 2.8.0 de Arcane, on lit par défaut les unités de longueur si
460 // si la variable d'environnement ARCANE_LIMA_DEFAULT_NO_UNIT est définie.
461 bool use_length_unit = true;
462 if (!platform::getEnvironmentVariable("ARCANE_LIMA_DEFAULT_NO_UNIT").null())
463 use_length_unit = false;
464 info() << "Default value for unit usage: " << use_length_unit;
465
466 if (use_unit_str.empty())
467 use_unit_str = mesh_node.attrValue(use_unit_attr_name);
468 info() << "Checking for attribute '" << use_unit_attr_name << "' value='" << use_unit_str << "'";
469 if (!use_unit_str.empty()){
470 if (use_unit_str=="1" || use_unit_str=="true")
471 use_length_unit = true;
472 else if (use_unit_str=="0" || use_unit_str=="false")
473 use_length_unit = false;
474 else
475 ARCANE_FATAL("Invalid value boolean value '{0}' for '{1}' attribute."
476 " Valid values are '0', '1' 'true' or 'false'",
477 use_unit_str,use_unit_attr_name);
478 }
479
480 info() << "Utilise l'unité de longueur de Lima: " << use_length_unit << " (lang=" << case_doc_lang << ")";
481
482 LimaMeshReader reader(sd);
483 return reader.readMesh(mesh,filename,dir_name,use_internal_partition,use_length_unit);
484}
485
486/*---------------------------------------------------------------------------*/
487/*---------------------------------------------------------------------------*/
488
489IMeshReader::eReturnType LimaMeshReader::
490readMesh(IPrimaryMesh* mesh,const String& filename,const String& dir_name,
491 bool use_internal_partition, bool use_length_unit)
492{
493 if (filename.null() || filename.empty())
495
496 ISubDomain* sd = m_sub_domain;
497 ITimerMng* timer_mng = sd->timerMng();
498 LimaMeshBase* lm = 0;
499 ICaseDocument* case_doc = sd->caseDocument();
500
501 info() << "Lima: use_length_unit=" << use_length_unit
502 << " use_internal_partition=" << use_internal_partition;
503 Real length_multiplier = 0.0;
504 if (use_length_unit){
505 String code_system;
506 if (case_doc)
507 code_system = case_doc->codeUnitSystem();
508 if (code_system.null() || code_system.empty()){
509 info() << "No unit system configured. Use MKS unit system.";
510 length_multiplier = 1.0;
511 }
512 else if (code_system=="CGS"){
513 length_multiplier = 100.0;
514 }
515 else if (code_system=="MKS"){
516 length_multiplier = 1.0;
517 }
518 else{
519 ARCANE_FATAL("Unknown unit system '{0}' (valid values are: 'CGS' ou 'MKS'",code_system);
520 }
521 }
522
523 std::string loc_file_name = filename.localstr();
524 size_t rpos = loc_file_name.rfind(".mli");
525 size_t rpos2 = loc_file_name.rfind(".mli2");
526 info() << " FILE_NAME=" << loc_file_name;
527 info() << " RPOS MLI=" << rpos << " s=" << loc_file_name.length();
528 info() << " RPOS MLI2=" << rpos2 << " s=" << loc_file_name.length();
529 //TODO mettre has_thread = true que si on utilise le gestionnaire de parallelisme
530 // via les threads
531 bool has_thread = false; //arcaneHasThread();
532 // On ne peut pas utiliser l'api mali pp avec les threads
533 if (!has_thread && use_internal_partition && ((rpos+4)==loc_file_name.length())){
534 info() << "Use direct partitioning with mli";
535#ifdef ARCANE_LIMA_HAS_MLI
536 return _directLimaPartitionMalipp(timer_mng,mesh,filename,length_multiplier);
537#else
538 ARCANE_FATAL("Can not use 'mli' files because Lima is not compiled with 'mli' support");
539#endif
540 }
541 else if (!has_thread && use_internal_partition && ((rpos2+5)==loc_file_name.length())){
542 info() << "Use direct partitioning with mli2";
543#ifdef ARCANE_LIMA_HAS_MLI2
544 return _directLimaPartitionMalipp2(timer_mng,mesh,filename,length_multiplier);
545#else
546 ARCANE_FATAL("Can not use 'mli2' files because Lima is not compiled with 'mli2' support");
547#endif
548 }
549 else {
550 info() << "Chargement Lima du fichier '" << filename << "'";
551
552 const char* version = Lima::lima_version();
553 info() << "Utilisation de la version " << version << " de Lima";
554
555 Timer time_to_read(sd,"ReadLima",Timer::TimerReal);
556
557 // Aucune préparation spécifique à faire
558 LM_TYPEMASQUE preparation = LM_ORIENTATION | LM_COMPACTE;
559
560 log() << "Début lecture fichier " << filename;
561
562 Lima::Maillage lima(filename.localstr());
563
564 try{
565 {
566 Timer::Sentry sentry(&time_to_read);
567 Timer::Phase t_action(sd,TP_InputOutput);
568 lima.lire(filename.localstr(),Lima::SUFFIXE,true);
569 //warning() << "Preparation lima supprimée";
570 lima.preparation_parametrable(preparation);
571 }
572 }
573 catch(const Lima::erreur& ex){
574 ARCANE_FATAL("Can not read lima file '{0}' error is '{1}'",filename,ex.what());
575 }
576 catch(...){
577 ARCANE_FATAL("Can not read lima file '{0}'",filename);
578 }
579
580 info() << "Temps de lecture et préparation du maillage (unité: seconde): "
581 << time_to_read.lastActivationTime();
582 // Si la dimension n'est pas encore positionnée, utilise celle
583 // donnée par Lima.
584 if (mesh->dimension()<=0){
585 if (lima.dimension()==Lima::D3){
586 mesh->setDimension(3);
587 info() << "Maillage 3D";
588 }
589 else if (lima.dimension()==Lima::D2){
590 mesh->setDimension(2);
591 info() << "Maillage 2D";
592 }
593 }
594
595 if (mesh->dimension()==3){
596 lm = new LimaWrapper<Lima3DReaderWrapper>(sd);
597 }
598 else if (mesh->dimension()==2){
599 lm = new LimaWrapper<Lima2DReaderWrapper>(sd);
600 }
601 if (!lm){
602 log() << "Dimension du maillage non reconnue par lima";
604 }
605
606 bool ret = lm->readMesh(lima,mesh,filename,dir_name,use_internal_partition,length_multiplier);
607 if (ret)
609
610 // A faire si plusieurs couches de mailles fantomes
611 {
612 Integer nb_ghost_layer = mesh->ghostLayerMng()->nbGhostLayer();
613 if (nb_ghost_layer>1)
615 }
616
617 delete lm;
618 }
619
620 return IMeshReader::RTOk;
621}
622
623/*---------------------------------------------------------------------------*/
624/*---------------------------------------------------------------------------*/
625
626template<typename ReaderWrapper> bool LimaWrapper<ReaderWrapper>::
627readMesh(Lima::Maillage& lima,IPrimaryMesh* mesh,const String& filename,
628 const String& dir_name,bool use_internal_partition,Real length_multiplier)
629{
630 return _readMesh(lima,mesh,filename,dir_name,use_internal_partition,length_multiplier);
631}
632
633/*---------------------------------------------------------------------------*/
634/*---------------------------------------------------------------------------*/
635
636template<typename ReaderWrapper> bool LimaWrapper<ReaderWrapper>::
637_readMesh(Lima::Maillage& lima,IPrimaryMesh* mesh,const String& file_name,
638 const String& dir_name,bool use_internal_partition,Real length_multiplier)
639{
640 ARCANE_UNUSED(file_name);
641
642 // Il faut utiliser le parallelMng du maillage qui peut être différent
643 // de celui du sous-domaine, par exemple si le maillage est séquentiel.
644 IParallelMng* pm = mesh->parallelMng();
645
646 bool is_parallel = pm->isParallel();
647 Integer sid = pm->commRank();
648
649 Integer mesh_nb_node = 0;
650 Integer nb_edge = 0;
651 Integer lima_nb_face = 0;
652 Integer mesh_nb_cell = 0;
653
654 m_wrapper.setLima(lima);
655
656 mesh_nb_node = CheckedConvert::toInteger(lima.nb_noeuds());
657 mesh_nb_cell = m_wrapper.nbCell(); //lima.nb_polyedres();
658 lima_nb_face = m_wrapper.nbFace(); //lima.nb_polygones();
659 nb_edge = 0; //lima.nb_bras();
660
661 info() << "-- Informations sur le maillage (Interne):";
662 info() << "Nombre de noeuds " << mesh_nb_node;
663 info() << "Nombre d'arêtes " << nb_edge;
664 info() << "Nombre de faces " << lima_nb_face;
665 info() << "Nombre de mailles " << mesh_nb_cell;
666 info() << "-- Informations sur le maillage (Lima):";
667 info() << "Nombre de noeuds " << lima.nb_noeuds();
668 info() << "Nombre d'arêtes " << lima.nb_bras();
669 info() << "Nombre de polygones " << lima.nb_polygones();
670 info() << "Nombre de polyedres " << lima.nb_polyedres();
671 info() << "Nombre de surfaces " << lima.nb_surfaces();
672 info() << "Nombre de volumes " << lima.nb_volumes();
673
674 info() << "Unité de longueur du fichier: " << lima.unite_longueur();
675 // Si 0.0, indique qu'on ne souhaite pas utiliser l'unité du fichier.
676 // Dans ce, cela correspond à un multiplicateur de 1.0
677 if (length_multiplier==0.0)
678 length_multiplier = 1.0;
679 else
680 length_multiplier *= lima.unite_longueur();
681
682 if (mesh_nb_node==0){
683 ARCANE_FATAL("No node in mesh");
684 }
685
686 // ------------------------------------------------------------
687 // -------------------------------- Création des mailles
688 // ------------------------------------------------------------
689
690
691 // Lit les numéros uniques des entités (en parallèle)
692 UniqueArray<Int64> nodes_unique_id(mesh_nb_node);
693 UniqueArray<Int64> cells_unique_id(mesh_nb_cell);
694 if (is_parallel && !use_internal_partition && pm->commSize()>1){
695 m_cut_infos_reader->readItemsUniqueId(nodes_unique_id,cells_unique_id,dir_name);
696 }
697 else{
698 for( Integer i=0; i<mesh_nb_node; ++i )
699 nodes_unique_id[i] = i;
700 for( Integer i=0; i<mesh_nb_cell; ++i )
701 cells_unique_id[i] = i;
702 }
703
704 // Pour l'instant, laisse à false.
705 // Si true, les uid sont incrémentés pour commencer à un.
706 bool first_uid_is_one = false;
707 if (!platform::getEnvironmentVariable("ARCANE_LIMA_UNIQUE_ID").null()){
708 first_uid_is_one = true;
709 info() << "WARNING: UniqueId begin at 1";
710 }
711 if (first_uid_is_one){
712 for( Integer i=0; i<mesh_nb_node; ++i )
713 ++nodes_unique_id[i];
714 for( Integer i=0; i<mesh_nb_cell; ++i )
715 ++cells_unique_id[i];
716 }
717
718 HashTableMapT<Int64,Real3> nodes_coords(mesh_nb_node,true);
719 if (!math::isEqual(length_multiplier,1.0)){
720 info() << "Using length multiplier v=" << length_multiplier;
721 for( Integer i=0; i<mesh_nb_node; ++i ){
722 const Lima::Noeud& node = lima.noeud(i);
723 Real3 coord(node.x(),node.y(),node.z());
724 coord *= length_multiplier;
725 nodes_coords.nocheckAdd(nodes_unique_id[i],coord);
726 }
727 }
728 else{
729 for( Integer i=0; i<mesh_nb_node; ++i ){
730 const Lima::Noeud& node = lima.noeud(i);
731 Real3 coord(node.x(),node.y(),node.z());
732 nodes_coords.nocheckAdd(nodes_unique_id[i],coord);
733 }
734 }
735
736 Integer cells_infos_index = 0;
737
738 UniqueArray<Integer> cells_filter;
739
740 bool use_own_mesh = false;
741
742 if (is_parallel && pm->commSize()>1){
743 use_own_mesh = true;
744 if (use_internal_partition)
745 use_own_mesh = false;
746 }
747
748 typedef typename ReaderWrapper::LimaCellGroup LimaCellGroup;
749 typedef typename ReaderWrapper::LimaCell LimaCell;
750 typedef typename ReaderWrapper::LimaFaceGroup LimaFaceGroup;
751 typedef typename ReaderWrapper::LimaFace LimaFace;
752
753 if (use_own_mesh){
754 Integer nb = m_wrapper.nbCellGroup();
755 for( Integer i=0; i<nb; ++i ){
756 const LimaCellGroup& lima_group = m_wrapper.cellGroup(i);
757 std::string group_name = lima_group.nom();
758 if (group_name=="LOCAL" || group_name=="local"){
759 Integer nb_own_cell = m_wrapper.cellGroupNbCell(lima_group);
760 cells_filter.resize(nb_own_cell);
761 for( Integer z=0; z<nb_own_cell; ++z ){
762 cells_filter[z] = CheckedConvert::toInteger(m_wrapper.cellCellGroup(lima_group,z).id() - 1);
763 }
764 }
765 }
766 }
767 else{
768 if (use_internal_partition && sid!=0){
769 mesh_nb_cell = 0;
770 mesh_nb_node = 0;
771 lima_nb_face = 0;
772 }
773 cells_filter.resize(mesh_nb_cell);
774 for( Integer i=0; i<mesh_nb_cell; ++i )
775 cells_filter[i] = i;
776 }
777
778 // Calcul le nombre de mailles/noeuds
779 Integer mesh_nb_cell_node = 0;
780 for( Integer j=0, js=cells_filter.size(); j<js; ++j ){
781 mesh_nb_cell_node += CheckedConvert::toInteger(m_wrapper.cell(cells_filter[j]).nb_noeuds());
782 }
783
784 // Tableau contenant les infos aux mailles (voir IMesh::allocateMesh())
785 UniqueArray<Int64> cells_infos(mesh_nb_cell_node+cells_filter.size()*2);
786
787 // Remplit le tableau contenant les infos des mailles
788 for( Integer i_cell=0, s_cell=cells_filter.size(); i_cell<s_cell; ++i_cell ){
789
790 Integer cell_indirect_id = cells_filter[i_cell];
791 LimaCell lima_cell = m_wrapper.cell(cell_indirect_id);
792 Integer n = CheckedConvert::toInteger(lima_cell.nb_noeuds());
793
794 Integer ct = ReaderWrapper::cellToType(n);
795 if (ct==IT_NullType)
796 throw UnknownItemTypeException("Lima::readFile: Cell",n,cell_indirect_id);
797 // Stocke le type de la maille
798 cells_infos[cells_infos_index] = ct;
799 ++cells_infos_index;
800 // Stocke le numéro unique de la maille
801 cells_infos[cells_infos_index] = cells_unique_id[cell_indirect_id];
802 ++cells_infos_index;
803
804 // Rempli la liste des numéros des noeuds de la maille
805 for( Integer z=0, sz=n; z<sz; ++z ){
806 Int64 node_uid = nodes_unique_id[CheckedConvert::toInteger(lima_cell.noeud(z).id()-1)];
807 cells_infos[cells_infos_index+z] = node_uid;
808 }
809
810#if 0
811 cout << "CELL LIMA1 " << cells_unique_id[cell_indirect_id] << " ";
812 for( Integer z=0; z<n; ++z )
813 cout << " " << cells_infos[cells_infos_index+z];
814 cout << '\n';
815#endif
816
817 cells_infos_index += n;
818 }
819
820 logdate() << "Début allocation du maillage nb_cell=" << cells_filter.size();
821 mesh->allocateCells(cells_filter.size(),cells_infos,false);
822 logdate() << "Fin allocation du maillage";
823
824 // Positionne les propriétaires des noeuds à partir des groupes de noeuds de Lima
825 if (use_internal_partition){
826 ItemInternalList nodes(mesh->itemsInternal(IK_Node));
827 for( Integer i=0, is=nodes.size(); i<is; ++i )
828 nodes[i]->setOwner(sid,sid);
829 ItemInternalList cells(mesh->itemsInternal(IK_Cell));
830 for( Integer i=0, is=cells.size(); i<is; ++i )
831 cells[i]->setOwner(sid,sid);
832 }
833 else{
834 Int64UniqueArray unique_ids;
835 Int32UniqueArray local_ids;
836 Integer sub_domain_id = subDomain()->subDomainId();
837 Integer nb = CheckedConvert::toInteger(lima.nb_nuages());
838 for( Integer i=0; i<nb; ++i ){
839 const Lima::Nuage& lima_group = lima.nuage(i);
840 Integer nb_item_in_group = CheckedConvert::toInteger(lima_group.nb_noeuds());
841 std::string group_name = lima_group.nom();
842 unique_ids.resize(nb_item_in_group);
843 local_ids.resize(nb_item_in_group);
844 for( Integer z=0; z<nb_item_in_group; ++z ){
845 unique_ids[z] = nodes_unique_id[CheckedConvert::toInteger(lima_group.noeud(z).id() - 1)];
846 }
847 mesh->nodeFamily()->itemsUniqueIdToLocalId(local_ids,unique_ids,false);
848 bool remove_group = false;
849 if (group_name=="LOCALN" || group_name=="localn"){
850 info() << "Utilisation du groupe 'LOCALN' pour indiquer que les "
851 << "noeuds appartiennent au sous-domaine";
852 ItemInternalList nodes(mesh->itemsInternal(IK_Node));
853 for( Integer z=0, sz=nb_item_in_group; z<sz; ++z ){
854 Integer local_id = local_ids[z];
855 if (local_id!=NULL_ITEM_ID)
856 nodes[local_id]->setOwner(sub_domain_id,sub_domain_id);
857 }
858 remove_group = true;
859 }
860 debug() << "Vérification du groupe '" << group_name << "'";
861 if (group_name.length()>3 && !remove_group){
862 String grp = group_name; //.c_str();
863 if (grp.startsWith("NF_")){
864 grp = grp.substring(3);
865 Int32 ghost_sub_domain_id = 0;
866 bool is_bad = builtInGetValue(ghost_sub_domain_id,grp);
867 debug() << "Vérification du groupe '" << group_name << "' (3) " << is_bad;
868 if (!is_bad){
869 info() << "Utilisation du groupe " << group_name << " pour indiquer que le "
870 << "sous-domaine " << ghost_sub_domain_id << " est propriétaire de ses noeuds";
871 ItemInternalList nodes(mesh->itemsInternal(IK_Node));
872 for( Integer z=0, sz=nb_item_in_group; z<sz; ++z ){
873 Integer local_id = local_ids[z];
874 if (local_id!=NULL_ITEM_ID)
875 nodes[local_ids[z]]->setOwner(ghost_sub_domain_id,sub_domain_id);
876 }
877 remove_group = true;
878 }
879 }
880 }
881 }
882 }
883
884 mesh->endAllocate();
885
886 // Comme le maillage créé lui même ses faces sans tenir compte de celles qui
887 // existent éventuellement dans Lima, il faut maintenant déterminer le numéro
888 // local dans notre maillage de chaque face de Lima.
889 UniqueArray<Integer> faces_id(lima_nb_face); // Numéro de la face lima dans le maillage \a mesh
890 {
891 // Nombre de faces/noeuds
892 Integer face_nb_node = 0;
893 for( Integer i_face=0; i_face<lima_nb_face; ++i_face ){
894 const LimaFace& lima_face = m_wrapper.face(i_face);
895 face_nb_node += CheckedConvert::toInteger(lima_face.nb_noeuds());
896 }
897
898 UniqueArray<Int64> faces_first_node_unique_id(lima_nb_face);
899 UniqueArray<Int32> faces_first_node_local_id(lima_nb_face);
900 UniqueArray<Int64> faces_nodes_unique_id(face_nb_node);
901 Integer faces_nodes_unique_id_index = 0;
902
903 UniqueArray<Int64> orig_nodes_id;
904 orig_nodes_id.reserve(100);
905
906 UniqueArray<Integer> face_nodes_index;
907 face_nodes_index.reserve(100);
908
909 ItemInternalList mesh_nodes(mesh->itemsInternal(IK_Node));
910
911 for( Integer i_face=0; i_face<lima_nb_face; ++i_face ){
912 const LimaFace& lima_face = m_wrapper.face(i_face);
913 Integer n = CheckedConvert::toInteger(lima_face.nb_noeuds());
914 orig_nodes_id.resize(n);
915 face_nodes_index.resize(n);
916 for( Integer z=0; z<n; ++z )
917 orig_nodes_id[z] = nodes_unique_id[CheckedConvert::toInteger(lima_face.noeud(z).id() - 1)];
918 //face_orig_nodes_id[z] = lima_face.noeud(z).id() - 1;
919
920#if 0
921 cout << "FACE LIMA1 " << lima_face.id()-1 << " ";
922 for( Integer z=0; z<n; ++z )
923 cout << " " << orig_nodes_id[z];
924 cout << '\n';
925#endif
926
927 mesh_utils::reorderNodesOfFace2(orig_nodes_id,face_nodes_index);
928 for( Integer z=0; z<n; ++z )
929 faces_nodes_unique_id[faces_nodes_unique_id_index+z] = orig_nodes_id[face_nodes_index[z]];
930 faces_first_node_unique_id[i_face] = orig_nodes_id[face_nodes_index[0]];
931 faces_nodes_unique_id_index += n;
932 }
933
934 mesh->nodeFamily()->itemsUniqueIdToLocalId(faces_first_node_local_id,faces_first_node_unique_id);
935
936 faces_nodes_unique_id_index = 0;
937 for( Integer i_face=0; i_face<lima_nb_face; ++i_face ){
938 const LimaFace& lima_face = m_wrapper.face(i_face);
939 Integer n = CheckedConvert::toInteger(lima_face.nb_noeuds());
940 Int64ConstArrayView face_nodes_id(n,&faces_nodes_unique_id[faces_nodes_unique_id_index]);
941 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
942 Face face = mesh_utils::getFaceFromNodesUnique(current_node,face_nodes_id);
943
944 if (face.null()){
945 OStringStream ostr;
946 ostr() << "(Nodes:";
947 for( Integer z=0; z<n; ++z )
948 ostr() << ' ' << face_nodes_id[z];
949 ostr() << " - " << current_node.localId() << ")";
950 ARCANE_FATAL("INTERNAL: Lima face index={0} with nodes '{1}' is not in node/face connectivity",
951 i_face,ostr.str());
952 }
953 faces_id[i_face] = face.localId();
954
955 faces_nodes_unique_id_index += n;
956 }
957 }
958
959 IItemFamily* node_family = mesh->nodeFamily();
960 IItemFamily* face_family = mesh->faceFamily();
961 IItemFamily* cell_family = mesh->cellFamily();
962
963 // Création des groupes
964 if (use_internal_partition && sid!=0){
965 {
966 Integer nb = CheckedConvert::toInteger(lima.nb_nuages());
967 for( Integer i=0; i<nb; ++i ){
968 const Lima::Nuage& lima_group = lima.nuage(i);
969 std::string group_name = lima_group.nom();
970 LimaUtils::createGroup(node_family,group_name,Int32ArrayView());
971 }
972 }
973 {
974 Integer nb = m_wrapper.nbFaceGroup();
975 for( Integer i=0; i<nb; ++i ){
976 const LimaFaceGroup& lima_group = m_wrapper.faceGroup(i);
977 std::string group_name = lima_group.nom();
978 LimaUtils::createGroup(face_family,group_name,Int32ArrayView());
979 }
980 }
981 {
982 Integer nb = m_wrapper.nbCellGroup();
983 for( Integer i=0; i<nb; ++i ){
984 const LimaCellGroup& lima_group = m_wrapper.cellGroup(i);
985 std::string group_name = lima_group.nom();
986 LimaUtils::createGroup(cell_family,group_name,Int32ArrayView());
987 }
988 }
989 }
990 else{
991 UniqueArray<Int64> unique_ids;
992 UniqueArray<Int32> local_ids;
993 Integer sub_domain_id = subDomain()->subDomainId();
994 // Création des groupes de noeuds
995 {
996 Integer nb = CheckedConvert::toInteger(lima.nb_nuages());
997 for( Integer i=0; i<nb; ++i ){
998 const Lima::Nuage& lima_group = lima.nuage(i);
999 Integer nb_item_in_group = CheckedConvert::toInteger(lima_group.nb_noeuds());
1000 std::string group_name = lima_group.nom();
1001 unique_ids.resize(nb_item_in_group);
1002 local_ids.resize(nb_item_in_group);
1003 for( Integer z=0; z<nb_item_in_group; ++z ){
1004 Integer lima_node_id = CheckedConvert::toInteger(lima_group.noeud(z).id());
1005 unique_ids[z] = nodes_unique_id[lima_node_id - 1];
1006 }
1007 mesh->nodeFamily()->itemsUniqueIdToLocalId(local_ids,unique_ids);
1008 bool remove_group = false;
1009 if (group_name=="LOCALN" || group_name=="localn"){
1010 remove_group = true;
1011 }
1012 debug() << "Vérification du groupe '" << group_name << "'";
1013 if (group_name.length()>3 && !remove_group){
1014 String grp = group_name.c_str();
1015 //grp.left(3);
1016 debug() << "Vérification du groupe '" << group_name << "' (2) '" << grp << "'";
1017 if (grp.startsWith("NF_")){
1018 //grp = group_name.c_str();
1019 //grp.right(group_name.length()-3);
1020 grp = grp.substring(3);
1021 Integer ghost_sub_domain_id = 0;
1022 bool is_bad = builtInGetValue(ghost_sub_domain_id,grp);
1023 debug() << "Vérification du groupe '" << group_name << "' (3) " << is_bad;
1024 if (!is_bad){
1025 remove_group = true;
1026 }
1027 }
1028 }
1029 if (!remove_group){
1030 log() << "NodeGroup Name <" << group_name << "> (" << nb_item_in_group << " elements)";
1031 LimaUtils::createGroup(node_family,group_name,local_ids);
1032 }
1033 }
1034 }
1035 // Création des groupes de faces
1036 {
1037 Integer nb = m_wrapper.nbFaceGroup();
1038 for( Integer i=0; i<nb; ++i ){
1039 const LimaFaceGroup& lima_group = m_wrapper.faceGroup(i);
1040 Integer nb_item_in_group = m_wrapper.faceGroupNbFace(lima_group);
1041 local_ids.resize(nb_item_in_group);
1042 // Comme les numéros des faces données par Lima ne correspondent
1043 // pas à celles créées dans Arcane, on utilise le tableau de correspondance
1044 for( Integer z=0; z<nb_item_in_group; ++z ){
1045 local_ids[z] = faces_id[CheckedConvert::toInteger(m_wrapper.faceFaceGroup(lima_group,z).id() - 1)];
1046 }
1047 std::string group_name = lima_group.nom();
1048 log() << "FaceGroup Name <" << group_name << "> (" << nb_item_in_group << " elements)";
1049 LimaUtils::createGroup(face_family,group_name,local_ids);
1050 }
1051 }
1052 // Création des groupes de mailles
1053 {
1054 Integer nb = m_wrapper.nbCellGroup();
1055 for( Integer i=0; i<nb; ++i ){
1056 const LimaCellGroup& lima_group = m_wrapper.cellGroup(i);
1057 Integer nb_item_in_group = m_wrapper.cellGroupNbCell(lima_group);
1058 std::string group_name = lima_group.nom();
1059 unique_ids.resize(nb_item_in_group);
1060 local_ids.resize(nb_item_in_group);
1061 for( Integer z=0; z<nb_item_in_group; ++z ){
1062 unique_ids[z] = cells_unique_id[CheckedConvert::toInteger(m_wrapper.cellCellGroup(lima_group,z).id() - 1)];
1063 }
1064 mesh->cellFamily()->itemsUniqueIdToLocalId(local_ids,unique_ids);
1065 bool remove_group = false;
1066 if (group_name=="LOCAL" || group_name=="local"){
1067 ItemInternalList cells(mesh->itemsInternal(IK_Cell));
1068 for( Integer z=0, sz=nb_item_in_group; z<sz; ++z )
1069 cells[local_ids[z]]->setOwner(sub_domain_id,sub_domain_id);
1070 remove_group = true;
1071 }
1072 if (!remove_group){
1073 String grp(group_name.c_str());
1074 if (grp.startsWith("MF_")){
1075 info() << "Le groupe de mailles " << group_name << " n'est pas utilisé";
1076 remove_group = true;
1077 }
1078 }
1079 if (!remove_group){
1080 log() << "CellGroup Name <" << group_name << "> (" << nb_item_in_group << " elements)";
1081 LimaUtils::createGroup(cell_family,group_name,local_ids);
1082 }
1083 }
1084 }
1085 }
1086
1087
1088 {
1089 // Remplit la variable contenant les coordonnées des noeuds
1090 // En parallèle avec le maillage déjà découpé par Decoupe3D, le
1091 // maillage contient déjà une couche de mailles fantomes. Pour
1092 // avoir les coordonnées des noeuds si on a besoin que d'une couche
1093 // de mailles fantomes, il suffit donc de parcourir tous
1094 // les noeuds. Si on a besoin de plusieurs couches de mailles fantomes,
1095 // il faut faire une synchronisation.
1096 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
1097 NodeGroup nodes = mesh->allNodes();
1098 Integer nb_ghost_layer = mesh->ghostLayerMng()->nbGhostLayer();
1099 if (nb_ghost_layer>1)
1100 nodes = mesh->ownNodes();
1101 ENUMERATE_NODE(i,nodes){
1102 const Node& node = *i;
1103 nodes_coord_var[node] = nodes_coords.lookupValue(node.uniqueId());
1104 //info() << "Coord: " << node.uniqueId() << " v=" << nodes_coord_var[node];
1105 }
1106 if (nb_ghost_layer>1)
1107 nodes_coord_var.synchronize();
1108 }
1109
1110
1111 // -------------------------------- Lecture des groupes
1112 info() << "Nombre de nuages " << lima.nb_nuages();
1113 info() << "Nombre de lignes " << lima.nb_lignes();
1114 info() << "Nombre de surfaces " << lima.nb_surfaces();
1115 info() << "Nombre de volumes " << lima.nb_volumes();
1116
1117 // -------------------------------- Création des structures internes.
1118
1119 //_buildInternalMesh();
1120
1121 logdate() << "Fin de lecture du fichier";
1122 return false;
1123}
1124
1125/*---------------------------------------------------------------------------*/
1126/*---------------------------------------------------------------------------*/
1127
1128template<typename ReaderWrapper> void LimaWrapper<ReaderWrapper>::
1129_getProcList(UniqueArray<Integer>& proc_list,const String& dir_name)
1130{
1131 ISubDomain* sd = subDomain();
1132 StringBuilder comm_file_nameb;
1133 if (!dir_name.empty()){
1134 comm_file_nameb += dir_name;
1135 comm_file_nameb += "/";
1136 }
1137 comm_file_nameb += "Communications";
1138 String comm_file_name = comm_file_nameb.toString();
1139
1140 // Lecture du fichier de communication
1141 ScopedPtrT<IXmlDocumentHolder> doc_holder(sd->ioMng()->parseXmlFile(comm_file_name));
1142 if (!doc_holder.get())
1143 ARCANE_FATAL("Invalid file '{0}'",comm_file_name);
1144
1145 XmlNode root_elem = doc_holder->documentNode().documentElement();
1146 XmlNode cpu_elem;
1147 XmlNodeList cpu_list = root_elem.child(String("cpus")).children(String("cpu-from"));
1148
1149 String ustr_buf = String::fromNumber(sd->subDomainId());
1150 String ustr_id(String("id"));
1151 for( Integer i=0, s=cpu_list.size(); i<s; ++i ){
1152 String id_str = cpu_list[i].attrValue(ustr_id);
1153 if (id_str==ustr_buf){
1154 cpu_elem = cpu_list[i];
1155 break;
1156 }
1157 }
1158 if (cpu_elem.null())
1159 ARCANE_FATAL("No element <cpus/cpu-from[@id=\"{0}\"]>",sd->subDomainId());
1160 {
1161 cpu_list = cpu_elem.children(String("cpu-to"));
1162 debug() << "Nb procs " << cpu_list.size();
1163 for( Integer i=0; i<cpu_list.size(); ++i ){
1164 Integer v = cpu_list[i].valueAsInteger();
1165 proc_list.add(v);
1166 debug() << "Read proc " << v;
1167 }
1168 }
1169}
1170
1171/*---------------------------------------------------------------------------*/
1172/*---------------------------------------------------------------------------*/
1173
1175: public AbstractService
1176, public ICaseMeshReader
1177{
1178 public:
1179
1181 : public IMeshBuilder
1182 {
1183 public:
1184
1185 explicit Builder(ISubDomain* sd, const CaseMeshReaderReadInfo& read_info)
1186 : m_sub_domain(sd)
1187 , m_trace_mng(sd->traceMng())
1188 , m_read_info(read_info)
1189 {}
1190
1191 public:
1192
1193 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1194 {
1195 ARCANE_UNUSED(build_info);
1196 }
1198 {
1199 LimaMeshReader reader(m_sub_domain);
1200 String fname = m_read_info.fileName();
1201 m_trace_mng->info() << "Lima Reader (ICaseMeshReader) file_name=" << fname;
1202 bool use_length_unit = true; // Avec le ICaseMeshReader on utilise toujours le système d'unité.
1203 String directory_name = m_read_info.directoryName();
1204 IMeshReader::eReturnType ret = reader.readMesh(pm, fname, directory_name, m_read_info.isParallelRead(), use_length_unit);
1205 if (ret != IMeshReader::RTOk)
1206 ARCANE_FATAL("Can not read MSH File");
1207 }
1208
1209 private:
1210
1211 ISubDomain* m_sub_domain;
1212 ITraceMng* m_trace_mng;
1213 CaseMeshReaderReadInfo m_read_info;
1214 };
1215
1216 public:
1217
1218 explicit LimaCaseMeshReader(const ServiceBuildInfo& sbi)
1219 : AbstractService(sbi), m_sub_domain(sbi.subDomain())
1220 {}
1221
1222 public:
1223
1224 Ref<IMeshBuilder> createBuilder(const CaseMeshReaderReadInfo& read_info) const override
1225 {
1226 IMeshBuilder* builder = nullptr;
1227 String str = read_info.format();
1228 if (str=="unf" || str=="mli" || str=="mli2" || str=="ice" || str=="uns" || str=="unv")
1229 builder = new Builder(m_sub_domain, read_info);
1230 return makeRef(builder);
1231 }
1232
1233 private:
1234
1235 ISubDomain* m_sub_domain = nullptr;
1236};
1237
1238/*---------------------------------------------------------------------------*/
1239/*---------------------------------------------------------------------------*/
1240
1241ARCANE_REGISTER_SERVICE(LimaCaseMeshReader,
1242 ServiceProperty("LimaCaseMeshReader", ST_SubDomain),
1243 ARCANE_SERVICE_INTERFACE(ICaseMeshReader));
1244
1245/*---------------------------------------------------------------------------*/
1246/*---------------------------------------------------------------------------*/
1247
1248/*---------------------------------------------------------------------------*/
1249/*---------------------------------------------------------------------------*/
1250
1252: public AbstractService
1253, public IMeshWriter
1254{
1255 public:
1257 : AbstractService(sbi), m_sub_domain(sbi.subDomain()) {}
1258 public:
1259 virtual void build() {}
1260 virtual bool writeMeshToFile(IMesh* mesh,const String& file_name);
1261
1262 private:
1263 ISubDomain* m_sub_domain;
1264 void _writeItem(Lima::Maillage& lima_mesh,ConstArrayView<Lima::Noeud> nodes,
1265 ItemWithNodes item);
1266};
1267
1268/*---------------------------------------------------------------------------*/
1269/*---------------------------------------------------------------------------*/
1270
1271ARCANE_REGISTER_SERVICE(LimaMeshWriter,
1272 ServiceProperty("Lima",ST_SubDomain),
1273 ARCANE_SERVICE_INTERFACE(IMeshWriter));
1274
1275/*---------------------------------------------------------------------------*/
1276/*---------------------------------------------------------------------------*/
1277
1278void LimaMeshWriter::
1279_writeItem(Lima::Maillage& m,ConstArrayView<Lima::Noeud> nodes,ItemWithNodes c)
1280{
1281 switch(c.type()){
1282 case IT_Octaedron12:
1283 m.ajouter(Lima::Polyedre(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1284 nodes[c.node(2).localId()],nodes[c.node(3).localId()],
1285 nodes[c.node(4).localId()],nodes[c.node(5).localId()],
1286 nodes[c.node(6).localId()],nodes[c.node(7).localId()],
1287 nodes[c.node(8).localId()],nodes[c.node(9).localId()],
1288 nodes[c.node(10).localId()],nodes[c.node(11).localId()]));
1289 break;
1290 case IT_Heptaedron10:
1291 m.ajouter(Lima::Polyedre(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1292 nodes[c.node(2).localId()],nodes[c.node(3).localId()],
1293 nodes[c.node(4).localId()],nodes[c.node(5).localId()],
1294 nodes[c.node(6).localId()],nodes[c.node(7).localId()],
1295 nodes[c.node(8).localId()],nodes[c.node(9).localId()]));
1296 break;
1297 case IT_Hexaedron8:
1298 m.ajouter(Lima::Polyedre(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1299 nodes[c.node(2).localId()],nodes[c.node(3).localId()],
1300 nodes[c.node(4).localId()],nodes[c.node(5).localId()],
1301 nodes[c.node(6).localId()],nodes[c.node(7).localId()]));
1302 break;
1303 case IT_Pentaedron6:
1304 m.ajouter(Lima::Polyedre(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1305 nodes[c.node(2).localId()],nodes[c.node(3).localId()],
1306 nodes[c.node(4).localId()],nodes[c.node(5).localId()]));
1307 break;
1308 case IT_Pyramid5:
1309 m.ajouter(Lima::Polyedre(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1310 nodes[c.node(2).localId()],nodes[c.node(3).localId()],
1311 nodes[c.node(4).localId()]));
1312 break;
1313 case IT_Tetraedron4:
1314 m.ajouter(Lima::Polyedre(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1315 nodes[c.node(2).localId()],nodes[c.node(3).localId()]));
1316 break;
1317 case IT_Hexagon6:
1318 m.ajouter(Lima::Polygone(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1319 nodes[c.node(2).localId()],nodes[c.node(3).localId()],
1320 nodes[c.node(4).localId()],nodes[c.node(5).localId()]));
1321 break;
1322 case IT_Pentagon5:
1323 m.ajouter(Lima::Polygone(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1324 nodes[c.node(2).localId()],nodes[c.node(3).localId()],
1325 nodes[c.node(4).localId()]));
1326 break;
1327 case IT_Quad4:
1328 m.ajouter(Lima::Polygone(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1329 nodes[c.node(2).localId()],nodes[c.node(3).localId()]));
1330 break;
1331 case IT_Triangle3:
1332 m.ajouter(Lima::Polygone(nodes[c.node(0).localId()],nodes[c.node(1).localId()],
1333 nodes[c.node(2).localId()]));
1334 break;
1335 case IT_Line2:
1336 m.ajouter(Lima::Bras(nodes[c.node(0).localId()],nodes[c.node(1).localId()]));
1337 break;
1338 }
1339}
1340
1341/*---------------------------------------------------------------------------*/
1342/*---------------------------------------------------------------------------*/
1343/*!
1344 * \brief Ecriture du maillage au format Lima.
1345 *
1346 * \warning La numérotation des entités doit être contiguee.
1347 */
1349writeMeshToFile(IMesh* mesh,const String& file_name)
1350{
1351 ITraceMng* trace = mesh->traceMng();
1352 int dimension = mesh->dimension();
1353
1354 std::string std_file_name = file_name.localstr();
1355 //TODO: FAIRE EXTENSION si non presente
1356 // Regarde si le fichier a l'extension '.unf' ou '.mli'.
1357 // Sinon, ajoute '.mli'
1358 std::string::size_type std_end = std::string::npos;
1359 if (std_file_name.rfind(".mli")==std_end && std_file_name.rfind(".unf")==std_end){
1360 std_file_name += ".mli";
1361 }
1362 info() << "FINAL_FILE_NAME=" << std_file_name;
1363 Lima::Maillage lima(std_file_name);
1364
1365 if (dimension==3)
1366 lima.dimension(Lima::D3);
1367 else if (dimension==2)
1368 lima.dimension(Lima::D2);
1369
1370 IItemFamily* node_family = mesh->nodeFamily();
1371 IItemFamily* edge_family = mesh->edgeFamily();
1372 IItemFamily* face_family = mesh->faceFamily();
1373 IItemFamily* cell_family = mesh->cellFamily();
1374
1375 Integer mesh_nb_node = node_family->nbItem();
1376 Integer mesh_nb_edge = edge_family->nbItem();
1377 Integer mesh_nb_face = face_family->nbItem();
1378 Integer mesh_nb_cell = cell_family->nbItem();
1379
1380 NodeInfoListView nodes(node_family);
1381 EdgeInfoListView edges(edge_family);
1382 FaceInfoListView faces(face_family);
1383 CellInfoListView cells(cell_family);
1384
1385 UniqueArray<Lima::Noeud> lm_nodes(mesh_nb_node);
1386
1387 VariableItemReal3& nodes_coords = mesh->nodesCoordinates();
1388
1389 // Sauve les noeuds
1390 for( Integer i=0; i<mesh_nb_node; ++i ){
1391 Node node = nodes[i];
1392 Real3 coord = nodes_coords[node];
1393 lm_nodes[i].set_x(Convert::toDouble(coord.x));
1394 lm_nodes[i].set_y(Convert::toDouble(coord.y));
1395 lm_nodes[i].set_z(Convert::toDouble(coord.z));
1396 lima.ajouter(lm_nodes[i]);
1397 }
1398
1399 // Sauve les arêtes
1400 for( Integer i=0; i<mesh_nb_edge; ++i ){
1401 _writeItem(lima,lm_nodes,edges[i]);
1402 }
1403
1404 // Sauve les faces
1405 for( Integer i=0; i<mesh_nb_face; ++i ){
1406 _writeItem(lima,lm_nodes,faces[i]);
1407 }
1408
1409 // Sauve les mailles
1410 for( Integer i=0; i<mesh_nb_cell; ++i ){
1411 _writeItem(lima,lm_nodes,cells[i]);
1412 }
1413
1414 try{
1415
1416 // Sauve les groupes de noeuds
1417 for( ItemGroupCollection::Enumerator i(node_family->groups()); ++i; ){
1418 ItemGroup group = *i;
1419 if (group.isAllItems())
1420 continue;
1421 Lima::Nuage lm_group(group.name().localstr());
1422 lima.ajouter(lm_group);
1423 ENUMERATE_ITEM(iitem,group){
1424 lm_group.ajouter(lima.noeud(iitem.localId()));
1425 }
1426 }
1427
1428 // Sauve les groupes d'arêtes
1429 for( ItemGroupCollection::Enumerator i(edge_family->groups()); ++i; ){
1430 ItemGroup group = *i;
1431 if (group.isAllItems())
1432 continue;
1433 Lima::Ligne lm_group(group.name().localstr());
1434 lima.ajouter(lm_group);
1435 ENUMERATE_ITEM(iitem,group){
1436 lm_group.ajouter(lima.bras(iitem.localId()));
1437 }
1438 }
1439
1440 // Sauve les groupes de face
1441 for( ItemGroupCollection::Enumerator i(face_family->groups()); ++i; ){
1442 ItemGroup group = *i;
1443 if (group.isAllItems())
1444 continue;
1445 if (dimension==3){
1446 Lima::Surface lm_group(group.name().localstr());
1447 lima.ajouter(lm_group);
1448 ENUMERATE_ITEM(iitem,group){
1449 lm_group.ajouter(lima.polygone(iitem.localId()));
1450 }
1451 }
1452 else if (dimension==2){
1453 Lima::Ligne lm_group(group.name().localstr());
1454 lima.ajouter(lm_group);
1455 ENUMERATE_ITEM(iitem,group){
1456 lm_group.ajouter(lima.bras(iitem.localId()));
1457 }
1458 }
1459 }
1460
1461 // Sauve les groupes de maille
1462 for( ItemGroupCollection::Enumerator i(cell_family->groups()); ++i; ){
1463 ItemGroup group = *i;
1464 if (group.isAllItems())
1465 continue;
1466 if (dimension==3){
1467 Lima::Volume lm_group(group.name().localstr());
1468 lima.ajouter(lm_group);
1469 ENUMERATE_ITEM(iitem,group){
1470 lm_group.ajouter(lima.polyedre(iitem.localId()));
1471 }
1472 }
1473 else if (dimension==2){
1474 Lima::Surface lm_group(group.name().localstr());
1475 lima.ajouter(lm_group);
1476 ENUMERATE_ITEM(iitem,group){
1477 lm_group.ajouter(lima.polygone(iitem.localId()));
1478 }
1479 }
1480 }
1481 info(4) << "Writing file '" << std_file_name << "'";
1482
1483 lima.ecrire(std_file_name);
1484 }
1485 catch(const std::exception& ex){
1486 trace->warning() << "Exception (std::exception) in LIMA: Can not write file <" << std_file_name << ">"
1487 << " Exception: " << ex.what() << '\n';
1488 return true;
1489 }
1490 catch(...){
1491 trace->warning() << "Exception (unknown) in LIMA: Can not write file <" << std_file_name << ">";
1492 return true;
1493 }
1494
1495 return false;
1496}
1497
1498/*---------------------------------------------------------------------------*/
1499/*---------------------------------------------------------------------------*/
1500/*!
1501 * \brief Créé un groupe d'entités.
1502 *
1503 * Pour assurer la reproductibilité, s'assure que les entités sont
1504 * triées suivant leur localid. S'assure aussi qu'il n'y a pas de doublons
1505 * dans la liste car lima l'autorise mais pas Arcane.
1506 */
1507void LimaUtils::
1508createGroup(IItemFamily* family,const String& name,Int32ArrayView local_ids)
1509{
1510 ITraceMng* tm = family->traceMng();
1511 if (!local_ids.empty())
1512 std::sort(std::begin(local_ids),std::end(local_ids));
1513 Integer nb_item = local_ids.size();
1514 Integer nb_duplicated = 0;
1515 // Détecte les doublons
1516 for( Integer i=1; i<nb_item; ++i )
1517 if (local_ids[i]==local_ids[i-1]){
1518 ++nb_duplicated;
1519 }
1520 if (nb_duplicated!=0){
1521 tm->warning() << "Duplicated items in group name=" << name
1522 << " nb_duplicated=" << nb_duplicated;
1523 auto xbegin = std::begin(local_ids);
1524 auto xend = std::end(local_ids);
1525 Integer new_size = CheckedConvert::toInteger(std::unique(xbegin,xend)-xbegin);
1526 tm->info() << "NEW_SIZE=" << new_size << " old=" << nb_item;
1527 local_ids = local_ids.subView(0,new_size);
1528 }
1529
1530 family->createGroup(name,local_ids,true);
1531}
1532
1533/*---------------------------------------------------------------------------*/
1534/*---------------------------------------------------------------------------*/
1535
1536} // End namespace Arcane
1537
1538/*---------------------------------------------------------------------------*/
1539/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Classe de base d'un service.
Informations nécessaires pour la lecture d'un fichier de maillage.
Vue sur les informations des mailles.
Vue sur les informations des arêtes.
Vue sur les informations des faces.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual String language() const =0
Langage utilisé dans le jeu de données.
virtual String codeUnitSystem() const =0
Nom du système d'unité du document.
Interface du service de lecture du maillage à partir du jeu de données.
virtual Integer nbGhostLayer() const =0
Nombre de couches fantômes.
Interface d'une famille d'entités.
virtual ItemGroupCollection groups() const =0
Liste des groupes de cette famille.
virtual ItemGroup createGroup(const String &name, Int32ConstArrayView local_ids, bool do_override=false)=0
Créé un groupe d'entités de nom name contenant les entités local_ids.
virtual ITraceMng * traceMng() const =0
Gestionnaire de trace associé
virtual Integer nbItem() const =0
Nombre d'entités.
virtual ITraceMng * traceMng()=0
Gestionnaire de message associé
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual IItemFamily * edgeFamily()=0
Retourne la famille des arêtes.
virtual Integer dimension()=0
Dimension du maillage (1D, 2D ou 3D).
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
Interface d'un service de création/lecture du maillage.
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
@ RTIrrelevant
Non concerné par l'opération. Cela signifie que le format de fichier ne correspond pas à ce lecteur o...
Definition IMeshReader.h:50
@ RTError
Erreur lors de l'opération.
Definition IMeshReader.h:44
@ RTOk
Opération effectuée avec succès.
Definition IMeshReader.h:43
Interface d'un service d'écriture d'un maillage.
Definition IMeshWriter.h:36
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual void synchronizeGroupsAndVariables()=0
Synchronise tous les groupes et les variables du maillage.
virtual IGhostLayerMng * ghostLayerMng() const =0
Gestionnare de couche fantômes associé
virtual void setDimension(Integer dim)=0
Positionne la dimension du maillage (1D, 2D ou 3D).
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual ICaseDocument * caseDocument()=0
Document XML du cas.
virtual IParallelMng * parallelMng()=0
Retourne le gestionnaire de parallélisme.
virtual ITimerMng * timerMng() const =0
Retourne le gestionnaire de timers.
Interface d'un gestionnaire de timer.
Definition ITimerMng.h:53
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
Definition ItemGroup.cc:609
Elément de maillage s'appuyant sur des noeuds (Edge,Face,Cell).
Definition Item.h:714
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Remplit build_info avec les informations nécessaires pour créer le maillage.
Definition Lima.cc:1193
void allocateMeshItems(IPrimaryMesh *pm) override
Alloue les entités du maillage géré par ce service.
Definition Lima.cc:1197
Ref< IMeshBuilder > createBuilder(const CaseMeshReaderReadInfo &read_info) const override
Retourne un builder pour créer et lire le maillage dont les informations sont spécifiées dans read_in...
Definition Lima.cc:1224
Construction d'un maillage 3D.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:86
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:362
eReturnType readMeshFromFile(IPrimaryMesh *mesh, const XmlNode &mesh_node, const String &file_name, const String &dir_name, bool use_internal_partition) override
Lit un maillage à partir d'un fichier.
Definition Lima.cc:426
void build()
Construction de niveau build du service.
Definition Lima.cc:369
bool allowExtension(const String &str) override
Vérifie si le service supporte les fichiers avec l'extension str.
Definition Lima.cc:373
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:337
virtual bool writeMeshToFile(IMesh *mesh, const String &file_name)
Ecriture du maillage au format Lima.
Definition Lima.cc:1349
virtual void build()
Construction de niveau build du service.
Definition Lima.cc:1259
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Paramètres nécessaires à la construction d'un maillage.
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Dom.h:204
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
ISubDomain * subDomain() const
Accès au ISubDomain associé.
Structure contenant les informations pour créer un service.
@ TimerReal
Timer utilisant le temps réel.
Definition Timer.h:76
Noeud d'un arbre DOM.
Definition XmlNode.h:51
String attrValue(const String &name, bool throw_exception=false) const
Valeur de l'attribut name.
Definition XmlNode.cc:225
Vue modifiable d'un tableau d'un type T.
constexpr ArrayView< T > subView(Integer abegin, Integer asize) noexcept
Sous-vue à partir de l'élément abegin et contenant asize éléments.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
constexpr bool empty() const noexcept
Retourne true si le tableau est vide (dimension nulle)
Vue constante d'un tableau de type T.
Interface du gestionnaire de traces.
virtual TraceMessage warning()=0
Flot pour un message d'avertissement.
virtual TraceMessage info()=0
Flot pour un message d'information.
Chaîne de caractères unicode.
bool empty() const
Vrai si la chaîne est vide (nulle ou "")
Definition String.cc:315
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:304
TraceMessage warning() const
Flot pour un message d'avertissement.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage log() const
Flot pour un message de log.
Vecteur 1D de données avec sémantique par valeur (style STL).
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
Integer toInteger(Real r)
Converti un Int64 en un Integer.
double toDouble(Real r)
Converti un Real en double.
Definition Convert.h:40
__host__ __device__ double log(double v)
Logarithme népérien de v.
Definition Math.h:40
constexpr __host__ __device__ bool isEqual(const _Type &a, const _Type &b)
Teste l'égalité bit à bit entre deux valeurs.
Definition Numeric.h:253
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:513
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:638
ArrayView< Int32 > Int32ArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:611
Int32 Integer
Type représentant un entier.
Real y
deuxième composante du triplet
Definition Real3.h:36
Real z
troisième composante du triplet
Definition Real3.h:37
Real x
première composante du triplet
Definition Real3.h:35