inmost_mesh.h 85.3 KB
Newer Older
Kirill Terekhov's avatar
Kirill Terekhov committed
1
2
3
4
5
6
7
8
9
10
11
#pragma once
#ifndef INMOST_MESH_H_INCLUDED
#define INMOST_MESH_H_INCLUDED

#include "inmost_common.h"

#if defined(USE_MESH)

#define __NDT 3
#define __NET 6

Kirill Terekhov's avatar
Kirill Terekhov committed
12
13
14
15
#define NEW_MARKERS
#define NEW_CONNECTIONS
#define NEW_SPARSE

Kirill Terekhov's avatar
Kirill Terekhov committed
16
17
namespace INMOST
{
Kirill Terekhov's avatar
Kirill Terekhov committed
18
19


Kirill Terekhov's avatar
Kirill Terekhov committed
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
	class Mesh;
	class Storage;
	class Element;
	class TagManager;
	class Node;
	class Edge;
	class Face;
	class Cell;

	typedef INMOST_DATA_BULK_TYPE ElementType;
	static const ElementType NONE = 0x00;
	static const ElementType NODE = 0x01;
	static const ElementType EDGE = 0x02;
	static const ElementType FACE = 0x04;
	static const ElementType CELL = 0x08;
	static const ElementType ESET = 0x10;
	static const ElementType MESH = 0x20;
	
	
	typedef INMOST_DATA_BULK_TYPE GeometricData;
	static const GeometricData CENTROID     = 0;
	static const GeometricData NORMAL       = 1;
	static const GeometricData ORIENTATION  = 2;
	static const GeometricData MEASURE      = 3;
	static const GeometricData BARYCENTER   = 4;
	
Kirill Terekhov's avatar
Kirill Terekhov committed
46
47
48
49
50
51
	typedef INMOST_DATA_BULK_TYPE SyncBitOp; //< This type is used for marker synchronization
	static const SyncBitOp SYNC_BIT_NEW = 0;
	static const SyncBitOp SYNC_BIT_OR  = 1;
	static const SyncBitOp SYNC_BIT_XOR = 2;
	static const SyncBitOp SYNC_BIT_AND = 3;

Kirill Terekhov's avatar
Kirill Terekhov committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
	//Use topolgy checking for debug purposes
	typedef INMOST_DATA_ENUM_TYPE TopologyCheck; 
	static const TopologyCheck THROW_EXCEPTION        = 0x00000001; //done//throw TopologyError exception on error
	static const TopologyCheck PRINT_NOTIFY           = 0x00000002; //done//print topology notify to std::cerr
	static const TopologyCheck DELETE_ON_ERROR        = 0x00000004; //done//element should be deleted if there is an error in EndTopologyCheck
	static const TopologyCheck MARK_ON_ERROR          = 0x00000008; //done//bitwise OR of errors is recorded to sparse integer tag of element (if not deleted), availible by TopologyErrorTag()
	static const TopologyCheck DUPLICATE_EDGE         = 0x00000010; //done//check that edge already exists, on occurance CreateEdge silently returns existant edge
	static const TopologyCheck DUPLICATE_FACE         = 0x00000020; //done//check that face already exists, on occurance CreateFace silently returns existant face
	static const TopologyCheck DUPLICATE_CELL         = 0x00000040; //done//check that cell already exists, on occurance CreateCell silently returns existant cell
	static const TopologyCheck DEGENERATE_EDGE        = 0x00000080; //done//check that edge have more then two nodes (no support for this kind of object)
	static const TopologyCheck DEGENERATE_FACE        = 0x00000100; //done//produce error if face consists of less then 3 edges
	static const TopologyCheck DEGENERATE_CELL        = 0x00000200; //done//produce error if cell consists of less then 4 faces
	static const TopologyCheck FACE_ORIENTATION       = 0x00000400; //done//produce error if face have wrong orientation of edges, for star-shaped elements only
	static const TopologyCheck FACE_PLANARITY         = 0x00000800; //done//produce error if face is non planar
	static const TopologyCheck INTERLEAVED_FACES      = 0x00001000; //done//produce error if there is another face that already uses same nodes
	static const TopologyCheck TRIPLE_SHARED_FACE     = 0x00002000; //done//check that every face have exectly two neighbours, if DUPLICATE_CELL is activated, then checks for cell duplication
	static const TopologyCheck FLATTENED_CELL         = 0x00004000; //done//produce error if one of the faces of the cell contains all the nodes of the cell
	static const TopologyCheck ADJACENT_DUPLICATE     = 0x00008000; //done//produce error if provided array of elements for creation contain duplications
	static const TopologyCheck ADJACENT_HIDDEN        = 0x00010000; //done//hidden elements should not be used when new elements are created
	static const TopologyCheck ADJACENT_ALIEN         = 0x00020000; //done//elements that belong to another mesh should not be used
	static const TopologyCheck ADJACENT_DIMENSION     = 0x00040000; //done//produce error if provided array of elements have wrong geometric dimension
	static const TopologyCheck PROHIBIT_MULTILINE     = 0x00080000; //done//(needs NEED_TEST_CLOSURE) produce error if edges of faces are not closed, or face is folded
	static const TopologyCheck PROHIBIT_POLYGON       = 0x00100000; //done//allow only known types of elements: Tet,Quad, Line
	static const TopologyCheck PROHIBIT_MULTIPOLYGON  = 0x00200000; //done//(needs NEED_TEST_CLOSURE) produce error if faces of cell are not closed, or cell is folded
	static const TopologyCheck PROHIBIT_POLYHEDRON    = 0x00400000; //done//allow only known types of elements: Tet,Hex,Prism,Pyramid
	static const TopologyCheck FACE_EDGES_ORDER       = 0x00800000; //not implemented(implement CheckEdgeOrder,FixEdgeOrder, class Cell,Face)//edges of the face should form one closed loop
	static const TopologyCheck PROHIBIT_CONCAVE_FACE  = 0x01000000; //not implemented//don't allow concave face
	static const TopologyCheck PROHIBIT_CONCAVE_CELL  = 0x02000000; //not implemented//don't allow concave cell
	static const TopologyCheck PROHIBIT_NONSTAR_FACE  = 0x04000000; //not implemented//don't allow non-star shaped face
	static const TopologyCheck PROHIBIT_NONSTAR_CELL  = 0x08000000; //not implemented//don't allow non-star shaped concave cell
	static const TopologyCheck FACE_SELF_INTERSECTION = 0x10000000; //not implemented//edges of the face don't cross each other
	static const TopologyCheck CELL_SELF_INTERSECTION = 0x20000000; //not implemented//faces of the cell don't cross each other
	static const TopologyCheck NEED_TEST_CLOSURE      = 0x40000000; //done//silent, test's for closure in ComputeGeometricType, needed to detect MultiLine and MultiPolygon
	static const TopologyCheck DISABLE_2D             = 0x80000000; //done//don't allow 2d grids, where edges appear to be vertexes, faces are edges and cells are faces
	static const TopologyCheck GRID_CONFORMITY        = NEED_TEST_CLOSURE | PROHIBIT_MULTILINE | PROHIBIT_MULTIPOLYGON  | INTERLEAVED_FACES | TRIPLE_SHARED_FACE;
Kirill Terekhov's avatar
Kirill Terekhov committed
87
	static const TopologyCheck DEFAULT_CHECK          = THROW_EXCEPTION | DUPLICATE_EDGE | DUPLICATE_FACE | PRINT_NOTIFY;
Kirill Terekhov's avatar
Kirill Terekhov committed
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
	
