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

475
476
#endif //USE_AUTODIFF && USE_MESH

477
#endif //INMOST_AUTODIFF_H_INCLUDED