inmost_autodiff.h 30.1 KB
Newer Older
Kirill Terekhov committed
1

Kirill Terekhov committed
2 3
#ifndef INMOST_AUTODIFF_H_INCLUDED
#define INMOST_AUTODIFF_H_INCLUDED
4

Kirill Terekhov committed
5 6 7
#include "inmost_common.h"
#include "inmost_mesh.h"

8
#if defined(USE_AUTODIFF) && defined(USE_MESH)
Kirill Terekhov committed
9 10 11 12

namespace INMOST
{
	class Automatizator; //forward declaration
Kirill Terekhov committed
13
	
14 15 16 17 18 19 20 21
	//return specific type with specific template
	template<class T> struct Demote;
	template<> struct Demote<INMOST_DATA_INTEGER_TYPE> {typedef INMOST_DATA_INTEGER_TYPE type;};
	template<> struct Demote<INMOST_DATA_REAL_TYPE> {typedef INMOST_DATA_REAL_TYPE type;};
	template<> struct Demote<unknown> {typedef unknown type;};
	template<> struct Demote<variable> {typedef unknown type;};
	template<> struct Demote<hessian_variable> {typedef unknown type;};
	
22 23 24 25 26
	/// This class is used to organize unknowns in abstract way,
	/// it should be registered with and managed by class Automatizator.
	/// \todo
	/// 1. Is there a need for layout on how matrices are returned?
	/// 2. Is there a need for layout on how unknowns and equations are arrenged?
27 28
	/// 3. Function for update of variables.
	/// 4. Function for synchronization of variables.
29 30 31 32 33 34 35
	class AbstractEntry
	{
		INMOST_DATA_ENUM_TYPE              reg_index;    ///< Index of block registry with Automatizator.
		TagInteger                         offset_tag;   ///< Starting index of the entry.
		MarkerType                         mask;         ///< Allows to enable or disable the entire block.
		ElementType                        etype;        ///< Type of elements on which unknowns are defined.
	public:
36 37
		AbstractEntry(ElementType etype = NONE, MarkerType mask = 0)
		: reg_index(ENUMUNDEF), offset_tag(Tag()), mask(mask), etype(etype) {}
38 39 40 41 42 43 44 45 46 47 48 49 50
		/// Retrive mask of the block.
		MarkerType GetMask() const {return mask;}
		/// Set mask for the block.
		void SetMask(MarkerType _mask) {mask = _mask;}
		/// Retrive element type of the block.
		ElementType GetElementType() const {return etype;}
		/// Set element type for the block.
		void SetElementType(ElementType _etype) {etype = _etype;}
		/// Retrive tag that stores enumeration offset on each element.
		TagInteger GetOffsetTag() const {return offset_tag;}
		/// Retrive tag that stores enumeration offset on each element.
		void SetOffsetTag(TagInteger tag) {offset_tag = tag;}
		/// Check that the block is valid on given element.
51
		bool isValid(const Storage & e) const {return reg_index != ENUMUNDEF && (e.GetElementType() & etype) && (mask == 0 || e->GetMarker(mask));}
52
		/// Return value in vector of unknowns of the block at certain position.
Kirill Terekhov committed
53
		/// @param pos Position for which to extract the value, should be no larger then MatrixSize.
54 55
		virtual INMOST_DATA_REAL_TYPE Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const = 0;
		/// Return value in vector of unknowns of the block at certain position.
Kirill Terekhov committed
56
		/// @param pos Position for which to extract the value, should be no larger then MatrixSize.
57 58 59
		virtual INMOST_DATA_REAL_TYPE & Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) = 0;
		/// Return index in vector of indices of the block at certain position.
		/// The index may be ENUMUNDEF if the unknown is inactive.
Kirill Terekhov committed
60
		/// @param pos Position for which to extract the index, should be no larger then MatrixSize.
61 62
		virtual INMOST_DATA_ENUM_TYPE Index(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const = 0;
		/// Return unknown in vector of variables of the block at certain position.
Kirill Terekhov committed
63
		/// @param pos Position for which to extract the unknown, should be no larger then MatrixSize.
64 65
		virtual unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const = 0;
		/// Return vector filled with values of unknowns of the block.
66
		virtual rpMatrix Value(const Storage & e) const = 0;
67
		/// Return vector filled with indices of unknowns of the block.
68
		virtual ipMatrix Index(const Storage & e) const = 0;
69
		/// Return vector filled with unknowns of the block with their derivatives.
70
		virtual upMatrix Unknown(const Storage & e) const = 0;
Kirill Terekhov committed
71 72
		/// Return vector filled with either values or indices or unknowns of the block,
		/// depending on the template parameter.
73 74 75
		template<typename T>
		Matrix<typename Demote<T>::type, pool_array_t<typename Demote<T>::type> >
		Access(const Storage &e) const;
Kirill Terekhov committed
76 77 78
		/// Return either value or index or unknown at specified position of the block,
		/// depending on the template parameter.
		/// @param pos Position in the block, should be no larger then MatrixSize.
79 80 81
		template<typename T>
		typename Demote<T>::type
		Access(const Storage &e, INMOST_DATA_ENUM_TYPE pos) const;
82
		/// Return vector filled with unknowns of the block with their derivatives.
83
		virtual upMatrix operator [](const Storage & e) const = 0;
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
		/// The intended size of the matrix for this entry.
		virtual INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const = 0;
		/// Number of tags in block.
		virtual INMOST_DATA_ENUM_TYPE Size() const = 0;
		/// Total number of entries that this block expands to on given element,
		/// count variable-sized entries.
		/// This is an important function since it determines offset of
		/// each block when enumerated by Automatizator::EnumerateEntries.
		/// See also MatrixSize.
		virtual INMOST_DATA_ENUM_TYPE Size(const Storage & e) const = 0;
		/// Retrive component of the tag related to unknown.
		virtual INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const = 0;
		/// Retrive tag related to unknown value.
		virtual TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const = 0;
		/// Retrive mesh pointer.
		virtual Mesh * GetMeshLink() const = 0;
		/// Make a copy of the object
		virtual AbstractEntry * Copy() const = 0;
		/// Retrive a registration index.
		INMOST_DATA_ENUM_TYPE GetRegistrationIndex() const {return reg_index;}
104 105 106
		/// Update variables  contained in block on ghost elements of the grid.
		/// For synchronization of data in all blocks see Automatizator::SynhronizeData.
		void SynchronizeData();
107 108 109 110
		/// Destructor.
		virtual ~AbstractEntry() {}
		
		friend class Automatizator; //provide registration index from inside of Automatizator
111
		friend class Model; //provide registration index from inside of Model
112
	};
Kirill Terekhov committed
113 114 115
	
	
	
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
	/// This class is used to organize unknowns into blocks,
	/// blocks enumeration are managed by class Automatizator.
	class BlockEntry : public AbstractEntry
	{
		std::vector<TagRealArray>          unknown_tags; ///< Tags for unknown values that enter the block.
		std::vector<INMOST_DATA_ENUM_TYPE> unknown_comp; ///< Component of the tag used as unknown.
	public:
		/// Default constructor.
		BlockEntry(ElementType etype = NONE, MarkerType mask = 0) : AbstractEntry(etype,mask) {}
		/// Add a component of the tag as unknown, by default all components of the tag are added.
		/// Adding all components of variable-sized tags is not supported.
		/// \warning Tags should belong to the same mesh and should be defined on the elements indicated in etype.
		void AddTag(Tag value, INMOST_DATA_ENUM_TYPE comp = ENUMUNDEF);
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return unknown_tags[pos][e][unknown_comp[pos]];}
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE & Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) {return unknown_tags[pos][e][unknown_comp[pos]];}
		/// Return index in vector of indices of the block at certain position.
		INMOST_DATA_ENUM_TYPE Index(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return isValid(e) ? GetOffsetTag()[e]+pos : ENUMUNDEF;}
		/// Return unknown in vector of variables of the block at certain position.
		unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return unknown(Value(e,pos),Index(e,pos));}
		/// Return vector filled with values of unknowns of the block.