	__INLINE static const char * TopologyCheckNotifyString(TopologyCheck c)
	{
		switch(c)
		{
			case THROW_EXCEPTION:        return "exception thrown";
			case PRINT_NOTIFY:           return "print notify";
			case DELETE_ON_ERROR:        return "element should be deleted on error";
			case MARK_ON_ERROR:          return "element is marked on error";
			case DUPLICATE_EDGE:         return "search for duplicate edge";
			case DUPLICATE_FACE:         return "search for duplicate face";
			case DUPLICATE_CELL:         return "search for duplicate cell";
			case DEGENERATE_EDGE:        return "TOPOLOGY ERROR: curvilinear edge found"; 
			case DEGENERATE_FACE:        return "TOPOLOGY ERROR: degenerate face found";
			case DEGENERATE_CELL:        return "TOPOLOGY ERROR: degenerate cell found";
			case FACE_ORIENTATION:       return "TOPOLOGY ERROR: bad face orientation";
			case FACE_PLANARITY:         return "TOPOLOGY ERROR: non-planar face found";
			case INTERLEAVED_FACES:      return "TOPOLOGY ERROR: interleaving faces found";
			case TRIPLE_SHARED_FACE:     return "TOPOLOGY ERROR: face have more then two neighbours"; 
			case FLATTENED_CELL:         return "TOPOLOGY ERROR: flattened cell found"; 
			case ADJACENT_DUPLICATE:     return "TOPOLOGY ERROR: duplicates in adjacent elements";
			case ADJACENT_HIDDEN:        return "TOPOLOGY ERROR: hidden element is used as adjacent"; 
			case ADJACENT_ALIEN:         return "TOPOLOGY ERROR: element from other mesh is used as adjacent"; 
			case ADJACENT_DIMENSION:     return "TOPOLOGY ERROR: wrong dimension of adjacent elements";
			case PROHIBIT_MULTILINE:     return "TOPOLOGY ERROR: multiline is prohibited"; 
			case PROHIBIT_POLYGON:       return "TOPOLOGY ERROR: polygon is prohibited"; 
			case PROHIBIT_MULTIPOLYGON:  return "TOPOLOGY ERROR: multipolygon is prohibited"; 
			case PROHIBIT_POLYHEDRON:    return "TOPOLOGY ERROR: polyhedron is prohibited"; 
			case FACE_EDGES_ORDER:       return "TOPOLOGY ERROR: no order in face edges"; 
			case PROHIBIT_CONCAVE_FACE:  return "TOPOLOGY ERROR: concave faces are prohibited"; 
			case PROHIBIT_CONCAVE_CELL:  return "TOPOLOGY ERROR: concave cells are prohibited"; 
			case PROHIBIT_NONSTAR_FACE:  return "TOPOLOGY ERROR: non star-shaped faces are prohibited"; 
			case PROHIBIT_NONSTAR_CELL:  return "TOPOLOGY ERROR: non star-shpaed cells are prohibited"; 
			case FACE_SELF_INTERSECTION: return "TOPOLOGY ERROR: self intersection of face edges detected"; 
			case CELL_SELF_INTERSECTION: return "TOPOLOGY ERROR: self intersection of cell faces detected"; 
			case DISABLE_2D:             return "TOPOLOGY ERROR: 2d mesh support is disabled"; 
			default: return "unknown";
		}
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
128
129
130
	/// This function helps to determine whether one type is chosen or multiple
	__INLINE static bool OneType(ElementType t) {return t > 0 && (t & (t-1)) == 0;}

Kirill Terekhov's avatar
Kirill Terekhov committed
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
	__INLINE static int ElementNum(ElementType t)
	{
		unsigned int v = static_cast<unsigned int>(t);  // 32-bit value to find the log2 of 
		static const unsigned int b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
		register unsigned int r = (v & b[0]) != 0;
		r |= ((v & b[4]) != 0) << 4;
		r |= ((v & b[3]) != 0) << 3;
		r |= ((v & b[2]) != 0) << 2;
		r |= ((v & b[1]) != 0) << 1;
		return static_cast<int>(r);
	}
	
	
	__INLINE static const char * ElementTypeName(ElementType t)
	{
		switch(t)
		{
			case NONE: return "NONE";
			case NODE: return "NODE";
			case EDGE: return "EDGE";
			case FACE: return "FACE";
			case CELL: return "CELL";
			case ESET: return "ESET";
			case MESH: return "MESH";
		}
		return "UNKNOWN";
	}
	
	
	
	typedef array<INMOST_DATA_REAL_TYPE>    inner_real_array;
	typedef array<INMOST_DATA_INTEGER_TYPE> inner_integer_array;
	typedef array<INMOST_DATA_BULK_TYPE>    inner_bulk_array;
Kirill Terekhov's avatar
Kirill Terekhov committed
164
	typedef array<Element *>                inner_reference_array;
Kirill Terekhov's avatar
Kirill Terekhov committed
165
166
167
168
169
170
171
172
173
		
	enum DataType
	{
		DATA_REAL      = 0, 
		DATA_INTEGER   = 1, 
		DATA_BULK      = 2,
		DATA_REFERENCE = 3
	};
	
Kirill Terekhov's avatar
Kirill Terekhov committed
174
	__INLINE static INMOST_DATA_ENUM_TYPE DataTypeBytesSize(DataType t)
Kirill Terekhov's avatar
Kirill Terekhov committed
175
176
177
178
179
180
181
182
183
184
185
	{
		switch(t)
		{
			case DATA_BULK:      return sizeof(INMOST_DATA_BULK_TYPE);
			case DATA_INTEGER:   return sizeof(INMOST_DATA_INTEGER_TYPE);
			case DATA_REAL:      return sizeof(INMOST_DATA_REAL_TYPE);
			case DATA_REFERENCE: return sizeof(Element *);
		}
		return 0;
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
186
	__INLINE static INMOST_DATA_ENUM_TYPE VariableDataSize(DataType t)
Kirill Terekhov's avatar
Kirill Terekhov committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	{
		switch(t)
		{
			case DATA_REAL:      return sizeof(inner_real_array);
			case DATA_INTEGER:   return sizeof(inner_integer_array);
			case DATA_BULK:      return sizeof(inner_bulk_array);
			case DATA_REFERENCE: return sizeof(inner_reference_array);
		}
		return 0;
	}
	
	__INLINE static const char * DataTypeName(DataType t)
	{
		switch(t)
		{
			case DATA_REAL:      return "REAL";
			case DATA_INTEGER:   return "INTEGER";
			case DATA_BULK:      return "BULK";
			case DATA_REFERENCE: return "REFERENCE";
		}
		return "UNKNOWN";
	}


Kirill Terekhov's avatar
Kirill Terekhov committed
211
212
213
214
215
	typedef INMOST_DATA_ENUM_TYPE MarkerType; // low 8 bits - marker mask, rest high bits - position of marker
	static const INMOST_DATA_ENUM_TYPE MarkerFields = 16;   // number of chars to hold all markers, total number (MarkerFields * bits_per_char)
	static const INMOST_DATA_BULK_TYPE MarkerMask   = static_cast<INMOST_DATA_BULK_TYPE>(-1); // bit mask to obtain marker mask within MarkerType
	static const INMOST_DATA_BULK_TYPE MarkerShift  = sizeof(INMOST_DATA_BULK_TYPE)*8;    // sizeof(char) * bits_per_char

Kirill Terekhov's avatar
Kirill Terekhov committed
216
217
218
219
220
221
222
223
224

	class TagMemory //implemented in tag.cpp
	{
	public:
		~TagMemory();
		TagMemory(Mesh * m, const TagMemory & other);
		TagMemory & operator =(TagMemory const & other);
	private:
		TagMemory();
Kirill Terekhov's avatar
Kirill Terekhov committed
225
226
227
228
229
230
		INMOST_DATA_ENUM_TYPE  pos[__NET]; 
		DataType               dtype;                 
		std::string            tagname;            
		INMOST_MPI_Type        bulk_data_type;   
		INMOST_DATA_ENUM_TYPE  size;       
		bool                   sparse[__NET];
Kirill Terekhov's avatar
Kirill Terekhov committed
231
		INMOST_DATA_ENUM_TYPE  record_size;
Kirill Terekhov's avatar
Kirill Terekhov committed
232
233
		TagManager *           tag_manager;
		Mesh *                 m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
234
		friend class Tag;
Kirill Terekhov's avatar
Kirill Terekhov committed
235
		friend class Storage; //for debug
Kirill Terekhov's avatar
Kirill Terekhov committed
236
237
238
239
240
241
242
	};

	class Tag //implemented in tag.cpp
	{
	private:
		TagMemory * mem;
		Tag(Mesh * m, std::string name, DataType _dtype, INMOST_DATA_ENUM_TYPE size); //Create me through TagManager::CreateTag
Kirill Terekhov's avatar
Kirill Terekhov committed
243
		__INLINE INMOST_DATA_ENUM_TYPE  GetRecordSize() const {return mem->record_size;}
Kirill Terekhov's avatar
Kirill Terekhov committed
244
245
246
247
248
		__INLINE void                   SetSize(INMOST_DATA_ENUM_TYPE size) {mem->size = size;}
		__INLINE void                   SetPosition(INMOST_DATA_ENUM_TYPE pos, ElementType type) {mem->pos[ElementNum(type)] = pos;}
		__INLINE INMOST_DATA_ENUM_TYPE  GetPosition(ElementType type) const {assert(mem != NULL); return mem->pos[ElementNum(type)];}
		__INLINE void                   SetSparse(ElementType type) {mem->sparse[ElementNum(type)] = true;}
		__INLINE void                   SetTagManager(TagManager * tm) {mem->tag_manager = tm;}
Kirill Terekhov's avatar
Kirill Terekhov committed
249
250
		__INLINE TagManager *           GetTagManager() const {return mem->tag_manager;}
		void                            ReallocateData(ElementType t,INMOST_DATA_ENUM_TYPE new_size);
Kirill Terekhov's avatar
Kirill Terekhov committed
251
252
		__INLINE INMOST_DATA_ENUM_TYPE  GetPositionNum(INMOST_DATA_ENUM_TYPE typenum) const {assert(mem != NULL); return mem->pos[typenum];}
		__INLINE void                   SetBulkDataType(INMOST_MPI_Type type){assert(mem!=NULL); if( mem->dtype == DATA_BULK ) mem->bulk_data_type = type;}
Kirill Terekhov's avatar
Kirill Terekhov committed
253
254
255
256
257
258
259
260
261
	public:
		~Tag() {mem = NULL;}
		Tag() {mem = NULL;}
		Tag(const Tag & other) {mem = other.mem;}
		bool operator <(const Tag & other) const {return mem < other.mem;}
		bool operator >(const Tag & other) const {return mem > other.mem;}
		bool operator ==(const Tag & other) const {return mem == other.mem;}
		bool operator !=(const Tag & other) const {return mem != other.mem;}
		Tag & operator =(Tag const & other) {mem = other.mem; return *this;	}
Kirill Terekhov's avatar
Kirill Terekhov committed
262
263
		__INLINE DataType               GetDataType() const {assert(mem!=NULL); return mem->dtype;}
		__INLINE INMOST_MPI_Type        GetBulkDataType() const {assert(mem!=NULL); return mem->bulk_data_type;}
Kirill Terekhov's avatar
Kirill Terekhov committed
264
		__INLINE INMOST_DATA_ENUM_TYPE  GetBytesSize() const {assert(mem!=NULL); return DataTypeBytesSize(mem->dtype);}
Kirill Terekhov's avatar
Kirill Terekhov committed
265
266
267
268
269
270
271
		__INLINE INMOST_DATA_ENUM_TYPE  GetSize() const {assert(mem!=NULL); return mem->size;}
		__INLINE std::string            GetTagName() const {assert(mem!=NULL); return mem->tagname;}
		__INLINE bool                   isDefined(ElementType type) const {assert(mem!=NULL && OneType(type)); return GetPosition(type) != ENUMUNDEF;}
		__INLINE bool                   isSparse(ElementType type) const {assert(mem!=NULL && OneType(type)); return mem->sparse[ElementNum(type)];}
		__INLINE bool                   isValid() const {return mem != NULL;}
		__INLINE Mesh *                 GetMeshLink() const {assert(mem!=NULL); return mem->m_link;}		
		__INLINE bool                   isSparseNum(INMOST_DATA_ENUM_TYPE typenum) const {assert(mem!=NULL); return mem->sparse[typenum];}
Kirill Terekhov's avatar
Kirill Terekhov committed
272
273
274
275
276
277
278
279
280
281
282
283
		friend class TagManager;
		friend class Storage;
		friend class Mesh;
	};
	
	class TagManager //implemented in tag.cpp
	{
	protected:
		TagManager();
		TagManager(Mesh * m, const TagManager & other);
		TagManager & assign(Mesh * m, TagManager const & other);
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
284
285
286
287
288
289
290
291
292
293
		//typedef chunk_array<INMOST_DATA_ENUM_TYPE>   empty_data;
		//typedef chunk_array<Tag>                     tag_array_type;
		typedef std::vector<INMOST_DATA_ENUM_TYPE> 	   empty_data;
		typedef std::vector<Tag>                       tag_array_type;
		typedef tag_array_type::iterator               iteratorTag;
		typedef chunk_array<INMOST_DATA_BULK_TYPE,15>  dense_sub_type;
		typedef chunk_array< dense_sub_type,8>         dense_data_array_type;
		typedef struct{void * tag, * rec;}             sparse_sub_record;
		typedef array< sparse_sub_record >             sparse_sub_type;
		typedef chunk_array< sparse_sub_type, 15>      sparse_data_array_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
294
295
		virtual ~TagManager();
		
Kirill Terekhov's avatar
Kirill Terekhov committed
296
297
298
299
300
301
302
303
304
305
306
		bool                            HaveTag            (std::string name) const;
		Tag                             GetTag             (std::string name) const;
		void                            ListTagNames       (std::vector<std::string> & list) const;
		Tag                             CreateTag          (Mesh * m, std::string name, DataType dtype, ElementType etype, ElementType sparse, INMOST_DATA_ENUM_TYPE size = ENUMUNDEF); 
		virtual Tag                     DeleteTag          (Tag tag, ElementType mask); 
		__INLINE INMOST_DATA_ENUM_TYPE  NumberOfTags       () const { return static_cast<INMOST_DATA_ENUM_TYPE>(tags.size()); }
		__INLINE iteratorTag            BeginTag           () {return tags.begin(); }
		__INLINE iteratorTag            EndTag             () {return tags.end(); }
		bool                            ElementDefined     (Tag const & tag, ElementType etype) const;
	protected:
		void                            ReallocateData     (ElementType etype);
Kirill Terekhov's avatar
Kirill Terekhov committed
307
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
308
309
		typedef tag_array_type::iterator            tag_iterator;
		typedef tag_array_type::const_iterator      tag_const_iterator;
Kirill Terekhov's avatar
Kirill Terekhov committed
310
311
312
313
314
315
316
317
318
319
		tag_array_type                              tags;
		empty_data                                  empty_dense_data;
		dense_data_array_type                       dense_data;
#if defined(NEW_SPARSE)
		sparse_data_array_type                      sparse_data[6];
		__INLINE sparse_sub_type const & GetSparseData      (int etypenum, int local_id) const {return sparse_data[etypenum][local_id];}
		__INLINE sparse_sub_type &       GetSparseData      (int etypenum, int local_id) {return sparse_data[etypenum][local_id];}
#endif
		__INLINE dense_sub_type const &  GetDenseData       (int pos) const {return dense_data[pos];}
		__INLINE dense_sub_type &        GetDenseData       (int pos) {return dense_data[pos];}
Kirill Terekhov's avatar
Kirill Terekhov committed
320
321
322
323
324
		friend class Storage;
		friend class Tag;
		friend class Mesh;
	};
	
325
326
327
328
329
	/// Base class for Mesh, Element, and ElementSet classes.
	/// This base class is used for the Mesh class, as well as Element classes, and ElementSet class.
	/// 
	/// Storage class is used for representing different data objects in memory.
	/// Each data object is associated with corresponding Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
330
331
332
333
334
335
336
	class Storage //implemented in storage.cpp
	{
	protected:
		Storage(const Storage & other);           // never use this
		Storage(Mesh * m, INMOST_DATA_ENUM_TYPE lid, const Storage & other); // use this instead
		Storage & assign(Mesh * m, INMOST_DATA_ENUM_TYPE lid, Storage const & other);
		Storage(Mesh *m, ElementType _etype);
Kirill Terekhov's avatar
Kirill Terekhov committed
337
#if !defined(NEW_SPARSE)
Kirill Terekhov's avatar
Kirill Terekhov committed
338
339
		typedef std::pair<Tag, void *>    sparse_sub_type;
		typedef array< sparse_sub_type >  sparse_data_array_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
340
341
342
343
344
345
346
#else
		typedef TagManager::sparse_sub_type sparse_type;
		typedef TagManager::sparse_sub_record sparse_rec;
		__INLINE static sparse_rec mkrec(const Tag & t) {sparse_rec ret; ret.tag = t.mem; ret.rec = NULL; return ret;}
#endif
		static void                       CopyData(Tag t, void * adata, void * bdata);
		static void                       DestroyVariableData(Tag t, void * adata);
Kirill Terekhov's avatar
Kirill Terekhov committed
347
348
349
350
		void                              MoveData(INMOST_DATA_INTEGER_TYPE new_local_id);
		INMOST_DATA_ENUM_TYPE             etypenum;
		INMOST_DATA_ENUM_TYPE             local_id;
		Mesh *                            m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
351
352
353
354
#if !defined(NEW_MARKERS)
		MarkerType                        markers;
#endif
#if !defined(NEW_SPARSE)
Kirill Terekhov's avatar
Kirill Terekhov committed
355
		sparse_data_array_type            inner_data;
Kirill Terekhov's avatar
Kirill Terekhov committed
356
357
358
359
360
361
362
363
364
365
366
367
		__INLINE void * &                 GetSparseLink(const Tag & t) {for(sparse_data_array_type::iterator it = inner_data.begin(); it != inner_data.end(); ++it) if( it->first == t ) return it->second; inner_data.push_back(sparse_sub_type(t,(void *)NULL)); return inner_data.back().second;}
		__INLINE void *                   GetSparseLink(const Tag & t) const {for(sparse_data_array_type::const_iterator it = inner_data.begin(); it != inner_data.end(); ++it) if( it->first == t ) return it->second; return NULL;}
#else
		__INLINE sparse_type const &      SLink() const {return reinterpret_cast<TagManager *>(GetMeshLink())->GetSparseData(etypenum,LocalID());}
		__INLINE sparse_type &            SLink() {return reinterpret_cast<TagManager *>(GetMeshLink())->GetSparseData(etypenum,LocalID());}
		__INLINE void * &                 GetSparseLink(const Tag & t) {sparse_type & s = SLink(); for(int i = 0; i < s.size(); ++i) if( s[i].tag == t.mem ) return s[i].rec; s.push_back(mkrec(t)); return s.back().rec;}
		__INLINE void *                   GetSparseLink(const Tag & t) const {sparse_type const & s = SLink(); for(int i = 0; i < s.size(); ++i) if( s[i].tag == t.mem ) return s[i].rec; return NULL;}
#endif
		__INLINE void *                   GetDenseLink (const Tag & t) const {return &(t.GetTagManager()->GetDenseData(t.GetPositionNum(etypenum))[LocalID()]);}
		//__INLINE void *                   GetDenseLink (const Tag & t) const {return &(t.mem->tag_manager->dense_data[t.mem->pos[etypenum]][local_id*t.mem->record_size]);}
		__INLINE void *                   GetLink      (const Tag & t) {void * p; if( !t.isSparseNum(etypenum) ) p = GetDenseLink(t); else {void * & q = GetSparseLink(t); if( q == NULL ) q = calloc(1,t.GetRecordSize()); p = q;} return p;}
		__INLINE void *                   GetLink      (const Tag & t) const {void * p; if( !t.isSparseNum(etypenum) ) p = GetDenseLink(t); else p = GetSparseLink(t); return p;}
Kirill Terekhov's avatar
Kirill Terekhov committed
368
	public:
369
		/// Storage type for representing real values.
Kirill Terekhov's avatar
Kirill Terekhov committed
370
		typedef INMOST_DATA_REAL_TYPE     real; 
371
		/// Storage type for representing integer values.
Kirill Terekhov's avatar
Kirill Terekhov committed
372
		typedef INMOST_DATA_INTEGER_TYPE  integer;
373
		/// Storage type for representing one byte of abstact data.
Kirill Terekhov's avatar
Kirill Terekhov committed
374
		typedef INMOST_DATA_BULK_TYPE     bulk;
375
		/// Storage type for representing references to Element.
Kirill Terekhov's avatar
Kirill Terekhov committed
376
		typedef Element *                 reference;
377
		/// Storage type for representing arrays of real values.
Kirill Terekhov's avatar
Kirill Terekhov committed
378
		typedef shell<real>               real_array;
379
		/// Storage type for representing arrays of integer values.
Kirill Terekhov's avatar
Kirill Terekhov committed
380
		typedef shell<integer>            integer_array;
381
		/// Storage type for representing abstact data as a series of bytes.
Kirill Terekhov's avatar
Kirill Terekhov committed
382
		typedef shell<bulk>               bulk_array;
383
		/// Storage type for representing arrays of Element references.
Kirill Terekhov's avatar
Kirill Terekhov committed
384
		typedef shell<reference>          reference_array;
Kirill Terekhov's avatar
Kirill Terekhov committed
385
		virtual ~Storage();
386
		/// Retrieve real value associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
387
		__INLINE real      &              Real            (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REAL     ); void * p = GetLink(tag); if( tag.GetSize() != ENUMUNDEF ) return static_cast<Storage::real     *>(p)[0]; else return static_cast<inner_real_array     *>(p)->at_safe(0);}
388
		/// Retrieve integer value associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
389
		__INLINE integer   &              Integer         (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_INTEGER  ); void * p = GetLink(tag); if( tag.GetSize() != ENUMUNDEF ) return static_cast<Storage::integer  *>(p)[0]; else return static_cast<inner_integer_array  *>(p)->at_safe(0);}
390
		/// Retrieve one byte of abstract data associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
391
		__INLINE bulk      &              Bulk            (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_BULK     ); void * p = GetLink(tag); if( tag.GetSize() != ENUMUNDEF ) return static_cast<Storage::bulk     *>(p)[0]; else return static_cast<inner_bulk_array     *>(p)->at_safe(0);}
392
		/// Retrieve Element reference associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
393
		__INLINE reference &              Reference       (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REFERENCE); void * p = GetLink(tag); if( tag.GetSize() != ENUMUNDEF ) return static_cast<Storage::reference*>(p)[0]; else return static_cast<inner_reference_array*>(p)->at_safe(0);}
