inmost_mesh.h 204 KB
Newer Older
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
1

Kirill Terekhov's avatar
Kirill Terekhov committed
2 3 4 5 6 7 8 9 10 11 12 13
#ifndef INMOST_MESH_H_INCLUDED
#define INMOST_MESH_H_INCLUDED

#include "inmost_common.h"

#if defined(USE_MESH)

#define __NDT 3
#define __NET 6

namespace INMOST
{
Kirill Terekhov's avatar
Kirill Terekhov committed
14 15


Kirill Terekhov's avatar
Kirill Terekhov committed
16 17 18 19 20 21 22 23
	class Mesh;
	class Storage;
	class Element;
	class TagManager;
	class Node;
	class Edge;
	class Face;
	class Cell;
Kirill Terekhov's avatar
Kirill Terekhov committed
24
	class ElementSet;
Kirill Terekhov's avatar
Kirill Terekhov committed
25 26 27 28 29 30 31 32 33

	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;
Kirill Terekhov's avatar
Kirill Terekhov committed
34 35 36 37 38

	typedef INMOST_DATA_ENUM_TYPE HandleType;
	static const INMOST_DATA_ENUM_TYPE handle_etype_bits  = 3;
	static const INMOST_DATA_ENUM_TYPE handle_etype_shift = sizeof(HandleType)*8-handle_etype_bits;
	static const INMOST_DATA_ENUM_TYPE handle_id_mask     = (1 << handle_etype_shift)-1;
Kirill Terekhov's avatar
Kirill Terekhov committed
39 40 41 42 43 44 45 46
	
	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
47
	typedef INMOST_DATA_BULK_TYPE SyncBitOp; //< This type is used for marker synchronization
Kirill Terekhov's avatar
Kirill Terekhov committed
48
	static const SyncBitOp SYNC_BIT_SET = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
49 50 51 52
	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
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
	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;
	typedef array<HandleType>               inner_reference_array;

	enum DataType
	{
		DATA_REAL      = 0, 
		DATA_INTEGER   = 1, 
		DATA_BULK      = 2,
		DATA_REFERENCE = 3
	};

	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_ENUM_TYPE MarkerMask   = static_cast<INMOST_DATA_BULK_TYPE>(-1); // bit mask to obtain marker mask within MarkerType
	static const INMOST_DATA_ENUM_TYPE MarkerShift  = sizeof(INMOST_DATA_BULK_TYPE)*8;    // sizeof(char) * bits_per_char
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
70
	__INLINE static MarkerType InvalidMarker() {return ENUMUNDEF;}
Kirill Terekhov's avatar
Kirill Terekhov committed
71 72 73 74 75 76 77


	static const INMOST_DATA_ENUM_TYPE chunk_bits_elems       = 13;
	static const INMOST_DATA_ENUM_TYPE chunk_bits_empty       = 8;
	static const INMOST_DATA_ENUM_TYPE chunk_bits_tags        = 6;
	static const INMOST_DATA_ENUM_TYPE chunk_bits_dense_array = 6;

Kirill Terekhov's avatar
Kirill Terekhov committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
	//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
Kirill Terekhov's avatar
Kirill Terekhov committed
95
	static const TopologyCheck ADJACENT_DUPLICATE     = 0x00008000; //done//produce error if provided array of elements for construction contain duplications
Kirill Terekhov's avatar
Kirill Terekhov committed
96
	static const TopologyCheck ADJACENT_HIDDEN        = 0x00010000; //done//hidden elements should not be used when new elements are created
Kirill Terekhov's avatar
Kirill Terekhov committed
97
	static const TopologyCheck ADJACENT_VALID         = 0x00020000; //done//check that all handles are valid
Kirill Terekhov's avatar
Kirill Terekhov committed
98 99 100 101 102
	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
Kirill Terekhov's avatar
Kirill Terekhov committed
103
	static const TopologyCheck FACE_EDGES_ORDER       = 0x00800000; //done//edges of the face should form one closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
104 105 106 107 108 109 110 111 112
	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
Fixes  
Kirill Terekhov committed
113
	static const TopologyCheck DEFAULT_CHECK          = THROW_EXCEPTION | DUPLICATE_EDGE | DUPLICATE_FACE | DUPLICATE_CELL | PRINT_NOTIFY;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
114 115 116 117 118 119 120 121 122 123
	const char *                             TopologyCheckNotifyString(TopologyCheck c); //mesh.cpp
	const char *                             DataTypeName         (DataType t); //tag.cpp
	__INLINE bool                            OneType              (ElementType t) {return t > 0 && (t & (t-1)) == 0;}
	__INLINE ElementType                     FirstElementType     () {return NODE;}
	__INLINE ElementType                     LastElementType      () {return MESH << 1;}
	__INLINE ElementType                     NextElementType      (ElementType etype) {return etype << 1;}
	__INLINE ElementType                     PrevElementType      (ElementType etype) {return etype >> 1;}
	__INLINE ElementType                     ElementTypeFromDim   (INMOST_DATA_INTEGER_TYPE dim) {return 1 << dim;}
	const char *                             ElementTypeName      (ElementType t); //mesh.cpp
	__INLINE INMOST_DATA_INTEGER_TYPE        ElementNum           (ElementType t)
Kirill Terekhov's avatar
Kirill Terekhov committed
124 125
	{
		unsigned int v = static_cast<unsigned int>(t);  // 32-bit value to find the log2 of 
Kirill Terekhov's avatar
Kirill Terekhov committed
126 127
		//static const unsigned int b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
		static const unsigned int b[] = {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0};
Kirill Terekhov's avatar
Kirill Terekhov committed
128
		register unsigned int r = (v & b[0]) != 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
129 130
		//r |= ((v & b[4]) != 0) << 4;
		//r |= ((v & b[3]) != 0) << 3;
Kirill Terekhov's avatar
Kirill Terekhov committed
131 132
		r |= ((v & b[2]) != 0) << 2;
		r |= ((v & b[1]) != 0) << 1;
Kirill Terekhov's avatar
Kirill Terekhov committed
133
		return static_cast<INMOST_DATA_INTEGER_TYPE>(r);
Kirill Terekhov's avatar
Kirill Terekhov committed
134
	}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
135 136 137 138 139
	__INLINE HandleType                      InvalidHandle        () {return 0;}
	__INLINE INMOST_DATA_INTEGER_TYPE        GetHandleID          (HandleType h) {return (h & handle_id_mask)-1;}
	__INLINE INMOST_DATA_INTEGER_TYPE        GetHandleElementNum  (HandleType h) {return h >> handle_etype_shift;}
	__INLINE ElementType                     GetHandleElementType (HandleType h) {return 1 << GetHandleElementNum(h);}
	__INLINE HandleType                      ComposeHandle        (ElementType etype, INMOST_DATA_INTEGER_TYPE ID) {return ID == -1 ? InvalidHandle() : ((ElementNum(etype) << handle_etype_shift) + (1+ID));}
140
	__INLINE HandleType                      ComposeHandleNum     (INMOST_DATA_INTEGER_TYPE etypenum, INMOST_DATA_INTEGER_TYPE ID) {return ID == -1 ? InvalidHandle() : ((etypenum << handle_etype_shift) + (1+ID));}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
141
	__INLINE bool                            isValidHandle        (HandleType h) {return h != 0;}
Kirill Terekhov's avatar
Kirill Terekhov committed
142
	
Kirill Terekhov's avatar
Kirill Terekhov committed
143

Kirill Terekhov's avatar
Kirill Terekhov committed
144
	
Kirill Terekhov's avatar
Kirill Terekhov committed
145 146 147 148 149 150 151 152 153

	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
154 155 156 157
		INMOST_DATA_ENUM_TYPE  pos[__NET]; 
		DataType               dtype;                 
		std::string            tagname;            
		INMOST_MPI_Type        bulk_data_type;   
Kirill Terekhov's avatar
Kirill Terekhov committed
158
		INMOST_DATA_ENUM_TYPE  size, bytes_size;
Kirill Terekhov's avatar
Kirill Terekhov committed
159
		bool                   sparse[__NET];
Kirill Terekhov's avatar
Kirill Terekhov committed
160
		INMOST_DATA_ENUM_TYPE  record_size;
Kirill Terekhov's avatar
Kirill Terekhov committed
161
		Mesh *                 m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
162
		friend class Tag;
Kirill Terekhov's avatar
Kirill Terekhov committed
163
		friend class Storage; //for debug
Kirill Terekhov's avatar
Kirill Terekhov committed
164 165 166 167 168 169 170
	};

	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
171
		__INLINE INMOST_DATA_ENUM_TYPE  GetRecordSize() const {return mem->record_size;}
Kirill Terekhov's avatar
Kirill Terekhov committed
172 173 174 175
		__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;}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
176
		__INLINE INMOST_DATA_ENUM_TYPE  GetPositionByDim(INMOST_DATA_ENUM_TYPE typenum) const {return mem->pos[typenum];}
Kirill Terekhov's avatar
Kirill Terekhov committed
177 178 179 180 181 182 183 184 185
	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
186 187
		__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
188
		__INLINE INMOST_DATA_ENUM_TYPE  GetBytesSize() const {assert(mem!=NULL); return mem->bytes_size;}
