]> SALOME platform Git repositories - modules/med.git/blob - src/MEDMEM/MEDMEM_Support.cxx
Salome HOME
NRI : Merge from V1_2.
[modules/med.git] / src / MEDMEM / MEDMEM_Support.cxx
1 //  MED MEDMEM : MED files in memory
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : MEDMEM_Support.cxx
25 //  Module : MED
26
27 using namespace std;
28 /*
29  File Support.cxx
30  $Header$
31 */
32
33 #include <set>
34 #include <list>
35
36 //#include "utilities.h"
37 //#include "MEDMEM_define.hxx"
38 #include "MEDMEM_DriversDef.hxx"
39 #include "MEDMEM_Support.hxx"
40 //#include "MEDMEM_Family.hxx"
41 //#include "MEDMEM_Group.hxx"
42 #include "MEDMEM_Mesh.hxx"
43
44 using namespace MED_EN;
45
46 /* This class is a generic class for family and group */
47
48 /*!
49   Constructor.
50 */
51 //--------------------------------------------------------------------------
52 SUPPORT::SUPPORT(): _name(""),  _description(""), _mesh((MESH*)NULL),
53                     _entity(MED_CELL), _numberOfGeometricType(0),
54                     _geometricType((medGeometryElement*)NULL),
55                     _numberOfGaussPoint((int*)NULL),
56                     //_geometricTypeNumber((int*)NULL),
57                     _isOnAllElts(false),
58                     _numberOfElements((int*)NULL),
59                     _totalNumberOfElements(0),
60                     _number((MEDSKYLINEARRAY*)NULL)
61 //--------------------------------------------------------------------------
62 {
63     MESSAGE("SUPPORT::SUPPORT()");
64 }; 
65
66 /*!
67   Constructor.
68 */
69 //--------------------------------------------------------------------------
70 SUPPORT::SUPPORT(MESH* Mesh, string Name/*=""*/, medEntityMesh Entity/*=MED_CELL*/):
71                 _name(Name), _description(""), _mesh(Mesh), _entity(Entity),
72                 _numberOfGeometricType(0),
73                 _geometricType((medGeometryElement*)NULL),
74                 _numberOfGaussPoint((int*)NULL),
75                 //_geometricTypeNumber((int*)NULL),
76                 _isOnAllElts(true), 
77                 _numberOfElements((int*)NULL),
78                 _totalNumberOfElements(0),
79                 _number((MEDSKYLINEARRAY*)NULL)
80 //--------------------------------------------------------------------------
81 {
82   MESSAGE("SUPPORT::SUPPORT(MESH*Mesh,string Name,medEntityMesh Entity)");
83   update() ;
84 };
85
86 /*!
87   Copy constructor.
88 */
89 //--------------------------------------------------------------------------
90 SUPPORT::SUPPORT(const SUPPORT & m)
91 //--------------------------------------------------------------------------
92 {
93   const char * LOC = "SUPPORT::SUPPORT(SUPPORT & m) : " ;
94   BEGIN_OF(LOC) ;
95
96   _name = m._name;
97   _description = m._description;
98   _mesh = m._mesh; // on recopie uniquement l'adresse
99   _entity = m._entity;
100   _numberOfGeometricType = m._numberOfGeometricType;
101   if (m._geometricType != NULL)
102     {
103       _geometricType = new medGeometryElement[m._numberOfGeometricType];
104       memcpy(_geometricType,m._geometricType,m._numberOfGeometricType*sizeof(medGeometryElement));
105     }
106   else
107     _geometricType = (medGeometryElement *) NULL;
108   if (m._numberOfGaussPoint != NULL)
109     {
110       _numberOfGaussPoint = new int[m._numberOfGeometricType];
111       memcpy(_numberOfGaussPoint,m._numberOfGaussPoint,m._numberOfGeometricType*sizeof(int));
112     }
113   else
114     _numberOfGaussPoint = (int *) NULL;
115 //    if (m._geometricTypeNumber != NULL)
116 //      {
117 //        _geometricTypeNumber = new int[m._numberOfGeometricType];
118 //        memcpy(_geometricTypeNumber,m._geometricTypeNumber,m._numberOfGeometricType*sizeof(int));
119 //      }
120 //    else
121 //      _geometricTypeNumber = (int *) NULL;
122   _isOnAllElts = m._isOnAllElts;
123   if (m._numberOfElements != NULL)
124     {
125       _numberOfElements = new int[_numberOfGeometricType];
126       memcpy(_numberOfElements,m._numberOfElements,_numberOfGeometricType*sizeof(int));
127     }
128   else
129     _numberOfElements = (int *) NULL;
130   _totalNumberOfElements = m._totalNumberOfElements;
131   if (m._isOnAllElts == false)
132     _number = new MEDSKYLINEARRAY(* m._number);
133   else
134     _number = (MEDSKYLINEARRAY *) NULL;
135
136   END_OF(LOC) ;
137 };
138
139
140 /*!
141   Destructor.
142 */
143 //-----------------
144 SUPPORT::~SUPPORT() 
145 //-----------------
146 {
147   MESSAGE("Destructeur ~SUPPORT()");
148   if (_geometricType != (medGeometryElement *) NULL) 
149     delete [] _geometricType ;
150   if (_numberOfGaussPoint != (int *) NULL) 
151     delete [] _numberOfGaussPoint ;
152   //      if (_geometricTypeNumber!=NULL) 
153   //                    delete[] _geometricTypeNumber ;
154   if (_numberOfElements != (int *) NULL) 
155     delete[] _numberOfElements ;
156   if (_number != (MEDSKYLINEARRAY *) NULL) 
157     delete _number ;
158 }
159
160 /*!
161   operator <<.
162 */
163 //--------------------------------------------------
164 ostream & operator<<(ostream &os, const SUPPORT &my)
165 //--------------------------------------------------
166 {
167   os << "Name : "<< my._name << endl ;
168   os << "Description : "<< my._description << endl ;
169   os << "Mesh name : ";
170   if (my._mesh==NULL)
171     os << "ERROR : Mesh not defined !" << endl ;
172   else
173     os << my._mesh->getName() << endl ;
174   os << "Entity : "<< my._entity << endl;
175   os << "Entity list : "<< endl;
176   if (!(my._isOnAllElts)) {
177     int numberoftypes = my._numberOfGeometricType ;
178     os << "NumberOfTypes : "<<numberoftypes<<endl;
179     medGeometryElement * types = my._geometricType;
180     for (int j=0;j<numberoftypes;j++) {
181       os << "    * Type "<<types[j]<<" : ";
182       int numberOfElements = my._numberOfElements[j];
183       const int * number = my._number->getI(j+1);
184       for (int k=0; k<numberOfElements;k++)
185         os << number[k] << " ";
186       os << endl ;
187     }
188   } else
189     os << "Is on all entities !"<< endl;
190   
191   return os ;
192 }
193
194 /*!
195   Updade the SUPPORT attributs with rigth MESH information.
196   
197   It has an effect only if SUPPORT is on all elements.
198
199   No more need in future release.
200 */
201 //-------------------
202 void SUPPORT::update()
203 //-------------------
204 {
205   const char * LOC = "SUPPORT::update() : " ;
206   BEGIN_OF(LOC) ;
207
208   if (_isOnAllElts) {
209     if (_entity == MED_NODE) {
210       _numberOfGeometricType=1 ;
211       _geometricType=new medGeometryElement[1] ;
212       _geometricType[0]=MED_NONE ;
213       _numberOfElements = new int[1] ;
214       _numberOfElements[0]=_mesh->getNumberOfNodes();
215       _totalNumberOfElements=_numberOfElements[0];
216       _numberOfGaussPoint = new int[1] ;
217       _numberOfGaussPoint[0]=1;
218     } else { // we duplicate information from _mesh
219       _numberOfGeometricType=_mesh->getNumberOfTypes(_entity);
220       if (_geometricType == (medGeometryElement *) NULL)
221         _geometricType = new medGeometryElement[_numberOfGeometricType] ;
222       memcpy(_geometricType,_mesh->getTypes(_entity),_numberOfGeometricType*sizeof(medGeometryElement));
223       if (_numberOfElements == (int *) NULL)
224         _numberOfElements = new int[_numberOfGeometricType] ;
225       if (_numberOfGaussPoint == (int *) NULL)
226         _numberOfGaussPoint = new int[_numberOfGeometricType] ;
227       _totalNumberOfElements=0;
228       for (int i=0;i<_numberOfGeometricType;i++) {
229         _numberOfElements[i]=_mesh->getNumberOfElements(_entity,_geometricType[i]) ;
230         _totalNumberOfElements+=_numberOfElements[i];
231         _numberOfGaussPoint[i]=1 ;
232       }
233     }
234   }
235   END_OF(LOC);
236 };
237
238 /*!
239   Blend the given SUPPORT into it.
240 */
241 //-------------------
242 void SUPPORT::blending(SUPPORT * mySupport) 
243 //-------------------
244 {
245   const char * LOC = "SUPPORT::blending() : " ;
246   BEGIN_OF(LOC) ;
247
248   MESSAGE(LOC<< "SUPPORT entry : " << *mySupport) ;
249
250   // on same entity :
251   if ( _entity != mySupport->getEntity() )
252     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Entities are different !"));
253
254   int * tmp_NumberOfElementsInType = new int[MED_NBR_GEOMETRIE_MAILLE];
255   medGeometryElement * myType = new medGeometryElement[MED_NBR_GEOMETRIE_MAILLE];
256   int * whereIsType = new int[MED_NBR_GEOMETRIE_MAILLE];
257   //MESH_ENTITIES myMeshEntities() ;
258   list<MED_FR::med_geometrie_element>::const_iterator listIt ;
259   int it=0 ;
260   for(listIt=(MED_FR::meshEntities[(MED_FR::med_entite_maillage)_entity]).begin();listIt!=(MED_FR::meshEntities[(MED_FR::med_entite_maillage)_entity]).end();listIt++){
261     tmp_NumberOfElementsInType[it]=0;
262     whereIsType[it]=0 ;
263     try {
264       tmp_NumberOfElementsInType[it]+=getNumberOfElements((medGeometryElement)(*listIt)) ;
265       whereIsType[it]+=1 ;
266     }
267     catch (const MEDEXCEPTION & ex) {};
268     try {
269       tmp_NumberOfElementsInType[it]+=mySupport->getNumberOfElements((medGeometryElement)(*listIt)) ;
270       whereIsType[it]+=2 ;
271     }
272     catch (const MEDEXCEPTION & ex) {};
273     if (whereIsType[it]!=0) {
274       myType[it]=(medGeometryElement)(*listIt) ;
275       it++;
276     }
277   }
278   // set new value :
279   int * numberOfElements=_numberOfElements ;
280   _numberOfElements = new int[it] ;
281   _totalNumberOfElements = 0 ;
282   //int totalSize = 0 ;
283   int ** tmp_array = new (int*)[it];
284   for (int i=0;i<it;i++) {
285     int numberOfElementsInType = tmp_NumberOfElementsInType[i] ;
286     _numberOfElements[i] = numberOfElementsInType ;
287     tmp_array[i] = new int[numberOfElementsInType] ;
288     //totalSize+=numberOfElementsInType*(myType[i]%100) ;
289     _totalNumberOfElements+=numberOfElementsInType ;
290     if (whereIsType[i] == 1) { // only first Support
291       memcpy(tmp_array[i],getNumber(myType[i]),sizeof(int)*numberOfElementsInType);
292     } else if (whereIsType[i] == 2) { // only second Support
293       memcpy(tmp_array[i],mySupport->getNumber(myType[i]),sizeof(int)*numberOfElementsInType);
294     } else if (whereIsType[i] == 3) { // more difficult :-)
295       set<int> elementList ;
296       int i1 = 0 ;
297       int i2 = 0 ;
298       int ii = 0 ;
299       const int * number1 = getNumber(myType[i]) ;
300       const int * number2 = mySupport->getNumber(myType[i]) ;
301
302       SCRUTE(number1);
303       SCRUTE(number2);
304
305       int numberOfElements1 = numberOfElements[i] ;
306       int numberOfElements2 = mySupport->getNumberOfElements(myType[i]) ;
307
308       SCRUTE(numberOfElements1);
309       SCRUTE(numberOfElements2);
310
311       for(int j=0;j<numberOfElements1;j++){
312         elementList.insert(number1[j]) ;
313       }
314
315       for(int j=0;j<numberOfElements2;j++){
316         SCRUTE(number2[j]);
317         elementList.insert(number2[j]) ;
318       }
319
320       //create the array !
321       int newNumberOfElements = elementList.size() ;
322       _numberOfElements[i] = newNumberOfElements ;
323       int * tmp_arrayNew = new int[newNumberOfElements];
324
325       set<int>::iterator its ;
326       for(its=elementList.begin();its!=elementList.end(); its++) {
327         tmp_arrayNew[ii]=*its ;
328         ii++;
329       }
330
331       delete[] tmp_array[i] ;
332       tmp_array[i] = tmp_arrayNew ;
333       _totalNumberOfElements-=(numberOfElementsInType-newNumberOfElements) ;
334
335     } else
336       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"ERROR")) ;
337   }
338   delete[] whereIsType ;
339   delete[] tmp_NumberOfElementsInType ;
340
341   _numberOfGeometricType = it ;
342   medGeometryElement * geometricType=_geometricType ;
343   _geometricType = new medGeometryElement[it] ;
344   int * numberOfGaussPoint=_numberOfGaussPoint ;
345   _numberOfGaussPoint= new int[it] ;
346 //    int * geometricTypeNumber=_geometricTypeNumber ;
347 //    _geometricTypeNumber = new int[it] ;
348
349 //    MEDSKYLINEARRAY* numberNew = new MEDSKYLINEARRAY(it,_totalNumberOfElements);
350 //    int * numberIndex = numberNew->getIndex() ;
351   int size = _mesh->getNumberOfElements(_entity,MED_ALL_ELEMENTS);
352   if (_totalNumberOfElements == size) _isOnAllElts = true;
353
354   int * numberValue = new int[_totalNumberOfElements] ;
355   int * numberIndex = new int[it+1] ;
356   numberIndex[0]=1;
357   for (int i=0;i<it;i++) {
358     memcpy(numberValue+numberIndex[i]-1,tmp_array[i],sizeof(int)*_numberOfElements[i]) ;
359     delete[] tmp_array[i] ;
360     numberIndex[i+1]=numberIndex[i]+_numberOfElements[i] ;
361
362     _geometricType[i]=myType[i] ;
363     _numberOfGaussPoint[i]=1 ;
364   }
365   if ( _number != (MEDSKYLINEARRAY *) NULL) delete _number ;
366   //_number = numberNew ;
367   _number = new MEDSKYLINEARRAY(it,_totalNumberOfElements,numberIndex,numberValue);
368   delete[] numberIndex;
369
370   delete[] numberValue;
371
372   delete[] myType ;
373   delete[] tmp_array ;
374
375   delete[] geometricType ;
376   delete[] numberOfGaussPoint ;
377 //    delete[] geometricTypeNumber ;
378   delete[] numberOfElements ;
379
380   END_OF(LOC);
381 };
382
383 /*!
384     This function allows the user to set a support not on all entities Entity,
385     it should be used after an initialisation with the constructor
386     SUPPORT(MESH* Mesh, string Name="", medEntityMesh Entity=MED_CELL) and
387     after the call to the function setAll(false).
388     It allocates and initialises all the attributs of the class SUPPORT.
389  */
390
391 //-------------------
392 void SUPPORT::setpartial(string Description, int NumberOfGeometricType,
393                          int TotalNumberOfElements,
394                          medGeometryElement *GeometricType,
395                          int *NumberOfElements, int *NumberValue) 
396 //-------------------
397 {
398   const char * LOC = "SUPPORT::setpartial(string , int , int , medGeometryElement * , int * , int *) : " ;
399   BEGIN_OF(LOC) ;
400
401   _isOnAllElts = false ;
402
403   _description=Description;
404
405   _numberOfGeometricType=NumberOfGeometricType;
406
407   if (_geometricType!=NULL) delete[] _geometricType ;
408   _geometricType = new medGeometryElement[NumberOfGeometricType];
409   if (_numberOfElements!=NULL) delete[] _numberOfElements ;
410   _numberOfElements = new int[NumberOfGeometricType];
411   _totalNumberOfElements = TotalNumberOfElements;
412   if (_numberOfGaussPoint!=NULL) delete[] _numberOfGaussPoint ;
413   _numberOfGaussPoint = new int[NumberOfGeometricType];
414   int * index = new int[_numberOfGeometricType+1];
415   index[0]=1;
416   for (int i=0;i<_numberOfGeometricType;i++) {
417     _geometricType[i] = GeometricType[i] ;
418     _numberOfElements[i] = NumberOfElements[i] ;
419     _numberOfGaussPoint[i] = 1 ;
420     index[i+1] = index[i]+NumberOfElements[i] ;
421   }
422   
423   if (_number!=NULL) delete _number ;
424   _number = new MEDSKYLINEARRAY(_numberOfGeometricType,_totalNumberOfElements,index,NumberValue);
425
426   delete[] index ;
427
428   END_OF(LOC);
429 };
430
431
432 /*!
433   This method gets the boundary elements of the mesh. The support has to be
434   build using the constructor SUPPORT(MESH *,string, medEntityMesh) or
435   SUPPORT() followed by setMesh(MESH*) setName(string) and
436   setEntity(medEntityMesh) before using this method.
437 */
438 //-------------------
439 void SUPPORT::getBoundaryElements() throw (MEDEXCEPTION)
440 //-------------------
441 {
442   const char * LOC = "SUPPORT::getBoundaryElements() : " ;
443   BEGIN_OF(LOC) ;
444
445   if (_mesh == (MESH*)NULL) throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"You shlould use the appropriate SUPPORT Constructor before calling this method"));
446
447   int spaceDimension = _mesh->getSpaceDimension();
448
449   if (spaceDimension == 3)
450     if (_entity != MED_FACE)
451       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined in 3D mesh for entity "<<_entity<<" !"));
452   if (spaceDimension == 2) 
453     if (_entity != MED_EDGE)
454       throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<"Not defined in 2D mesh for entity "<<_entity<<" !"));
455
456   setAll(false);
457
458   const int * myConnectivityValue = _mesh->getReverseConnectivity(MED_DESCENDING) ;
459   const int * myConnectivityIndex = _mesh->getReverseConnectivityIndex(MED_DESCENDING) ;
460   int numberOf = _mesh->getNumberOfElements(_entity,MED_ALL_ELEMENTS) ;
461   list<int> myElementsList ;
462   int size = 0 ;
463   SCRUTE(numberOf) ;
464   for (int i=0 ; i<numberOf; i++)
465     if (myConnectivityValue[myConnectivityIndex[i]] == 0) {
466       SCRUTE(i+1) ;
467       myElementsList.push_back(i+1) ;
468       size++ ;
469     }
470   SCRUTE(size) ;
471   // Well, we must know how many geometric type we have found
472   int * myListArray = new int[size] ;
473   int id = 0 ;
474   list<int>::iterator myElementsListIt ;
475   for (myElementsListIt=myElementsList.begin();myElementsListIt!=myElementsList.end();myElementsListIt++) {
476     myListArray[id]=(*myElementsListIt) ;
477     SCRUTE(id);
478     SCRUTE(myListArray[id]);
479     id ++ ;
480   }
481
482   int numberOfGeometricType ;
483   medGeometryElement* geometricType ;
484   int * numberOfGaussPoint ;
485   int * geometricTypeNumber ;
486   int * numberOfElements ;
487   //MEDSKYLINEARRAY * mySkyLineArray = new MEDSKYLINEARRAY() ;
488   int * mySkyLineArrayIndex ;
489
490   int numberOfType = _mesh->getNumberOfTypes(_entity) ;
491   if (numberOfType == 1) { // wonderfull : it's easy !
492     numberOfGeometricType = 1 ;
493     geometricType = new medGeometryElement[1] ;
494     const medGeometryElement *  allType = _mesh->getTypes(_entity);
495     geometricType[0] = allType[0] ;
496     numberOfGaussPoint = new int[1] ;
497     numberOfGaussPoint[0] = 1 ;
498     geometricTypeNumber = new int[1] ; // not use, but initialized to nothing
499     geometricTypeNumber[0] = 0 ;
500     numberOfElements = new int[1] ;
501     numberOfElements[0] = size ;
502     mySkyLineArrayIndex = new int[2] ;
503     mySkyLineArrayIndex[0]=1 ;
504     mySkyLineArrayIndex[1]=1+size ;
505   }
506   else {// hemmm
507     map<medGeometryElement,int> theType ;
508     for (myElementsListIt=myElementsList.begin();myElementsListIt!=myElementsList.end();myElementsListIt++) {
509       medGeometryElement myType = _mesh->getElementType(_entity,*myElementsListIt) ;
510       if (theType.find(myType) != theType.end() )
511         theType[myType]+=1 ;
512       else
513         theType[myType]=1 ;
514     }
515     numberOfGeometricType = theType.size() ;
516     geometricType = new medGeometryElement[numberOfGeometricType] ;
517     const medGeometryElement *  allType = _mesh->getTypes(_entity);
518     numberOfGaussPoint = new int[numberOfGeometricType] ;
519     geometricTypeNumber = new int[numberOfGeometricType] ; // not use, but initialized to nothing
520     numberOfElements = new int[numberOfGeometricType] ;
521     mySkyLineArrayIndex = new int[numberOfGeometricType+1] ;
522     int index = 0 ;
523     mySkyLineArrayIndex[0]=1 ;
524     map<medGeometryElement,int>::iterator theTypeIt ;
525     for (theTypeIt=theType.begin();theTypeIt!=theType.end();theTypeIt++) {
526       geometricType[index] = (*theTypeIt).first ;
527       numberOfGaussPoint[index] = 1 ;
528       geometricTypeNumber[index] = 0 ;
529       numberOfElements[index] = (*theTypeIt).second ;
530       mySkyLineArrayIndex[index+1]=mySkyLineArrayIndex[index]+numberOfElements[index] ;
531       index++ ;
532     }
533   }
534   //mySkyLineArray->setMEDSKYLINEARRAY(numberOfGeometricType,size,mySkyLineArrayIndex,myListArray) ;
535   MEDSKYLINEARRAY * mySkyLineArray = new MEDSKYLINEARRAY(numberOfGeometricType,size,mySkyLineArrayIndex,myListArray) ;
536
537   setNumberOfGeometricType(numberOfGeometricType) ;
538   //  setGeometricType(geometricType) ;
539   //  setNumberOfGaussPoint(numberOfGaussPoint) ;
540   for (int i=0;i<numberOfGeometricType;i++)
541     {
542       _numberOfGaussPoint[i] = numberOfGaussPoint[i];
543       _geometricType[i] = geometricType[i];
544     }
545
546   setNumberOfElements(numberOfElements) ;
547   setTotalNumberOfElements(size) ;
548   //  setNumber(mySkyLineArray) ;
549
550   _number = new MEDSKYLINEARRAY(numberOfGeometricType,size);
551
552   _number->setIndex(mySkyLineArrayIndex);
553
554   for (int i=0;i<size;i++)
555     {
556       _number->setIndexValue(i+1,myListArray[i]);
557     }
558
559   delete[] numberOfElements;
560   delete[] geometricTypeNumber;
561   delete[] numberOfGaussPoint;
562   delete[] geometricType;
563   delete[] mySkyLineArrayIndex;
564   delete[] myListArray;
565   delete mySkyLineArray;
566
567   END_OF(LOC) ;
568 }