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