Kirill Terekhov's avatar
Kirill Terekhov committed
189 190 191 192 193 194
		__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;}		
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
195 196
		__INLINE bool                   isSparseByDim(INMOST_DATA_INTEGER_TYPE typenum) const {assert(mem!=NULL); return mem->sparse[typenum];}
		__INLINE bool                   isDefinedByDim(INMOST_DATA_INTEGER_TYPE typenum) const {assert(mem!=NULL); return GetPositionByDim(typenum) != ENUMUNDEF;}
Kirill Terekhov's avatar
Kirill Terekhov committed
197
		__INLINE void                   SetBulkDataType(INMOST_MPI_Type type) {assert(mem!=NULL && mem->dtype == DATA_BULK ); mem->bulk_data_type = type;}
Kirill Terekhov's avatar
Kirill Terekhov committed
198 199 200 201 202 203 204 205 206
		friend class TagManager;
		friend class Storage;
		friend class Mesh;
	};
	
	class TagManager //implemented in tag.cpp
	{
	protected:
		TagManager();
Kirill Terekhov's avatar
Kirill Terekhov committed
207 208 209 210 211 212 213 214 215 216 217 218 219
		TagManager(const TagManager & other);
		TagManager & operator = (TagManager const & other);
		typedef chunk_array<INMOST_DATA_ENUM_TYPE,chunk_bits_empty>    empty_data;
		typedef chunk_array<Tag, chunk_bits_tags>                      tag_array_type;
		typedef chunk_bulk_array<chunk_bits_elems>                     dense_sub_type;
		typedef chunk_array<dense_sub_type,chunk_bits_dense_array>     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,chunk_bits_elems>         sparse_data_array_type;
		typedef chunk_array<INMOST_DATA_INTEGER_TYPE,chunk_bits_elems> back_links_type;
		//typedef std::vector<INMOST_DATA_INTEGER_TYPE>                  back_links_type;
	public:
		typedef tag_array_type::iterator                               iteratorTag;
Kirill Terekhov's avatar
Kirill Terekhov committed
220 221
	public:
		virtual ~TagManager();
Kirill Terekhov's avatar
Kirill Terekhov committed
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
		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); 
		bool                             ElementDefined     (Tag const & tag, ElementType etype) const;
	protected:
		void                             ReallocateData     (const Tag & t, INMOST_DATA_INTEGER_TYPE etypenum,INMOST_DATA_ENUM_TYPE new_size);
		void                             ReallocateData     (INMOST_DATA_INTEGER_TYPE etypenum, INMOST_DATA_ENUM_TYPE new_size);
		__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];}
		__INLINE dense_sub_type const &  GetDenseData       (int pos) const {return dense_data[pos];}
		__INLINE dense_sub_type &        GetDenseData       (int pos) {return dense_data[pos];}
		static void                      CopyData           (const Tag & t, void * adata, const void * bdata);
		static void                      DestroyVariableData(const Tag & t, void * adata);
Kirill Terekhov's avatar
Kirill Terekhov committed
237
	protected:
Kirill Terekhov's avatar
Kirill Terekhov committed
238 239
		typedef tag_array_type::iterator            tag_iterator;
		typedef tag_array_type::const_iterator      tag_const_iterator;
Kirill Terekhov's avatar
Kirill Terekhov committed
240
	protected:
Kirill Terekhov's avatar
Kirill Terekhov committed
241 242 243 244
		tag_array_type                              tags;
		empty_data                                  empty_dense_data;
		dense_data_array_type                       dense_data;
		sparse_data_array_type                      sparse_data[6];
Kirill Terekhov's avatar
Kirill Terekhov committed
245
		back_links_type                             back_links[6];
Kirill Terekhov's avatar
Kirill Terekhov committed
246 247
	};
	
248 249 250 251 252
	/// 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
