inmost_autodiff.h 29.5 KB
Newer Older
Kirill Terekhov's avatar
Kirill Terekhov committed
1

Kirill Terekhov's avatar
Kirill Terekhov committed
2 3
#ifndef INMOST_AUTODIFF_H_INCLUDED
#define INMOST_AUTODIFF_H_INCLUDED
4

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

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

namespace INMOST
{
	class Automatizator; //forward declaration
Kirill Terekhov's avatar
Kirill Terekhov committed
13
	
14 15 16 17 18
	/// 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?
19 20
	/// 3. Function for update of variables.
	/// 4. Function for synchronization of variables.
21 22 23 24 25 26 27
	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:
28 29
		AbstractEntry(ElementType etype = NONE, MarkerType mask = 0)
		: reg_index(ENUMUNDEF), offset_tag(Tag()), mask(mask), etype(etype) {}
30 31 32 33 34 35 36 37 38 39 40 41 42
		/// 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.
43
		bool isValid(const Storage & e) const {return reg_index != ENUMUNDEF && (e.GetElementType() & etype) && (mask == 0 || e->GetMarker(mask));}
44
		/// Return value in vector of unknowns of the block at certain position.
Kirill Terekhov's avatar
Kirill Terekhov committed
45
		/// @param pos Position for which to extract the value, should be no larger then MatrixSize.
46 47
		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's avatar
Kirill Terekhov committed
48
		/// @param pos Position for which to extract the value, should be no larger then MatrixSize.
49 50 51
		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's avatar
Kirill Terekhov committed
52
		/// @param pos Position for which to extract the index, should be no larger then MatrixSize.
53 54
		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's avatar
Kirill Terekhov committed
55
		/// @param pos Position for which to extract the unknown, should be no larger then MatrixSize.
56 57 58 59 60 61
		virtual unknown Unknown(const Storage & e, INMOST_DATA_ENUM_TYPE pos) const = 0;
		/// Return vector filled with values of unknowns of the block.
		virtual rMatrix Value(const Storage & e) const = 0;
		/// Return vector filled with indices of unknowns of the block.
		virtual iMatrix Index(const Storage & e) const = 0;
		/// Return vector filled with unknowns of the block with their derivatives.
62
		virtual uMatrix Unknown(const Storage & e) const = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
63 64 65 66 67 68 69
		/// Return vector filled with either values or indices or unknowns of the block,
		/// depending on the template parameter.
		template<typename T> Matrix<T> Access(const Storage &e) const;
		/// 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.
		template<typename T> T Access(const Storage &e, INMOST_DATA_ENUM_TYPE pos) const;
70
		/// Return vector filled with unknowns of the block with their derivatives.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
		virtual uMatrix operator [](const Storage & e) const = 0;
		/// 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;}
92 93 94
		/// Update variables  contained in block on ghost elements of the grid.
		/// For synchronization of data in all blocks see Automatizator::SynhronizeData.
		void SynchronizeData();
95 96 97 98
		/// Destructor.
		virtual ~AbstractEntry() {}
		
		friend class Automatizator; //provide registration index from inside of Automatizator
99
		friend class Model; //provide registration index from inside of Model
100
	};
Kirill Terekhov's avatar
Kirill Terekhov committed
101 102 103
	
	
	
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
	/// 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.
		rMatrix Value(const Storage & e) const {rMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
		/// Return vector filled with indices of unknowns of the block.
		iMatrix Index(const Storage & e) const {iMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
		/// Return vector filled with unknowns of the block with their derivatives.
130 131
		uMatrix Unknown(const Storage & e) const {return BlockEntry::operator [](e);}
		/// Return vector filled with unknowns of the block with their derivatives.
132 133
		uMatrix operator [](const Storage & e) const {uMatrix ret(MatrixSize(e),1); for(unsigned k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
		/// The intended size of the matrix for this entry.
134
        INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return Size();}
135
		/// Number of tags in block.
136
		INMOST_DATA_ENUM_TYPE Size() const {return (INMOST_DATA_ENUM_TYPE)unknown_tags.size();}
137
		/// Number of entries for each tag in the block.
138
        INMOST_DATA_ENUM_TYPE Size(const Storage & e) const {(void)e; return (INMOST_DATA_ENUM_TYPE)unknown_tags.size();}
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
		/// 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.
161
        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];}
162
		/// Return value in vector of unknowns of the block at certain position.
163
        INMOST_DATA_REAL_TYPE & Value(const Storage & e, INMOST_DATA_ENUM_TYPE pos) {(void)pos; assert(pos==0); return unknown_tag[e][unknown_comp];}
164
		/// Return index in vector of indices of the block at certain position.
165
        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;}