394
		/// Retrieve array of real values associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
395
		__INLINE real_array               RealArray       (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REAL     ); void * p = GetLink(tag); if( tag.GetSize() == ENUMUNDEF ) return Storage::real_array     (*static_cast<inner_real_array     *>(p)); else return Storage::real_array     (static_cast<Storage::real      *>(p),tag.GetSize());}
396
		/// Retrieve array of integer values associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
397
		__INLINE integer_array            IntegerArray    (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_INTEGER  ); void * p = GetLink(tag); if( tag.GetSize() == ENUMUNDEF ) return Storage::integer_array  (*static_cast<inner_integer_array  *>(p)); else return Storage::integer_array  (static_cast<Storage::integer   *>(p),tag.GetSize());}
398
		/// Retrieve abstract data associated with Tag as a series of bytes.
Kirill Terekhov's avatar
Kirill Terekhov committed
399
		__INLINE bulk_array               BulkArray       (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_BULK     ); void * p = GetLink(tag); if( tag.GetSize() == ENUMUNDEF ) return Storage::bulk_array     (*static_cast<inner_bulk_array     *>(p)); else return Storage::bulk_array     (static_cast<Storage::bulk      *>(p),tag.GetSize());}
400
		/// Retrieve array of Element references associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
401
		__INLINE reference_array          ReferenceArray  (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REFERENCE); void * p = GetLink(tag); if( tag.GetSize() == ENUMUNDEF ) return Storage::reference_array(*static_cast<inner_reference_array*>(p)); else return Storage::reference_array(static_cast<Storage::reference *>(p),tag.GetSize());}
Kirill Terekhov's avatar
Kirill Terekhov committed
402
403
		
		//optimized data requests for dense data with fixed size
Kirill Terekhov's avatar
Kirill Terekhov committed
404
405
406
407
408
409
410
411
		__INLINE real_array               RealArrayDF     (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REAL      && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::real_array     (static_cast<Storage::real     *>(GetDenseLink(tag)),tag.GetSize());}
		__INLINE integer_array            IntegerArrayDF  (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_INTEGER   && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::integer_array  (static_cast<Storage::integer  *>(GetDenseLink(tag)),tag.GetSize());}
		__INLINE bulk_array               BulkArrayDF     (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_BULK      && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::bulk_array     (static_cast<Storage::bulk     *>(GetDenseLink(tag)),tag.GetSize());}
		__INLINE reference_array          ReferenceArrayDF(const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REFERENCE && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::reference_array(static_cast<Storage::reference*>(GetDenseLink(tag)),tag.GetSize());}
		__INLINE real      &              RealDF          (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REAL      && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<Storage::real     *>(GetDenseLink(tag))[0];}
		__INLINE integer   &              IntegerDF       (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_INTEGER   && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<Storage::integer  *>(GetDenseLink(tag))[0];}
		__INLINE bulk      &              BulkDF          (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_BULK      && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<Storage::bulk     *>(GetDenseLink(tag))[0];}
		__INLINE reference &              ReferenceDF     (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REFERENCE && tag.GetSize() != ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<Storage::reference*>(GetDenseLink(tag))[0];}
Kirill Terekhov's avatar
Kirill Terekhov committed
412
413
		
		//optimized data requests for dense data with variable size
Kirill Terekhov's avatar
Kirill Terekhov committed
414
415
416
417
418
419
420
421
		__INLINE real_array               RealArrayDV     (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REAL      && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::real_array     (*static_cast<inner_real_array     *>(GetDenseLink(tag)));}
		__INLINE integer_array            IntegerArrayDV  (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_INTEGER   && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::integer_array  (*static_cast<inner_integer_array  *>(GetDenseLink(tag)));}
		__INLINE bulk_array               BulkArrayDV     (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_BULK      && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::bulk_array     (*static_cast<inner_bulk_array     *>(GetDenseLink(tag)));}
		__INLINE reference_array          ReferenceArrayDV(const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REFERENCE && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType())); return Storage::reference_array(*static_cast<inner_reference_array*>(GetDenseLink(tag)));}
		__INLINE real      &              RealDV          (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REAL      && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<inner_real_array     *>(GetDenseLink(tag))->at_safe(0);}
		__INLINE integer   &              IntegerDV       (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_INTEGER   && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<inner_integer_array  *>(GetDenseLink(tag))->at_safe(0);}
		__INLINE bulk      &              BulkDV          (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_BULK      && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<inner_bulk_array     *>(GetDenseLink(tag))->at_safe(0);}
		__INLINE reference &              ReferenceDV     (const Tag & tag) {assert(tag.isValid() && GetMeshLink() == tag.GetMeshLink() && tag.GetDataType() == DATA_REFERENCE && tag.GetSize() == ENUMUNDEF && !tag.isSparse(GetElementType()));  return static_cast<inner_reference_array*>(GetDenseLink(tag))->at_safe(0);}
Kirill Terekhov's avatar
Kirill Terekhov committed
422
		
423
424
425
		/// Return the data length associated with Tag.
		/// For abstract data return the number of bytes, otherwise return the length of associated array. 
		/// @see Storage::SetDataSize
Kirill Terekhov's avatar
Kirill Terekhov committed
426
		INMOST_DATA_ENUM_TYPE            GetDataSize      (const Tag & tag) const; //For DATA_BULK return number of bytes, otherwise return the length of array
427
428
429
430
		/// Set the length of  data associated with Tag.
		/// @param tag Identifying Tag.
		/// @param new_size The number of bytes for abstract data, otherwise the length of the array.
		/// @see Storage::GetDataSize
Kirill Terekhov's avatar
Kirill Terekhov committed
431
		void                             SetDataSize      (const Tag & tag,INMOST_DATA_ENUM_TYPE new_size);
432
433
434
435
436
437
438
439
440
		/// Extract part of the data associated with Tag.
		/// Copy part of the associated array or data to the destination memory.
		/// @param tag Identifying Tag.
		/// @param shift Starting position of the copied data.
		/// For abstact data – number of bytes to skip, otherwise number of values to skip.
		/// @param size Number of elements to copy.
		/// For abstact data – number of bytes to copy, otherwise number of values to copy.
		/// @param data Destination position to copy data to.
		/// @see Storage::SetData
Kirill Terekhov's avatar
Kirill Terekhov committed
441
442
443
		void                                   GetData        (const Tag & tag,INMOST_DATA_ENUM_TYPE shift, INMOST_DATA_ENUM_TYPE size, void * data) const;
		void                                   SetData        (const Tag & tag,INMOST_DATA_ENUM_TYPE shift, INMOST_DATA_ENUM_TYPE size, void * data);
		void                                   DelData        (const Tag & tag);
444
		/// Check if any data is associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
445
		bool                                   HaveData       (const Tag & tag) const {if(tag.isSparseNum(etypenum)) { if( GetSparseLink(tag) != NULL ) return true; return false; } else {if( tag.GetPositionNum(etypenum) != ENUMUNDEF ) return true; return false;}}
Kirill Terekhov's avatar
Kirill Terekhov committed
446
		/// Swap dense data with the element of the same type and given local_id 