253 254 255
	class Storage //implemented in storage.cpp
	{
	public:
256
		/// Storage type for representing real values.
Kirill Terekhov's avatar
Kirill Terekhov committed
257
		typedef INMOST_DATA_REAL_TYPE     real; 
258
		/// Storage type for representing integer values.
Kirill Terekhov's avatar
Kirill Terekhov committed
259
		typedef INMOST_DATA_INTEGER_TYPE  integer;
260
		/// Storage type for representing one byte of abstact data.
Kirill Terekhov's avatar
Kirill Terekhov committed
261
		typedef INMOST_DATA_BULK_TYPE     bulk;
Kirill Terekhov's avatar
Kirill Terekhov committed
262 263
		/// type for representing unsigned integer values.
		typedef INMOST_DATA_ENUM_TYPE     enumerator;
264
		/// Storage type for representing references to Element.
Kirill Terekhov's avatar
Kirill Terekhov committed
265
		typedef HandleType                reference;
266
		/// Storage type for representing arrays of real values.
Kirill Terekhov's avatar
Kirill Terekhov committed
267
		typedef shell<real>               real_array;
268
		/// Storage type for representing arrays of integer values.
Kirill Terekhov's avatar
Kirill Terekhov committed
269
		typedef shell<integer>            integer_array;
270
		/// Storage type for representing abstact data as a series of bytes.
Kirill Terekhov's avatar
Kirill Terekhov committed
271
		typedef shell<bulk>               bulk_array;
272
		/// Storage type for representing arrays of Element references.
Kirill Terekhov's avatar
Kirill Terekhov committed
273 274 275 276
		class reference_array : public shell<HandleType>
		{
			Mesh * m;
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
277
			reference_array() : m(NULL) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
278 279
			reference_array(Mesh * m, inner_reference_array & arr) : shell<reference>(arr), m(m) {} 
			reference_array(Mesh * m, reference * arr, size_type size) : shell<reference>(arr,size), m(m) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
280 281
			~reference_array() {}
			void push_back(const Storage & elem);
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
282 283
			void push_back(HandleType h) {shell<reference>::push_back(h);} //is it needed?
			Element operator[] (size_type n);
Kirill Terekhov's avatar
Kirill Terekhov committed
284 285 286 287 288
			Element operator[] (size_type n) const;
			class iterator : public shell<HandleType>::iterator
			{
				Mesh * m;
			public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
289 290 291
				iterator(Mesh * m, const shell<HandleType>::iterator & other) : shell<HandleType>::iterator(other), m(m) {}
				iterator(const iterator & other) : shell<HandleType>::iterator(other), m(other.m) {}
				iterator & operator =(iterator const & other) {m = other.m; shell<HandleType>::iterator::operator=(other); return *this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
292 293 294 295 296 297 298 299 300 301
				iterator & operator ++() {shell<HandleType>::iterator::operator++(); return *this;}
				iterator   operator ++(int) {iterator ret(*this); shell<HandleType>::iterator::operator++(); return ret;}
				iterator & operator --() {shell<HandleType>::iterator::operator--(); return *this;}
				iterator   operator --(int) {iterator ret(*this); shell<HandleType>::iterator::operator--(); return ret;}
				Element operator->();
			};
			class const_iterator : public shell<HandleType>::const_iterator
			{
				Mesh * m;
			public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
302 303 304
				const_iterator(Mesh * m, const shell<HandleType>::const_iterator & other) : shell<HandleType>::const_iterator(other) , m(m) {}
				const_iterator(const const_iterator & other) : shell<HandleType>::const_iterator(other), m(other.m) {}
				const_iterator & operator =(const_iterator const & other) {m = other.m; shell<HandleType>::const_iterator::operator=(other); return *this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
305 306 307 308 309 310 311 312 313 314
				const_iterator & operator ++() {shell<HandleType>::const_iterator::operator++(); return *this;}
				const_iterator   operator ++(int) {const_iterator ret(*this); shell<HandleType>::const_iterator::operator++(); return ret;}
				const_iterator & operator --() {shell<HandleType>::const_iterator::operator--(); return *this;}
				const_iterator   operator --(int) {const_iterator ret(*this); shell<HandleType>::const_iterator::operator--(); return ret;}
				Element operator->();
			};
			class reverse_iterator : public shell<HandleType>::reverse_iterator
			{
				Mesh * m;
			public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
315 316 317
				reverse_iterator(Mesh * m, const shell<HandleType>::reverse_iterator & other) : shell<HandleType>::reverse_iterator(other), m(m) {}
				reverse_iterator(const reverse_iterator & other) : shell<HandleType>::reverse_iterator(other), m(other.m)  {}
				reverse_iterator & operator =(reverse_iterator const & other) {m = other.m; shell<HandleType>::reverse_iterator::operator=(other); return *this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
318 319 320 321 322 323 324 325 326 327
				reverse_iterator & operator ++() {shell<HandleType>::reverse_iterator::operator++(); return *this;}
				reverse_iterator   operator ++(int) {reverse_iterator ret(*this); shell<HandleType>::reverse_iterator::operator++(); return ret;}
				reverse_iterator & operator --() {shell<HandleType>::reverse_iterator::operator--(); return *this;}
				reverse_iterator   operator --(int) {reverse_iterator ret(*this); shell<HandleType>::reverse_iterator::operator--(); return ret;}
				Element operator->();
			};
			class const_reverse_iterator : public shell<HandleType>::const_reverse_iterator
			{
				Mesh * m;
			public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
328 329 330
				const_reverse_iterator(Mesh * m, const shell<HandleType>::const_reverse_iterator & other) : shell<HandleType>::const_reverse_iterator(other), m(m) {}
				const_reverse_iterator(const const_reverse_iterator & other) : shell<HandleType>::const_reverse_iterator(other), m(other.m) {}
				const_reverse_iterator & operator =(const_reverse_iterator const & other) {m = other.m; shell<HandleType>::const_reverse_iterator::operator=(other); return *this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
331 332 333 334 335 336
				const_reverse_iterator & operator ++() {shell<HandleType>::const_reverse_iterator::operator++(); return *this;}
				const_reverse_iterator   operator ++(int) {const_reverse_iterator ret(*this); shell<HandleType>::const_reverse_iterator::operator++(); return ret;}
				const_reverse_iterator & operator --() {shell<HandleType>::const_reverse_iterator::operator--(); return *this;}
				const_reverse_iterator   operator --(int) {const_reverse_iterator ret(*this); shell<HandleType>::const_reverse_iterator::operator--(); return ret;}
				Element operator->();
			};
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
337 338 339 340 341 342 343 344
			iterator begin() {return iterator(m,shell<HandleType>::begin());}
			const_iterator begin() const {return const_iterator(m,shell<HandleType>::begin());}
			reverse_iterator rbegin() {return reverse_iterator(m,shell<HandleType>::rbegin());}
			const_reverse_iterator rbegin() const {return const_reverse_iterator(m,shell<HandleType>::rbegin());}
			iterator end() {return iterator(m,shell<HandleType>::end());}
			const_iterator end() const {return const_iterator(m,shell<HandleType>::end());}
			reverse_iterator rend() {return reverse_iterator(m,shell<HandleType>::rend());}
			const_reverse_iterator rend() const {return const_reverse_iterator(m,shell<HandleType>::rend());}
Kirill Terekhov's avatar
Kirill Terekhov committed
345
			void SetMeshLink(Mesh * new_m) {m = new_m;}
Kirill Terekhov's avatar
Kirill Terekhov committed
346 347 348 349
		};
		//typedef shell<reference>          reference_array;
	protected:
		HandleType                        handle;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
350
		HandleType *                      handle_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
351 352 353
	private:
		Mesh *                            m_link;
	public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
354 355 356 357 358 359 360
		Storage(const Storage & other) : handle(other.handle), handle_link(other.handle_link), m_link(other.m_link) {}
		Storage(Mesh * mesh, HandleType handle) : handle(handle), handle_link(NULL), m_link(mesh) {}
		/// This constructor allows for remote handle modification
		Storage(Mesh * mesh, HandleType * handle) : handle(*handle), handle_link(handle), m_link(mesh) {}
		/// If there is a link to handle provided (automatically by ElementArray and reference_array),
		/// then remote handle value will be modified
		Storage & operator =(Storage const & other); 
Kirill Terekhov's avatar
Kirill Terekhov committed
361 362 363 364 365 366
		bool      operator <(const Storage & other) const {return handle < other.handle;}
		bool      operator >(const Storage & other) const {return handle > other.handle;}
		bool      operator <=(const Storage & other) const {return handle <= other.handle;}
		bool      operator >=(const Storage & other) const {return handle >= other.handle;}
		bool      operator ==(const Storage & other) const {return handle == other.handle;} //m_link may be NULL if Invalidxxx is used
		bool      operator !=(const Storage & other) const {return handle != other.handle;} //m_link may be NULL if Invalidxxx is used
Kirill Terekhov's avatar
Kirill Terekhov committed
367 368 369 370
		Storage * operator ->() {return this;}
		const Storage * operator->() const {return this;}
		Storage & self() {return *this;}
		const Storage & self() const {return *this;}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
371
		virtual ~Storage() {}
Kirill Terekhov's avatar
Kirill Terekhov committed
372
	public:
373
		/// Retrieve real value associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
374
		real      &              Real            (const Tag & tag) const;
375
		/// Retrieve integer value associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
376
		integer   &              Integer         (const Tag & tag) const;
377
		/// Retrieve one byte of abstract data associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
378
		bulk      &              Bulk            (const Tag & tag) const;
379
		/// Retrieve Element reference associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
380
		reference &              Reference       (const Tag & tag) const;
381
		/// Retrieve array of real values associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
382
		real_array               RealArray       (const Tag & tag) const;
383
		/// Retrieve array of integer values associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
384
		integer_array            IntegerArray    (const Tag & tag) const;
385
		/// Retrieve abstract data associated with Tag as a series of bytes.
Kirill Terekhov's avatar
Kirill Terekhov committed
386
		bulk_array               BulkArray       (const Tag & tag) const;
387
		/// Retrieve array of Element references associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
388
		reference_array          ReferenceArray  (const Tag & tag) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
389 390
		
		//optimized data requests for dense data with fixed size
Kirill Terekhov's avatar
Kirill Terekhov committed
391 392 393 394 395 396 397 398
		real_array               RealArrayDF     (const Tag & tag) const;
		integer_array            IntegerArrayDF  (const Tag & tag) const;
		bulk_array               BulkArrayDF     (const Tag & tag) const;
		reference_array          ReferenceArrayDF(const Tag & tag) const;
		real      &              RealDF          (const Tag & tag) const;
		integer   &              IntegerDF       (const Tag & tag) const;
		bulk      &              BulkDF          (const Tag & tag) const;
		reference &              ReferenceDF     (const Tag & tag) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
399 400
		
		//optimized data requests for dense data with variable size
Kirill Terekhov's avatar
Kirill Terekhov committed
401 402 403 404 405 406 407 408
		real_array               RealArrayDV     (const Tag & tag) const;
		integer_array            IntegerArrayDV  (const Tag & tag) const;
		bulk_array               BulkArrayDV     (const Tag & tag) const;
		reference_array          ReferenceArrayDV(const Tag & tag) const;
		real      &              RealDV          (const Tag & tag) const;
		integer   &              IntegerDV       (const Tag & tag) const;
		bulk      &              BulkDV          (const Tag & tag) const;
		reference &              ReferenceDV     (const Tag & tag) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
409
		
410 411 412
		/// 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
413
		INMOST_DATA_ENUM_TYPE    GetDataSize     (const Tag & tag) const; //For DATA_BULK return number of bytes, otherwise return the length of array
414 415 416 417
		/// 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
418
		void                     SetDataSize     (const Tag & tag,INMOST_DATA_ENUM_TYPE new_size) const;
419 420 421 422 423 424 425 426 427
		/// 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
428 429 430 431 432 433 434
		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, const void * data) const;
		void                     DelData         (const Tag & tag) const;
		/// Deallocates space allocated for sparse data, frees variable array if necessary
		void                     DelSparseData   (const Tag & tag) const;
		/// Frees variable array or fills field with zeroes
		void                     DelDenseData    (const Tag & tag) const;
435
		/// Check if any data is associated with Tag.
Kirill Terekhov's avatar
Kirill Terekhov committed
436 437 438 439 440 441 442 443 444 445
		bool                     HaveData        (const Tag & tag) const;
		__INLINE ElementType     GetElementType  () const {return GetHandleElementType(handle);}
		__INLINE integer         GetElementNum   () const {return GetHandleElementNum(handle);}
		void                     SetMarker       (MarkerType n) const;
		bool                     GetMarker       (MarkerType n) const;
		void                     RemMarker       (MarkerType n) const;
		void                     ClearMarkerSpace() const;
		void                     GetMarkerSpace  (bulk copy[MarkerFields]) const;
		void                     SetMarkerSpace  (bulk source[MarkerFields]) const;
		__INLINE integer         LocalID         () const {return GetHandleID(handle);}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
446 447 448
		/// This number is guaranteed to be between 0 and Mesh::NumberOf(type of element)
		/// after Mesh::ReorderEmpty
		integer                  DataLocalID     () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
449 450 451
		bool                     isValid         () const;
		__INLINE Mesh *          GetMeshLink     () const {return m_link;}
		__INLINE HandleType      GetHandle       () const {return handle;}
Kirill Terekhov's avatar
Kirill Terekhov committed
452 453 454
		friend class Mesh;
	};
	
Kirill Terekhov's avatar
Kirill Terekhov committed
455 456
	template <typename StorageType>
	class ElementArray
Kirill Terekhov's avatar
Kirill Terekhov committed
457
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
458 459 460
	public:
		typedef dynarray<HandleType,64>      cont_t;
		typedef cont_t::size_type            size_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
461
	private:
Kirill Terekhov's avatar
Kirill Terekhov committed
462 463
		Mesh *                               m_link;
		cont_t                               container;
Kirill Terekhov's avatar
Kirill Terekhov committed
464
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
465 466 467 468 469 470 471 472 473 474 475 476
		const cont_t & GetContainer() {return container;}
		~ElementArray() {}
		ElementArray() : m_link(NULL) {}
		ElementArray(Mesh * m_link) : m_link(m_link) {}
		ElementArray(Mesh * m_link, size_type n, HandleType h = InvalidHandle())  : m_link(m_link), container(n,h) {}
		ElementArray(Mesh * m_link, const cont_t & c)  : m_link(m_link), container(c) {}
		ElementArray(const ElementArray & other) : m_link(other.m_link), container(other.container) {}
		template<class InputIterator>
		ElementArray(Mesh * m_link, InputIterator first, InputIterator last) :m_link(m_link), container(first,last) {}
		ElementArray & operator=(ElementArray const & other) {m_link = other.m_link; container = other.container; return *this;}
	public:
		class iterator : public cont_t::iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
477
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
478
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
479
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
480 481
			iterator(Mesh * m, const cont_t::iterator & other ) : cont_t::iterator(other) , m_link(m){assert(m_link);}
			iterator(const iterator & other ) : cont_t::iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
482 483 484 485 486 487
			iterator &    operator ++() {cont_t::iterator::operator++(); return *this;}
			iterator      operator ++(int) {iterator ret(*this); cont_t::iterator::operator++(); return ret;}
			iterator &    operator --() {cont_t::iterator::operator--(); return *this;}
			iterator      operator --(int) {iterator ret(*this); cont_t::iterator::operator--(); return ret;}
			iterator &    operator =(iterator const & other) {m_link = other.m_link; cont_t::iterator::operator=(static_cast<cont_t::iterator const &>(other)); return *this; }
			HandleType &  operator *() { return cont_t::iterator::operator *(); }
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
488
			StorageType   operator->() { return StorageType(m_link,&cont_t::iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
489
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
490
		class reverse_iterator : public cont_t::reverse_iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
491
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
492
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
493
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
494 495
			reverse_iterator(Mesh * m, const cont_t::reverse_iterator & other ) : cont_t::reverse_iterator(other), m_link(m) {assert(m_link);}
			reverse_iterator(const reverse_iterator & other ) : cont_t::reverse_iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
496 497 498 499 500 501
			reverse_iterator &    operator ++() {cont_t::reverse_iterator::operator++(); return *this;}
			reverse_iterator      operator ++(int) {reverse_iterator ret(*this); cont_t::reverse_iterator::operator++(); return ret;}
			reverse_iterator &    operator --() {cont_t::reverse_iterator::operator--(); return *this;}
			reverse_iterator      operator --(int) {reverse_iterator ret(*this); cont_t::reverse_iterator::operator--(); return ret;}
			reverse_iterator & operator =(reverse_iterator const & other) {m_link = other.m_link; cont_t::reverse_iterator::operator=(static_cast<cont_t::reverse_iterator const &>(other)); return *this; }
			HandleType &       operator *() { return cont_t::reverse_iterator::operator *(); }
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
502
			StorageType        operator->() { return StorageType(m_link,&cont_t::reverse_iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
503
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
504
		class const_iterator : public cont_t::const_iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
505
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
506
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
507
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
508 509
			const_iterator(Mesh * m, const cont_t::const_iterator & other ) : cont_t::const_iterator(other), m_link(m) {assert(m_link);}
			const_iterator(const const_iterator & other ) : cont_t::const_iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
510 511 512 513 514 515 516
			const_iterator &    operator ++() {cont_t::const_iterator::operator++(); return *this;}
			const_iterator      operator ++(int) {const_iterator ret(*this); cont_t::const_iterator::operator++(); return ret;}
			const_iterator &    operator --() {cont_t::const_iterator::operator--(); return *this;}
			const_iterator      operator --(int) {const_iterator ret(*this); cont_t::const_iterator::operator--(); return ret;}
			const_iterator &    operator =(const_iterator const & other) {m_link = other.m_link; cont_t::const_iterator::operator=(static_cast<cont_t::const_iterator const &>(other)); return *this; }
			const HandleType &  operator *() { return cont_t::const_iterator::operator *(); }
			StorageType         operator->() { return StorageType(m_link,cont_t::const_iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
517
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
518
		class const_reverse_iterator : public cont_t::const_reverse_iterator
Kirill Terekhov's avatar
Kirill Terekhov committed
519
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
520
			Mesh * m_link;
Kirill Terekhov's avatar
Kirill Terekhov committed
521
		public:
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
522 523
			const_reverse_iterator(Mesh * m, const cont_t::const_reverse_iterator & other) : cont_t::const_reverse_iterator(other), m_link(m) {assert(m_link);}
			const_reverse_iterator(const const_reverse_iterator & other ) : cont_t::const_reverse_iterator(other), m_link(other.m_link) {assert(m_link);}
Kirill Terekhov's avatar
Kirill Terekhov committed
524 525 526 527 528 529 530
			const_reverse_iterator &    operator ++() {cont_t::const_reverse_iterator::operator++(); return *this;}
			const_reverse_iterator      operator ++(int) {const_reverse_iterator ret(*this); cont_t::const_reverse_iterator::operator++(); return ret;}
			const_reverse_iterator &    operator --() {cont_t::const_reverse_iterator::operator--(); return *this;}
			const_reverse_iterator      operator --(int) {const_reverse_iterator ret(*this); cont_t::const_reverse_iterator::operator--(); return ret;}
			const_reverse_iterator & operator =(const_reverse_iterator const & other) { cont_t::const_reverse_iterator::operator=(static_cast<cont_t::const_reverse_iterator const &>(other)); return *this; }
			const HandleType &       operator *() { return cont_t::const_reverse_iterator::operator *(); }
			StorageType              operator->() { return StorageType(m_link,cont_t::const_reverse_iterator::operator *()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
531
		};
Kirill Terekhov's avatar
Kirill Terekhov committed
532
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
533
		template<class InputIterator>
Kirill Terekhov's avatar
Kirill Terekhov committed
534 535 536 537 538 539 540 541 542 543 544 545
		__INLINE void             insert      (iterator pos,InputIterator pbeg, InputIterator pend) {container.insert(static_cast<cont_t::iterator>(pos),pbeg,pend);}
		__INLINE iterator         erase       (iterator pos) {return iterator(m_link,container.erase(static_cast<cont_t::iterator>(pos)));}

		__INLINE iterator         begin       () { return iterator(m_link,container.begin()); }
		__INLINE iterator         end         () { return iterator(m_link,container.end()); }
		__INLINE reverse_iterator rbegin      () { return reverse_iterator(m_link,container.rbegin()); }
		__INLINE reverse_iterator rend        () { return reverse_iterator(m_link,container.rend()); }
		__INLINE const_iterator         begin () const { return const_iterator(m_link,container.begin()); }
		__INLINE const_iterator         end   () const { return const_iterator(m_link,container.end()); }
		__INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(m_link,container.rbegin()); }
		__INLINE const_reverse_iterator rend  () const { return const_reverse_iterator(m_link,container.rend()); }
		
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
546
		__INLINE StorageType      operator [] (size_type n) {assert(m_link); return StorageType(m_link,&container[n]);}
Kirill Terekhov's avatar
Kirill Terekhov committed
547
		__INLINE StorageType      operator [] (size_type n) const {assert(m_link); return StorageType(m_link,container[n]);}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
548
		__INLINE StorageType      front       () {assert(m_link); return StorageType(m_link,&container.front()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
549
		__INLINE StorageType      front       () const {assert(m_link); return StorageType(m_link,container.front()); }
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
550
		__INLINE StorageType      back        ()  {assert(m_link); return StorageType(m_link,&container.back()); }
Kirill Terekhov's avatar
Kirill Terekhov committed
551 552 553 554 555 556 557 558
		__INLINE StorageType      back        () const {assert(m_link); return StorageType(m_link,container.back()); }
		__INLINE HandleType       atfront     () const { return container.front(); }
		__INLINE HandleType       atback      () const { return container.back(); }
		__INLINE HandleType &     atfront     () { return container.front(); }
		__INLINE HandleType &     atback      () { return container.back(); }
		__INLINE HandleType &     at          (size_type n) { return container.at(n); }
		__INLINE HandleType       at          (size_type n) const { return container.at(n); }
		__INLINE void             swap        (ElementArray<StorageType> & other) {Mesh * t = m_link; m_link = other.m_link; other.m_link = t; container.swap(other.container);}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
559
		__INLINE void             push_back   (const Storage & x) {if( m_link == NULL ) m_link = x.GetMeshLink(); assert(x.GetMeshLink() == m_link); container.push_back(x.GetHandle());}
Kirill Terekhov's avatar
Kirill Terekhov committed
560
		//__INLINE void             push_back   (const StorageType & x) {container.push_back(x.GetHandle());}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
561
		__INLINE void             push_back   (HandleType x) {assert(m_link != NULL); container.push_back(x);}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
562
		__INLINE void             pop_back    () {container.pop_back();}
Kirill Terekhov's avatar
Kirill Terekhov committed
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
		__INLINE void             resize      (size_type n) {container.resize(n);}
		__INLINE bool             empty       () const {return container.empty();}
		__INLINE void             clear       () {container.clear();}
		__INLINE void             reserve     (size_type n) {container.reserve(n);}
		__INLINE size_type        size        () const {return container.size(); }
		__INLINE HandleType *     data        () {return container.data();}
		__INLINE const HandleType*data        () const {return container.data();}
		__INLINE Mesh *           GetMeshLink () const {assert(m_link); return m_link;}
		__INLINE void             SetMeshLink (Mesh * m) {m_link = m;}
		//implemented in mesh_array.cpp
		void                      Unite       (const HandleType * h, INMOST_DATA_ENUM_TYPE num);
		void                      Subtract    (const HandleType * h, INMOST_DATA_ENUM_TYPE num);
		void                      Intersect   (const HandleType * h, INMOST_DATA_ENUM_TYPE num);
		template<typename EType>
		void                      Unite       (const ElementArray<EType> & other) {Unite(other.data(),static_cast<INMOST_DATA_ENUM_TYPE>(other.size()));}
		template<typename EType>
		void                      Subtract    (const ElementArray<EType> & other) {Subtract(other.data(),static_cast<INMOST_DATA_ENUM_TYPE>(other.size()));}
		template<typename EType>
		void                      Intersect   (const ElementArray<EType> & other) {Intersect(other.data(),static_cast<INMOST_DATA_ENUM_TYPE>(other.size()));}
		void                      SetMarker   (MarkerType n) const;
		void                      RemMarker   (MarkerType n) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
584 585 586 587 588 589
	};
	
			
	class Element : public Storage //implemented in element.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
590 591 592 593 594 595 596 597 598 599 600 601 602 603
		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;
Kirill Terekhov's avatar
Kirill Terekhov committed
604 605 606
		static const GeometricType Set          = 253;
		static const GeometricType MeshPart     = 254;
		static const GeometricType MaxType      = 255;
Kirill Terekhov's avatar
Kirill Terekhov committed
607
		//enum GeometricType {Unset,Vertex,Line,MultiLine,Tri,Quad,Polygon,MultiPolygon,Tet,Hex,Prism,Pyramid,Polyhedron,Set};
Kirill Terekhov's avatar
Kirill Terekhov committed
608
		static const char *       GeometricTypeName(GeometricType t);
Kirill Terekhov's avatar
Kirill Terekhov committed
609
		static integer            GetGeometricDimension(GeometricType m_type);
Kirill Terekhov's avatar
Kirill Terekhov committed
610 611 612 613 614 615 616
		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
617
		typedef inner_reference_array            adj_type;
Kirill Terekhov's avatar
Kirill Terekhov committed
618 619 620 621
		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
622 623 624
	public:
		//adj_type &                  HighConn                () const;
		//adj_type &                  LowConn                 () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
625
	protected:
Kirill Terekhov's avatar
Kirill Terekhov committed
626 627 628 629
		void                        SetGeometricType        (GeometricType t);
	public:
		Element() : Storage(NULL,InvalidHandle()) {}
		Element(Mesh * m, HandleType h) : Storage(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
630
		Element(Mesh * m, HandleType * h) : Storage(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
631 632 633 634 635 636
		Element(const Element & other) : Storage(other) {}
		Element & operator =(Element const & other) {Storage::operator =(other); return *this;}
		Element * operator ->() {return this;}
		const Element * operator ->() const {return this;}
		Element & self() {return *this;}
		const Element & self() const {return *this;}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
637
		virtual ~Element() {}
Kirill Terekhov's avatar
Kirill Terekhov committed
638
	public:
Igor Konshin's avatar
Igor Konshin committed
639
		/// Retrieve number of adjacent elements.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
640 641
		/// For etype you can either pass one type as CELL,
		/// or several types as bitwise mask: NODE | CELL.
Kirill Terekhov's avatar
Kirill Terekhov committed
642 643 644
		/// @param etype bitwise mask of element types
		/// @return number of adjacent elements.
		virtual enumerator                nbAdjElements           (ElementType etype) const;
Igor Konshin's avatar
Igor Konshin committed
645
		/// Retrieve unordered array of adjacent elements.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
646 647 648
		/// If you care about orderness of nodes for face you should you Face::getNodes() instead.
		/// If you want faster access you may use direct access to handles stored in memory
		/// through Mesh::HighConn for upper adjacencies and Mesh::LowConn for lower adjacencies.
Kirill Terekhov's avatar
Kirill Terekhov committed
649 650 651
		/// @param etype bitwise mask of element types
		/// @return array of elements
		virtual ElementArray<Element>     getAdjElements          (ElementType etype) const;  //unordered
Igor Konshin's avatar
Igor Konshin committed
652
		/// Retrieve number of adjacent elements with marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
653 654 655 656 657 658 659
		/// As etype you can either pass one type as CELL,
		/// or several types as bitwise mask: NODE | CELL
		/// @param etype bitwise mask of element types
		/// @param mask marker to be set 
		/// @param invert_mask if true then those are selected on wich marker is not set
		/// @return number of adjacent elements.
		virtual enumerator                nbAdjElements           (ElementType etype, MarkerType mask, bool invert_mask = false) const;
Igor Konshin's avatar
Igor Konshin committed
660
		/// Retrieve unordered array of adjacent elements with marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
661 662 663 664 665
		/// @param etype bitwise mask of element types
		/// @param mask marker to be set 
		/// @param invert_mask if true then those are selected on wich marker is not set
		/// @return array of elements
		virtual ElementArray<Element>     getAdjElements          (ElementType etype, MarkerType mask, bool invert_mask = false) const;  //unordered
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
666 667 668 669 670
		ElementArray<Element>       BridgeAdjacencies       (ElementType Bridge, ElementType Dest, MarkerType mask = 0, bool invert_mask = false) const;
		ElementArray<Node>          BridgeAdjacencies2Node  (ElementType Bridge, MarkerType mask = 0, bool invert_mask = false) const;
		ElementArray<Edge>          BridgeAdjacencies2Edge  (ElementType Bridge, MarkerType mask = 0, bool invert_mask = false) const;
		ElementArray<Face>          BridgeAdjacencies2Face  (ElementType Bridge, MarkerType mask = 0, bool invert_mask = false) const;
		ElementArray<Cell>          BridgeAdjacencies2Cell  (ElementType Bridge, MarkerType mask = 0, bool invert_mask = false) const;
Igor Konshin's avatar
Igor Konshin committed
671
		/// Retrieve all the nodes of the element.
672
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
673
		/// For a node returns itself.
674
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
675
		/// For an edge returns ordered pair of nodes. The order of nodes in the edge is preserved from the first construction.
676
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
677 678 679
		/// For a face returns ordered set of nodes. In the case Face::CheckNormalOrientation returns true the
		/// order of nodes will follow right hand side rule with respect to normal vector, otherwise it follows
		/// left hand side rule with respect to normal vector.
680
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
681 682 683 684
		/// For a cell returns the same order that was provided through suggest_nodes_oreder in Mesh::CreateCell.
		/// In the case suggest_nodes_order was not provided, the order of nodes follows VTK format for known types
		/// of elements such as Element::Tet, Element::Prism, Element::Hex, Element::Pyramid. For a general polyhedron
		/// the order is unspecified.
685
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
686 687 688
		/// @return array of elements
		/// @see Face::CheckNormalOrientation
		/// @see Face::FaceOrientedOutside
Kirill Terekhov's avatar
Kirill Terekhov committed
689
		virtual ElementArray<Node>  getNodes                () const; //unordered
Igor Konshin's avatar
Igor Konshin committed
690
		/// Retrieve all the edges of the element.
691
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
692
		/// For a node returns unordered set of edges.
693
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
694
		/// For an edge returns itself.
695
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
696
		/// For a face returns ordered set of edges.
697
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
698
		/// For a cell returns unordered set of edges.
699
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
700
		/// @return array of elements
Kirill Terekhov's avatar
Kirill Terekhov committed
701
		virtual ElementArray<Edge>  getEdges                () const; //unordered
Igor Konshin's avatar
Igor Konshin committed
702
		/// Retrieve all the faces of the element.
703
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
704
		/// For a node returns unordered set of faces.
705
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
706
		/// For an edge returns unordered set of faces.
707
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
708
		/// For a face returns itself.
709
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
710
		/// For a cell return ordered set of faces. The order of faces in the cell is preserved from the first construction.
711
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
712
		/// @return array of elements
Kirill Terekhov's avatar
Kirill Terekhov committed
713
		virtual ElementArray<Face>  getFaces                () const; //unordered
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
714
		/// Return all the cells of the element.
715
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
716
		/// For a node returns unordered set of cells.
717
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
718
		/// For an edge returns unordered set of cells.
719
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
720 721
		/// For a face returns a pair of cells. In the case Face::CheckNormalOrientation returns true
		/// then the normal points from the first cell to the second and in oppisite direction otherwise.
722
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
723
		/// For a cell returns itself.
724
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
725 726
		/// @return array of elements
		/// @see Face::FaceOrientedOutside
Kirill Terekhov's avatar
Kirill Terekhov committed
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
		virtual ElementArray<Cell>  getCells                () const; //unordered
		virtual ElementArray<Node>  getNodes                (MarkerType mask,bool invert_mask = false) const; //unordered
		virtual ElementArray<Edge>  getEdges                (MarkerType mask,bool invert_mask = false) const; //unordered
		virtual ElementArray<Face>  getFaces                (MarkerType mask,bool invert_mask = false) const; //unordered
		virtual ElementArray<Cell>  getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
		Node                        getAsNode               () const;
		Edge                        getAsEdge               () const;
		Face                        getAsFace               () const;
		Cell                        getAsCell               () const;
		ElementSet                  getAsSet                () const;
		GeometricType               GetGeometricType        () const;
		unsigned int                GetElementDimension     () const {return GetGeometricDimension(GetGeometricType());}
		Status                      GetStatus               () const;
		void                        SetStatus               (Status status) const;
		Storage::integer &          GlobalID                () const;
		bool                        CheckElementConnectivity() const;
		void                        PrintElementConnectivity() const;
		static bool                 CheckConnectivity       (Mesh * m);
Kirill Terekhov's avatar
Kirill Terekhov committed
745
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
746 747 748 749 750 751 752
		void                        CastRay                 (real * pos, real * dir, dynarray< std::pair<Element, real> , 16 > & hits) const;
		void                        ComputeGeometricType    () const;
		void                        Centroid                (real * cnt) const;
		void                        Barycenter              (real * cnt) const;
		Storage::real               Mean                    (real (*func)(real* x,real t),real time) const;
		bool                        Boundary                () const;
		bool                        Planarity               () const; // check that all nodes lay on one plane
Kirill Terekhov's avatar
Kirill Terekhov committed
753
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
754 755 756 757 758 759
		bool                        Hide                    () const; // if true then element was hidden, works only inside BeginModification and EndModification, on EndModification all Hidden elements are deleted
		bool                        Show                    () const; // if true then element was recovered
		bool                        Delete                  (); // if true then element was deleted, otherwise it was hidden
		bool                        Hidden                  () const;
		bool                        New                     () const;
		void                        Disconnect              (bool delete_upper_adjacent) const; //disconnect all elements, delete upper dependent
760
		/// Disconnect element.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
761 762
		/// Disconnects nodes from this edge, edges from this face, faces from this cell, cannot disconnect cells from this node; \n
		/// Disconnects edges from this node, faces from this edge, cells from this face, cannot disconnect nodes from this cell; \n
Kirill Terekhov's avatar
Kirill Terekhov committed
763
		/// Updates geometric data and cell nodes automatically.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
764
		void                        Disconnect              (const HandleType * adjacent, INMOST_DATA_ENUM_TYPE num) const;
Kirill Terekhov's avatar
Kirill Terekhov committed
765 766 767
		/// \brief Connects lower adjacencies to current element.
		/// Geometric data and cell nodes are updated automatically.
		///
768
		/// \todo
Kirill Terekhov's avatar
Kirill Terekhov committed
769 770 771
		///	  1. Asserts in this function should be replaced by Topography checks.
		///	  2. This function should be used for construction of elements instead of current implementation.
		///	  3. Should correctly account for order of edges (may be implemented through CheckEdgeOrder, FixEdgeOrder).
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
772
		void                        Connect                 (const HandleType * adjacent, INMOST_DATA_ENUM_TYPE num) const; 
Kirill Terekhov's avatar
Kirill Terekhov committed
773
		/// Update geometric data for element, calls RecomputeGeometricData from Mesh.
Kirill Terekhov's avatar
Kirill Terekhov committed
774
		void                        UpdateGeometricData     () const; 
Kirill Terekhov's avatar
Kirill Terekhov committed
775 776
	};
	
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
777 778
	__INLINE const Element & InvalidElement() {static Element ret(NULL,InvalidHandle()); return ret;}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
779 780 781
	class Node : public Element //implemented in node.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
782 783 784
		Node() : Element() {}
		Node(const Node & other) : Element(other) {}
		Node(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
785
		Node(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
786 787 788 789 790 791 792 793 794
		Node & operator =(Node const & other) {Element::operator =(other); return *this;}
		Node * operator ->() {return this;}
		const Node * operator ->() const {return this;}
		Node & self() {return *this;}
		const Node & self() const {return *this;}
	public:
		ElementArray<Edge>          getEdges                () const; //unordered
		ElementArray<Face>          getFaces                () const; //unordered
		ElementArray<Cell>          getCells                () const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
795

Kirill Terekhov's avatar
Kirill Terekhov committed
796 797 798
		ElementArray<Edge>          getEdges                (MarkerType mask,bool invert_mask = false) const; //unordered
		ElementArray<Face>          getFaces                (MarkerType mask,bool invert_mask = false) const; //unordered
		ElementArray<Cell>          getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
799

Kirill Terekhov's avatar
Kirill Terekhov committed
800
		Storage::real_array         Coords                  () const; 
Kirill Terekhov's avatar
Kirill Terekhov committed
801
	};
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
802 803

	__INLINE const Node & InvalidNode() {static Node ret(NULL,InvalidHandle()); return ret;}
Kirill Terekhov's avatar
Kirill Terekhov committed
804 805 806 807
	
	class Edge : public Element //implemented in edge.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
808 809 810
		Edge() : Element() {}
		Edge(const Edge & other) : Element(other) {}
		Edge(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
811
		Edge(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
812 813 814 815 816 817
		Edge & operator =(Edge const & other) {Element::operator =(other); return *this;}
		Edge * operator ->() {return this;}
		const Edge * operator ->() const {return this;}
		Edge & self() {return *this;}
		const Edge & self() const {return *this;}
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
818
		
Kirill Terekhov's avatar
Kirill Terekhov committed
819 820 821
		ElementArray<Node>          getNodes                () const; //ordered
		ElementArray<Face>          getFaces                () const; //unordered
		ElementArray<Cell>          getCells                () const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
822

Kirill Terekhov's avatar
Kirill Terekhov committed
823 824 825
		ElementArray<Node>          getNodes                (MarkerType mask,bool invert_mask = false) const; //ordered
		ElementArray<Face>          getFaces                (MarkerType mask,bool invert_mask = false) const; //unordered
		ElementArray<Cell>          getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
826

Kirill Terekhov's avatar
Kirill Terekhov committed
827 828
		Node                        getBeg                  () const;
		Node                        getEnd                  () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
829
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
830 831 832 833
		static Edge                 UniteEdges              (ElementArray<Edge> & edges, MarkerType del_protect);
		static bool                 TestUniteEdges          (const ElementArray<Edge> & edges, MarkerType del_protect);
		static ElementArray<Edge>   SplitEdge               (Edge e, const ElementArray<Node> & nodes, MarkerType del_protect); //provide ordered array of nodes, that lay between former nodes of the edge
		static bool                 TestSplitEdge           (Edge e, const ElementArray<Node> & nodes, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
834
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
835
		Storage::real               Length                  () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
836
	};
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
837 838

	__INLINE const Edge & InvalidEdge() {static Edge ret(NULL,InvalidHandle()); return ret;}
Kirill Terekhov's avatar
Kirill Terekhov committed
839
	
Kirill Terekhov's avatar
Kirill Terekhov committed
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860

	/// \brief An interface for elements of type FACE.
	///
	/// This interface carry the link to the mesh and the element's handle that
	/// represents position of the element's data in the mesh. 
	///
	/// Interface provides some operations that can be done uniquely on the object of class 
	/// Element for which Element::GetElementType retruns FACE.
	///
	/// For the basic set of operations on all of the elements check class Element.
	///
	/// For the basic set of operations on the data of the element check class Storage.
	///
	/// You can obtain object of class Face from Mesh::iteratorFace,
	/// in this case obtained object is always valid.
	/// Also you can get it through Mesh::FaceByLocalID, check with Element::isValid to see whether you
	/// have obtained a valid object.
	/// You can convert an object of class Element into an object of class Face by Element::getAsFace. In debug
	/// mode it will internally check that the element is of type FACE.
	/// You may compose an object of class Face by using constructor and specifing pointer to the mesh
	/// and providing element's handle. You can make a handle with ComposeHandle(FACE,local_id) function.
Kirill Terekhov's avatar
Kirill Terekhov committed
861 862 863
	class Face : public Element //implemented in face.cpp
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
864 865 866
		Face() : Element() {}
		Face(const Face & other) : Element(other) {}
		Face(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
867
		Face(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
868 869 870 871 872 873
		Face & operator =(Face const & other) {Element::operator =(other); return *this;}
		Face * operator ->() {return this;}
		const Face * operator ->() const {return this;}
		Face & self() {return *this;}
		const Face & self() const {return *this;}
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
874
		
Kirill Terekhov's avatar
Kirill Terekhov committed
875 876 877
		ElementArray<Node>          getNodes                () const; //ordered
		ElementArray<Edge>          getEdges                () const; //ordered
		ElementArray<Cell>          getCells                () const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
878

Kirill Terekhov's avatar
Kirill Terekhov committed
879 880 881
		ElementArray<Node>          getNodes                (MarkerType mask,bool invert_mask = false) const; //ordered
		ElementArray<Edge>          getEdges                (MarkerType mask,bool invert_mask = false) const; //ordered
		ElementArray<Cell>          getCells                (MarkerType mask,bool invert_mask = false) const; //unordered
Kirill Terekhov's avatar
Kirill Terekhov committed
882 883

		//this is for 2d case when the face is represented by segment
Kirill Terekhov's avatar
Kirill Terekhov committed
884 885
		Node                        getBeg                  () const;
		Node                        getEnd                  () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
886 887
		/// \brief Retrieve the cell for which the normal points outwards.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
888
		/// \warning Depending on the grid construction the normal may incorrectly point inwards.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
889
		/// You can resolve this situation by Face::FixNormalOrientation.
Kirill Terekhov's avatar
Kirill Terekhov committed
890
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
891 892
		/// @return the cell for which normal points outwards.
		/// @see Face::FixNormalOrientation
Kirill Terekhov's avatar
Kirill Terekhov committed
893
		Cell                        BackCell                () const;
Kirill Terekhov's avatar
Kirill Terekhov committed
894 895
		/// \brief Retrieve the cell for which the normal points inwards.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
896
		/// \warning Depending on the grid construction the normal may incorrectly point outwards.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
897
		/// You can resolve this situation by Face::FixNormalOrientation.
Kirill Terekhov's avatar
Kirill Terekhov committed
898
		///
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
899 900
		/// @return the cell for which normal points inwards.
		/// @see Face::FixNormalOrientation
Kirill Terekhov's avatar
Kirill Terekhov committed
901 902 903 904 905
		Cell                        FrontCell               () const;
		bool                        FaceOrientedOutside     (Cell c) const;
		void                        ReorderEdges            () const;
		bool                        CheckEdgeOrder          () const; //not implemented// returns true if edges of face form an ordered closed loop
		bool                        FixEdgeOrder            () const; //not implemented// returns true if edges were successfully reordered to form a closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
906
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
907 908 909 910 911
		static Face                 UniteFaces              (ElementArray<Face> & faces, MarkerType del_protect);
		static bool                 TestUniteFaces          (const ElementArray<Face> & faces,  MarkerType del_protect);
		static ElementArray<Face>   SplitFace               (Face face, const ElementArray<Edge> & edges, MarkerType del_protect); //provide all edges that lay inside face
		static bool                 TestSplitFace           (Face face, const ElementArray<Edge> & edges, MarkerType del_protect);	
		void                        SwapCells               (); //swap back cell and front cell
Kirill Terekhov's avatar
Kirill Terekhov committed
912
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
913 914 915 916 917 918 919 920
		Storage::real               Area                    () const;
		void                        Normal                  (real * nrm) const;
		void                        UnitNormal              (real * nrm) const;
		void                        OrientedNormal          (Cell c, real * nrm) const;
		void                        OrientedUnitNormal      (Cell c, real * nrm) const;
		bool                        FixNormalOrientation    () const;  //returns true if orientation was corrected, otherwise returns false
		bool                        CheckNormalOrientation  () const; //returns true if orientation is correct, otherwise returns false
		bool                        Closure                 () const; // test integrity of polygon
Kirill Terekhov's avatar
Kirill Terekhov committed
921
	};
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
922 923

	__INLINE const Face & InvalidFace() {static Face ret(NULL,InvalidHandle()); return ret;}
Kirill Terekhov's avatar
Kirill Terekhov committed
924
	
Kirill Terekhov's avatar
Kirill Terekhov committed
925 926 927 928 929 930
	//implemented in cell.cpp
	/// \brief An interface for elements of type CELL.
	///
	/// This interface carry the link to the mesh and the element's handle that
	/// represents position of the element's data in the mesh. 
	///
Kirill Terekhov's avatar
Kirill Terekhov committed
931 932
	/// Interface provides some operations that can be done uniquely on the object of class 
	/// Element for which Element::GetElementType retruns CELL.
Kirill Terekhov's avatar
Kirill Terekhov committed
933 934 935 936 937 938 939 940 941
	///
	/// For the basic set of operations on all of the elements check class Element.
	///
	/// For the basic set of operations on the data of the element check class Storage.
	///
	/// You can obtain object of class Cell from Mesh::iteratorCell,
	/// in this case obtained object is always valid.
	/// Also you can get it through Mesh::CellByLocalID, check with Element::isValid to see whether you
	/// have obtained valid object.
Kirill Terekhov's avatar
Kirill Terekhov committed
942 943 944 945
	/// You can convert an object of class Element into an object of class Cell by Element::getAsCell. In debug
	/// mode it will internally check that the element is of type CELL.
	/// You may compose an object of class Cell by using constructor and specifing pointer to the mesh
	/// and providing element's handle. You can make a handle with ComposeHandle(CELL,local_id) function.
Kirill Terekhov's avatar
Kirill Terekhov committed
946
	class Cell : public Element
Kirill Terekhov's avatar
Kirill Terekhov committed
947 948
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
949 950 951 952 953 954 955 956 957 958
		/// \brief Basic constructor.
		///
		/// Constructs invalid cell.
		Cell() : Element() {} 
		/// \brief Basic constructor with fixed handle.
		///
		/// When constructed this way, only handle within object may change.
		///
		/// @param m Pointer to the mesh to which the element belongs.
		/// @param h Unique handle that describes position of the element within the mesh.
Kirill Terekhov's avatar
Kirill Terekhov committed
959
		Cell(Mesh * m, HandleType h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
960 961 962 963 964
		/// \brief Basic constructor with an assignable handle.
		///
		/// When constructed this way, the provided memory location for handle
		/// will be modified on assignment.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
965
		/// The purpose of this function is to be used in various non-constant iterators
Kirill Terekhov's avatar
Kirill Terekhov committed
966 967 968 969
		/// of containers that allow underlaying contents to be changed.
		///
		/// @param m Pointer to the mesh to which the element belongs.
		/// @param h Pointer to the handle that describes position of the element within mesh.
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
970
		Cell(Mesh * m, HandleType * h) : Element(m,h) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
971 972 973 974 975
		/// \brief Copy constructor.
		///
		/// New object will inherit the assignment behavior of the initial object.
		///
		/// @param other Object of type Cell to be duplicated.
Kirill Terekhov's avatar
Kirill Terekhov committed
976
		Cell(const Cell & other) : Element(other) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
		/// \brief Assignment operator
		///
		/// Assigned object will inherit the asignment behavior of the initial object only
		/// in case it was constructed without pointer to a handle. Otherwise it will
		/// only modify the memory location to which it points.
		///
		/// @param other Object of type Cell to be duplicated.
		/// @return Reference to the current object.
		Cell & operator =(Cell const & other) {Element::operator =(other); return *this;} ///< Assignment Operator.
		/// \brief Operator of dereference to pointer.
		///
		/// This is needed for iterators to work properly.
		///
		/// @return Pointer to the current object.
		Cell * operator ->() {return this;} 
		/// \brief Operator of dereference to constant pointer. 
		///
		/// This is needed for const_iterators to work properly.
		///
		/// @return Constant pointer to the current object.
Kirill Terekhov's avatar
Kirill Terekhov committed
997
		const Cell * operator ->() const {return this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
		/// \brief Get self-reference.
		///
		/// Main purpose is to convert iterators into elements and to pass them as arguments of functions.
		///
		/// @return Constant reference to the current object.
		Cell & self() {return *this;} 
		/// \brief Get constant self-reference.
		///
		/// Main purpose is to convert iterators into elements and to pass them as arguments of functions.
		///
		/// @return Reference to the current object.
Kirill Terekhov's avatar
Kirill Terekhov committed
1009 1010
		const Cell & self() const {return *this;}
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
1011 1012 1013 1014
		/// \brief Get all the nodes of the current cell.
		///
		/// This function traverses up the adjacency graph by one level.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
1015
		/// The order of nodes will be preserved from the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
		/// When suggest_nodes array is not supplied into the Mesh::CreateCell functions, then
		/// for known types the order of nodes follows VTK convention. For polyhedral cells
		/// the order is unspecified. When suggest_nodes_order was provided into Mesh::CreateCell
		/// then the order follows provided order.
		///
		/// @return Set of nodes that compose current cell.
		ElementArray<Node>          getNodes                () const;
		/// \brief Get all the edges of the current cell.
		///
		/// This function traverses down the adjacency graph by two levels.
		///
		/// The order of the edges is unspecified.
		///
		/// @return Set of edges that compose current cell.
		///
		/// \todo
		/// One should thoroughly check three scenarios of function execution in shared parallel environment
		/// for different types of cells (simple tet/hex cells as well as complex polyhedral cells) and
		/// draw a conclusion on the best scenario for each condition. One of the development versions
		/// contains all the algorithms, ask for the files.
		///  1. Use of markers (current wariant).
		///  2. Put all elements into array with duplications, then run std::sort and std::unique.
		///  3. Put all elements into array, check for duplication by running through array.
Kirill Terekhov's avatar
Kirill Terekhov committed
1039 1040 1041 1042 1043 1044 1045
		///
		/// \warning Note that this function uses markers to check for duplication of edges
		/// in output array. This allows for faster algorithm, but will lead to penalties
		/// in shared parallel execution, since operations on markers are declared atomic.
		/// For atomic declaration to work you have to define USE_OMP during CMake configuration
		/// or in inmost_common.h. If you attempt to use this function in shared parallel execution
		/// without USE_OMP you may expect side effects.
Kirill Terekhov's avatar
Kirill Terekhov committed
1046 1047 1048 1049 1050 1051
		ElementArray<Edge>          getEdges                () const;
		/// \brief Get all the faces of the current cell.
		///
		/// This function traverses down the adjacency graph by one level.
		///
		/// The order of the faces returned by this function is preserved from 
Kirill Terekhov's avatar
Kirill Terekhov committed
1052
		/// the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
1053 1054 1055 1056 1057 1058 1059
		///
		/// @return Set of faces that compose current cell.
		ElementArray<Face>          getFaces                () const;
		/// \brief Get the subset of the nodes of the current cell that are (not) marked by provided marker.
		///
		/// This function traverses up the adjacency graph by one level.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
1060
		/// The order of nodes will be preserved from the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
1061 1062 1063 1064 1065 1066 1067 1068 1069
		/// When suggest_nodes array is not supplied into the Mesh::CreateCell functions, then
		/// for known types the order of nodes follows VTK convention. For polyhedral cells
		/// the order is unspecified. When suggest_nodes_order was provided into Mesh::CreateCell
		/// then the order follows provided order.
		///
		/// @param mask Marker that should be used to filter elements.
		/// @param invert_mask If false then those elements that are marked will be taken, otherwise
		///                    elements that are not marked will be taken.
		/// @return Set of the nodes that compose current cell and (not) marked by marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
1070 1071 1072
		///
		/// \warning To work correctly in shared parallel environment this function requires
		/// USE_OMP to be defined in CMake or in inmost_common.h.
Kirill Terekhov's avatar
Kirill Terekhov committed
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
		ElementArray<Node>          getNodes                (MarkerType mask,bool invert_mask = false) const;
		/// \brief Get the subset of the edges of the current cell that are (not) marked by provided marker.
		///
		/// This function traverses down the adjacency graph by two levels.
		///
		/// The order of the edges is unspecified.
		///
		/// @param mask Marker that should be used to filter elements.
		/// @param invert_mask If false then those elements that are marked will be taken, otherwise
		///                    elements that are not marked will be taken.
		/// @return Set of the edges that compose current cell and (not) marked by marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
1084 1085 1086
		///
		/// \warning To work correctly in shared parallel environment this function requires
		/// USE_OMP to be defined in CMake or in inmost_common.h.
Kirill Terekhov's avatar
Kirill Terekhov committed
1087 1088 1089 1090 1091 1092
		ElementArray<Edge>          getEdges                (MarkerType mask,bool invert_mask = false) const;
		/// \brief Get the subset of the faces of the current cell that are (not) marked by provided marker.
		///
		/// This function traverses down the adjacency graph by one level.
		///
		/// The order of the faces returned by this function is preserved from 
Kirill Terekhov's avatar
Kirill Terekhov committed
1093
		/// the moment of the construction of the cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
1094 1095 1096 1097 1098
		///
		/// @param mask Marker that should be used to filter elements.
		/// @param invert_mask If false then those elements that are marked will be taken, otherwise
		///                    elements that are not marked will be taken.
		/// @return Set of the faces that compose current cell and (not) marked by marker.
Kirill Terekhov's avatar
Kirill Terekhov committed
1099 1100 1101
		///
		/// \warning To work correctly in shared parallel environment this function requires
		/// USE_OMP to be defined in CMake or in inmost_common.h.
Kirill Terekhov's avatar
Kirill Terekhov committed
1102 1103 1104
		ElementArray<Face>          getFaces                (MarkerType mask,bool invert_mask = false) const;
		/// \brief Check that sequence of edges form a closed loop and each edge have a node that matches one of the nodes at the next edge.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
1105
		/// This function works for cells for which Element::GetElementDimension returns 2.
Kirill Terekhov's avatar
Kirill Terekhov committed
1106 1107 1108 1109 1110 1111 1112
		///
		/// @return True if edges form the correct closed loop.
		///
		/// \todo
		///   1. Implement.
		///   2. Use in topology check algorithms.
		///   3. Use in Element::Connect.
Kirill Terekhov's avatar
Kirill Terekhov committed
1113
		bool                        CheckEdgeOrder          () const; //not implemented//2D only, returns true if edges of face form an ordered closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
		/// \brief Repair the sequence of edges so that each edge have node that matches one of the nodes at the next edge.
		///
		/// This function works for cells for which Element::GetGeometricDimension returns 2.
		///
		/// This function may fail if all the edges does not form a closed loop.
		///
		/// @return True if edges were successfully reordered to form a closed loop.
		///
		/// \todo
		///   1. Implement.
		///   2. Use in topology check algorithms.
		///   3. Use in Element::Connect.
Kirill Terekhov's avatar
Kirill Terekhov committed
1126
		bool                        FixEdgeOrder            () const; //not implemented//2D only, returns true if edges were successfully reordered to form a closed loop
Kirill Terekhov's avatar
Kirill Terekhov committed
1127
		//implemented in modify.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
1128 1129 1130 1131 1132 1133 1134 1135 1136
		/// \brief Unite a set of given cells into one cell.
		///
		/// This will create a cell whose faces are formed by symmetric difference
		/// of faces of given cells.
		/// If you specify a nonzero marker then the procedure will fail 
		/// if any marked element have to be deleted during union.
		/// @param cells A set of cells to be united.
		/// @param del_protect A marker that protects elements from deletion. Zero means no check.
		/// @return A new cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
1137
		static Cell                 UniteCells              (ElementArray<Cell> & cells, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
1138 1139 1140 1141
		/// \brief Test that no marked element will be deleted during union of given cells.
		/// @param cells A set of cells to be united.
		/// @param del_protect A marker that protects elements from deletion. Zero means no check.
		/// @return True if no element deleted, false otherwise.
Kirill Terekhov's avatar
Kirill Terekhov committed
1142
		static bool                 TestUniteCells          (const ElementArray<Cell> & cells, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
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
		/// \brief Separate a cell according to the set of provided faces.
		///
		/// You should first separate all edges with new nodes by Edge::SplitEdge, then faces with new edges by Face::SplitFace
		/// and then create faces using new edges from faces of initial cell and optionally edges from inside of the cell. 
		/// All faces are supposed to be internal with respect to the current cell. 
		/// Internally this function will resolve geometry of new cells inside of the 
		/// current cell by running through adjacency graph.
		///
		/// @param cell A cell to be split.
		/// @param faces A set of faces, internal for current cell, that will be used for construction of new cells.
		/// @param del_protect Marker that may be used to protect some elements from deletion by algorithm. 
		///        Zero means no check.
		/// @return A set of new cells.
		/// @see Edge::SplitEdge
		/// @see Face::SplitFace
		///
		/// \todo
		///   1. The algorithm inside is minimizing the size of the adjacency graph for each new cell.
		///      The correct behavior is to calculate volume of the cell for each adjacency graph and choose the graph with minimal volume.
		///      This requires calculation of volume for non-convex cells. For correct calculation of volume on non-convex cells one should 
		///      find one face for which normal orientation can be clearly determined and then orient all edges of the cell with respect to
		///      the orientation of edges of this face and establish normals for all faces. Once the algorithm is implemented here it should 
		///      be implemented in geometrical services or vice verse.
		///   2. Probably the algorithm should minimize the volume and adjacency graph size altogether. Between the cells with smallest volume
		///      within some tolerance select those that have smallest adjacency graph.
Kirill Terekhov's avatar
Kirill Terekhov committed
1168
		static ElementArray<Cell>   SplitCell               (Cell cell, const ElementArray<Face> & faces, MarkerType del_protect); //provide all faces, that lay inside cell
Kirill Terekhov's avatar
Kirill Terekhov committed
1169 1170 1171 1172 1173 1174
		/// \brief This functions checks is it possible to split the cell by the given set of faces without deleting marked elements.
		///
		/// @param cell A cell to be split.
		/// @param faces Set of faces, internal for current cell, that will be used for new cells.
		/// @param del_protect Marker that may be used to protect some elements from deletion by algorithm. Zero means no check.
		/// @return True if possible, otherwise false.
Kirill Terekhov's avatar
Kirill Terekhov committed
1175
		static bool                 TestSplitCell           (Cell cell, const ElementArray<Face> & faces, MarkerType del_protect);
Kirill Terekhov's avatar
Kirill Terekhov committed
1176
		//implemented in geometry.cpp
Kirill Terekhov's avatar
Kirill Terekhov committed
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
		/// \brief Get a cell that share a face with the current cell.
		///
		/// Don't forget to check that the returned cell is valid.
		/// It would return invalid cell for boundary face.
		///
		/// @param face A face of current cell for which neighbouring cell is determined.
		/// @return A cell that shares a given face with the current cell.
		Cell                        Neighbour               (Face face) const;
		/// \brief Get all cells that share the face with the current cell.
		/// @return Set of cells that share a face with the current cell.
Kirill Terekhov's avatar
Kirill Terekhov committed
1187
		ElementArray<Cell>          NeighbouringCells       () const; // get all cells that share any face with current
Kirill Terekhov's avatar
Kirill Terekhov committed
1188 1189
		/// \brief Determine, if point lies inside element.
		///
Kirill Terekhov's avatar
Kirill Terekhov committed
1190 1191 1192 1193 1194 1195
		/// Now it works only for 3-dimensional elements, at future it will be
		/// extended to support polygons and segments.
		/// @param point coordinates of the point, it is assumed that number of the
		/// coordinates is the same as the number of dimensions in the mesh.
		/// @return returns true if points inside element, false otherwise
		/// @see Mesh::GetDimensions
Kirill Terekhov's avatar
Kirill Terekhov committed
1196 1197 1198 1199 1200 1201 1202 1203 1204
		///
		/// \todo
		///   1. Should be checked or extended for 2d cells. (done, testing)
		bool                        Inside                  (const real * point) const; //is point inside cell, check for 2d case
		/// \brief Return volume of the cell.
		///
		/// Note that currently the volume for non-convex cells may be calculated incorrectly.
		/// \todo
		///   1. Geometric services should correctly resolve volume for non-convex cells.
Kirill Terekhov's avatar
Kirill Terekhov committed
1205
		real                        Volume                  () const;