]> SALOME platform Git repositories - modules/homard.git/blob - src/HOMARD/HOMARD_DriverTools.cxx
Salome HOME
Merge from V6_3_BR 06/06/2011
[modules/homard.git] / src / HOMARD / HOMARD_DriverTools.cxx
1 // Copyright (C) 2011  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 //  File   : HOMARD_DriverTools.cxx
20 //  Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
21 //
22 // ----------------------------------------------------------------------------
23
24 #include "HOMARD_DriverTools.hxx"
25 #include "HOMARD_Boundary.hxx"
26 #include "HOMARD_Cas.hxx"
27 #include "HOMARD_Hypothesis.hxx"
28 #include "HOMARD_Iteration.hxx"
29 #include "HOMARD_Zone.hxx"
30 #include <sstream>
31 #include <cstdlib>
32 #include "utilities.h"
33
34 namespace HOMARD
35 {
36
37   const char* const SEPARATOR = "|";
38
39   /*!
40     \brief Read next chunk of data from the string
41     \internal
42     
43     The function tries to read next chunk of the data from the input string \a str.
44     The parameter \a start specifies the start position of next chunk. If the operation
45     read the chunk successfully, after its completion this parameter will refer to the
46     start position of the next chunk. The function returns resulting chunk as a string.
47     The status of the operation is returned via \a ok parameter.
48     
49     \param str source data stream string
50     \param start start position to get next chunk
51     \param ok in this variable the status of the chunk reading operation is returned
52     \return next chunk read from the string
53   */
54   static std::string getNextChunk( const std::string& str, std::string::size_type& start, bool& ok )
55   {
56     std::string chunk = "";
57     ok = false;
58     if ( start <= str.size() ) {
59       std::string::size_type end = str.find( separator(), start );
60       chunk = str.substr( start, end == std::string::npos ? std::string::npos : end-start );
61       start = end == std::string::npos ? str.size()+1 : end + separator().size();
62       ok = true;
63     }
64     return chunk;
65   }
66
67   /*!
68     \brief Get persistence signature
69     \param type persistence entity type
70     \return persistence signature
71   */
72   std::string GetSignature( SignatureType type )
73   {
74     std::string signature = "";
75     switch ( type ) {
76     case Case:       signature = "CASE"; break;
77     case Zone:       signature = "ZONE"; break;
78     case Hypothesis: signature = "HYPO"; break;
79     case Iteration:  signature = "ITER"; break;
80     case Boundary:   signature = "BOUNDARY"; break;
81     default: break;
82     }
83     signature += separator();
84     return signature;
85   }
86
87   /*!
88     \brief Get data separator
89     \return string that is used to separate data entities in the stream
90   */
91   std::string separator()
92   {
93     return std::string( SEPARATOR );
94   }
95
96 // =======================
97 // Case
98 // =======================
99   /*!
100     \brief Dump case to the string
101     \param cas case being dumped
102     \return string representation of the case
103   */
104   std::string Dump( const HOMARD_Cas& cas )
105   {
106     std::stringstream os;
107     // ...
108     MESSAGE( ". Dump du cas "<<cas.GetName());
109     os << cas.GetName();
110     os << separator() << cas.GetDirName();
111     os << separator() << cas.GetConfType();
112
113     std::vector<double> coor = cas.GetBoundingBox();
114     os << separator() << coor.size();
115     for ( int i = 0; i < coor.size(); i++ )
116           os << separator() << coor[i];
117
118     std::list<std::string> ListString = cas.GetIterations();
119     os << separator() << ListString.size();
120     std::list<std::string>::const_iterator it;
121     for ( it = ListString.begin(); it != ListString.end(); ++it )
122           os << separator() << *it;
123
124     ListString = cas.GetGroups();
125     os << separator() << ListString.size();
126     for ( it = ListString.begin(); it != ListString.end(); ++it )
127          os << separator() << *it;
128     ListString = cas.GetBoundaryGroup();
129     os << separator() << ListString.size();
130     for ( it = ListString.begin(); it != ListString.end(); ++it )
131          os << separator() << *it;
132     return os.str();
133   }
134 //
135 // Iteration
136 // ==========
137 //
138   /*!
139     \brief Dump iteration to the string
140     \param iteration iteration being dumped
141     \return string representation of the iteration
142   */
143   std::string Dump( const HOMARD_Iteration& iteration )
144   {
145     std::stringstream os;
146     // ...
147     MESSAGE( ". Dump de l'iteration "<<iteration.GetName());
148     os << iteration.GetName();
149     os << separator() << iteration.GetEtat();
150     os << separator() << iteration.GetNumber();
151     os << separator() << iteration.GetMeshFile();
152     os << separator() << iteration.GetMessFile();
153     os << separator() << iteration.GetMeshName();
154     os << separator() << iteration.GetFieldFile();
155     os << separator() << iteration.GetTimeStep();
156     os << separator() << iteration.GetRank();
157     os << separator() << iteration.GetIterParent();
158     //
159     std::list<std::string> ListString = iteration.GetIterations();
160     os << separator() << ListString.size();
161     std::list<std::string>::const_iterator it;
162     for ( it = ListString.begin(); it != ListString.end(); ++it )
163       os << separator() << *it;
164
165     os << separator() << iteration.GetHypoName();
166     os << separator() << iteration.GetCaseName();
167     os << separator() << iteration.GetDirName();
168     return os.str();
169   }
170 //
171 // hypothese
172 // ==============================
173   /*!
174     \brief Dump hypothesis to the string
175     \param hypothesis hypothesis being dumped
176     \return string representation of the hypothesis
177   */
178   std::string Dump( const HOMARD_Hypothesis& hypothesis )
179   {
180     std::stringstream os;
181     // ...
182     MESSAGE( ". Dump de l'hypothese "<<hypothesis.GetName());
183     os << hypothesis.GetName();
184     os << separator() << hypothesis.GetCaseCreation();
185     os << separator() << hypothesis.GetAdapType();
186     os << separator() << hypothesis.GetRefinType();
187     os << separator() << hypothesis.GetUnRefType();
188     os << separator() << hypothesis.GetFieldName();
189     os << separator() << hypothesis.GetRefinThrType();
190     os << separator() << hypothesis.GetThreshR();
191     os << separator() << hypothesis.GetUnRefThrType();
192     os << separator() << hypothesis.GetThreshC();
193     os << separator() << hypothesis.GetUseCompI();
194     os << separator() << hypothesis.GetTypeFieldInterp();
195
196
197     std::list<std::string> ListString = hypothesis.GetIterations();
198     std::list<std::string>::const_iterator it;
199     os << separator() << ListString.size();
200     for ( it = ListString.begin(); it != ListString.end(); ++it )
201          os << separator() << *it;
202
203     ListString = hypothesis.GetZones();
204     os << separator() << ListString.size();
205     for ( it = ListString.begin(); it != ListString.end(); ++it )
206           os << separator() << *it;
207
208     ListString = hypothesis.GetListComp();
209     os << separator() << ListString.size();
210     for ( it = ListString.begin(); it != ListString.end(); ++it )
211          os << separator() << *it;
212
213     ListString = hypothesis.GetGroups();
214     os << separator() << ListString.size();
215     for ( it = ListString.begin(); it != ListString.end(); ++it )
216           os << separator() << *it;
217
218     ListString = hypothesis.GetListFieldInterp();
219     os << separator() << ListString.size();
220     for ( it = ListString.begin(); it != ListString.end(); ++it )
221           os << separator() << *it;
222     return os.str();
223   }
224 //
225 // Zone
226 // =========================
227
228   /*!
229     \brief Dump zone to the string
230     \param zone zone being dumped
231     \return string representation of the zone
232   */
233   std::string Dump( const HOMARD_Zone& zone )
234   {
235     std::stringstream os;
236     os << zone.GetName();
237     os << separator() << zone.GetZoneType();
238
239     std::vector<double> box = zone.GetBox();
240     for ( int i = 0; i < box.size(); i++ )
241       os << separator() << ( i < box.size() ? box[i] : 0. );
242
243     std::vector<double> sphere = zone.GetSphere();
244     for ( int i = 0; i < 4; i++ )
245       os << separator() << ( i < sphere.size() ? sphere[i] : 0. );
246
247     std::vector<double> limit = zone.GetLimit();
248     for ( int i = 0; i < 3; i++ )
249       os << separator() << ( i < limit.size() ? limit[i] : 0. );
250
251     std::list<std::string> hypos = zone.GetHypo();
252     os << separator() << hypos.size();
253     std::list<std::string>::const_iterator it;
254     for ( it = hypos.begin(); it != hypos.end(); ++it )
255       os << separator() << *it;
256     return os.str();  
257
258
259   }
260 //
261 // 1.5. Archivage d'une frontiere
262 // ==============================
263
264   /*!
265     \brief Dump boundary to the string
266     \param boundary boundary being dumped
267     \return string representation of the boundary
268   */
269   std::string Dump( const HOMARD_Boundary& boundary )
270   {
271     std::stringstream os;
272
273     os << boundary.GetName() ;
274     os << separator() << boundary.GetBoundaryType() ;
275     os << separator() << boundary.GetCaseCreation() ;
276     os << separator() << boundary.GetMeshFile();
277     os << separator() << boundary.GetMeshName();
278
279     std::vector<double> coor = boundary.GetLimit();
280     for ( int i = 0; i < coor.size(); i++ )
281           os << separator() << coor[i];
282
283     coor = boundary.GetCylinder() ; 
284     for ( int i = 0; i < coor.size(); i++ )
285           os << separator() << coor[i];
286
287     coor = boundary.GetSphere() ; 
288     for ( int i = 0; i < coor.size(); i++ )
289           os << separator() << coor[i];
290     return os.str();
291
292     std::list<std::string> ListString = boundary.GetGroups();
293     std::list<std::string>::const_iterator it;
294     os << separator() << ListString.size();
295     for ( it = ListString.begin(); it != ListString.end(); ++it )
296           os << separator() << *it;
297
298   }
299
300 //
301 // Restauration des objets
302 // ==========================
303 // Case
304 // ==========================
305 //
306   /*!
307     \brief Restore case from the string
308     \param cas case being restored
309     \param stream string representation of the case
310     \return \c true if case is correctly restored or \c false otherwise
311   */
312   bool Restore( HOMARD_Cas& cas, const std::string& stream )
313   {
314     std::string::size_type start = 0;
315     std::string chunk, chunkNext;
316     bool ok;
317     // ...
318     chunk = getNextChunk( stream, start, ok );
319     if ( !ok ) return false;
320     cas.SetName( chunk.c_str() );
321
322     chunk = getNextChunk( stream, start, ok );
323     if ( !ok ) return false;
324     cas.SetDirName( chunk.c_str() );
325
326     chunk = getNextChunk( stream, start, ok );
327     if ( !ok ) return false;
328     cas.SetConfType( atoi( chunk.c_str() ) );
329
330     chunk = getNextChunk( stream, start, ok );
331     if ( !ok ) return false;
332
333     int size = atoi( chunk.c_str() );
334     std::vector<double> boite;
335     boite.resize( size );
336     for ( int i = 0; i < size; i++ ) {
337       chunk = getNextChunk( stream, start, ok );
338       if ( !ok ) return false;
339       boite[i] = strtod( chunk.c_str(), 0 );
340     }
341     cas.SetBoundingBox( boite );
342
343     chunk = getNextChunk( stream, start, ok );
344     if ( !ok ) return false;
345
346     size = atoi( chunk.c_str() );
347     for ( int i = 0; i < size; i++ ) {
348       chunk = getNextChunk( stream, start, ok );
349       if ( !ok ) return false;
350       cas.AddIteration( chunk.c_str() );
351     }
352
353     chunk = getNextChunk( stream, start, ok );
354     if ( !ok ) return false;
355     size = atoi( chunk.c_str() );
356     for ( int i = 0; i < size; i++ ) 
357     {
358       chunk = getNextChunk( stream, start, ok );
359       if ( !ok ) return false;
360       cas.AddGroup( chunk.c_str() );
361     }
362
363     chunk = getNextChunk( stream, start, ok );
364     if ( !ok ) return false;
365     size = atoi( chunk.c_str() );
366     for ( int i = 0; i < size; i++ ) {
367       chunk = getNextChunk( stream, start, ok );
368       if ( !ok ) return false;
369       i++;
370       chunkNext = getNextChunk( stream, start, ok );
371       if ( !ok ) return false;
372       cas.AddBoundaryGroup( chunk.c_str(), chunkNext.c_str() );
373     }
374     return true;
375   }
376 //
377 //  Iteration
378 // =================================
379   /*!
380     \brief Restore iteration from the string
381     \param iteration iteration being restored
382     \param stream string representation of the iteration
383     \return \c true if iteration is correctly restored or \c false otherwise
384   */
385   bool Restore( HOMARD_Iteration& iteration, const std::string& stream )
386   {
387     std::string::size_type start = 0;
388     std::string chunk;
389     bool ok;
390     chunk = getNextChunk( stream, start, ok );
391     if ( !ok ) return false;
392
393     iteration.SetName( chunk.c_str() );
394     chunk = getNextChunk( stream, start, ok );
395     if ( !ok ) return false;
396     iteration.SetEtat( (bool)atoi( chunk.c_str() ) );
397     chunk = getNextChunk( stream, start, ok );
398     if ( !ok ) return false;
399     iteration.SetNumber( atoi( chunk.c_str() ) );
400     chunk = getNextChunk( stream, start, ok );
401     if ( !ok ) return false;
402     iteration.SetMeshFile( chunk.c_str() );
403     chunk = getNextChunk( stream, start, ok );
404     if ( !ok ) return false;
405     iteration.SetMessFile( chunk.c_str() );
406     chunk = getNextChunk( stream, start, ok );
407     if ( !ok ) return false;
408     iteration.SetMeshName( chunk.c_str() );
409     chunk = getNextChunk( stream, start, ok );
410     if ( !ok ) return false;
411     iteration.SetFieldFile( chunk.c_str() );
412     // .
413     int timestep, rank;
414     chunk = getNextChunk( stream, start, ok );
415     if ( !ok ) return false;
416     timestep = atoi( chunk.c_str() );
417     chunk = getNextChunk( stream, start, ok );
418     if ( !ok ) return false;
419     rank = atoi( chunk.c_str() );
420     iteration.SetTimeStepRank( timestep, rank );
421     chunk = getNextChunk( stream, start, ok );
422     if ( !ok ) return false;
423     iteration.SetIterParent( chunk.c_str() );
424     //
425     chunk = getNextChunk( stream, start, ok );
426     if ( !ok ) return false;
427     int size = atoi( chunk.c_str() );
428     for ( int i = 0; i < size; i++ ) {
429       chunk = getNextChunk( stream, start, ok );
430       if ( !ok ) return false;
431       iteration.AddIteration( chunk.c_str() );
432     }
433     // 
434     chunk = getNextChunk( stream, start, ok );
435     if ( !ok ) return false;
436     iteration.SetHypoName( chunk.c_str() );
437     chunk = getNextChunk( stream, start, ok );
438     if ( !ok ) return false;
439     iteration.SetCaseName( chunk.c_str() );
440     chunk = getNextChunk( stream, start, ok );
441     if ( !ok ) return false;
442     iteration.SetDirName( chunk.c_str() );
443     return true;
444   }
445
446 //
447 // hypothese
448 // =================================
449   /*!
450     \brief Restore hypothesis from the string
451     \param hypothesis hypothesis being restored
452     \param stream string representation of the hypothesis
453     \return \c true if hypothesis is correctly restored or \c false otherwise
454   */
455   bool Restore( HOMARD_Hypothesis& hypothesis, const std::string& stream )
456   {
457     std::string::size_type start = 0;
458     std::string chunk;
459     bool ok;
460
461     chunk = getNextChunk( stream, start, ok );
462     if ( !ok ) return false;
463     hypothesis.SetName( chunk.c_str() );
464
465     chunk = getNextChunk( stream, start, ok );
466     if ( !ok ) return false;
467     hypothesis.SetCaseCreation( chunk.c_str() );
468
469     chunk = getNextChunk( stream, start, ok );
470     if ( !ok ) return false;
471     hypothesis.SetAdapType( atoi( chunk.c_str() ) );
472
473     chunk = getNextChunk( stream, start, ok );
474     if ( !ok ) return false;
475     int typeraff = atoi( chunk.c_str() );
476     chunk = getNextChunk( stream, start, ok );
477     if ( !ok ) return false;
478     int typedera = atoi( chunk.c_str() );
479     hypothesis.SetRefinTypeDera( typeraff, typedera );
480
481     chunk = getNextChunk( stream, start, ok );
482     if ( !ok ) return false;
483     hypothesis.SetField( chunk.c_str() );
484
485     chunk = getNextChunk( stream, start, ok );
486     if ( !ok ) return false;
487     int typethr = atoi( chunk.c_str() );
488     chunk = getNextChunk( stream, start, ok );
489     if ( !ok ) return false;
490     double threshr = strtod( chunk.c_str(), 0 );
491     hypothesis.SetRefinThr( typethr, threshr );
492
493     chunk = getNextChunk( stream, start, ok );
494     if ( !ok ) return false;
495     int typethc = atoi( chunk.c_str() );
496     chunk = getNextChunk( stream, start, ok );
497     if ( !ok ) return false;
498     double threshc = strtod( chunk.c_str(), 0 );
499     hypothesis.SetUnRefThr( typethc, threshc );
500
501     chunk = getNextChunk( stream, start, ok );
502     if ( !ok ) return false;
503     hypothesis.SetUseComp(atoi(chunk.c_str()));
504
505     chunk = getNextChunk( stream, start, ok );
506     if ( !ok ) return false;
507     hypothesis.SetTypeFieldInterp(atoi(chunk.c_str()));
508
509     chunk = getNextChunk( stream, start, ok );
510     if ( !ok ) return false;
511     int size = atoi( chunk.c_str() );
512     for ( int i = 0; i < size; i++ ) {
513       chunk = getNextChunk( stream, start, ok );
514       if ( !ok ) return false;
515       hypothesis.AddIteration( chunk.c_str() );
516     }
517
518     chunk = getNextChunk( stream, start, ok );
519     if ( !ok ) return false;
520     size = atoi( chunk.c_str() );
521     for ( int i = 0; i < size; i++ ) {
522       chunk = getNextChunk( stream, start, ok );
523       if ( !ok ) return false;
524       hypothesis.AddZone( chunk.c_str() );
525     }
526
527     chunk = getNextChunk( stream, start, ok );
528     if ( !ok ) return false;
529     size = atoi( chunk.c_str() );
530     for ( int i = 0; i < size; i++ ) {
531       chunk = getNextChunk( stream, start, ok );
532       if ( !ok ) return false;
533       hypothesis.AddComp( chunk.c_str() );
534     }
535
536     chunk = getNextChunk( stream, start, ok );
537     if ( !ok ) return false;
538     size = atoi( chunk.c_str() );
539     for ( int i = 0; i < size; i++ ) {
540       chunk = getNextChunk( stream, start, ok );
541       if ( !ok ) return false;
542       hypothesis.AddGroup( chunk.c_str() );
543     }
544
545     chunk = getNextChunk( stream, start, ok );
546     if ( !ok ) return false;
547     size = atoi( chunk.c_str() );
548     for ( int i = 0; i < size; i++ ) {
549       chunk = getNextChunk( stream, start, ok );
550       if ( !ok ) return false;
551       hypothesis.AddFieldInterp( chunk.c_str() );
552     }
553     return true;
554   }
555
556 //
557 // Zone
558 // ============================
559   /*!
560     \brief Restore zone from the string
561     \param zone zone being restored
562     \param stream string representation of the zone
563     \return \c true if zone is correctly restored or \c false otherwise
564   */
565   bool Restore( HOMARD_Zone& zone, const std::string& stream )
566   {
567     std::string::size_type start = 0;
568     std::string chunk;
569     bool ok;
570     // 
571     chunk = getNextChunk( stream, start, ok );
572     if ( !ok ) return false;
573     zone.SetName( chunk.c_str() );
574     //
575     chunk = getNextChunk( stream, start, ok );
576     if ( !ok ) return false;
577     zone.SetZoneType( atoi( chunk.c_str() ) );
578     //
579     std::vector<double> coords;
580     coords.resize( 6 );
581     for ( int i = 0; i < 6; i++ ) {
582       chunk = getNextChunk( stream, start, ok );
583       if ( !ok ) return false;
584       coords[i] = strtod( chunk.c_str(), 0 );
585     }
586     zone.SetBox( coords[0], coords[1], coords[2], coords[3], coords[4], coords[5] );
587     //
588     for ( int i = 0; i < 4; i++ ) {
589       chunk = getNextChunk( stream, start, ok );
590       if ( !ok ) return false;
591       coords[i] = strtod( chunk.c_str(), 0 );
592     }
593     zone.SetSphere( coords[0], coords[1], coords[2], coords[3] );
594
595     //
596     for ( int i = 0; i < 3; i++ ) {
597       chunk = getNextChunk( stream, start, ok );
598       if ( !ok ) return false;
599       coords[i] = strtod( chunk.c_str(), 0 );
600     }
601     zone.SetLimit( coords[0], coords[1], coords[2]);
602
603     chunk = getNextChunk( stream, start, ok );
604     if ( !ok ) return false;
605     int size = atoi( chunk.c_str() );
606     for ( int i = 0; i < size; i++ ) {
607       chunk = getNextChunk( stream, start, ok );
608       if ( !ok ) return false;
609       zone.AddHypo( chunk.c_str() );
610     }
611     return true;
612   }
613
614
615 //
616 // 2.5. Restauration d'une frontiere
617 // =================================
618
619   /*!
620     \brief Restore boundary from the string
621     \param boundary boundary being restored
622     \param stream string representation of the boundary
623     \return \c true if zone is correctly restored or \c false otherwise
624   */
625   bool Restore( HOMARD_Boundary& boundary, const std::string& stream )
626   {
627     std::string::size_type start = 0;
628     std::string chunk;
629     bool ok;
630
631     chunk = getNextChunk( stream, start, ok );
632     if ( !ok ) return false;
633     boundary.SetName( chunk.c_str() );
634
635     chunk = getNextChunk( stream, start, ok );
636     if ( !ok ) return false;
637     boundary.SetBoundaryType(atoi( chunk.c_str()) );
638
639     chunk = getNextChunk( stream, start, ok );
640     if ( !ok ) return false;
641     boundary.SetCaseCreation( chunk.c_str() );
642
643     chunk = getNextChunk( stream, start, ok );
644     if ( !ok ) return false;
645     boundary.SetMeshFile( chunk.c_str() );
646
647     chunk = getNextChunk( stream, start, ok );
648     if ( !ok ) return false;
649     boundary.SetMeshName( chunk.c_str() );
650
651
652     std::vector<double> coords;
653     coords.resize( 3 );
654     for ( int i = 0; i < 3; i++ ) {
655       chunk = getNextChunk( stream, start, ok );
656       if ( !ok ) return false;
657       coords[i] = strtod( chunk.c_str(), 0 );
658     }
659     boundary.SetLimit( coords[0], coords[1], coords[2]);
660
661     coords.resize( 7 );
662     for ( int i = 0; i < 7; i++ ) {
663       chunk = getNextChunk( stream, start, ok );
664       if ( !ok ) return false;
665       coords[i] = strtod( chunk.c_str(), 0 );
666     }
667     boundary.SetCylinder(coords[0],coords[1],coords[2],coords[3],coords[4],coords[5],coords[6]);
668
669     coords.resize( 4 );
670     for ( int i = 0; i < 4; i++ ) {
671       chunk = getNextChunk( stream, start, ok );
672       if ( !ok ) return false;
673       coords[i] = strtod( chunk.c_str(), 0 );
674     }
675     boundary.SetSphere( coords[0], coords[1], coords[2], coords[3]);
676
677     chunk = getNextChunk( stream, start, ok );
678     if ( !ok ) return false;
679     int size = atoi( chunk.c_str() );
680     for ( int i = 0; i < size; i++ ) {
681       chunk = getNextChunk( stream, start, ok );
682       if ( !ok ) return false;
683       boundary.AddGroup( chunk.c_str() );
684     }
685
686     return true;
687   }
688
689 } // namespace HOMARD /end/