Kirill Terekhov's avatar
Kirill Terekhov committed
447
		void                                   SwapDenseData  (INMOST_DATA_INTEGER_TYPE local_id);
Kirill Terekhov's avatar
Kirill Terekhov committed
448
		/// Swap sparse data with the element of the same type and given local_id 
Kirill Terekhov's avatar
Kirill Terekhov committed
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
		void                                   SwapSparseData (INMOST_DATA_INTEGER_TYPE local_id);
		__INLINE ElementType                   GetElementType () const {return 1 << etypenum;}
		__INLINE INMOST_DATA_ENUM_TYPE         GetElementNum  () const {return etypenum;}
#if defined(NEW_MARKERS)
		void                                   SetMarker      (MarkerType n);
		bool                                   GetMarker      (MarkerType n) const;
		void                                   RemMarker      (MarkerType n) ;
		void                                   ClearMarkerSpace();
		void                                   GetMarkerSpace(Storage::bulk copy[MarkerFields]) const;
		void                                   SetMarkerSpace(Storage::bulk source[MarkerFields]);
		static INMOST_DATA_ENUM_TYPE           MaxMarker() {return MarkerShift * MarkerFields;}
#else
		__INLINE void                          SetMarker       (MarkerType n)  {markers |= n;}
		__INLINE bool                          GetMarker       (MarkerType n) const  {return (markers & n) != 0;}
		__INLINE void                          RemMarker       (MarkerType n) {markers &= ~n;}
		__INLINE void                          ClearMarkerSpace() {markers = 0;}
		__INLINE MarkerType                    GetMarkerSpace  () const {return markers;}
		__INLINE void                          SetMarkerSpace  (MarkerType _markers) {markers = _markers;}
		__INLINE static INMOST_DATA_ENUM_TYPE  MaxMarker() {return sizeof(MarkerType)*8;}
Kirill Terekhov's avatar
Kirill Terekhov committed
468
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
469
470
471
		__INLINE INMOST_DATA_ENUM_TYPE         LocalID         () const {return local_id;}
		__INLINE Mesh *                        GetMeshLink     () const {return m_link;}
		friend void                            SwapElement     (void * pa, void * pb, void * udata);
Kirill Terekhov's avatar
Kirill Terekhov committed
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
		friend class Mesh;
	};

	
	class ElementSet : public Storage //implemented in eset.cpp
	{
	private:
		typedef std::set<Element *,bool(*)(Element *,Element *)> element_set_type;
		bool ordered;
	public:
		class iterator : public element_set_type::iterator
		{
		public:
			iterator() {}
			iterator(const element_set_type::iterator & other ) : element_set_type::iterator(other) { }
			iterator(const iterator & other ) : element_set_type::iterator(other) { }
			iterator & operator =(iterator const & other) { element_set_type::iterator::operator=(static_cast<element_set_type::iterator const &>(other)); return *this; }
			Element & operator *() { return *element_set_type::iterator::operator *(); }
			Element * operator->() { return element_set_type::iterator::operator *(); }
		};
		class reverse_iterator : public element_set_type::reverse_iterator
		{
		public:
			reverse_iterator() {};
			reverse_iterator(const element_set_type::reverse_iterator & other ) : element_set_type::reverse_iterator(other) { }
			reverse_iterator(const reverse_iterator & other ) : element_set_type::reverse_iterator(other) { }
			reverse_iterator & operator =(reverse_iterator const & other) { element_set_type::reverse_iterator::operator=(static_cast<element_set_type::reverse_iterator const &>(other)); return *this; }
			Element & operator *() { return *element_set_type::reverse_iterator::operator *(); }
			Element * operator->() { return element_set_type::reverse_iterator::operator *(); }
		};
		ElementSet(Mesh *m,  bool ordered);
		ElementSet(bool ordered = false);
		ElementSet(const ElementSet & other);
		ElementSet(Mesh *m, INMOST_DATA_ENUM_TYPE lid,const ElementSet & other);
		ElementSet & operator =(ElementSet const & other);
		~ElementSet();
		std::pair< ElementSet::iterator, bool > Insert(const Element * e);
		template<class InputIterator>
		void Insert(InputIterator first, InputIterator last) {isInputForwardIterators<Element *, InputIterator>(); eset.insert(first,last);}
Kirill Terekhov's avatar
Kirill Terekhov committed
511
		void Insert(const ElementSet & e);
Kirill Terekhov's avatar
Kirill Terekhov committed
512
513
514
515
516
517
518
519
520
521
522
523
		void Insert(std::vector<Element *> e);
		void Insert(array<Element *> e);
		bool Erase(Element * e);
		void Erase(iterator e);
		void Intersection(ElementSet other);
		void Union(ElementSet other);
		void Difference(ElementSet other);
		iterator find(Element * e);
		iterator begin();
		iterator end();
		reverse_iterator rbegin();
		reverse_iterator rend();
Kirill Terekhov's avatar
Kirill Terekhov committed
524
		INMOST_DATA_ENUM_TYPE size() const;
Kirill Terekhov's avatar
Kirill Terekhov committed
525
526
		void clear();
		bool empty() const;
Kirill Terekhov's avatar
Kirill Terekhov committed
527
528
		void SetElementsMarker(MarkerType marker);
		void RemElementsMarker(MarkerType marker);
Kirill Terekhov's avatar
Kirill Terekhov committed
529
530
531
532
533
534
535
536
537
		bool isOrdered(){return ordered;}
	private:
		element_set_type eset;
	};
	
	
	template <typename AdjacentType>
	class adjacent
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
538
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
539
		//typedef typename std::vector<Element *> container_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
540
		//typedef container_type::size_t enumerator;
Kirill Terekhov's avatar
Kirill Terekhov committed
541
		typedef dynarray<Element *,64> container_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
542
		typedef container_type::enumerator enumerator;
Kirill Terekhov's avatar
Kirill Terekhov committed
543
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
544
		container_type container;
Kirill Terekhov's avatar
Kirill Terekhov committed
545
546
547
548
		adjacent(const container_type & other) : container(other) {}
		container_type & get_container() {return container;};
	public:
		adjacent() {}
Kirill Terekhov's avatar
Kirill Terekhov committed
549
		adjacent(enumerator n) : container(n) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
		template<class InputIterator>
		adjacent(InputIterator first, InputIterator last) :container(first,last) {isInputForwardIterators<Element *, InputIterator>();}
		adjacent(const adjacent & other ) {container = other.container;}
		~adjacent() {container.clear();}
		adjacent & operator=(adjacent const & other) {container = other.container; return *this;}
		class iterator : public container_type::iterator
		{
		public:
			iterator(const container_type::iterator & other ) : container_type::iterator(other) { }
			iterator(const iterator & other ) : container_type::iterator(other) { }
			iterator & operator =(iterator const & other) { container_type::iterator::operator=(static_cast<container_type::iterator const &>(other)); return *this; }
			AdjacentType & operator *() { return static_cast<AdjacentType &>(*(container_type::iterator::operator *())); }
			AdjacentType * operator->() { return static_cast<AdjacentType *>(container_type::iterator::operator *()); }
		};
		class reverse_iterator : public container_type::reverse_iterator
		{
		public:
			reverse_iterator(const container_type::reverse_iterator & other ) : container_type::reverse_iterator(other) { }
			reverse_iterator(const reverse_iterator & other ) : container_type::reverse_iterator(other) { }
			reverse_iterator & operator =(reverse_iterator const & other) { container_type::reverse_iterator::operator=(static_cast<container_type::reverse_iterator const &>(other)); return *this; }
			AdjacentType & operator *() { return static_cast<AdjacentType &>(*container_type::reverse_iterator::operator *()); }
			AdjacentType * operator->() { return static_cast<AdjacentType *>(container_type::reverse_iterator::operator *()); }
		};
		template<class InputIterator>
		void insert(iterator pos,InputIterator pbeg, InputIterator pend) {container.insert(pos,pbeg,pend);}
		iterator erase(iterator pos) {return container.erase(pos);}
Kirill Terekhov's avatar
Kirill Terekhov committed
576
577
578
579
580
581
582
583
		__INLINE iterator begin() { return iterator(container.begin()); }
		__INLINE iterator end() { return iterator(container.end()); }
		__INLINE reverse_iterator rbegin() { return reverse_iterator(container.rbegin()); }
		__INLINE reverse_iterator rend() { return reverse_iterator(container.rend()); }
		__INLINE AdjacentType & operator [] (enumerator n) {return static_cast<AdjacentType &>(*(container[n]));}
		__INLINE AdjacentType & front() { return static_cast<AdjacentType &>(*(container.front())); }
		__INLINE AdjacentType & back() { return static_cast<AdjacentType &>(*(container.back())); }
		__INLINE AdjacentType & at(enumerator n) { return static_cast<AdjacentType &>(*(container.at(n))); }
Kirill Terekhov's avatar
Kirill Terekhov committed
584
		void swap(adjacent<AdjacentType> & other) {container.swap(other.container);}
Kirill Terekhov's avatar
Kirill Terekhov committed
585
586
587
588
		__INLINE void push_back(Element & x) {container.push_back(&x);}
		__INLINE void push_back(Element * x) {container.push_back(x);}
		void resize(enumerator n) {container.resize(n);}
		__INLINE bool empty() {return container.empty();}
Kirill Terekhov's avatar
Kirill Terekhov committed
589
		void clear() {container.clear();}
Kirill Terekhov's avatar
Kirill Terekhov committed
590
591
592
		void reserve(enumerator n) {container.reserve(n);}
		__INLINE enumerator size() const { return container.size(); }
		__INLINE AdjacentType ** data() {return reinterpret_cast<AdjacentType **>(container.data());}
Kirill Terekhov's avatar
Kirill Terekhov committed
593
594
595
596
597
598
599
600
601
		void unite(const adjacent<AdjacentType>  & other);
		void substract(const adjacent<AdjacentType>  & other);
		void intersect(const adjacent<AdjacentType>  & other);
	};
	
			
	class Element : public Storage //implemented in element.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
		typedef INMOST_DATA_BULK_TYPE GeometricType;
		static const GeometricType Unset        = 0;
		static const GeometricType Vertex       = 1;
		static const GeometricType Line         = 2;
		static const GeometricType MultiLine    = 3;
		static const GeometricType Tri          = 4;
		static const GeometricType Quad         = 5;
		static const GeometricType Polygon      = 6;
		static const GeometricType MultiPolygon = 7;
		static const GeometricType Tet          = 8;
		static const GeometricType Hex          = 9;
		static const GeometricType Prism        = 10;
		static const GeometricType Pyramid      = 11;
		static const GeometricType Polyhedron   = 12;
		static const GeometricType Set          = 100;
		//enum GeometricType {Unset,Vertex,Line,MultiLine,Tri,Quad,Polygon,MultiPolygon,Tet,Hex,Prism,Pyramid,Polyhedron,Set};
Kirill Terekhov's avatar
Kirill Terekhov committed
618
619
		static const char *       GeometricTypeName(GeometricType t);
		static unsigned int       GetGeometricDimension(GeometricType m_type);
Kirill Terekhov's avatar
Kirill Terekhov committed
620
621
622
623
624
625
626
		typedef INMOST_DATA_BULK_TYPE Status;
		static const Status Owned  = 1;
		static const Status Shared = 2;
		static const Status Ghost  = 4;
		static const Status Any    = 0;
		static const char * StatusName(Status s);
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
627
		typedef inner_reference_array            adj_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
628
629
630
631
		typedef adj_type::iterator               adj_iterator;
		typedef adj_type::const_iterator         const_adj_iterator;
		typedef adj_type::reverse_iterator       adj_reverse_iterator;
		typedef adj_type::const_reverse_iterator const_adj_reverse_iterator;
Kirill Terekhov's avatar
Kirill Terekhov committed
632
	protected:
Kirill Terekhov's avatar
Kirill Terekhov committed
633
634
635
636
637
638
639
640
641
642
643
644
645
646
#if defined(NEW_CONNECTIONS)
		adj_type &              HighConn();
		adj_type &              LowConn ();
		adj_type const &        HighConn() const;
		adj_type const &        LowConn () const;
#else
		adj_type            high_conn_;
		adj_type            low_conn_;
		__INLINE adj_type &              HighConn() {return high_conn_;}
		__INLINE adj_type &              LowConn () {return low_conn_;}
		__INLINE adj_type const &        HighConn() const {return high_conn_;}
		__INLINE adj_type const &        LowConn () const {return low_conn_;}
