1 // Copyright (C) 2007-2023 CEA, EDF
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : SauvReader.cxx
20 // Created : Tue Aug 16 13:57:42 2011
21 // Author : Edward AGAPOV (eap)
24 #include "SauvReader.hxx"
26 #include "SauvMedConvertor.hxx"
28 #include "NormalizedUnstructuredMesh.hxx"
29 #include "MEDCouplingRefCountObject.hxx"
35 using namespace MEDCoupling;
36 using namespace SauvUtilities;
39 #define GIBI_EQUAL(var_str, stat_str) (strncmp (var_str, stat_str, strlen(stat_str)) == 0)
49 _locale = setlocale(LC_NUMERIC, NULL);
50 setlocale(LC_NUMERIC, "C");
54 setlocale(LC_NUMERIC, _locale.c_str());
59 //================================================================================
61 * \brief Creates a reader of a given sauve file
63 //================================================================================
65 SauvReader* SauvReader::New(const std::string& fileName)
67 if ( fileName.empty() ) THROW_IK_EXCEPTION("Invalid file name");
69 MEDCoupling::MCAuto< SauvUtilities::FileReader> parser;
72 parser = new XDRReader( fileName.c_str() );
75 SauvReader* reader = new SauvReader;
76 reader->_fileReader = parser.retn();
80 // try to open as ASCII
81 parser = new ASCIIReader( fileName.c_str() );
84 SauvReader* reader = new SauvReader;
85 reader->_fileReader = parser.retn();
89 THROW_IK_EXCEPTION("Unable to open file |"<< fileName << "|");
91 //================================================================================
95 //================================================================================
97 SauvReader::~SauvReader()
99 _fileReader->decrRef();
102 std::size_t SauvReader::getHeapMemorySizeWithoutChildren() const
107 std::vector<const BigMemoryObject *> SauvReader::getDirectChildrenWithNull() const
109 return std::vector<const BigMemoryObject *>();
112 //================================================================================
114 * \brief Return current line of ASCII file to report an error
116 //================================================================================
118 std::string SauvReader::lineNb() const
121 return string(" (line #") + SauvUtilities::toString
122 ( static_cast<SauvUtilities::ASCIIReader*>( _fileReader )->lineNb() ) + ")";
127 //================================================================================
129 * \brief Reads contents of the sauve file and convert it to MEDFileData
131 //================================================================================
133 MEDCoupling::MEDFileData * SauvReader::loadInMEDFileDS()
135 Localizer loc; // localization, to read numbers in "C" locale
137 SauvUtilities::IntermediateMED iMed; // intermadiate DS
140 char* line; // a current line
141 const char* enregistrement_type=" ENREGISTREMENT DE TYPE";
143 while ( getNextLine(line, /*raiseOEF=*/false)) // external loop looking for "ENREGISTREMENT DE TYPE"
145 if ( isASCII() && !GIBI_EQUAL( line, enregistrement_type ))
146 continue; // "ENREGISTREMENT DE TYPE" not found -> read the next line
148 // read the number of a record
151 recordNumber = atoi( line + strlen(enregistrement_type) + 1 );
153 recordNumber = getInt();
156 if ( recordNumber == 2 )
158 else if (recordNumber == 4 )
160 else if (recordNumber == 7 )
162 else if (recordNumber == 8 )
164 else if (recordNumber == 5 )
165 break; // stop reading
168 THROW_IK_EXCEPTION("XDR : ENREGISTREMENT DE TYPE " << recordNumber << " not implemented!!!");
171 MEDCoupling::MEDFileData* medFileData = iMed.convertInMEDFileDS();
176 //================================================================================
178 * \brief Reads "ENREGISTREMENT DE TYPE 4"
180 //================================================================================
182 void SauvReader::readRecord4()
186 getInt(); // skip NIVEAU
187 getInt(); // skip ERREUR
188 _iMed->_spaceDim = getInt();
189 getFloat(); // skip DENSITE
195 const char* s = " NIVEAU 15 NIVEAU ERREUR 0 DIMENSION";
196 _iMed->_spaceDim = atoi( line + strlen( s ) + 1 );
197 if ( !GIBI_EQUAL( line, " NIVEAU" ))
198 THROW_IK_EXCEPTION( "Could not read space dimension" << lineNb() );
200 if ( _iMed->_spaceDim < 1 )
201 THROW_IK_EXCEPTION( "Invalid space dimension:" << _iMed->_spaceDim );
204 //================================================================================
206 * \brief Reads "ENREGISTREMENT DE TYPE 7"
208 //================================================================================
210 void SauvReader::readRecord7()
214 getInt(); // skip NOMBRE INFO CASTEM2000
215 getInt(); // skip IFOUR
216 getInt(); // skip NIFOUR
217 getInt(); // skip IFOMOD
218 getInt(); // skip IECHO
219 getInt(); // skip IIMPI
220 getInt(); // skip IOSPI
221 getInt(); // skip ISOTYP
222 getInt(); // skip NSDPGE
227 // NOMBRE INFO CASTEM2000 8
228 // IFOUR 2 NIFOUR 0 IFOMOD 2 IECHO 1 IIMPI 0 IOSPI 0 ISOTYP 1
237 //================================================================================
239 * \brief Reads "ENREGISTREMENT DE TYPE 8"
241 //================================================================================
243 void SauvReader::readRecord8()
245 // This record is useless (a constant table)
262 while (i <= nbIntToSkip) {
269 //================================================================================
271 * \brief Reads the pile number, nb of objects and nb named of objects
273 //================================================================================
275 int SauvReader::readPileNumber(int& nbNamedObjects, int& nbObjects)
277 // FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
282 pileNumber = getInt(); next();
283 nbNamedObjects = getInt(); next();
284 nbObjects = getInt(); next();
290 const char *s1 = " PILE NUMERO", *s2 = "NBRE OBJETS NOMMES", *s3 = "NBRE OBJETS";
291 if ( ! GIBI_EQUAL( line, s1 ) )
292 THROW_IK_EXCEPTION("Could not read the pile number " << lineNb() );
293 line = line + strlen(s1);
294 pileNumber = atoi( line );
295 line = line + 4 + strlen(s2);
296 nbNamedObjects = atoi( line );
297 line = line + 8 + strlen(s3);
298 nbObjects = atoi( line );
300 if ( nbNamedObjects<0 )
301 THROW_IK_EXCEPTION("Invalid nb of named objects: " << nbNamedObjects << lineNb() );
303 THROW_IK_EXCEPTION("Invalid nb of objects: " << nbObjects << lineNb() );
304 // It appears to be a valid case
305 // if ( nbObjects<nbNamedObjects)
306 // THROW_IK_EXCEPTION("In PILE " << pileNumber <<
307 // " nb of objects is less than nb of named objects" << lineNb() );
311 //================================================================================
313 * \brief Reads "ENREGISTREMENT DE TYPE 2"
315 //================================================================================
317 void SauvReader::readRecord2()
319 if ( _iMed->_spaceDim == 0 )
320 THROW_IK_EXCEPTION("Missing ENREGISTREMENT DE TYPE 4");
322 // read a pile number
323 int pileNumber, nbNamedObjects, nbObjects;
324 pileNumber = readPileNumber(nbNamedObjects, nbObjects);
326 if ( !_encounteredPiles.insert( pileNumber ).second && // piles may repeat
330 // read object names and their indices
331 vector<string> objectNames(nbNamedObjects);
332 for ( initNameReading( nbNamedObjects ); more(); next() )
333 objectNames[ index() ] = getName();
335 vector<int> nameIndices(nbNamedObjects);
336 for ( initIntReading( nbNamedObjects ); more(); next() )
337 nameIndices[ index() ] = getInt();
339 switch ( pileNumber )
341 case PILE_SOUS_MAILLAGE:
342 read_PILE_SOUS_MAILLAGE(nbObjects, objectNames, nameIndices);
344 case PILE_NODES_FIELD:
345 read_PILE_NODES_FIELD(nbObjects, objectNames, nameIndices);
348 read_PILE_TABLES(nbObjects, objectNames, nameIndices);
351 read_PILE_LREEL(nbObjects, objectNames, nameIndices);
354 read_PILE_LOGIQUES(nbObjects, objectNames, nameIndices);
357 read_PILE_FLOATS(nbObjects, objectNames, nameIndices);
360 read_PILE_INTEGERS(nbObjects, objectNames, nameIndices);
363 read_PILE_STRINGS(nbObjects, objectNames, nameIndices);
366 read_PILE_LMOTS(nbObjects, objectNames, nameIndices);
369 read_PILE_NOEUDS(nbObjects, objectNames, nameIndices);
371 case PILE_COORDONNEES:
372 read_PILE_COORDONNEES(nbObjects, objectNames, nameIndices);
375 read_PILE_MODL(nbObjects, objectNames, nameIndices);
378 read_PILE_FIELD(nbObjects, objectNames, nameIndices);
382 THROW_IK_EXCEPTION("XDR : reading PILE " << pileNumber << " not implemented !!!");
386 //================================================================================
388 * \brief Reads "PILE NUMERO 1": gibi sub-meshes that are converted into med groups
390 //================================================================================
392 void SauvReader::read_PILE_SOUS_MAILLAGE(const int nbObjects,
393 std::vector<std::string>& objectNames,
394 std::vector<int>& nameIndices)
396 _iMed->_groups.reserve(nbObjects*2); // fields may add some groups
399 map<int,int> strangeGroupType;
402 for (int object=0; object!=nbObjects; ++object) // loop on sub-groups
405 int castemCellType = getIntNext();
406 int nbSubGroups = getIntNext();
407 int nbReferences = getIntNext();
408 int nbNodesPerElem = getIntNext();
409 int nbElements = getIntNext();
411 _iMed->_groups.push_back(Group());
412 SauvUtilities::Group & group = _iMed->_groups.back();
414 // Issue 0021311. Allocate places for names of referring groups
415 // that will be possibly filled after reading long names from
416 // PILE_TABLES and PILE_STRINGS
417 group._refNames.resize( nbReferences );
419 // castemCellType=0 corresponds to a sub-mesh composed of other sub-meshes
420 if (castemCellType==0 && nbSubGroups>0)
422 group._groups.resize( nbSubGroups );
423 for ( initIntReading( nbSubGroups ); more(); next() )
424 group._groups[ index() ] = & _iMed->_groups[ getInt() - 1 ];
425 //std::sort( group._groups.begin(), group._groups.end() ); // for _groups comparison in getFieldSupport()
429 for ( i = 0; i < nbReferences; i += 10 ) // FORMAT(10I8)
432 for (initIntReading(nbReferences); more(); next());
436 for ( i = 0; i < nbElements; i += 10 )
439 for (initIntReading(nbElements); more(); next());
441 // not a composite group
442 if (castemCellType>0 && nbSubGroups==0)
444 group._cellType = SauvUtilities::gibi2medGeom(castemCellType);
446 initIntReading( nbElements * nbNodesPerElem );
447 if ( group._cellType == INTERP_KERNEL::NORM_ERROR ) // look for group end
449 for ( ; more(); next());
450 strangeGroupType.insert( make_pair( object, castemCellType ));
454 // if ( group._cellType == MED_POINT1 ) group._cellType = NORM_ERROR; // issue 21199
456 // read connectivity of elements of a group
457 SauvUtilities::Cell ma( nbNodesPerElem );
458 SauvUtilities::Node* pNode;
459 group._cells.resize( nbElements );
460 for ( i = 0; i < nbElements; ++i )
463 for ( int n = 0; n < nbNodesPerElem; ++n )
465 int nodeID = getIntNext();
466 pNode = _iMed->getNode( nodeID );
467 ma._nodes[n] = pNode;
468 _iMed->_nbNodes += ( !pNode->isUsed() );
469 pNode->_number = nodeID;
471 ma._number = _iMed->getNbCellsOfType( group._cellType ) + 1;
472 group._cells[i] = _iMed->insert( group._cellType, ma );
479 for (i=0; i!=(int)objectNames.size(); ++i)
481 int grpID = nameIndices[i];
482 SauvUtilities::Group & grp = _iMed->_groups[ grpID-1 ];
483 if ( !grp._name.empty() ) // a group has several names
484 { // create a group with subgroup grp and named grp.name
485 SauvUtilities::Group* newGroup = _iMed->addNewGroup();
486 newGroup->_groups.push_back( &_iMed->_groups[ grpID-1 ]);
487 newGroup->_name = grp._name;
489 grp._name=objectNames[i];
491 map<int,int>::iterator it = strangeGroupType.find( grpID - 1 );
492 if ( it != strangeGroupType.end() )
493 cout << "Skip " << grp._name << " of not supported CASTEM type: " << it->second << endl;
496 } // read_PILE_SOUS_MAILLAGE()
498 //================================================================================
500 * \brief Skip "PILE NUMERO 18" of XDR file
502 //================================================================================
504 void SauvReader::read_PILE_LREEL (const int nbObjects, std::vector<std::string>&, std::vector<int>&)
508 for (int object=0; object!=nbObjects; ++object) // pour chaque Group
511 int nb_vals = getIntNext();
512 initDoubleReading(nb_vals);
513 for(int i=0; i<nb_vals; i++) next();
518 //================================================================================
520 * \brief Skip "PILE NUMERO 24" of XDR file
522 //================================================================================
524 void SauvReader::read_PILE_LOGIQUES (const int, std::vector<std::string>&, std::vector<int>&)
529 int nb_vals = getIntNext();
530 initIntReading(nb_vals);
531 for(int i=0; i<nb_vals; i++) next();
535 //================================================================================
537 * \brief Skip "PILE NUMERO 25" of XDR file
539 //================================================================================
541 void SauvReader::read_PILE_FLOATS (const int, std::vector<std::string>&, std::vector<int>&)
546 int nb_vals = getIntNext();
547 initDoubleReading(nb_vals);
548 for(int i=0; i<nb_vals; i++) next();
552 //================================================================================
554 * \brief Skip "PILE NUMERO 26" of XDR file
556 //================================================================================
558 void SauvReader::read_PILE_INTEGERS (const int, std::vector<std::string>&, std::vector<int>&)
563 int nb_vals = getIntNext();
564 initIntReading(nb_vals);
565 for(int i=0; i<nb_vals; i++) next();
569 //================================================================================
571 * \brief Skip "PILE NUMERO 29" of XDR file
573 //================================================================================
575 void SauvReader::read_PILE_LMOTS (const int nbObjects, std::vector<std::string>&, std::vector<int>&)
579 for (int object=0; object!=nbObjects; ++object) // pour chaque Group
582 int len = getIntNext();
583 int nb_vals = getIntNext();
584 int nb_char = len*nb_vals;
586 int fixed_length = 71;
587 while (nb_char_tmp < nb_char)
589 int remain_len = nb_char - nb_char_tmp;
591 if ( remain_len > fixed_length )
593 width = fixed_length;
599 initNameReading(1, width);
601 nb_char_tmp += width;
607 //================================================================================
609 * \brief Skip "PILE NUMERO 38" of XDR file
611 //================================================================================
613 void SauvReader::read_PILE_MODL (const int nbObjects, std::vector<std::string>&, std::vector<int>&)
617 for (int object=0; object!=nbObjects; ++object) // pour chaque Group
621 int n1 = getIntNext();
622 int nm2 = getIntNext();
623 int nm3 = getIntNext();
624 int nm4 = getIntNext();
625 int nm5 = getIntNext();
626 int n45 = getIntNext();
627 /*int nm6 =*/ getIntNext();
628 /*int nm7 =*/ getIntNext();
633 for (initIntReading(nm1); more(); next());
634 for (initIntReading(nm9); more(); next());
635 for (initNameReading(nm5, 8); more(); next());
636 for (initNameReading(nm2, 8); more(); next());
637 for (initNameReading(nm3, 8); more(); next());
638 for (initIntReading(nm4); more(); next());
641 } // Fin case pile 38
643 //================================================================================
645 * \brief Read "PILE NUMERO 32": links to node coordinates
647 //================================================================================
649 void SauvReader::read_PILE_NOEUDS (const int nbObjects, std::vector<std::string>&, std::vector<int>&)
652 int nb_indices = getIntNext();
654 if (nb_indices != nbObjects)
655 THROW_IK_EXCEPTION("Error of reading PILE NUMERO " << PILE_NOEUDS << lineNb() );
657 for ( initIntReading( nbObjects ); more(); next() )
659 int coordID = getInt();
660 _iMed->getNode( index()+1 )->_coordID = coordID;
664 //================================================================================
666 * \brief Read "PILE NUMERO 33": node coordinates
668 //================================================================================
670 void SauvReader::read_PILE_COORDONNEES (const int nbObjects, std::vector<std::string>&, std::vector<int>&)
673 int nbReals = getIntNext();
675 if ( nbReals < (int)(_iMed->_nbNodes*(_iMed->_spaceDim+1)) )
676 THROW_IK_EXCEPTION("Error of reading PILE NUMERO " << PILE_COORDONNEES << lineNb() );
678 // there are coordinates + density for each node
679 _iMed->_coords.resize( nbReals - nbReals/(_iMed->_spaceDim+1));
680 double* coordPtr = &_iMed->_coords[0];
682 initDoubleReading( nbReals );
685 for (unsigned j = 0; j < _iMed->_spaceDim; ++j, next())
686 *coordPtr++ = getDouble();
693 //================================================================================
695 * \brief Find or create a Group equal to a given field support
697 //================================================================================
699 void SauvReader::setFieldSupport(const vector<SauvUtilities::Group*>& supports,
700 SauvUtilities::DoubleField* field)
702 SauvUtilities::Group* group = NULL;
703 set<SauvUtilities::Group*> sup_set( supports.begin(), supports.end() );
704 if ( sup_set.size() == 1 ) // one or equal supports
710 // check if sub-components are on cells of different types
711 map<int,int> nbGaussByCellType;
712 for ( size_t i = 0; i < supports.size(); ++i )
714 map<int,int>::iterator ct2ng = nbGaussByCellType.find( supports[i]->_cellType );
715 if ( ct2ng == nbGaussByCellType.end() )
716 nbGaussByCellType[ supports[i]->_cellType ] = field->_sub[i].nbGauss();
717 else if ( ct2ng->second != field->_sub[i].nbGauss() )
720 bool isSameCellType = ( nbGaussByCellType.size() == 1 );
721 // try to find an existing composite group with the same sub-groups
722 if ( isSameCellType )
723 for ( size_t i = 0; i < _iMed->_groups.size() && !group; ++i )
725 Group & grp = _iMed->_groups[i];
726 if (sup_set.size() == grp._groups.size())
728 bool sameOrder = true;
729 for ( size_t j = 0; j < supports.size() && sameOrder; ++j )
730 sameOrder = ( supports[j] == grp._groups[ j % grp._groups.size() ]);
732 group = & _iMed->_groups[i];
735 if ( !group ) // no such a group, add a new one
737 vector<SauvUtilities::Group*> newGroups( supports.begin(),
738 supports.begin() + sup_set.size() );
739 // check if supports includes newGroups in the same order
740 bool sameOrder = true;
741 for ( size_t j = newGroups.size(); j < supports.size() && sameOrder; ++j )
742 sameOrder = ( supports[j] == newGroups[ j % newGroups.size() ]);
745 group = _iMed->addNewGroup( & newGroups );
746 group->_groups.swap( newGroups );
749 // sort field sub-components and supports by cell type
750 if ( group && !isSameCellType )
753 vector<SauvUtilities::Group*>& groups = group->_groups;
754 bool isModified = false, isSwapped = true;
758 for ( std::size_t i = 1; i < groups.size(); ++i )
760 std::size_t nbN1 = groups[i-1]->empty() ? 0 : groups[i-1]->_cells[0]->_nodes.size();
761 std::size_t nbN2 = groups[i ]->empty() ? 0 : groups[i ]->_cells[0]->_nodes.size();
764 isSwapped = isModified = true;
765 std::swap( groups[i], groups[i-1] );
769 // relocate sub-components according to a new order of groups
772 vector< DoubleField::_Sub_data > newSub ( field->_sub.size() );
773 vector< vector< double > > newValues( field->_comp_values.size() );
774 size_t iFromSub = 0, iNewSub = 0, iNewComp = 0;
775 for ( ; iFromSub < field->_sub.size(); iFromSub += groups.size() )
777 size_t iFromComp = iNewComp;
778 for ( size_t iG = 0; iG < groups.size(); ++iG )
780 size_t iComp = iFromComp;
781 for ( size_t iSub = iFromSub; iSub < field->_sub.size(); ++iSub )
782 if ( field->_sub[ iSub ]._support == groups[ iG ] )
784 newSub[ iNewSub++ ] = field->_sub[ iSub ];
785 int iC = 0, nbC = field->_sub[ iSub ].nbComponents();
786 for ( ; iC < nbC; ++iC )
787 newValues[ iNewComp++ ].swap( field->_comp_values[ iComp++ ]);
792 iComp += field->_sub[ iSub ].nbComponents();
796 field->_sub.swap( newSub );
797 field->_comp_values.swap( newValues );
802 group->_isProfile = true;
804 field->_group = group;
807 //================================================================================
809 * \brief Set field names
811 //================================================================================
813 void SauvReader::setFieldNames(const vector<SauvUtilities::DoubleField* >& fields,
814 const vector<string>& objets_nommes,
815 const vector<int>& indices_objets_nommes)
818 for ( i = 0; i < indices_objets_nommes.size(); ++i )
820 int fieldIndex = indices_objets_nommes[ i ];
821 if ( fields[ fieldIndex - 1 ] )
822 fields[ fieldIndex - 1 ]->_name = objets_nommes[ i ];
826 //================================================================================
828 * \brief Read "PILE NUMERO 2": NODE FIELDS
830 //================================================================================
832 void SauvReader::read_PILE_NODES_FIELD (const int nbObjects,
833 std::vector<std::string>& objectNames,
834 std::vector<int>& nameIndices)
836 _iMed->_nodeFields.resize( nbObjects, (SauvUtilities::DoubleField*) 0 );
837 for (int object=0; object!=nbObjects; ++object) // loop on fields
839 // EXAMPLE ( with no values )
842 // (2) -88 0 3 -89 0 1 -90 0 2 -91
844 // (3) FX FY FZ FZ FX FY FLX
846 // (5) cree par muc pri
850 // (1): nb subcomponents, nb components(total), IFOUR, nb attributes
851 int nb_sub, total_nb_comp, nb_attr;
854 nb_sub = getIntNext();
855 total_nb_comp = getIntNext();
856 next(); // ignore IFOUR
857 nb_attr = getIntNext();
858 if ( nb_sub < 0 || total_nb_comp < 0 || nb_attr < 0 )
859 THROW_IK_EXCEPTION("Error of field reading " << lineNb());
861 // (2) loop on subcomponents of a field, for each read
862 // (a) support, (b) number of values and (c) number of components
863 vector<Group*> supports( nb_sub );
864 vector<int> nb_values ( nb_sub );
865 vector<int> nb_comps ( nb_sub );
866 int total_nb_values = 0;
867 initIntReading( nb_sub * 3 );
868 for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
870 int supId = -getIntNext(); // (a) reference to support
871 if ( supId < 1 || supId > (int)_iMed->_groups.size() )
872 THROW_IK_EXCEPTION("Wrong mesh reference: "<< supId << lineNb() );
873 supports[ i_sub ] = &_iMed->_groups[ supId-1 ]; // (a) reference to support
875 nb_values[ i_sub ] = getIntNext(); // (b) nb points
876 total_nb_values += nb_values[ i_sub ];
877 if ( nb_values[ i_sub ] < 0 )
878 THROW_IK_EXCEPTION(" Wrong nb of points: " << nb_values[ i_sub ] << lineNb() );
879 nb_comps[ i_sub ] = getInt(); next(); // (c) nb of components in i_sub
882 // create a field if there are values
883 SauvUtilities::DoubleField* fdouble = 0;
884 if ( total_nb_values > 0 )
885 fdouble = new DoubleField( nb_sub, total_nb_comp );
886 _iMed->_nodeFields[ object ] = fdouble;
888 // (3) component names
889 initNameReading( total_nb_comp, 4 );
890 for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
892 // store support id and nb components of a sub
894 fdouble->_sub[ i_sub ].setData( nb_comps[ i_sub ], supports[ i_sub ] );
895 for ( i_comp = 0; i_comp < nb_comps[ i_sub ]; ++i_comp, next() )
897 // store component name
898 string compName = getName();
900 fdouble->_sub[ i_sub ].compName( i_comp ) = compName;
903 // (4) nb harmonics ( ignored )
904 for ( initIntReading( total_nb_comp ); more(); next() );
905 // (5) TYPE ( ignored )
906 for (initNameReading(1, /*length=*/71); more(); next());
907 // (6) TITRE ( ignored )
908 for (initNameReading(1, /*length=*/71); more(); next());
909 // (7) attributes ( ignored )
910 for ( initIntReading( nb_attr ); more(); next() );
912 for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
914 // loop on components: read values
915 initDoubleReading( nb_values[ i_sub ] * nb_comps[ i_sub ] );
916 for ( i_comp = 0; i_comp < nb_comps[ i_sub ]; ++i_comp )
920 vector<double>& vals = fdouble->addComponent( nb_values[ i_sub ] );
921 for ( int i = 0; more() && i < nb_values[ i_sub ]; next(), ++i )
922 vals[ i ] = getDouble();
926 for ( int i = 0; i < nb_values[ i_sub ]; next(), ++i );
929 } // loop on subcomponents of a field
931 // set a supporting group including all subs supports but only
932 // if all subs have the same components
933 if ( fdouble && fdouble->hasSameComponentsBySupport() )
934 setFieldSupport( supports, fdouble );
936 for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
937 fdouble->_sub[ i_sub ]._support->_isProfile = true;
939 } // end loop on field objects
942 setFieldNames( _iMed->_nodeFields, objectNames, nameIndices );
944 } // read_PILE_NODES_FIELD()
946 //================================================================================
948 * \brief Read "PILE NUMERO 39": FIELDS
950 //================================================================================
952 void SauvReader::read_PILE_FIELD (const int nbObjects,
953 std::vector<std::string>& objectNames,
954 std::vector<int>& nameIndices)
959 // (2) CARACTERISTIQUES
960 // (3) -15 317773 4 0 0 0 -2 0 3
963 // (6) 317767 317761 317755 317815
964 // (7) YOUN NU H SIGY
965 // (8) REAL*8 REAL*8 REAL*8 REAL*8
967 // (10) 2.00000000000000E+05
969 // (12) 3.30000000000000E-01
971 // (14) 1.00000000000000E+04
973 // (16) 1.00000000000000E+02 1.00000000000000E+02 1.00000000000000E+02
974 // (17) 1.00000000000000E+02 1.00000000000000E+02 1.00000000000000E+02
977 _iMed->_cellFields.resize( nbObjects, (SauvUtilities::DoubleField*) 0 );
978 for (int object=0; object!=nbObjects; ++object) // pour chaque field
981 int i_sub, nb_sub = getIntNext(); // (1) <nb_sub> 2 6 <title length>
984 int title_length = getIntNext(); // <title length>
986 THROW_IK_EXCEPTION("Error of field reading: wrong nb of subcomponents " << nb_sub << lineNb() );
993 initNameReading(1, title_length);
994 description = getName();
1000 getNextLine( line ); // (2) title
1001 const int len = 72; // line length
1002 description = string(line + len - title_length, title_length); // title is right justified
1005 // look for a line starting with '-' : <reference to support>
1008 initIntReading( nb_sub * 9 );
1013 initIntReading( nb_sub * 9 );
1014 } while ( getInt() >= 0 );
1016 int total_nb_comp = 0;
1017 vector<Group*> supports( nb_sub );
1018 vector<int> nb_comp( nb_sub );
1019 for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
1021 int supportId = -getIntNext(); // <reference to support>
1022 next(); // ignore <address>
1023 nb_comp [ i_sub ] = getIntNext(); // <nb of components in the sub>
1024 for ( int i = 0; i < 6; ++i ) next(); // ignore 6 ints, in example "0 0 0 -2 0 3"
1026 if ( supportId < 1 || supportId > (int)_iMed->_groups.size() )
1027 THROW_IK_EXCEPTION("Error of field reading: wrong mesh reference "<< supportId << lineNb() );
1028 if ( nb_comp[ i_sub ] < 0 )
1029 THROW_IK_EXCEPTION("Error of field reading: wrong nb of components " <<nb_comp[ i_sub ] << lineNb() );
1031 supports[ i_sub ] = &_iMed->_groups[ supportId-1 ];
1032 total_nb_comp += nb_comp[ i_sub ];
1034 // (4) dummy strings
1035 for ( initNameReading( nb_sub, 17 ); more(); next() );
1036 // (5) dummy strings
1037 for ( initNameReading( nb_sub ); more(); next() );
1039 // loop on subcomponents of a field, each of which refers to
1040 // a certain support and has its own number of components;
1041 // read component values
1042 SauvUtilities::DoubleField* fdouble = 0;
1043 for ( i_sub = 0; i_sub < nb_sub; ++ i_sub )
1045 vector<string> comp_names( nb_comp[ i_sub ]), comp_type( nb_comp[ i_sub ]);
1046 // (6) nb_comp addresses of MELVAL structure
1047 for ( initIntReading( nb_comp[ i_sub ] ); more(); next() );
1048 // (7) component names
1049 for ( initNameReading( nb_comp[ i_sub ] ); more(); next() )
1050 comp_names[ index() ] = getName();
1051 // (8) component type
1052 for ( initNameReading( nb_comp[ i_sub ], 17 ); more(); next() ) // 17 is name width
1054 comp_type[ index() ] = getName();
1055 // component types must be the same
1056 if ( index() > 0 && comp_type[ index() ] != comp_type[ index() - 1] )
1057 THROW_IK_EXCEPTION( "Error of field reading: diff component types <"
1058 << comp_type[ index() ] << "> != <" << comp_type[ index() - 1 ]
1059 << ">" << lineNb() );
1061 // now type is known, create a field, one for all subs
1062 bool isReal = (nb_comp[i_sub] > 0) ? (comp_type[0] == "REAL*8") : true;
1063 if ( !fdouble && total_nb_comp )
1066 cout << "Warning: read NOT REAL field, type <" << comp_type[0] << ">" << lineNb() << endl;
1067 _iMed->_cellFields[ object ] = fdouble = new SauvUtilities::DoubleField( nb_sub, total_nb_comp );
1068 fdouble->_description = description;
1070 // store support id and nb components of a sub
1072 fdouble->_sub[ i_sub ].setData( nb_comp[ i_sub ], supports[ i_sub ]);
1073 // loop on components: read values
1074 for ( int i_comp = 0; i_comp < nb_comp[ i_sub ]; ++i_comp )
1077 initIntReading( 4 );
1078 int nb_val_by_elem = getIntNext();
1079 int nb_values = getIntNext();
1082 fdouble->_sub[ i_sub ]._nb_gauss[ i_comp ] = nb_val_by_elem;
1085 nb_values *= nb_val_by_elem;
1088 vector<double> & vals = fdouble->addComponent( nb_values );
1089 for ( isReal ? initDoubleReading( nb_values ) : initIntReading( nb_values ); more(); next())
1090 vals[ index() ] = getDouble();
1091 // store component name
1092 fdouble->_sub[ i_sub ].compName( i_comp ) = comp_names[ i_comp ];
1096 for ( isReal ? initDoubleReading( nb_values ) : initIntReading( nb_values ); more(); next() ) ;
1099 } // loop on subcomponents of a field
1101 // set id of a group including all sub supports but only
1102 // if all subs have the same nb of components
1103 if ( fdouble && fdouble->hasSameComponentsBySupport() )
1104 setFieldSupport( supports, fdouble );
1106 for ( i_sub = 0; i_sub < nb_sub; ++i_sub )
1107 fdouble->_sub[ i_sub ]._support->_isProfile = true;
1109 } // end loop on field objects
1112 setFieldNames( _iMed->_cellFields, objectNames, nameIndices );
1114 } // read_PILE_FIELD()
1116 //================================================================================
1118 * \brief Read "PILE NUMERO 10": TABLES
1120 //================================================================================
1122 void SauvReader::read_PILE_TABLES (const int nbObjects,
1123 std::vector<std::string>& objectNames,
1124 std::vector<int>& nameIndices)
1126 // IMP 0020434: mapping GIBI names to MED names
1128 string table_med_mail = "MED_MAIL";
1129 string table_med_cham = "MED_CHAM";
1130 string table_med_comp = "MED_COMP";
1131 int table_med_mail_id = -1;
1132 int table_med_cham_id = -1;
1133 int table_med_comp_id = -1;
1134 for (size_t iname = 0; iname < objectNames.size(); iname++)
1135 if (objectNames[iname] == table_med_mail) table_med_mail_id = nameIndices[iname];
1136 else if (objectNames[iname] == table_med_cham) table_med_cham_id = nameIndices[iname];
1137 else if (objectNames[iname] == table_med_comp) table_med_comp_id = nameIndices[iname];
1140 if (table_med_mail_id < 0 && table_med_cham_id < 0 && table_med_comp_id < 0)
1143 for (int itable = 1; itable <= nbObjects; itable++)
1145 // read tables "MED_MAIL", "MED_CHAM" and "MED_COMP", that keeps correspondence
1146 // between GIBI names (8 symbols if any) and MED names (possibly longer)
1148 int nb_table_vals = getIntNext();
1149 if (nb_table_vals < 0)
1150 THROW_IK_EXCEPTION("Error of reading PILE NUMERO 10" << lineNb() );
1152 int name_i_med_pile;
1153 initIntReading(nb_table_vals);
1154 for (int i = 0; i < nb_table_vals/4; i++)
1156 if (itable == table_med_mail_id ||
1157 itable == table_med_cham_id ||
1158 itable == table_med_comp_id)
1160 nameGIBItoMED name_i;
1161 name_i_med_pile = getIntNext();
1162 name_i.med_id = getIntNext();
1163 name_i.gibi_pile = getIntNext();
1164 name_i.gibi_id = getIntNext();
1166 if (name_i_med_pile != PILE_STRINGS)
1168 // error: med(long) names are always kept in PILE_STRINGS
1170 if (itable == table_med_mail_id)
1172 if (name_i.gibi_pile != PILE_SOUS_MAILLAGE) {
1173 // error: must be PILE_SOUS_MAILLAGE
1175 _iMed->_listGIBItoMED_mail.push_back(name_i);
1177 else if (itable == table_med_cham_id)
1179 if (name_i.gibi_pile != PILE_FIELD &&
1180 name_i.gibi_pile != PILE_NODES_FIELD)
1182 // error: must be PILE_FIELD or PILE_NODES_FIELD
1184 _iMed->_listGIBItoMED_cham.push_back(name_i);
1186 else if (itable == table_med_comp_id)
1188 if (name_i.gibi_pile != PILE_STRINGS)
1190 // error: gibi(short) names of components are kept in PILE_STRINGS
1192 _iMed->_listGIBItoMED_comp.push_back(name_i);
1198 for ( int ii = 0; ii < 4; ++ii ) next();
1201 } // for (int itable = 0; itable < nbObjects; itable++)
1204 //================================================================================
1206 * \brief Read "PILE NUMERO 27"
1208 //================================================================================
1210 void SauvReader::read_PILE_STRINGS (const int nbObjects,
1211 std::vector<std::string>& objectNames,
1212 std::vector<int>& nameIndices)
1214 // IMP 0020434: mapping GIBI names to MED names
1216 int stringLen = getIntNext();
1217 int nbSubStrings = getIntNext();
1218 if (nbSubStrings != nbObjects)
1219 THROW_IK_EXCEPTION("Error of reading PILE NUMERO 27" << lineNb() );
1221 string aWholeString;
1224 const int fixedLength = 71;
1225 while ((int)aWholeString.length() < stringLen)
1227 int remainLen = (int)(stringLen - aWholeString.length());
1229 if ( remainLen > fixedLength )
1237 initNameReading(1, len);
1238 aWholeString += getName();
1245 const int fixedLength = 71;
1246 while ((int)aWholeString.length() < stringLen)
1248 getNextLine( line );
1249 int remainLen = (int)(stringLen - aWholeString.length());
1250 if ( remainLen > fixedLength )
1252 aWholeString += line + 1;
1256 aWholeString += line + ( 72 - remainLen );
1262 initIntReading(nbSubStrings);
1263 for (int istr = 1; istr <= nbSubStrings; istr++, next())
1265 currOffset = getInt();
1267 _iMed->_mapStrings[istr] = aWholeString.substr(prevOffset, currOffset - prevOffset);
1268 prevOffset = currOffset;