138
		rpMatrix Value(const Storage & e) const {rpMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
139
		/// Return vector filled with indices of unknowns of the block.
140
		ipMatrix Index(const Storage & e) const {ipMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
141
		/// Return vector filled with unknowns of the block with their derivatives.
142
		upMatrix Unknown(const Storage & e) const {return BlockEntry::operator [](e);}
143
		/// Return vector filled with unknowns of the block with their derivatives.
144
		upMatrix operator [](const Storage & e) const {upMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
145
		/// The intended size of the matrix for this entry.
146
        INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return Size();}
147
		/// Number of tags in block.
148
		INMOST_DATA_ENUM_TYPE Size() const {return (INMOST_DATA_ENUM_TYPE)unknown_tags.size();}
149
		/// Number of entries for each tag in the block.
150
        INMOST_DATA_ENUM_TYPE Size(const Storage & e) const {(void)e; return (INMOST_DATA_ENUM_TYPE)unknown_tags.size();}
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
		/// Retrive component of the tag related to unknown.
		INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const {return unknown_comp[unk];}
		/// Retrive tag related to unknown value.
		TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const {return unknown_tags[unk];}
		/// Retrive mesh pointer.
		Mesh * GetMeshLink() const {return unknown_tags.back().GetMeshLink();}
		/// Make a copy of the object
		AbstractEntry * Copy() const {BlockEntry * ret = new BlockEntry(GetElementType(),GetMask()); for(unsigned k = 0; k < Size(); ++k) ret->AddTag(unknown_tags[k],unknown_comp[k]); return ret; }
	};
	/// This class is used to organize a single unknown,
	class SingleEntry : public AbstractEntry
	{
		TagRealArray          unknown_tag;
		INMOST_DATA_ENUM_TYPE unknown_comp;
	public:
		///Default constructor.
		SingleEntry(ElementType etype = NONE, MarkerType mask = 0) : AbstractEntry(etype,mask) {}
		///Constructor with tag.
		SingleEntry(ElementType etype, MarkerType mask, Tag unknown_tag, INMOST_DATA_ENUM_TYPE unknown_comp = 0) : AbstractEntry(etype,mask), unknown_tag(unknown_tag), unknown_comp(unknown_comp) {}
		///Provide tag.
		void SetTag(Tag unknown_tag_in, INMOST_DATA_ENUM_TYPE unknown_comp_in = 0) {unknown_tag = unknown_tag_in; unknown_comp = unknown_comp_in;}
		/// Return value in vector of unknowns of the block at certain position.
173
        INMOST_DATA_REAL_TYPE Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {(void)pos; assert(pos==0); return unknown_tag[e][unknown_comp];}
174
		/// Return value in vector of unknowns of the block at certain position.
175
        INMOST_DATA_REAL_TYPE & Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) {(void)pos; assert(pos==0); return unknown_tag[e][unknown_comp];}
176
		/// Return index in vector of indices of the block at certain position.
177
        INMOST_DATA_ENUM_TYPE Index(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {(void)pos; assert(pos==0); return isValid(e) ? GetOffsetTag()[e] : ENUMUNDEF;}
178 179 180
		/// Return unknown in vector of variables of the block at certain position.
		unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {assert(pos==0); return unknown(Value(e,pos),Index(e,pos));}
		/// Return vector filled with values of unknowns of the block.
181
		rpMatrix Value(const Storage & e) const { rpMatrix ret(1,1); ret(0,0) = Value(e,0); return ret; }
182
		/// Return vector filled with indices of unknowns of the block.
183
		ipMatrix Index(const Storage & e) const { ipMatrix ret(1,1); ret(0,0) = Index(e,0); return ret; }
184
		/// Return vector filled with unknowns of the block with their derivatives.
185
		upMatrix Unknown(const Storage & e) const {return SingleEntry::operator [](e);}
186
		/// Return vector filled with unknowns of the block with their derivatives.
187
		upMatrix operator [](const Storage & e) const { upMatrix ret(1,1); ret(0,0) = Unknown(e,0); return ret; }
188
		/// The intended size of the matrix for this entry.
189
        INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return 1;}
190 191 192
		/// Number of tags in block.
		INMOST_DATA_ENUM_TYPE Size() const {return 1;}
		/// Number of entries for each tag in the block.
193
        INMOST_DATA_ENUM_TYPE Size(const Storage & e) const {(void)e; return 1;}
194
		/// Retrive component of the tag related to unknown.
195
        INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk == 0); return unknown_comp;}