#endif
		void                    SetGeometricType(GeometricType t);
Kirill Terekhov's avatar
Kirill Terekhov committed
647
648
649
650
651
		friend class Mesh;
		friend class Node;
		friend class Edge;
		friend class Face;
		friend class Cell;
Kirill Terekhov's avatar
Kirill Terekhov committed
652
653
		friend int              CompareElementsUnique(Element * a,Element * b);
		friend int              CompareElementsCentroid(Element * a,Element * b);
Kirill Terekhov's avatar
Kirill Terekhov committed
654
655
656
657
658
659
660
	protected:
		Element(Mesh * m, ElementType _etype);
		Element(const Element & other);            // don't use this
		Element(Mesh * m, INMOST_DATA_ENUM_TYPE lid,const Element & other);  // use this instead
		Element & operator =(Element const & other);
	public:
		virtual ~Element();
Kirill Terekhov's avatar
Kirill Terekhov committed
661
662
		INMOST_DATA_ENUM_TYPE   nbAdjElements(ElementType _etype) const;
		adjacent<Element>       getAdjElements(ElementType _etype) const;  //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
663
664
665
666
667
668
669
		INMOST_DATA_ENUM_TYPE   nbAdjElements(ElementType _etype, MarkerType mask, bool invert_mask = false) const;
		adjacent<Element>       getAdjElements(ElementType _etype, MarkerType mask, bool invert_mask = false) const;  //unordered
		adjacent<Element>       BridgeAdjacencies(ElementType Bridge, ElementType Dest, MarkerType mask = 0, bool invert_mask = false);
		adjacent<Node>          BridgeAdjacencies2Node(ElementType Bridge, MarkerType mask = 0, bool invert_mask = false);
		adjacent<Edge>          BridgeAdjacencies2Edge(ElementType Bridge, MarkerType mask = 0, bool invert_mask = false);
		adjacent<Face>          BridgeAdjacencies2Face(ElementType Bridge, MarkerType mask = 0, bool invert_mask = false);
		adjacent<Cell>          BridgeAdjacencies2Cell(ElementType Bridge, MarkerType mask = 0, bool invert_mask = false);
Kirill Terekhov's avatar
Kirill Terekhov committed
670
671
672
673
		virtual adjacent<Node>  getNodes(); //unordered
		virtual adjacent<Edge>  getEdges(); //unordered
		virtual adjacent<Face>  getFaces(); //unordered
		virtual adjacent<Cell>  getCells(); //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
674
675
676
677
		virtual adjacent<Node>  getNodes(MarkerType mask,bool invert_mask = false); //unordered
		virtual adjacent<Edge>  getEdges(MarkerType mask,bool invert_mask = false); //unordered
		virtual adjacent<Face>  getFaces(MarkerType mask,bool invert_mask = false); //unordered
		virtual adjacent<Cell>  getCells(MarkerType mask,bool invert_mask = false); //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
678
679
680
681
		Node *                  getAsNode(); //does dynamic conversation for you, if not a node returns NULL
		Edge *                  getAsEdge(); //does dynamic conversation for you, if not an edge returns NULL
		Face *                  getAsFace(); //does dynamic conversation for you, if not a face returns NULL
		Cell *                  getAsCell(); //does dynamic conversation for you, if not a cell returns NULL
Kirill Terekhov's avatar
Kirill Terekhov committed
682
683
		GeometricType           GetGeometricType() const;
		unsigned int            GetElementDimension() const {return GetGeometricDimension(GetGeometricType());}
Kirill Terekhov's avatar
Kirill Terekhov committed
684
685
686
687
688
		Status                  GetStatus();
		void                    SetStatus(Status status);
		Storage::integer &      GlobalID();
		bool                    CheckElementConnectivity();
		static bool             CheckConnectivity(Mesh * m);
Kirill Terekhov's avatar
Kirill Terekhov committed
689
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
690
691
692
693
694
695
696
		void                    CastRay(Storage::real * pos, Storage::real * dir, dynarray< std::pair<Element *, Storage::real> , 16 > & hits);
		void                    ComputeGeometricType();
		void                    Centroid(Storage::real * cnt);
		void                    Barycenter(Storage::real * cnt);
		Storage::real           Mean(Storage::real (*func)(Storage::real* x,Storage::real t),Storage::real time);
		bool                    Boundary();
		bool                    Planarity(); // check that all nodes lay on one plane
Kirill Terekhov's avatar
Kirill Terekhov committed
697
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
698
699
700
701
702
703
		bool                    Hide(); // if true then element was hidden, works only inside BeginModification and EndModification, on EndModification all Hidden elements are deleted
		bool                    Show(); // if true then element was recovered
		bool                    Delete(); // if true then element was deleted, otherwise it was hidden
		bool                    Hidden();
		bool                    New();
		void                    Disconnect(bool delete_upper_adjacent); //disconnect all elements, delete upper dependent
Kirill Terekhov's avatar
Kirill Terekhov committed
704
705
706
707
708
709
710
711
712
		/// Disconnects nodes from this edge, edges from this face, faces from this cell, cannot disconnect cells from this node;
		/// Disconnects edges from this node, faces from this edge, cells from this face, cannot disconnect nodes from this cell;
		/// Updates geometric data and cell nodes automatically.
		void                    Disconnect(Element ** adjacent, INMOST_DATA_ENUM_TYPE num);
		/// Connects lower adjacencies to current element, 
		/// geometric data and cell nodes are updated automatically.
		/// TODO:
		///		1. asserts in this function should be replaced by Topography checks;
		///		2. this function should be used for creation of elements instead of current implementation.
Kirill Terekhov's avatar
Kirill Terekhov committed
713
		///     3. should correctly account for order of edges (may be implemented through CheckEdgeOrder, FixEdgeOrder)
Kirill Terekhov's avatar
Kirill Terekhov committed
714
715
716
		void                    Connect(Element ** adjacent, INMOST_DATA_ENUM_TYPE num); 
		/// Update geometric data for element, calls RecomputeGeometricData from Mesh.
		void                    UpdateGeometricData(); 