166 167 168 169 170 171 172
		/// 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.
		rMatrix Value(const Storage & e) const { rMatrix ret(1,1); ret(0,0) = Value(e,0); return ret; }
		/// Return vector filled with indices of unknowns of the block.
		iMatrix Index(const Storage & e) const { iMatrix ret(1,1); ret(0,0) = Index(e,0); return ret; }
		/// Return vector filled with unknowns of the block with their derivatives.
173 174
		uMatrix Unknown(const Storage & e) const {return SingleEntry::operator [](e);}
		/// Return vector filled with unknowns of the block with their derivatives.
175 176
		uMatrix operator [](const Storage & e) const { uMatrix ret(1,1); ret(0,0) = Unknown(e,0); return ret; }
		/// The intended size of the matrix for this entry.
177
        INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return 1;}
178 179 180
		/// Number of tags in block.
		INMOST_DATA_ENUM_TYPE Size() const {return 1;}
		/// Number of entries for each tag in the block.
181
        INMOST_DATA_ENUM_TYPE Size(const Storage & e) const {(void)e; return 1;}
182
		/// Retrive component of the tag related to unknown.
183
        INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk == 0); return unknown_comp;}
184
		/// Retrive tag related to unknown value.
185
        TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk == 0); return unknown_tag;}
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
		/// 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.
211
		rMatrix Value(const Storage & e) const { rMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Value(e,k); return ret; }
212
		/// Return vector filled with indices of unknowns of the block.
213
		iMatrix Index(const Storage & e) const { iMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(k,0) = Index(e,k); return ret; }
214
		/// Return vector filled with unknowns of the block with their derivatives.
215 216
		uMatrix Unknown(const Storage & e) const {return VectorEntry::operator [](e);}
		/// Return vector filled with unknowns of the block with their derivatives.
217
		uMatrix operator [](const Storage & e) const { uMatrix ret(MatrixSize(e),1); for(int k = 0; k < (int)unknown_tag[e].size(); ++k) ret(0,0) = Unknown(e,k); return ret; }
218
		/// The intended size of the matrix for this entry.
219
		INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {return (INMOST_DATA_ENUM_TYPE)unknown_tag[e].size();}
220 221 222
		/// Number of tags in block.
		INMOST_DATA_ENUM_TYPE Size() const {return 1;}
		/// Number of entries for each tag in the block.
223
		INMOST_DATA_ENUM_TYPE Size(const Storage & e) const {return (INMOST_DATA_ENUM_TYPE)unknown_tag[e].size();}
224
		/// Retrive component of the tag related to unknown.
225
        INMOST_DATA_ENUM_TYPE GetValueComp(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk==0); return ENUMUNDEF;}
226
		/// Retrive tag related to unknown value.
227
        TagRealArray GetValueTag(INMOST_DATA_ENUM_TYPE unk) const {(void)unk; assert(unk==0); return unknown_tag;}
228 229 230 231 232 233 234 235 236 237
		/// 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's avatar
Kirill Terekhov committed
238
	{
239 240 241 242
		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's avatar
Kirill Terekhov committed
243
	public:
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
		/// 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.
267
		rMatrix Value(const Storage & e) const {rMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Value(e,k); return ret; }
268
		/// Return vector filled with indices of unknowns of the block.
269
		iMatrix Index(const Storage & e) const {iMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Index(e,k); return ret; }
270
		/// Return vector filled with unknowns of the block with their derivatives.
271 272
		uMatrix Unknown(const Storage & e) const {return StatusBlockEntry::operator [](e);}
		/// Return vector filled with unknowns of the block with their derivatives.
273
		uMatrix operator [](const Storage & e) const {uMatrix ret(MatrixSize(e),1); for(INMOST_DATA_ENUM_TYPE k = 0; k < Size(); ++k) ret(k,0) = Unknown(e,k); return ret; }
274
		/// The intended size of the matrix for this entry.
275
        INMOST_DATA_ENUM_TYPE MatrixSize(const Storage & e) const {(void)e; return Size();}
276
		/// Number of tags in block.
277
		INMOST_DATA_ENUM_TYPE Size() const {return (INMOST_DATA_ENUM_TYPE)unknown_tags.size();}
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
		/// 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.
310
		INMOST_DATA_ENUM_TYPE NumEntries() const {return (INMOST_DATA_ENUM_TYPE)entries.size();}
311 312 313 314 315 316 317 318 319
		/// 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.
Kirill Terekhov's avatar
Kirill Terekhov committed
320
		rMatrix Value(const Storage & e) const;
321
		/// Return vector filled with indices of unknowns of the block.
Kirill Terekhov's avatar
Kirill Terekhov committed
322
		iMatrix Index(const Storage & e) const;
323
		/// Return vector filled with unknowns of the block with their derivatives.
324 325
		uMatrix Unknown(const Storage & e) const {return MultiEntry::operator [](e);}
		/// Return vector filled with unknowns of the block with their derivatives.
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
		uMatrix operator [](const Storage & e) const;
		/// 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's avatar
Kirill Terekhov committed
341
	};