196
		/// Retrive tag related to unknown value.
197
        TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk == 0); return unknown_tag;}
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
		/// Retrive mesh pointer.
		Mesh * GetMeshLink() const {return unknown_tag.GetMeshLink();}
		/// Make a copy of the object
		AbstractEntry * Copy() const {return new SingleEntry(GetElementType(),GetMask(),unknown_tag,unknown_comp);}
	};
	/// This class is used to organize multiple unknowns resided on single tag of variable or static size,
	class VectorEntry : public AbstractEntry
	{
		TagRealArray          unknown_tag;
	public:
		///Default constructor.
		VectorEntry(ElementType etype = NONE, MarkerType mask = 0) : AbstractEntry(etype,mask) {}
		///Constructor with tag.
		VectorEntry(ElementType etype, MarkerType mask, Tag unknown_tag) : AbstractEntry(etype,mask), unknown_tag(unknown_tag) {}
		///Provide tag.
		void SetTag(Tag unknown_tag_in) {unknown_tag = unknown_tag_in;}
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {assert(pos<unknown_tag[e].size()); return unknown_tag[e][pos];}
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE & Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) {assert(pos<unknown_tag[e].size()); return unknown_tag[e][pos];}
		/// Return index in vector of indices of the block at certain position.
		INMOST_DATA_ENUM_TYPE Index(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {assert(pos<unknown_tag[e].size()); return isValid(e) ? GetOffsetTag()[e]+pos : ENUMUNDEF;}
		/// Return unknown in vector of variables of the block at certain position.
		unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {assert(pos<unknown_tag[e].size()); return unknown(Value(e,pos),Index(e,pos));}
		/// Return vector filled with values of unknowns of the block.
223
		rpMatrix Value(const Storage & e) const { rpMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Value(e,k); return ret; }
224
		/// Return vector filled with indices of unknowns of the block.
225
		ipMatrix Index(const Storage & e) const { ipMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Index(e,k); return ret; }
226
		/// Return vector filled with unknowns of the block with their derivatives.
227
		upMatrix Unknown(const Storage & e) const {return VectorEntry::operator [](e);}
228
		/// Return vector filled with unknowns of the block with their derivatives.
229
		upMatrix operator [](const Storage & e) const { upMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(0,0) = Unknown(e,k); return ret; }
230
		/// The intended size of the matrix for this entry.
231
		INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {return (INMOST_DATA_ENUM_TYPE)unknown_tag[e].size();}
232 233 234
		/// Number of tags in block.
		INMOST_DATA_ENUM_TYPE Size() const {return 1;}
		/// Number of entries for each tag in the block.
235
		INMOST_DATA_ENUM_TYPE Size(const Storage & e) const {return (INMOST_DATA_ENUM_TYPE)unknown_tag[e].size();}
236
		/// Retrive component of the tag related to unknown.
237
        INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk==0); return ENUMUNDEF;}