Kirill Terekhov's avatar
Kirill Terekhov committed
717
718
719
720
721
722
723
724
725
726
727
728
	};
	
	class Node : public Element //implemented in node.cpp
	{
	private:
		Node(Mesh * m);
		Node(const Node & other);
		Node(Mesh * m, INMOST_DATA_ENUM_TYPE lid, const Node & other);
		Node & operator =(Node const & other);
	public:
		~Node();
		
Kirill Terekhov's avatar
Kirill Terekhov committed
729
730
731
732
		adjacent<Edge>              getEdges(); //unordered
		adjacent<Face>              getFaces(); //unordered
		adjacent<Cell>              getCells(); //unordered

Kirill Terekhov's avatar
Kirill Terekhov committed
733
734
735
		adjacent<Edge>              getEdges(MarkerType mask,bool invert_mask = false); //unordered
		adjacent<Face>              getFaces(MarkerType mask,bool invert_mask = false); //unordered
		adjacent<Cell>              getCells(MarkerType mask,bool invert_mask = false); //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
736
737

		Storage::real_array         Coords(); 
Kirill Terekhov's avatar
Kirill Terekhov committed
738
739
740
741
742
743
744
745
746
747
748
749
750
		friend class Mesh;
	};
	
	class Edge : public Element //implemented in edge.cpp
	{
	private:
		Edge(Mesh * m);
		Edge(const Edge & other);
		Edge(Mesh * m, INMOST_DATA_ENUM_TYPE lid, const Edge & other);
		Edge & operator =(Edge const & other);
	public:
		~Edge();
		
Kirill Terekhov's avatar
Kirill Terekhov committed
751
752
753
754
		adjacent<Node>              getNodes(); //ordered
		adjacent<Face>              getFaces(); //unordered
		adjacent<Cell>              getCells(); //unordered

Kirill Terekhov's avatar
Kirill Terekhov committed
755
756
757
		adjacent<Node>              getNodes(MarkerType mask,bool invert_mask = false); //ordered
		adjacent<Face>              getFaces(MarkerType mask,bool invert_mask = false); //unordered
		adjacent<Cell>              getCells(MarkerType mask,bool invert_mask = false); //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
758
759
760

		Node *                      getBeg() const;
		Node *                      getEnd() const;
Kirill Terekhov's avatar
Kirill Terekhov committed
761
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
762
763
764
765
		static Edge *               UniteEdges    (Edge ** edges, INMOST_DATA_ENUM_TYPE nedges, MarkerType del_protect);
		static bool                 TestUniteEdges(Edge ** edges, INMOST_DATA_ENUM_TYPE nedges, MarkerType del_protect);
		static dynarray<Edge *,32>  SplitEdge     (Edge * e, Node ** nodes, INMOST_DATA_ENUM_TYPE nnodes, MarkerType del_protect); //provide ordered array of nodes, that lay between former nodes of the edge
		static bool                 TestSplitEdge (Edge * e, Node ** nodes, INMOST_DATA_ENUM_TYPE nnodes, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
766
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
767
		Storage::real               Length();
Kirill Terekhov's avatar
Kirill Terekhov committed
768
769
770
771
772
773
774
775
776
777
778
779
780
		friend class Mesh;
	};
	
	class Face : public Element //implemented in face.cpp
	{
	private:
		Face(Mesh * m);
		Face(const Face & other);
		Face(Mesh * m, INMOST_DATA_ENUM_TYPE lid, const Face & other);
		Face & operator =(Face const & other);
	public:
		~Face();
		
Kirill Terekhov's avatar
Kirill Terekhov committed
781
782
783
784
		adjacent<Node>              getNodes(); //ordered
		adjacent<Edge>              getEdges(); //ordered
		adjacent<Cell>              getCells(); //unordered

Kirill Terekhov's avatar
Kirill Terekhov committed
785
786
787
		adjacent<Node>              getNodes(MarkerType mask,bool invert_mask = false); //ordered
		adjacent<Edge>              getEdges(MarkerType mask,bool invert_mask = false); //ordered
		adjacent<Cell>              getCells(MarkerType mask,bool invert_mask = false); //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
788
789
790
791
792
793
794
795
796
797
798

		//this is for 2d case when the face is represented by segment
		Node *                      getBeg() const;
		Node *                      getEnd() const;

		Cell *                      BackCell() const;
		Cell *                      FrontCell() const;
		bool                        FaceOrientedOutside(Cell * c) const;
		void                        ReorderEdges();
		bool                        CheckEdgeOrder(); //not implemented// returns true if edges of face form an ordered closed loop
		bool                        FixEdgeOrder(); //not implemented// returns true if edges were successfully reordered to form a closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
799
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
800
801
802
803
		static Face *               UniteFaces    (Face ** faces, INMOST_DATA_ENUM_TYPE nfaces, MarkerType del_protect);
		static bool                 TestUniteFaces(Face ** faces, INMOST_DATA_ENUM_TYPE nfaces,  MarkerType del_protect);
		static dynarray<Face *,32>  SplitFace     (Face * face, Edge ** edges, INMOST_DATA_ENUM_TYPE nedges, MarkerType del_protect); //provide all edges that lay inside face
		static bool                 TestSplitFace (Face * face, Edge ** edges, INMOST_DATA_ENUM_TYPE nedges, MarkerType del_protect);	
Kirill Terekhov's avatar
Kirill Terekhov committed
804
		void                        SwapCells(); //swap back cell and front cell
Kirill Terekhov's avatar
Kirill Terekhov committed
805
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
806
807
808
809
810
811
812
813
		Storage::real               Area();
		void                        Normal(Storage::real * nrm);
		void                        UnitNormal(Storage::real * nrm);
		void                        OrientedNormal(Cell * c, Storage::real * nrm);
		void                        OrientedUnitNormal(Cell * c, Storage::real * nrm);
		bool                        FixNormalOrientation();  //returns true if orientation was corrected, otherwise returns false
		bool                        CheckNormalOrientation(); //returns true if orientation is correct, otherwise returns false
		bool                        Closure(); // test integrity of polygon
Kirill Terekhov's avatar
Kirill Terekhov committed
814
815
816
817
818
819
820
821
822
823
824
825
826
		friend class Mesh;
	};
	
	class Cell : public Element //implemented in cell.cpp
	{
	private:
		Cell(Mesh * m);
		Cell(const Cell & other);
		Cell(Mesh * m, INMOST_DATA_ENUM_TYPE lid, const Cell & other);
		Cell & operator =(Cell const & other);
	public:
		~Cell();
		
Kirill Terekhov's avatar
Kirill Terekhov committed
827
828
829
830
		adjacent<Node>              getNodes(); //ordered (for known geometric types only)
		adjacent<Edge>              getEdges(); //unordered
		adjacent<Face>              getFaces(); //ordered (keeps order it was created in)

Kirill Terekhov's avatar
Kirill Terekhov committed
831
832
833
		adjacent<Node>              getNodes(MarkerType mask,bool invert_mask = false); //ordered (for known geometric types only)
		adjacent<Edge>              getEdges(MarkerType mask,bool invert_mask = false); //unordered
		adjacent<Face>              getFaces(MarkerType mask,bool invert_mask = false); //ordered (keeps order it was created in)
Kirill Terekhov's avatar
Kirill Terekhov committed
834
835
		
		
Kirill Terekhov's avatar
Kirill Terekhov committed
836
837
		bool                        CheckEdgeOrder(); //not implemented//2D only, returns true if edges of face form an ordered closed loop
		bool                        FixEdgeOrder(); //not implemented//2D only, returns true if edges were successfully reordered to form a closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
838
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
839
840
841
842
		static Cell *               UniteCells    (Cell ** cells, INMOST_DATA_ENUM_TYPE ncells, MarkerType del_protect);
		static bool                 TestUniteCells(Cell ** cells, INMOST_DATA_ENUM_TYPE ncells, MarkerType del_protect);
		static dynarray<Cell *,32>  SplitCell     (Cell * cell, Face ** faces, INMOST_DATA_ENUM_TYPE nfaces, MarkerType del_protect); //provide all faces, that lay inside cell
		static bool                 TestSplitCell (Cell * cell, Face ** faces, INMOST_DATA_ENUM_TYPE nfaces, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
843
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
844
845
846
847
848
		Cell *                      Neighbour(Face * f);
		adjacent<Cell>              NeighbouringCells(); // get all cells that share any face with current
		bool                        Inside(Storage::real * point); //is point inside cell, check for 2d case
		Storage::real               Volume();
		bool                        Closure(); // test integrity of cell
Kirill Terekhov's avatar
Kirill Terekhov committed
849
850
851
852
853
854
855
		friend class Mesh;
	};
	
	class Mesh : public TagManager, public Storage //implemented in mesh.cpp
	{
	public:
		enum MeshState {Serial, Parallel};
Kirill Terekhov's avatar
Kirill Terekhov committed
856
857
858
859
860
		typedef chunk_array<Node *,15>                 nodes_container;
		typedef chunk_array<Edge *,15>                 edges_container;
		typedef chunk_array<Face *,15>                 faces_container;
		typedef chunk_array<Cell *,15>                 cells_container;
		typedef chunk_array<ElementSet *,7>            sets_container;
Kirill Terekhov's avatar
Kirill Terekhov committed
861
		typedef chunk_array<INMOST_DATA_ENUM_TYPE,7>     empty_container;
Kirill Terekhov's avatar
Kirill Terekhov committed
862
863
864
865
866
867
868

		//typedef std::vector<Node *>                 nodes_container;
		//typedef std::vector<Edge *>                 edges_container;
		//typedef std::vector<Face *>                 faces_container;
		//typedef std::vector<Cell *>                 cells_container;
		//typedef std::vector<ElementSet *>           sets_container;
		//typedef std::vector<INMOST_DATA_ENUM_TYPE>  empty_container;
Kirill Terekhov's avatar
Kirill Terekhov committed
869
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
		Storage::real                               epsilon;
		cells_container                             cells;
		empty_container                             empty_cells;
		faces_container                             faces;
		empty_container                             empty_faces;
		edges_container                             edges;
		empty_container                             empty_edges;
		nodes_container                             nodes;
		empty_container                             empty_nodes;
		sets_container                              sets;
		empty_container                             empty_sets;
		Tag                                         tag_global_id;
		Tag                                         tag_coords;
		Tag                                         tag_low_conn;
		Tag                                         tag_high_conn;
		Tag                                         tag_markers;
		Tag                                         tag_geom_type;
		MeshState                                   m_state;
		unsigned int                                dim;
		Element *                                   last_created_element;
Kirill Terekhov's avatar
Kirill Terekhov committed
890
891
892
893
894
	public:
		Mesh();
		Mesh(const Mesh & other);
		~Mesh();
		Mesh & operator =(Mesh const & other);
Kirill Terekhov's avatar
Kirill Terekhov committed
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
		MarkerType                   CreateMarker();
		void                         ReleaseMarker(MarkerType n);
		__INLINE void                SetEpsilon(Storage::real e) {epsilon = e;}
		__INLINE Storage::real       GetEpsilon() const {return epsilon;}
		void                         SetDimensions(unsigned int dim);
		__INLINE unsigned int        GetDimensions() const {return dim;}
		__INLINE MeshState           GetMeshState() const {return m_state;}
		__INLINE const Tag &         GlobalIDTag() const {return tag_global_id;}
		__INLINE const Tag &         CoordsTag() const {return tag_coords;}
		__INLINE const Tag &         LowConnTag() const {return tag_low_conn;}
		__INLINE const Tag &         HighConnTag() const {return tag_high_conn;}
		__INLINE const Tag &         MarkersTag() const {return tag_markers;}
		__INLINE const Tag &         GeomTypeTag() const {return tag_geom_type;}
		Tag                          CreateTag(std::string name, DataType dtype, ElementType etype,ElementType sparse, INMOST_DATA_ENUM_TYPE size = ENUMUNDEF);
		Tag                          DeleteTag(Tag tag, ElementType mask = NODE | EDGE | FACE | CELL | ESET | MESH);
		Node *                       CreateNode(Storage::real * coords);
		std::pair<Edge *,bool>       CreateEdge(Node ** e_nodes, INMOST_DATA_ENUM_TYPE num_e_nodes);
		std::pair<Face *,bool>       CreateFace(Edge ** f_edges, INMOST_DATA_ENUM_TYPE num_f_edges);
		std::pair<Face *,bool>       CreateFace(Node ** f_nodes, INMOST_DATA_ENUM_TYPE num_f_nodes);
		std::pair<Cell *,bool>       CreateCell(Face ** c_faces, INMOST_DATA_ENUM_TYPE num_c_faces, 
												Node ** suggest_nodes_order = NULL, INMOST_DATA_ENUM_TYPE numsuggest_nodes_order = 0);
		std::pair<Cell *,bool>       CreateCell(Node ** c_f_nodes, const INMOST_DATA_ENUM_TYPE * c_f_numnodes, INMOST_DATA_ENUM_TYPE num_c_faces, 
												Node ** suggest_nodes_order = NULL, INMOST_DATA_ENUM_TYPE numsuggest_nodes_order = 0);
		std::pair<Cell *,bool>       CreateCell(Node ** c_nodes, const INMOST_DATA_ENUM_TYPE * c_f_nodeinds, const INMOST_DATA_ENUM_TYPE * c_f_numnodes, INMOST_DATA_ENUM_TYPE num_c_faces, 
												Node ** suggest_nodes_order = NULL, INMOST_DATA_ENUM_TYPE numsuggest_nodes_order = 0);
		Element *                    ElementByLocalID(ElementType etype, INMOST_DATA_INTEGER_TYPE lid)
Kirill Terekhov's avatar
Kirill Terekhov committed
921
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
922
			assert(OneType(etype));
Kirill Terekhov's avatar
Kirill Terekhov committed
923
924
925
926
927
928
929
930
931
			switch(etype)
			{
			case NODE: return nodes[lid];
			case EDGE: return edges[lid];
			case FACE: return faces[lid];
			case CELL: return cells[lid];
			}
			return NULL;
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
932
933
934
935
936
		Node *                       NodeByLocalID(INMOST_DATA_INTEGER_TYPE lid) { return nodes[lid]; }
		Edge *                       EdgeByLocalID(INMOST_DATA_INTEGER_TYPE lid) { return edges[lid]; }
		Face *                       FaceByLocalID(INMOST_DATA_INTEGER_TYPE lid) {return  faces[lid];}
		Cell *                       CellByLocalID(INMOST_DATA_INTEGER_TYPE lid) { return cells[lid]; }
		ElementSet *                 EsetByLocalID(INMOST_DATA_INTEGER_TYPE lid) { return sets[lid]; }
Kirill Terekhov's avatar
Kirill Terekhov committed
937

Kirill Terekhov's avatar
Kirill Terekhov committed
938
939
940
941
942
943
		INMOST_DATA_INTEGER_TYPE     MaxLocalIDNODE() const {return static_cast<INMOST_DATA_INTEGER_TYPE>(nodes.size());}
		INMOST_DATA_INTEGER_TYPE     MaxLocalIDEDGE() const {return static_cast<INMOST_DATA_INTEGER_TYPE>(edges.size());}
		INMOST_DATA_INTEGER_TYPE     MaxLocalIDFACE() const {return static_cast<INMOST_DATA_INTEGER_TYPE>(faces.size());}
		INMOST_DATA_INTEGER_TYPE     MaxLocalIDCELL() const {return static_cast<INMOST_DATA_INTEGER_TYPE>(cells.size());}
		INMOST_DATA_INTEGER_TYPE     MaxLocalIDESET() const {return static_cast<INMOST_DATA_INTEGER_TYPE>(sets.size());}
		INMOST_DATA_INTEGER_TYPE     MaxLocalID(ElementType etype) const
Kirill Terekhov's avatar
Kirill Terekhov committed
944
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
945
			assert(OneType(etype));
Kirill Terekhov's avatar
Kirill Terekhov committed
946
947
948
949
950
951
952
953
954
955
956
			switch(etype)
			{
			case NODE: return static_cast<INMOST_DATA_INTEGER_TYPE>(nodes.size());
			case EDGE: return static_cast<INMOST_DATA_INTEGER_TYPE>(edges.size());
			case FACE: return static_cast<INMOST_DATA_INTEGER_TYPE>(faces.size());
			case CELL: return static_cast<INMOST_DATA_INTEGER_TYPE>(cells.size());
			}
			return 0;
		}
		ElementSet * CreateSet();
		ElementSet * CreateOrderedSet();
Kirill Terekhov's avatar
Kirill Terekhov committed
957
		Element * FindSharedAdjacency(Element * const * arr, unsigned num) ;
Kirill Terekhov's avatar
Kirill Terekhov committed
958
		void ReorderEmpty(ElementType reordertypes);
Kirill Terekhov's avatar
Kirill Terekhov committed
959
		//Bug inside: sort would not work on chunk_array, because it is not contiguous in memory
Kirill Terekhov's avatar
Kirill Terekhov committed
960
961
		void ReorderApply(Tag index, ElementType mask);
		bool isOriginal(Element * e); //don't know now what this function was for, should detect the copy-constructed element, but copy-construction is prohibited
Kirill Terekhov's avatar
Kirill Terekhov committed
962
		INMOST_DATA_ENUM_TYPE GetArrayCapacity(ElementType etype); //This function is needed by TagManager, may be made private in future
Kirill Terekhov's avatar
Kirill Terekhov committed
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
		void RestoreCellNodes(Cell * c, dynarray<Node *,64> & ret);
	private:
		void MoveStorage(Storage * e, int new_local_id);
		void UntieElement(Storage * e);
		void TieElement(Storage * e);
		//implemented in mesh_parallel.cpp
	public:
		enum Action {AGhost, AMigrate};
		enum Prepare {UnknownSize, UnknownSource};
		typedef std::pair<int, std::vector<INMOST_DATA_BULK_TYPE> > proc_buffer_type;
		typedef std::vector< proc_buffer_type > exch_buffer_type;
		class exchange_data
		{
		public:
			std::vector<INMOST_MPI_Request> send_reqs, recv_reqs;
			exch_buffer_type send_buffers, recv_buffers;
		};
	private:
		ElementType have_global_id;
		INMOST_DATA_BIG_ENUM_TYPE parallel_mesh_unique_id;
		INMOST_MPI_Comm comm;
		Tag tag_shared, tag_owner, tag_processors, tag_layers, tag_sendto, tag_bridge, tag_redistribute;
		void ComputeSharedProcs();
		std::map< int , std::vector<Element *> > ComputeSharedSkinSet(ElementType bridge);
		void PackTagData(Tag tag, std::vector< std::vector<Element *> > & elements, ElementType mask, std::vector<INMOST_DATA_BULK_TYPE> & buffer);
		void UnpackTagData(Tag tag, std::vector< std::vector<Element *> > & elements, ElementType mask, std::vector<INMOST_DATA_BULK_TYPE> & buffer, int & position, void (*Operation)(Tag tag, Element * element,INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size));
		void PackElementsData(std::vector<Element *> & input, std::vector<INMOST_DATA_BULK_TYPE> & buffer, int destination, std::vector<std::string> tag_list);
		void UnpackElementsData(std::vector<Element *> & output, std::vector<INMOST_DATA_BULK_TYPE> & buffer, int source, std::vector<std::string> & tag_list);
		class elements_by_type
		{
		private:
			std::vector< std::vector<Element *> > container;
		public:
			elements_by_type() :container(4) {}
			elements_by_type(const elements_by_type & other){container = other.container;}
			~elements_by_type(){}
			std::vector<Element *> & operator [](int i){ return container[i]; }
			std::vector<std::vector<Element *> >::iterator begin(){ return container.begin(); }
			std::vector<std::vector<Element *> >::iterator end() { return container.end(); }
			std::vector<std::vector<Element *> > & get_container() {return container;}
		};
		typedef std::map<int, elements_by_type > parallel_storage;
#if defined(USE_PARALLEL_STORAGE)
		parallel_storage shared_elements, ghost_elements;
#endif
#if defined(USE_PARALLEL_WRITE_TIME)
		int num_exchanges;
		std::fstream out_time;
		int tab;
		int func_id;
#endif
#if defined(USE_MPI2)
		INMOST_MPI_Win window;
		unsigned * shared_space;
#endif
		int parallel_strategy, parallel_file_strategy;
		void PrepareReceiveInner(Prepare todo, exch_buffer_type & send_bufs, exch_buffer_type & recv_bufs);
		void ExchangeDataInnerBegin(std::vector<Tag> tag, parallel_storage & from, parallel_storage & to, ElementType mask, exchange_data & storage);
		void ExchangeDataInnerEnd(std::vector<Tag> tag, parallel_storage & from, parallel_storage & to, ElementType mask, void (*Operation)(Tag tag,Element * element,INMOST_DATA_BULK_TYPE * recv_data,INMOST_DATA_ENUM_TYPE recv_size), exchange_data & storage);
		void ExchangeBuffersInner(exch_buffer_type & send_bufs, exch_buffer_type & recv_bufs,std::vector<INMOST_MPI_Request> & send_reqs, std::vector<INMOST_MPI_Request> & recv_reqs);
		std::vector<int> FinishRequests(std::vector<INMOST_MPI_Request> & recv_reqs);
		void GatherParallelStorage(parallel_storage & ghost, parallel_storage & shared, ElementType mask);
		class Random // random generator to provide tag for communication
		{
		private: unsigned int n,a,c,m;
		public:
			Random(unsigned int seed = 50);
			Random(const Random & other);
			unsigned int Number();
		} randomizer;
	public:
#if defined(USE_PARALLEL_WRITE_TIME)	
		//this part is needed to test parallel performance
		void Enter();
		void Exit();
		int & GetFuncID() {return func_id;}
		std::fstream & GetStream();
		std::fstream & WriteTab(std::fstream & f);
#endif
		static void Initialize(int * argc, char *** argv);
		static void Finalize();
		void SetParallelStrategy(int strategy){if( strategy < 0 || strategy > 3 ) throw NotImplemented; parallel_strategy = strategy;}
		int GetParallelStrategy() {return parallel_strategy;}
		void SetParallelFileStrategy(int strategy){if( strategy < 0 || strategy > 1 ) throw NotImplemented; parallel_file_strategy = strategy;}
		int GetParallelFileStrategy() {return parallel_file_strategy;}
		int GetProcessorRank();
		int GetProcessorsNumber();
		INMOST_MPI_Comm GetCommunicator();
		void SetCommunicator(INMOST_MPI_Comm _comm);
		void ResolveShared();
		void RemoveGhost();
		void RemoveGhostElements(std::vector<Element *> ghost);
		void AssignGlobalID(ElementType mask);
		//exchange for tag of type DATA_REFERENCE is not implemented!
		void ExchangeData(Tag tag, ElementType mask);
		void ExchangeDataBegin(Tag tags, ElementType mask, exchange_data & storage);
		void ExchangeDataEnd(Tag tags, ElementType mask, exchange_data & storage);
		void ExchangeData(std::vector<Tag> tags, ElementType mask);
		void ExchangeDataBegin(std::vector<Tag> tags, ElementType mask, exchange_data & storage);
		void ExchangeDataEnd(std::vector<Tag> tags, ElementType mask, exchange_data & storage);
		void ReduceData(Tag tag, ElementType mask, void (*Operation)(Tag tag, Element * element, INMOST_DATA_BULK_TYPE * recv_data, INMOST_DATA_ENUM_TYPE recv_size) );
		void ReduceDataBegin(Tag tag, ElementType mask, exchange_data & storage);
		void ReduceDataEnd(Tag tag, ElementType mask, void (*Operation)(Tag tag, Element * element, INMOST_DATA_BULK_TYPE * recv_data, INMOST_DATA_ENUM_TYPE recv_size), exchange_data & storage );
		void ReduceData(std::vector<Tag> tags, ElementType mask, void (*Operation)(Tag tag, Element * element, INMOST_DATA_BULK_TYPE * recv_data, INMOST_DATA_ENUM_TYPE recv_size) );
		void ReduceDataBegin(std::vector<Tag> tags, ElementType mask, exchange_data & storage);
		void ReduceDataEnd(std::vector<Tag> tags, ElementType mask, void (*Operation)(Tag tag, Element * element, INMOST_DATA_BULK_TYPE * recv_data, INMOST_DATA_ENUM_TYPE recv_size), exchange_data & storage );
		void ExchangeMarked(enum Action action = AGhost);
		void ExchangeGhost(Storage::integer layers, ElementType bridge);
		void Redistribute();
		Storage::integer Enumerate(ElementType mask, Tag num_tag, Storage::integer start = 0);
		Storage::integer Enumerate(std::vector<Element *> elements, Tag num_tag, Storage::integer start = 0);
		Storage::integer EnumerateSet(ElementSet * set, Tag num_tag, Storage::integer start = 0);
		Storage::integer TotalNumberOf(ElementType mask);
		Storage::real Integrate(Storage::real input);
		Storage::integer Integrate(Storage::integer input);
		Storage::integer ExclusiveSum(Storage::integer input); 
		Storage::real Integrate(Tag t,ElementType mask);
1080
1081
		Storage::real AggregateMax(Storage::real input);
		Storage::integer AggregateMax(Storage::integer input);
Kirill Terekhov's avatar
Kirill Terekhov committed
1082
1083
1084
1085
1086
1087
1088
1089
		void RecomputeParallelStorage(ElementType mask);
		__INLINE const Tag SendtoTag() const {return tag_sendto;}
		__INLINE const Tag SharedTag() const {return tag_shared;}
		__INLINE const Tag OwnerTag() const {return tag_owner;}
		__INLINE const Tag LayersTag() const {return tag_layers;}
		__INLINE const Tag ProcessorsTag() const {return tag_processors;}
		__INLINE Tag RedistributeTag() {return CreateTag("TEMPORARY_NEW_OWNER",DATA_INTEGER,CELL,NONE,1);}
		
Kirill Terekhov's avatar
Kirill Terekhov committed
1090
		ElementType SynchronizeElementType(ElementType etype);
Kirill Terekhov's avatar
Kirill Terekhov committed
1091
		void SynchronizeMarker(MarkerType marker, ElementType mask, SyncBitOp op);
Kirill Terekhov's avatar
Kirill Terekhov committed
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
		
		//for debug
		void                 BeginSequentialCode();
		void                   EndSequentialCode();
		//iterator.cpp::::::::::::::::::::::::::::::::::::::::::::::::::
	public:
		class base_iterator;
		class iteratorElement;
		class iteratorSet;
		class iteratorCell;
		class iteratorFace;
		class iteratorEdge;
		class iteratorNode;
		
Kirill Terekhov's avatar
Kirill Terekhov committed
1106
1107
1108
1109
1110
		__INLINE INMOST_DATA_ENUM_TYPE NumberOfCells()   {return static_cast<INMOST_DATA_ENUM_TYPE>(cells.size() - empty_cells.size());}
		__INLINE INMOST_DATA_ENUM_TYPE NumberOfFaces()   { return static_cast<INMOST_DATA_ENUM_TYPE>(faces.size() - empty_faces.size()); }
		__INLINE INMOST_DATA_ENUM_TYPE NumberOfEdges()   { return static_cast<INMOST_DATA_ENUM_TYPE>(edges.size() - empty_edges.size()); }
		__INLINE INMOST_DATA_ENUM_TYPE NumberOfNodes()   { return static_cast<INMOST_DATA_ENUM_TYPE>(nodes.size() - empty_nodes.size()); }
		__INLINE INMOST_DATA_ENUM_TYPE NumberOfSets()    { return static_cast<INMOST_DATA_ENUM_TYPE>(sets.size() - empty_sets.size()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
1111
1112
		__INLINE INMOST_DATA_ENUM_TYPE NumberOfElements(){ return NumberOfCells() + NumberOfFaces() + NumberOfEdges() + NumberOfNodes(); }
		__INLINE INMOST_DATA_ENUM_TYPE NumberOfAll()     { return NumberOfSets() + NumberOfElements(); }
Kirill Terekhov's avatar
Kirill Terekhov committed
1113
		INMOST_DATA_ENUM_TYPE NumberOf(ElementType t);
Kirill Terekhov's avatar
Kirill Terekhov committed
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
		base_iterator Begin(ElementType Types);
		base_iterator End();
		iteratorElement BeginElement(ElementType Types);
		iteratorElement EndElement();
		iteratorSet  BeginSet();
		iteratorSet  EndSet();
		iteratorCell BeginCell();
		iteratorCell EndCell();
		iteratorFace BeginFace();
		iteratorFace EndFace();
		iteratorEdge BeginEdge();
		iteratorEdge EndEdge();
		iteratorNode BeginNode();
		iteratorNode EndNode();
		class base_iterator
		{
		protected:
			typedef int itenum;
			Mesh * m;
			itenum Number;
			ElementType CurrentType;
			ElementType types;
			base_iterator(ElementType Types, Mesh * mesh, bool last);
			base_iterator(Mesh * mesh) {m = mesh; CurrentType = NONE; types = NONE; Number = -1;}
		public:
			typedef Storage * pointer;
			typedef Storage & reference;
			typedef Storage value_type;
			typedef ptrdiff_t difference_type;
			typedef std::bidirectional_iterator_tag iterator_category;
			base_iterator() {Number = -1; CurrentType = NONE; m = NULL; types = NONE;}
			base_iterator(const base_iterator & other) {m = other.m; Number = other.Number;	types = other.types; CurrentType = other.CurrentType;}
			virtual ~base_iterator() {}
			base_iterator & operator ++();
			__INLINE base_iterator operator ++(int) {Mesh::base_iterator ret(*this); operator++(); return ret;}
			base_iterator & operator --();
			__INLINE base_iterator operator --(int) {Mesh::base_iterator ret(*this); operator--(); return ret;}
			__INLINE virtual reference operator *()
			{
				switch(CurrentType)
				{
					case NODE: return static_cast<Storage &>(*m->nodes[Number]); break;
					case EDGE: return static_cast<Storage &>(*m->edges[Number]); break;
					case FACE: return static_cast<Storage &>(*m->faces[Number]); break;
					case CELL: return static_cast<Storage &>(*m->cells[Number]); break;
					case ESET: return static_cast<Storage &>(*m->sets[Number]); break;
				}
				return *m;
			}
			__INLINE virtual pointer operator ->()
			{
				switch(CurrentType)
				{
					case NODE: return static_cast<Storage *>(m->nodes[Number]); break;
					case EDGE: return static_cast<Storage *>(m->edges[Number]); break;
					case FACE: return static_cast<Storage *>(m->faces[Number]); break;
					case CELL: return static_cast<Storage *>(m->cells[Number]); break;
					case ESET: return static_cast<Storage *>(m->sets[Number]); break;
				}
				return NULL;
			}
			__INLINE base_iterator & operator =(base_iterator const & other) {m = other.m; Number = other.Number; types = other.types; CurrentType = other.CurrentType; return *this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
1176
1177
1178
1179
1180
1181
			__INLINE bool operator ==(const base_iterator & other) const { assert( m == other.m ); if( Number == other.Number && CurrentType == other.CurrentType ) return true; return false;}
			__INLINE bool operator !=(const base_iterator & other) const { assert( m == other.m ); if( Number != other.Number || CurrentType != other.CurrentType ) return true; return false;}
			__INLINE bool operator <(const base_iterator & other) const { assert( m == other.m ); if( (CurrentType < other.CurrentType) || (CurrentType == other.CurrentType && Number < other.Number) ) return true; return false;}
			__INLINE bool operator >(const base_iterator & other) const { assert( m == other.m ); if( (CurrentType > other.CurrentType) || (CurrentType == other.CurrentType && Number > other.Number) ) return true; return false;}
			__INLINE bool operator <=(const base_iterator & other) const {assert( m != other.m ); if( (CurrentType < other.CurrentType) || (CurrentType == other.CurrentType && Number <= other.Number) ) return true; return false;}
			__INLINE bool operator >=(const base_iterator & other) const {assert( m == other.m ); if( (CurrentType > other.CurrentType) || (CurrentType == other.CurrentType && Number >= other.Number) ) return true; return false;}
Kirill Terekhov's avatar
Kirill Terekhov committed
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
			void Print();
			friend base_iterator Mesh::Begin(ElementType Types);
			friend base_iterator Mesh::End();
		};
		class iteratorElement : public base_iterator
		{
		private:
			iteratorElement(const base_iterator & other) :base_iterator(other) {}
		public:
			__INLINE Element & operator  *() {return static_cast<Element &>(Mesh::base_iterator::operator *());}
			__INLINE Element * operator ->() {return static_cast<Element *>(Mesh::base_iterator::operator ->());}
			friend iteratorElement Mesh::BeginElement(ElementType Types);
			friend iteratorElement Mesh::EndElement();
		};
		class iteratorSet : public base_iterator
		{
		private:
			iteratorSet(const base_iterator & other) :base_iterator(other) {}
		public:
			__INLINE ElementSet & operator  *() {return *m->sets[Number];}
			__INLINE ElementSet * operator ->() {return m->sets[Number];}
			friend iteratorSet Mesh::BeginSet();
			friend iteratorSet Mesh::EndSet();
		};
		class iteratorCell : public base_iterator
		{
		private:
			iteratorCell(const base_iterator & other) :base_iterator(other) {}
		public:
			__INLINE Cell & operator  *() {return *m->cells[Number];}
			__INLINE Cell * operator ->() {return  m->cells[Number];}
			friend iteratorCell Mesh::BeginCell();
			friend iteratorCell Mesh::EndCell();
		};
		class iteratorFace : public base_iterator
		{
		private:
			iteratorFace(const base_iterator & other) :base_iterator(other) {}
		public:
			__INLINE Face & operator  *() {return *m->faces[Number];}
			__INLINE Face * operator ->() {return  m->faces[Number];}
			friend iteratorFace Mesh::BeginFace();
			friend iteratorFace Mesh::EndFace();
		};
		class iteratorEdge : public base_iterator
		{
		private:
			iteratorEdge(const base_iterator & other) :base_iterator(other) {}
		public:
			__INLINE Edge & operator  *() {return *m->edges[Number];} 
			__INLINE Edge * operator ->() {return  m->edges[Number];}
			friend iteratorEdge Mesh::BeginEdge();
			friend iteratorEdge Mesh::EndEdge();
		};
		class iteratorNode : public base_iterator
		{
		private:
			iteratorNode(const base_iterator & other) :base_iterator(other) {}
		public:
			__INLINE Node & operator  *() {return *m->nodes[Number];}
			__INLINE Node * operator ->() {return  m->nodes[Number];}
			friend iteratorNode Mesh::BeginNode();
			friend iteratorNode Mesh::EndNode();
		};
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
1247
		int          GetTypeEnd(ElementType t);
Kirill Terekhov's avatar
Kirill Terekhov committed
1248
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
1249
		std::vector< std::pair<std::string, std::string> > file_options;
Kirill Terekhov's avatar
Kirill Terekhov committed
1250
1251
1252
1253
1254
		//implemented in io.hpp
		io_converter<INMOST_DATA_INTEGER_TYPE,INMOST_DATA_REAL_TYPE> iconv;
		io_converter<INMOST_DATA_ENUM_TYPE   ,INMOST_DATA_REAL_TYPE> uconv;
	private:
		//implemented in mesh_file.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
1255
1256
1257
1258
1259
		void         WriteTag  (std::ostream & output, Tag X);
		Tag          ReadTag   (std::istream & input);
		void         ReadData  (std::istream & input, Tag t, Storage * e,std::vector<Node *> & new_nodes,std::vector<Edge *> & new_edges,std::vector<Face *> & new_faces,std::vector<Cell *> & new_cells);
		void         WriteData (std::ostream & output, Tag t, Storage & e);
		void         WriteElementSet(std::ostream & output, ElementSet * X);
Kirill Terekhov's avatar
Kirill Terekhov committed
1260
		ElementSet * ReadElementSet(std::istream & input,std::vector<Node *> & new_nodes,std::vector<Edge *> & new_edges,std::vector<Face *> & new_faces,std::vector<Cell *> & new_cells);
Kirill Terekhov's avatar
Kirill Terekhov committed
1261
1262
1263
1264
1265
1266
1267
1268
		Node *       ReadNode(std::istream & input, std::vector<Node *> & old_nodes);
		void         WriteNode(std::ostream & output,Node * X);
		Edge *       ReadEdge(std::istream & input, std::vector<Node *> & nodes);
		void         WriteEdge(std::ostream & output,Edge * X);
		Face *       ReadFace(std::istream & input, std::vector<Edge *> & edges);
		void         WriteFace(std::ostream & output,Face * X);
		Cell *       ReadCell(std::istream & input,std::vector<Face *> & faces, std::vector<Node *> & nodes);
		void         WriteCell(std::ostream & output,Cell * X);
Kirill Terekhov's avatar
Kirill Terekhov committed
1269
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
1270
1271
		/// Current availible file options:
		/// "VTK_GRID_DIMS" - set "2" for two-dimensional vtk grids, "3" for three-dimensional vtk grids
Kirill Terekhov's avatar
Kirill Terekhov committed
1272
1273
1274
		/// "VERBOSITY"     - set "2" for progress messages, "1" for reports, "0" for silence
		void         SetFileOption(std::string,std::string);
		std::string  GetFileOption(std::string);
Kirill Terekhov's avatar
Kirill Terekhov committed
1275
		void         Load(std::string File); // .vtk, .pvtk, .pmf
Kirill Terekhov's avatar
Kirill Terekhov committed
1276
1277
1278
		/// Remeber: .pmf stores all references to elements. If reference are broken due to mesh modification,
		///          saving or loading such a mesh may lead to seagfault. To automatically maintain correct
		///          references modify mesh using BeginModification, ApplyModification, EndModification
Kirill Terekhov's avatar
Kirill Terekhov committed
1279
1280
		void         Save(std::string File); // .vtk, .pvtk, .gmv, .pmf
		bool         isParallelFileFormat(std::string File);
Kirill Terekhov's avatar
Kirill Terekhov committed
1281
1282
1283
1284
1285
	public:
		
		//implemented in geometry.cpp
	private:
		void RestoreGeometricTags();
Kirill Terekhov's avatar
Kirill Terekhov committed
1286
1287
1288
1289
1290
1291
1292
1293
		Tag          measure_tag;
		Tag          centroid_tag;
		Tag          normal_tag;
		Tag          barycenter_tag;
		Tag          dot_tag;
		bool         remember[5][3];
		bool         HideGeometricData(GeometricData type, ElementType mask) {return remember[type][ElementNum(mask)-1] = false;}
		bool         ShowGeometricData(GeometricData type, ElementType mask) {return remember[type][ElementNum(mask)-1] = true;}
Kirill Terekhov's avatar
Kirill Terekhov committed
1294
		//~ MarkerType reorient;
Kirill Terekhov's avatar
Kirill Terekhov committed
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
	public:
		typedef std::map<GeometricData, ElementType> GeomParam;
		// types for MEASURE:     EDGE | FACE | CELL   (length, area, volume)
		// types for CENTROID:    EDGE | FACE | CELL
		// types for BARYCENTER:  EDGE | FACE | CELL
		// types for NORMAL:      FACE | CELL          (may precompute normal for cells in 2d case)
		// types for ORIENTATION: FACE
		void PrepareGeometricData(GeomParam table);
		void RemoveGeometricData(GeomParam table);
		bool HaveGeometricData(GeometricData type, ElementType mask) const {return remember[type][ElementNum(mask)-1];} // requests to only one geometric and element type allowed
		void GetGeometricData(Element * e, GeometricData type, Storage::real * ret);
		void RecomputeGeometricData(Element * e); // Update all stored geometric data, runs automatically on element creation
		Tag GetGeometricTag(GeometricData type) {switch(type) {case MEASURE: return measure_tag; case CENTROID: return centroid_tag; case BARYCENTER: return barycenter_tag; case NORMAL: return normal_tag;} return Tag();}
		
		
		bool TestClosure(Element ** elements, unsigned num);

		std::vector<Face *> GatherBoundaryFaces();
		std::vector<Face *> GatherInteriorFaces();
		Storage::integer CountBoundaryFaces();
		Storage::integer CountInteriorFaces();
		Element::GeometricType ComputeGeometricType(ElementType element_type, Element ** lower_adjacent, INMOST_DATA_ENUM_TYPE lower_adjacent_size);
		//implemented in modify.cpp
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
1319
		MarkerType hide_element, new_element;
Kirill Terekhov's avatar
Kirill Terekhov committed
1320
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
1321
		bool isMeshModified() const {return new_element != 0;} //In case mesh is modified, on element creation TieElements will always place elements to the end
Kirill Terekhov's avatar
Kirill Terekhov committed
1322
1323
		MarkerType HideMarker() const {return hide_element;}
		MarkerType NewMarker() const {return new_element;}
Kirill Terekhov's avatar
Kirill Terekhov committed
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
		void SwapModification(); // swap hidden and new elements, so that old mesh is recovered
		void BeginModification();  //allow elements to be hidden
		void ApplyModification();  //modify DATA_REFERENCE tags so that links to hidden elements are converted to NULL and removed from sets
		void ResolveModification(); //resolve parallel state of newly created elements, restore ghost layers; not implemented
		void EndModification();    //delete hidden elements
		
		
		//Elements and data is only moved, copy implementation from ReorderEmpty
		//~ void BeginMoveModification();
		//~ void EndMoveModification();
		
Kirill Terekhov's avatar
Kirill Terekhov committed
1335
1336
		static INMOST_DATA_ENUM_TYPE getNext(Element * const * arr, INMOST_DATA_ENUM_TYPE size, INMOST_DATA_ENUM_TYPE k, MarkerType marker);
		static INMOST_DATA_ENUM_TYPE Count(Element * const * arr, INMOST_DATA_ENUM_TYPE size, MarkerType marker);
Kirill Terekhov's avatar
Kirill Terekhov committed
1337
1338
		//implemented in mesh.cpp
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
1339
1340
1341
1342
1343
		Tag            tag_topologyerror;
		TopologyCheck  checkset;
		TopologyCheck  errorset;
		TopologyCheck  BeginTopologyCheck(ElementType etype, Element ** adj, INMOST_DATA_ENUM_TYPE num); //check provided elements
		TopologyCheck  EndTopologyCheck(Element * e); //check created element
Kirill Terekhov's avatar
Kirill Terekhov committed
1344
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
1345
1346
1347
1348
		Tag            TopologyErrorTag() const {return tag_topologyerror;}
		TopologyCheck  GetTopologyCheck(TopologyCheck mask = ENUMUNDEF) const {return checkset & mask;}
		void           SetTopologyCheck(TopologyCheck mask) {checkset = checkset | mask;}
		void           RemTopologyCheck(TopologyCheck mask) {checkset = checkset & ~mask;}
Kirill Terekhov's avatar
Kirill Terekhov committed
1349

Kirill Terekhov's avatar
Kirill Terekhov committed
1350
1351
1352
		void           SetTopologyError(TopologyCheck mask) {errorset = errorset | mask;}
		TopologyCheck  GetTopologyError(TopologyCheck mask = ENUMUNDEF) const {return errorset & mask;}
		void           ClearTopologyError(TopologyCheck mask = ENUMUNDEF) {errorset = errorset & ~mask;}
Kirill Terekhov's avatar
Kirill Terekhov committed
1353
1354
1355

		friend class Storage;
	};
Kirill Terekhov's avatar
Kirill Terekhov committed
1356

Kirill Terekhov's avatar
Kirill Terekhov committed
1357
1358
1359
1360
1361
1362
	template <typename AdjacentType>