Kirill Terekhov's avatar
Kirill Terekhov committed
342 343 344 345 346 347 348 349 350
	/// 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
351
	/// 1. (test) UnRegisterTag.
Kirill Terekhov's avatar
Kirill Terekhov committed
352
	/// 2. (test) Copy constructor.
353
	/// 3. Rename
Kirill Terekhov's avatar
Kirill Terekhov committed
354 355 356
	class Automatizator
	{
	private:
357 358
		static Automatizator * CurrentAutomatizator; ///< Currently used automatizator for automatic differentiation acceleration structures.
		std::vector<Sparse::RowMerger> merger; ///< Automatic differentiation acceleration structures.
359
		typedef std::vector<AbstractEntry *>       blk_enum; ///< A type for an array of registered tags.
360
		typedef std::vector<INMOST_DATA_ENUM_TYPE> del_enum; ///< A type for an array of deleted positions.
361
		typedef std::vector<bool>                  act_enum; ///< A type for an array of deactivation flags.
Kirill Terekhov's avatar
Kirill Terekhov committed
362
	private:
363
		std::string           name; ///< Name of the automatizator.
364 365 366
		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
367 368
		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's avatar
Kirill Terekhov committed
369
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
370 371
		/// Make a copy.
		/// \warning
372
		/// Calls Automatizator::EnumerateEntries after copy for indices
Kirill Terekhov's avatar
Kirill Terekhov committed
373 374 375 376
		/// to be valid only if original was enumerated.
		Automatizator(const Automatizator & b);
		/// Performs assignment.
		/// \warning
377
		/// Calls Automatizator::EnumerateEntries after copy for indices
Kirill Terekhov's avatar
Kirill Terekhov committed
378 379 380 381 382 383
		/// 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's avatar
Kirill Terekhov committed
384
		~Automatizator();
Kirill Terekhov's avatar
Kirill Terekhov committed
385 386 387 388
		/// 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; }
389
		/// Set data of tag t defined on domain_mask to be dynamic data.
Kirill Terekhov's avatar
Kirill Terekhov committed
390 391 392
		/// @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.
393
		/// \warning
Kirill Terekhov's avatar
Kirill Terekhov committed
394
		/// 1. Don't register tag twice.
395
		/// 2. Have to call Automatizator::EnumerateEntries to compute indices.
Kirill Terekhov's avatar
Kirill Terekhov committed
396
		INMOST_DATA_ENUM_TYPE RegisterTag(Tag t, ElementType typemask, MarkerType domain_mask = 0);
397 398 399 400 401 402
		/// 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's avatar
Kirill Terekhov committed
403
		INMOST_DATA_ENUM_TYPE RegisterEntry(AbstractEntry & e);
Kirill Terekhov's avatar
Kirill Terekhov committed
404 405 406
		/// Erase a registered tag.
		/// @param ind Integer returned from Automatizator::RegisterTag.
		/// \warning
407 408
		/// 1. Have to call Automatizator::EnumerateEntries to recompute indices.
		void UnregisterEntry(INMOST_DATA_ENUM_TYPE ind);
409 410 411 412 413 414 415 416 417 418
		/// 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);
419
		/// Set index for every data entry of dynamic tag.
420
		void EnumerateEntries();
Kirill Terekhov's avatar
Kirill Terekhov committed
421 422
		/// Check whether the tag is still registered.
		/// @param True if tag is still registered.
423
		__INLINE bool isRegisteredEntry(INMOST_DATA_ENUM_TYPE ind) const {return reg_blocks[ind] != NULL;}
424 425 426 427 428 429 430 431 432 433
		/// 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's avatar
Kirill Terekhov committed
434
		/// @return Acceleration structure.
435
		__INLINE Sparse::RowMerger & GetMerger() {return merger[OMP_THREAD];}
Kirill Terekhov's avatar
Kirill Terekhov committed
436
		/// Remove global current automatizator used to set acceleration structures for automatic differentation.
437 438 439 440 441 442
		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's avatar
Kirill Terekhov committed
443
		/// @return Currently set automatizator.
444
		static Automatizator * GetCurrent() {return CurrentAutomatizator;}
Kirill Terekhov's avatar
Kirill Terekhov committed
445 446
		/// Lists all the indices of registered tags.
		/// @return An array with indices corresponding to all registered tags.
447
		std::vector<INMOST_DATA_ENUM_TYPE> ListRegisteredEntries() const;
448 449 450
		/// 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's avatar
Kirill Terekhov committed
451
	};
452
} //namespace INMOST
Kirill Terekhov's avatar
Kirill Terekhov committed
453

454 455
#endif //USE_AUTODIFF && USE_MESH

456
#endif //INMOST_AUTODIFF_H_INCLUDED