238
		/// Retrive tag related to unknown value.
239
        TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk==0); return unknown_tag;}
240 241 242 243 244 245 246 247 248 249
		/// Retrive mesh pointer.
		Mesh * GetMeshLink() const {return unknown_tag.GetMeshLink();}
		/// Make a copy of the object
		AbstractEntry * Copy() const {return new VectorEntry(GetElementType(),GetMask(),unknown_tag);}
	};
	/// This class is used to organize unknowns into blocks and provides mechanisms to change activation statuses of individual unknowns,
	/// blocks enumeration are managed by class Automatizator. This is less efficient then BlockEntry for single status.
	/// \todo
	/// 1. Check it works
	class StatusBlockEntry : public AbstractEntry 
Kirill Terekhov committed
250
	{
251 252 253 254
		std::vector<TagRealArray>          unknown_tags; ///< Tags for unknown values that enter the block.
		std::vector<INMOST_DATA_ENUM_TYPE> unknown_comp; ///< Component of the tag used as unknown.
		TagInteger                         status_tag; ///< Integer tag that determines current status of the block, value should be no greater then number of entries in status_tbl array.
		std::vector< std::vector<bool> >   status_tbl; ///< Array of statuses for activation of unknowns, length should be equal to number of unknowns, provided by user.
Kirill Terekhov committed
255
	public:
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
		/// Default constructor.
		StatusBlockEntry(ElementType etype = NONE, MarkerType mask = 0) : AbstractEntry(etype,mask), status_tag(Tag()) {}
		/// Constructor with status tag.
		StatusBlockEntry(ElementType etype, MarkerType mask, TagInteger status_tag) : AbstractEntry(etype,mask), status_tag(status_tag) {}
		/// Constructor with status tag and status table.
		StatusBlockEntry(ElementType etype, MarkerType mask, TagInteger status_tag, const std::vector< std::vector<bool> >  & status_tbl) : AbstractEntry(etype,mask), status_tag(status_tag), status_tbl(status_tbl) {}
		/// Add a component of the tag as unknown, by default all components of the tag are added.
		/// Adding all components of variable-sized tags is not supported.
		/// \warning Tags should belong to the same mesh and should be defined on the elements indicated in etype.
		void AddTag(Tag value, INMOST_DATA_ENUM_TYPE comp = ENUMUNDEF);
		/// Add status into table.
		void AddStatus(const std::vector<bool> & stat) {status_tbl.push_back(stat);}
		/// Set status tag.
		void SetStatusTag(TagInteger input) {status_tag = input;}
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return unknown_tags[pos][e][unknown_comp[pos]];}
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE & Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) {return unknown_tags[pos][e][unknown_comp[pos]];}
		/// Return index in vector of indices of the block at certain position.
		INMOST_DATA_ENUM_TYPE Index(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return isValid(e) && status_tbl[status_tag[e]][pos] ? GetOffsetTag()[e]+pos : ENUMUNDEF;}
		/// Return unknown in vector of variables of the block at certain position.
		unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const {return unknown(Value(e,pos),Index(e,pos));}
		/// Return vector filled with values of unknowns of the block.
279
		rpMatrix Value(const Storage & e) const {rpMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
280
		/// Return vector filled with indices of unknowns of the block.
281
		ipMatrix Index(const Storage & e) const {ipMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
282
		/// Return vector filled with unknowns of the block with their derivatives.
283
		upMatrix Unknown(const Storage & e) const {return StatusBlockEntry::operator [](e);}
284
		/// Return vector filled with unknowns of the block with their derivatives.
285
		upMatrix operator [](const Storage & e) const {upMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
286
		/// The intended size of the matrix for this entry.
287
        INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return Size();}
288
		/// Number of tags in block.
289
		INMOST_DATA_ENUM_TYPE Size() const {return (INMOST_DATA_ENUM_TYPE)unknown_tags.size();}
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
		/// Number of entries for each tag in the block.
		INMOST_DATA_ENUM_TYPE Size(const Storage & e) const;
		/// Retrive component of the tag related to unknown.
		INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const {return unknown_comp[unk];}
		/// Retrive tag related to unknown value.
		TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const {return unknown_tags[unk];}
		/// Retrive mesh pointer.
		Mesh * GetMeshLink() const {return unknown_tags.back().GetMeshLink();}
		/// Make a copy of the object
		AbstractEntry * Copy() const;
	};
	/// Stack together multiple objects of AbstractEntry class.
	/// This may help enumerate together variable-sized and constant-sized entries or blocks.
	/// Essentially can replace BlockEntry but may proove to be less efficient.
	/// \todo
	/// 1. Check it works
	/// 2. Check if it crashes with different combinations of entries on different element types or different masks.
	class MultiEntry : public AbstractEntry 
	{
		std::vector<AbstractEntry *> entries;
	public:
		///Default constructor.
		MultiEntry(ElementType etype = NONE, MarkerType mask = 0) : AbstractEntry(etype,mask) {}
		///Destructor.
		~MultiEntry() {for(unsigned k = 0; k < entries.size(); ++k) delete entries[k];}
		///Add entry into block of entries.
		void AddEntry(const AbstractEntry & entry);
		///Retirve entry from block of entries.
		AbstractEntry & GetEntry(INMOST_DATA_ENUM_TYPE k) {return *entries[k];}
		///Retirve entry from block of entries.
		const AbstractEntry & GetEntry(INMOST_DATA_ENUM_TYPE k) const {return *entries[k];}
		///Total number of entries.
322
		INMOST_DATA_ENUM_TYPE NumEntries() const {return (INMOST_DATA_ENUM_TYPE)entries.size();}
323 324 325 326 327 328 329 330 331
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const;
		/// Return value in vector of unknowns of the block at certain position.
		INMOST_DATA_REAL_TYPE & Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos);
		/// Return index in vector of indices of the block at certain position.
		INMOST_DATA_ENUM_TYPE Index(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const;
		/// Return unknown in vector of variables of the block at certain position.
		unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const;
		/// Return vector filled with values of unknowns of the block.
332
		rpMatrix Value(const Storage & e) const;
333
		/// Return vector filled with indices of unknowns of the block.
334
		ipMatrix Index(const Storage & e) const;
335
		/// Return vector filled with unknowns of the block with their derivatives.
336
		upMatrix Unknown(const Storage & e) const {return MultiEntry::operator [](e);}
337
		/// Return vector filled with unknowns of the block with their derivatives.
338
		upMatrix operator [](const Storage & e) const;
339 340 341 342 343 344 345 346 347 348 349 350 351 352
		/// The intended size of the matrix for this entry.
		INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const;
		/// Number of tags in block.
		INMOST_DATA_ENUM_TYPE Size() const {INMOST_DATA_ENUM_TYPE ret = 0; for(unsigned k = 0; k < entries.size(); ++k) ret += entries[k]->Size(); return ret;}
		/// Number of entries for each tag in the block.
		INMOST_DATA_ENUM_TYPE Size(const Storage & e) const {INMOST_DATA_ENUM_TYPE ret = 0; for(unsigned k = 0; k < entries.size(); ++k) ret += entries[k]->Size(e); return ret;}
		/// Retrive component of the tag related to unknown.
		INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const;
		/// Retrive tag related to unknown value.
		TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const;
		/// Retrive mesh pointer.
		Mesh * GetMeshLink() const {assert(!entries.empty()); return entries.back()->GetMeshLink();}
		/// Make a copy of the object
		AbstractEntry * Copy() const;
Kirill Terekhov committed
353
	};
Kirill Terekhov committed
354 355 356 357 358 359 360 361 362
	/// The Automatizator class helps in defining primary unknowns of the model and
	/// enhances user experience in interaction with automatic differentiation functionality.
	/// User may declare real-typed mesh data as primary unknowns on the mesh with the
	/// function RegisterTag. The returned integer code can be used with dynamic_variable
	/// class, that is part of automatic differentiation framework helping to assemble
	/// unknowns or expressions that could be evaluated into variable on the mesh element.
	/// In addition this class provides automatic differentiation with acceleration structures
	/// that help evaluate expressions faster.
	/// \todo
363
	/// 1. (test) UnRegisterTag.
Kirill Terekhov committed
364
	/// 2. (test) Copy constructor.
365
	/// 3. Rename
Kirill Terekhov committed
366 367 368
	class Automatizator
	{
	private:
369 370
		static Automatizator * CurrentAutomatizator; ///< Currently used automatizator for automatic differentiation acceleration structures.
		std::vector<Sparse::RowMerger> merger; ///< Automatic differentiation acceleration structures.
371
		typedef std::vector<AbstractEntry *>       blk_enum; ///< A type for an array of registered tags.
372
		typedef std::vector<INMOST_DATA_ENUM_TYPE> del_enum; ///< A type for an array of deleted positions.
373
		typedef std::vector<bool>                  act_enum; ///< A type for an array of deactivation flags.
Kirill Terekhov committed
374
	private:
375
		std::string           name; ///< Name of the automatizator.
376 377 378
		del_enum              del_blocks; ///< Array of deleted positions.
		blk_enum              reg_blocks; ///< Array of registered blocks.
		act_enum              act_blocks; ///< Deactivated blocks since they were deleted
379 380
		INMOST_DATA_ENUM_TYPE first_num; ///< First index in unknowns of locally owned elements.
		INMOST_DATA_ENUM_TYPE last_num; ///< Last index in unknowns of locally owned elements.
Kirill Terekhov committed
381
	public:
Kirill Terekhov committed
382 383
		/// Make a copy.
		/// \warning
384
		/// Calls Automatizator::EnumerateEntries after copy for indices
Kirill Terekhov committed
385 386 387 388
		/// to be valid only if original was enumerated.
		Automatizator(const Automatizator & b);
		/// Performs assignment.
		/// \warning
389
		/// Calls Automatizator::EnumerateEntries after copy for indices
Kirill Terekhov committed
390 391 392 393 394 395
		/// to be valid only if original was enumerated.
		Automatizator & operator =(Automatizator const & b);
		/// Makes an empty Automatizator.
		Automatizator(std::string name = "");
		/// Destructor for the automatizator, deletes all the tags corresponding to indices from
		/// respective meshes.
Kirill Terekhov committed
396
		~Automatizator();
Kirill Terekhov committed
397 398 399 400
		/// Retrive first index of unknowns, local to the processor.
		__INLINE INMOST_DATA_ENUM_TYPE GetFirstIndex() const { return first_num; }
		/// Retrive last index of unknowns, local to the processor.
		__INLINE INMOST_DATA_ENUM_TYPE GetLastIndex() const { return last_num; }
401
		/// Set data of tag t defined on domain_mask to be dynamic data.
Kirill Terekhov committed
402 403 404
		/// @param t Tag of DATA_REAL that represents independent data of the model.
		/// @param typemask Element types on which that data is independent.
		/// @param domain_mask Marker that may be used to mask indepndent data on certain elements.
405
		/// \warning
Kirill Terekhov committed
406
		/// 1. Don't register tag twice.
407
		/// 2. Have to call Automatizator::EnumerateEntries to compute indices.
Kirill Terekhov committed
408
		INMOST_DATA_ENUM_TYPE RegisterTag(Tag t, ElementType typemask, MarkerType domain_mask = 0);
409 410 411 412 413 414
		/// Register block with the automatizator.
		/// Note that copy of entry is stored with Automatizator.
		/// @param b Entry that represents block of indepenedent unknowns of the model.
		/// \warning
		/// 1. If you create your entry with intention to use it after registration, then you should use the function as entry = aut.GetEntry(aut.RegisterEntry(entry));
		INMOST_DATA_ENUM_TYPE RegisterEntry(const AbstractEntry & e);
Kirill Terekhov committed
415
		INMOST_DATA_ENUM_TYPE RegisterEntry(AbstractEntry & e);
Kirill Terekhov committed
416 417 418
		/// Erase a registered tag.
		/// @param ind Integer returned from Automatizator::RegisterTag.
		/// \warning
419 420
		/// 1. Have to call Automatizator::EnumerateEntries to recompute indices.
		void UnregisterEntry(INMOST_DATA_ENUM_TYPE ind);
421 422 423 424 425 426 427 428 429 430
		/// Swith a registered tag to be non-active, in this case it's unknowns are considered to be constant.
		/// @param ind Integer returned from Automatizator::RegisterTag.
		/// \warning
		/// 1. Have to call Automatizator::EnumerateEntries to recompute indices.
		void DeactivateEntry(INMOST_DATA_ENUM_TYPE ind);
		/// Swith a registered tag to be active, in this case it's unknowns are considered to be variable.
		/// @param ind Integer returned from Automatizator::RegisterTag.
		/// \warning
		/// 1. Have to call Automatizator::EnumerateEntries to recompute indices.
		void ActivateEntry(INMOST_DATA_ENUM_TYPE ind);
431
		/// Set index for every data entry of dynamic tag.
432
		void EnumerateEntries();
Kirill Terekhov committed
433 434
		/// Check whether the tag is still registered.
		/// @param True if tag is still registered.
435
		__INLINE bool isRegisteredEntry(INMOST_DATA_ENUM_TYPE ind) const {return reg_blocks[ind] != NULL;}
436 437 438 439 440 441 442 443 444 445
		/// Get index of the unknown associated with the entry on element.
		INMOST_DATA_ENUM_TYPE GetIndex(const Storage & e, INMOST_DATA_ENUM_TYPE reg_index, INMOST_DATA_ENUM_TYPE pos = 0) const {return GetEntry(reg_index).Index(e,pos);}
		/// Get value of the unknown associated with the entry on element.
		INMOST_DATA_REAL_TYPE GetValue(const Storage & e, INMOST_DATA_ENUM_TYPE reg_index, INMOST_DATA_ENUM_TYPE pos = 0) const {return GetEntry(reg_index).Value(e,pos);}
		/// Get unknown associated with the entry on element.
		unknown GetUnknown(const Storage & e, INMOST_DATA_ENUM_TYPE reg_index, INMOST_DATA_ENUM_TYPE pos = 0) const {return GetEntry(reg_index).Unknown(e,pos);}
		/// Retive the block from automatizator by index.
		AbstractEntry & GetEntry(INMOST_DATA_ENUM_TYPE ind) {return *reg_blocks[ind];}
		/// Retive the block from automatizator by index.
		const AbstractEntry & GetEntry(INMOST_DATA_ENUM_TYPE ind) const {return *reg_blocks[ind];}
Kirill Terekhov committed
446
		/// @return Acceleration structure.
447
		__INLINE Sparse::RowMerger & GetMerger() {return merger[OMP_THREAD];}
Kirill Terekhov committed
448
		/// Remove global current automatizator used to set acceleration structures for automatic differentation.
449 450 451 452 453 454
		static void RemoveCurrent() {CurrentAutomatizator = NULL;}
		/// Set current global automatizator, so that variable will be optimized with row merger.
		static void MakeCurrent(Automatizator * aut) {CurrentAutomatizator = aut;}
		/// Check that there is an automatizator.
		static bool HaveCurrent() {return CurrentAutomatizator != NULL;}
		/// Retrive the automatizator.
Kirill Terekhov committed
455
		/// @return Currently set automatizator.
456
		static Automatizator * GetCurrent() {return CurrentAutomatizator;}
Kirill Terekhov committed
457 458
		/// Lists all the indices of registered tags.
		/// @return An array with indices corresponding to all registered tags.
459
		std::vector<INMOST_DATA_ENUM_TYPE> ListRegisteredEntries() const;
460 461 462
		/// Update variables  contained in all block of automatizator on ghost elements of the grid.
		/// For synchronization of data in individual blocks see AbstractEntry::SynhronizeData.
		void SynchronizeData();
Kirill Terekhov committed
463
	};
464
} //namespace INMOST
Kirill Terekhov committed
465

466 467
#endif //USE_AUTODIFF && USE_MESH

468
#endif //INMOST_AUTODIFF_H_INCLUDED