parallel.cpp 257 KB
Newer Older
Kirill Terekhov's avatar
Kirill Terekhov committed
1
#ifdef _MSC_VER //kill some warnings
2
#ifndef _SCL_SECURE_NO_WARNINGS
Kirill Terekhov's avatar
Kirill Terekhov committed
3
4
#define _SCL_SECURE_NO_WARNINGS
#endif
5
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
6

Kirill Terekhov's avatar
Kirill Terekhov committed
7
8
9
10
11
12
13
#include "inmost.h"


#if defined(USE_MESH)
#include <iostream>
#include <fstream>
#include <sstream>
14
#include <string>
Kirill Terekhov's avatar
Kirill Terekhov committed
15
#include <queue>
Kirill Terekhov's avatar
Kirill Terekhov committed
16

Kirill Terekhov's avatar
Kirill Terekhov committed
17
//using namespace std;
Kirill Terekhov's avatar
Kirill Terekhov committed
18

Kirill Terekhov's avatar
fix    
Kirill Terekhov committed
19
#if defined(USE_PARALLEL_STORAGE)
20
bool allow_pack_by_gids = true;
Kirill Terekhov's avatar
fix    
Kirill Terekhov committed
21
22
23
24
#else // USE_PARALLEL_STORAGE
bool allow_pack_by_gids = false;
#endif // USE_PARALLEL_STORAGE

25

Kirill Terekhov's avatar
Kirill Terekhov committed
26
27
#if defined(USE_MPI)
static INMOST_DATA_BIG_ENUM_TYPE pmid = 0;
Kirill Terekhov's avatar
fix    
Kirill Terekhov committed
28
#endif // USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
29

30
31
32
33
34
35
36
37
static std::string NameSlash(std::string input)
{
	for(unsigned l = input.size(); l > 0; --l)
		if( input[l-1] == '/' || input[l-1] == '\\' )
			return std::string(input.c_str() + l);
	return input;
}

Kirill Terekhov's avatar
Kirill Terekhov committed
38
39
40
41
#if defined(USE_PARALLEL_WRITE_TIME)
#define REPORT_MPI(x) {WriteTab(out_time) << "<MPI><![CDATA[" << #x << "]]></MPI>" << std::endl; x;}
#define REPORT_STR(x) {WriteTab(out_time) << "<TEXT><![CDATA[" << x << "]]></TEXT>" << std::endl;}
#define REPORT_VAL(str,x) {WriteTab(out_time) << "<VALUE name=\"" << str << "\"> <CONTENT><![CDATA[" << x << "]]></CONTENT> <CODE><![CDATA[" << #x << "]]></CODE></VALUE>" << std::endl;}
Kirill Terekhov's avatar
Kirill Terekhov committed
42
#define ENTER_FUNC() double all_time = Timer(); {WriteTab(out_time) << "<FUNCTION name=\"" << __FUNCTION__ << "\" id=\"func" << func_id++ << "\">" << std::endl; Enter();}
43
44
45
#define ENTER_BLOCK() { double btime = Timer(); WriteTab(out_time) << "<FUNCTION name=\"" << __FUNCTION__ << ":" << NameSlash(__FILE__) << ":" << __LINE__ << "\" id=\"func" << GetFuncID()++ << "\">" << std::endl; Enter();
#define EXIT_BLOCK() WriteTab(out_time) << "<TIME>" << Timer() - btime << "</TIME>" << std::endl; Exit(); WriteTab(out_time) << "</FUNCTION>" << std::endl;}

Kirill Terekhov's avatar
Kirill Terekhov committed
46
47
#define EXIT_FUNC() {WriteTab(out_time) << "<TIME>" << Timer() - all_time << "</TIME>" << std::endl; Exit(); WriteTab(out_time) << "</FUNCTION>" << std::endl;}
#define EXIT_FUNC_DIE() {WriteTab(out_time) << "<TIME>" << -1 << "</TIME>" << std::endl; Exit(); WriteTab(out_time) << "</FUNCTION>" << std::endl;}
Kirill Terekhov's avatar
fix    
Kirill Terekhov committed
48
#else // USE_PARALLEL_WRITE_TIME
Kirill Terekhov's avatar
Kirill Terekhov committed
49
#define REPORT_MPI(x) x
Kirill Terekhov's avatar
Kirill Terekhov committed
50
51
52
#define REPORT_STR(x) {}
#define REPORT_VAL(str,x) {}
#define ENTER_FUNC() {}
53
54
#define ENTER_BLOCK()
#define EXIT_BLOCK()
Kirill Terekhov's avatar
Kirill Terekhov committed
55
56
#define EXIT_FUNC() {}
#define EXIT_FUNC_DIE()  {}
Kirill Terekhov's avatar
fix    
Kirill Terekhov committed
57
#endif // USE_PARALLEL_WRITE_TIME
Kirill Terekhov's avatar
Kirill Terekhov committed
58

Kirill Terekhov's avatar
Kirill Terekhov committed
59
60
61
62
63
64
65
66

#if defined(__LINUX__) || defined(__linux__) || defined(__APPLE__)
#include <unistd.h>
#define PROCESSID getpid()
#else
#define PROCESSID -1
#endif

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

#if 1
#define MPI_Pack_call(data,size,type,buf,buf_size,pos,comm)   MPI_Pack(data,size,type,buf,buf_size,pos,comm)
#define MPI_Pack_size_call(size,type,comm,ret)                MPI_Pack_size(size,type,comm,ret)
#define MPI_Unpack_call(buf,buf_size,pos,data,size,type,comm) MPI_Unpack(buf,buf_size,pos,data,size,type,comm)
#define POS_TYPE int
#define SEND_AS MPI_PACKED
#else
#define MPI_Pack_call(data,size,type,buf,buf_size,pos,comm)   MPI_Pack_external("external32",data,size,type,buf,buf_size,pos)
#define MPI_Pack_size_call(size,type,comm,ret)                MPI_Pack_external_size("external32",size,type,ret)
#define MPI_Unpack_call(buf,buf_size,pos,data,size,type,comm) MPI_Unpack_external("external32",buf,buf_size,pos,data,size,type)
#define POS_TYPE MPI_Aint
#define SEND_AS MPI_BYTE
#endif


#if SIZE_MAX == UCHAR_MAX
#define MPI_SIZE_T MPI_UNSIGNED_CHAR
#elif SIZE_MAX == USHRT_MAX
#define MPI_SIZE_T MPI_UNSIGNED_SHORT
#elif SIZE_MAX == UINT_MAX
#define MPI_SIZE_T MPI_UNSIGNED
#elif SIZE_MAX == ULONG_MAX
#define MPI_SIZE_T MPI_UNSIGNED_LONG
#elif SIZE_MAX == ULLONG_MAX
#define MPI_SIZE_T MPI_UNSIGNED_LONG_LONG
#else
#error "Cannot detect size_t type"
#endif


Kirill Terekhov's avatar
Kirill Terekhov committed
98
99
namespace INMOST
{
100
101
102
103
	
	template<typename T> struct MPIType;
	template<> struct MPIType<bool> {static MPI_Datatype Type() {return MPI_C_BOOL;}};
	template<> struct MPIType<char> {static MPI_Datatype Type() {return MPI_CHAR;}};
104
	template<> struct MPIType<const char> {static MPI_Datatype Type() {return MPI_CHAR;}};
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
	template<> struct MPIType<int> {static MPI_Datatype Type() {return MPI_INT;}};
	template<> struct MPIType<short> {static MPI_Datatype Type() {return MPI_SHORT;}};
	template<> struct MPIType<long> {static MPI_Datatype Type() {return MPI_LONG;}};
	template<> struct MPIType<long long> {static MPI_Datatype Type() {return MPI_LONG_LONG;}};
	template<> struct MPIType<unsigned char> {static MPI_Datatype Type() {return MPI_UNSIGNED_CHAR;}};
	template<> struct MPIType<unsigned short> {static MPI_Datatype Type() {return MPI_UNSIGNED_SHORT;}};
	template<> struct MPIType<unsigned> {static MPI_Datatype Type() {return MPI_UNSIGNED;}};
	template<> struct MPIType<unsigned long> {static MPI_Datatype Type() {return MPI_UNSIGNED_LONG;}};
	template<> struct MPIType<unsigned long long> {static MPI_Datatype Type() {return MPI_UNSIGNED_LONG_LONG;}};
	template<> struct MPIType<double> {static MPI_Datatype Type() {return MPI_DOUBLE;}};
	template<> struct MPIType<long double> {static MPI_Datatype Type() {return MPI_LONG_DOUBLE;}};
	template<> struct MPIType<float> {static MPI_Datatype Type() {return MPI_FLOAT;}};
	//template<> struct MPIType<size_t> {static MPI_Datatype Type() {return MPI_SIZE_T;}};
	
	template<typename T>
120
	void pack_data(Mesh::buffer_type & buf, const T & data, INMOST_MPI_Comm comm)
121
122
	{
		int ierr;
123
		POS_TYPE pack_size = 0, shift = 0;
124
		size_t write_pos = buf.size();
125
126
		ierr = MPI_Pack_size_call(1,MPIType<T>::Type(),comm,&pack_size); 
		if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
127
		buf.resize(write_pos+pack_size);
128
129
		ierr = MPI_Pack_call((void*)&data,1,MPIType<T>::Type(),&buf[write_pos],pack_size,&shift,comm);
		if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
130
131
132
		buf.resize(write_pos+shift);
	}
	
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
	template<typename T>
	size_t pack_data_size(INMOST_MPI_Comm comm)
	{
		int ierr;
		POS_TYPE pack_size = 0, shift = 0;
		size_t ret = 0;
		ierr = MPI_Pack_size_call(1,MPIType<T>::Type(),comm,&pack_size); 
		if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
		ret += pack_size;
		return ret;
	}
	
	
	template<typename T>
	void pack_data_array(Mesh::buffer_type & buf, const T * data, size_t N, INMOST_MPI_Comm comm)
	{
		int ierr;
		if( N )
		{
			POS_TYPE pack_size = 0;
			ierr = MPI_Pack_size_call(1,MPIType<T>::Type(),comm,&pack_size);
			if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
			size_t rec_bytes = static_cast<size_t>(pack_size);
			size_t max_bytes = rec_bytes*N;
			size_t chunk_bytes = std::min(max_bytes,static_cast<size_t>(INT_MAX));
			size_t chunk_size = chunk_bytes / rec_bytes;
			size_t offset = 0;
			while( offset != N )
			{
				size_t write_pos = buf.size();
				size_t chunk = std::min(chunk_size, N-offset);
				ierr = MPI_Pack_size_call(static_cast<POS_TYPE>(chunk),MPIType<T>::Type(),comm,&pack_size); //pack_size is expected to be within INT_MAX
				if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
				buf.resize(write_pos+pack_size);
				POS_TYPE shift = 0;
				ierr = MPI_Pack_call((void *)&data[offset],static_cast<POS_TYPE>(chunk),MPIType<T>::Type(),&buf[write_pos],pack_size,&shift,comm);
				if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
				buf.resize(write_pos+shift);
				offset += chunk;
			}
		}
	}
	
176
177
	
	template<typename T>
178
	void pack_data_vector(Mesh::buffer_type & buf, const std::vector<T> & data, INMOST_MPI_Comm comm)
179
	{
180
		int ierr;
181
		pack_data(buf,data.size(),comm);
182
183
184
185
186
187
188
189
190
191
		if( !data.empty() ) 
			pack_data_array(buf,&data[0],data.size(),comm);
	}
	
	template<typename T>
	size_t pack_data_array_size(size_t N, INMOST_MPI_Comm comm)
	{
		int ierr;
		size_t ret = 0;
		if( N )
192
		{
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
			POS_TYPE pack_size = 0;
			ierr = MPI_Pack_size_call(1,MPIType<T>::Type(),comm,&pack_size);
			if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
			size_t rec_bytes = static_cast<size_t>(pack_size);
			size_t max_bytes = rec_bytes*N;
			size_t chunk_bytes = std::min(max_bytes,static_cast<size_t>(INT_MAX));
			size_t chunk_size = chunk_bytes / rec_bytes;
			size_t offset = 0;
			while( offset != N )
			{
				size_t chunk = std::min(chunk_size, N-offset);
				ierr = MPI_Pack_size_call(static_cast<POS_TYPE>(chunk),MPIType<T>::Type(),comm,&pack_size); //pack_size is expected to be within INT_MAX
				if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
				ret += pack_size;
				offset += chunk;
			}
209
		}
210
211
212
213
214
215
216
217
218
		return ret;
	}
	
	template<typename T>
	size_t pack_data_vector_size(size_t N, INMOST_MPI_Comm comm)
	{
		size_t ret = pack_data_size<size_t>(comm);
		if( N ) ret += pack_data_array_size<T>(N,comm);
		return ret;
219
220
221
222
	}
	
	
	template<typename T>
223
	void unpack_data(Mesh::buffer_type & buf, size_t & buf_pos, T & data, INMOST_MPI_Comm comm)
224
	{
225
226
227
228
229
230
231
		int ierr;
		POS_TYPE shift = 0, pack_size;
		ierr = MPI_Pack_size_call(1,MPIType<T>::Type(),comm,&pack_size); 
		if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
		ierr = MPI_Unpack_call((void*)&buf[buf_pos],pack_size,&shift,&data,1,MPIType<T>::Type(),comm);
		if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
		buf_pos += shift;
232
233
	}
	
234
	
235
	template<typename T>
236
	void unpack_data_array(Mesh::buffer_type & buf, size_t & buf_pos, T * data, size_t N, INMOST_MPI_Comm comm)
237
	{
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
		int ierr;
		if( N )
		{
			POS_TYPE pack_size = 0;
			ierr = MPI_Pack_size_call(1,MPIType<T>::Type(),comm,&pack_size);
			if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
			size_t rec_bytes = static_cast<size_t>(pack_size);
			size_t max_bytes = rec_bytes*N;
			size_t chunk_bytes = std::min(max_bytes,static_cast<size_t>(INT_MAX));
			size_t chunk_size = chunk_bytes / rec_bytes;
			size_t offset = 0;
			while( offset != N )
			{
				size_t chunk = std::min(chunk_size, N-offset);
				ierr = MPI_Pack_size_call(static_cast<POS_TYPE>(chunk),MPIType<T>::Type(),comm,&pack_size); //pack_size is expected to be within INT_MAX
				if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
				POS_TYPE shift = 0;
				ierr = MPI_Unpack_call((void *)&buf[buf_pos],pack_size,&shift,&data[offset],static_cast<POS_TYPE>(chunk),MPIType<T>::Type(),comm);
				if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
				buf_pos += shift;
				offset += chunk;
			}
		}
	}
	
	template<typename T>
	void unpack_data_vector(Mesh::buffer_type & buf, size_t & buf_pos, std::vector<T> & data, INMOST_MPI_Comm comm)
	{
		int ierr;
267
		size_t unpack_size;
268
		unpack_data(buf,buf_pos,unpack_size,comm);
269
		data.resize(unpack_size);
270
271
		if( !data.empty() )
			unpack_data_array(buf,buf_pos,&data[0],data.size(),comm);
272
273
274
	}

    
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
275
276
277
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
310
311
312
313
314
315
316
317
	//////////////////////////////
	/// REDUCTION FUNCTIONS    ///
	//////////////////////////////
	void DefaultUnpack(const Tag & tag, const Element & element, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size == 0 )
		{
			if( tag.isDefined(element->GetElementType()) ) 
			{
				if( tag.isSparse(element->GetElementType()) )
				{
					if( element->HaveData(tag) )
						element->DelData(tag); 
				}
				else if( tag.GetSize() == ENUMUNDEF )
					element->SetDataSize(tag,size);
				else
				{
					std::cerr << "received zero size for dense nonzero tag" << std::endl;
					assert(false);
				}
			}
			return;
		}
		if( !element->HaveData(tag) )
			element->SetDataSize(tag,size);
		else if( size != element->GetDataSize(tag) )
		{
			if( tag.GetSize() == ENUMUNDEF )
				element->SetDataSize(tag,size);
			else
			{
				assert(false);
			}
		}
		element->SetData(tag,0,size,data);
	}


	void UnpackOnSkin(const Tag & tag, const Element & e, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size )
		{
318
			const Storage::integer * recv = static_cast<const Storage::integer *>(static_cast<const void *>(data));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
319
			Storage::integer_array arr = e->IntegerArray(tag);
320
			//for(int k = 0; k < size; ++k)
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
321
322
323
324
325
326
327
328
329
			arr.push_back(recv[0]);
		}
	}


	void UnpackSkin(const Tag & tag, const Element & e, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size )
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
			for(INMOST_DATA_ENUM_TYPE k = 0; k < size; k+=2 )
			{
				bool flag = true;
				const Storage::integer * recv = static_cast<const Storage::integer *>(static_cast<const void *>(data))+k;
				Storage::integer_array arr = e->IntegerArray(tag);
				for(Storage::integer_array::iterator it = arr.begin(); it != arr.end(); it+=2)
				{
					if( *it == recv[0] )
					{
						flag = false;
						break;
					}
				}
				if( flag ) 
				{
					arr.push_back(recv[0]);
					arr.push_back(recv[1]);
				}
			}
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
		}
	}
	


	void DeleteUnpack(const Tag & tag, const Element & e, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size ) 
		{
			int old_size;
			if( e->HaveData(tag) ) old_size = e->GetDataSize(tag);
			else old_size = 0;
			e->SetDataSize(tag,old_size+size);
			e->SetData(tag,old_size,size,data);
		}
	}
	
	void RedistUnpack(const Tag & tag,const Element & e, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size ) 
		{
			Storage::integer_array p1 = e->IntegerArray(tag);
			const Storage::integer * p2 = static_cast<const Storage::integer *>(static_cast<const void *>(data));
			dynarray<Storage::integer,64> result(p1.size()+size);
373
374
			result.resize(std::set_union(p1.begin(),p1.end(),p2,p2+size,result.begin())-result.begin());
			p1.replace(p1.begin(),p1.end(),result.begin(),result.end());
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
375
376
377
378
379
380
381
382
383
384
385
386
387
388
		}
	}

	void UnpackLayersMarker(const Tag & tag, const Element & e, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size )
		{
			int old_size;
			if( e->HaveData(tag) ) old_size = e->GetDataSize(tag);
			else old_size = 0;
			e->SetDataSize(tag,old_size+size);
			e->SetData(tag,old_size,size,data);
		}
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
389
/*
390
391
    void Mesh::CheckFaces()
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
392
        //std::cout << "Check faces" << endl;
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408

        for(Mesh::iteratorFace it = BeginFace(); it != EndFace(); ++it) 
        {
            std::set<int> set_nodes;
            ElementArray<Node> nodes = it->getNodes();
            bool suc = true;
            for (ElementArray<Node>::iterator node = nodes.begin(); node != nodes.end(); node++)
                if (set_nodes.find(node->LocalID()) != set_nodes.end())
                {
                    suc = false;
                    break;
                }
                else
                {
                    set_nodes.insert(node->LocalID());
                }
Kirill Terekhov's avatar
Kirill Terekhov committed
409
410
            //if (suc) std::cout << "-=== Good face: " << setw(2) << it->LocalID();
            //else std::cout << "-=== Error face: " << setw(2) << it->LocalID();
411

Kirill Terekhov's avatar
Kirill Terekhov committed
412
413
414
415
            //cout << ". Nodes = " << nodes.size() << ": ";
            //for (ElementArray<Node>::iterator node = nodes.begin(); node != nodes.end(); node++)
             //   std::cout << node->LocalID() << " ";
            //std::cout << endl;
416
417
        }
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
418
*/
419

420
	static void OperationMinDistance(const Tag & tag, const Element & element, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
Kirill Terekhov's avatar
Kirill Terekhov committed
421
422
423
424
425
426
427
428
429
430
	{
		(void)size;
		assert(size == 2);
		INMOST_DATA_INTEGER_TYPE * idata = (INMOST_DATA_INTEGER_TYPE *)data;
		Storage::integer_array rdata = element->IntegerArray(tag);
		if (idata[1] < rdata[1])
		{
			rdata[0] = idata[0];
			rdata[1] = idata[1];
		}
431
432
433
434
435
		else if(idata[1] == rdata[1] && idata[0] < rdata[0])
		{
			rdata[0] = idata[0];
			rdata[1] = idata[1];
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
436
	}
437
438
439
440
441
442
443
444
445
	
	static void OperationMinOwner(const Tag & tag, const Element & element, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		(void)size;
		assert(size == 1);
		INMOST_DATA_INTEGER_TYPE idata = *(INMOST_DATA_INTEGER_TYPE *)data;
		element->Integer(tag) = std::min(element->Integer(tag),idata);
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
446
447
	void Mesh::EquilibrateGhost(bool only_new)
	{
448
		static int counter = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
449
450
451
		if( GetProcessorsNumber() == 1 ) return;
		ENTER_FUNC();
#if defined(USE_MPI)
452
453
		//std::cout << "before_equiv"+std::to_string(counter)+".pvtk" << std::endl;
		//Save("before_equiv"+std::to_string(counter)+".pvtk");
454
455
		ElementType bridge = FACE;
		if( tag_bridge.isValid() ) bridge = ElementType(Integer(GetHandle(),tag_bridge));
456
		TagIntegerArray tag = CreateTag("TEMPORARY_OWNER_DISTANCE_TAG",DATA_INTEGER,CELL,CELL,2);
Kirill Terekhov's avatar
Kirill Terekhov committed
457
		std::queue<HandleType> cells_queue;
458
459
		ENTER_BLOCK();
		//TODO: compute graph distance only in new elements!!!!
Kirill Terekhov's avatar
Kirill Terekhov committed
460
461
462
463
		// Push nearest to owned cell into queue
		for(int k = 0; k < CellLastLocalID(); k++) if( isValidCell(k) )
		{
			Cell c = CellByLocalID(k);
Kirill Terekhov's avatar
Kirill Terekhov committed
464
			if (!c.Hidden() && c.GetStatus() != Element::Owned)
Kirill Terekhov's avatar
Kirill Terekhov committed
465
			{
466
467
				assert( c.GetStatus() == Element::Shared || c.GetStatus() == Element::Ghost );
				tag[c][0] = -1;
Kirill Terekhov's avatar
Kirill Terekhov committed
468
				tag[c][1] = INT_MAX; 
469
470
				//ElementArray<Cell> cells = c.NeighbouringCells();
				ElementArray<Cell> cells = c.BridgeAdjacencies2Cell(bridge);
Kirill Terekhov's avatar
Kirill Terekhov committed
471
472
473
474
475
476
477
478
479
				for(unsigned l = 0; l < cells.size(); l++) if (cells[l].GetStatus() == Element::Owned)
				{
					cells_queue.push(c.GetHandle());
					tag[c][0] = cells[l].Integer(tag_owner);
					tag[c][1] = 1;
					break;
				}
			}
		}
480
		EXIT_BLOCK();
Kirill Terekhov's avatar
Kirill Terekhov committed
481
		int cur_dist = 1; // For assert
482
		ENTER_BLOCK();
Kirill Terekhov's avatar
Kirill Terekhov committed
483
484
485
486
487
488
		while (!cells_queue.empty())
		{
			Cell c(this,cells_queue.front());
			cells_queue.pop();
			if (cur_dist > tag[c][1]) assert(0); 
			if (cur_dist < tag[c][1]) cur_dist++;
489
490
			//ElementArray<Cell> cells = c.NeighbouringCells();
			ElementArray<Cell> cells = c.BridgeAdjacencies2Cell(bridge);
Kirill Terekhov's avatar
Kirill Terekhov committed
491
492
			for(unsigned l = 0; l < cells.size(); l++) if (cells[l].GetStatus() != Element::Owned)
			{
493
				assert( cells[l].GetStatus() == Element::Shared || cells[l].GetStatus() == Element::Ghost );
Kirill Terekhov's avatar
Kirill Terekhov committed
494
495
496
497
498
499
500
501
				if (tag[cells[l]][1] > tag[c][1] + 1)
				{
					tag[cells[l]][0] = tag[c][0];
					tag[cells[l]][1] = tag[c][1] + 1;
					cells_queue.push(cells[l].GetHandle());
				}
			}
		}
502
503
504
505
506
507
508
509
		EXIT_BLOCK();
		
		//static int equiv = 0;
		//std::string file;
		//file = "aequiv"+std::to_string(equiv)+".pvtk";
		//std::cout << "Save " << file << std::endl;
		//Save(file);
		
510
		//CheckCentroids(__FILE__,__LINE__);
Kirill Terekhov's avatar
Kirill Terekhov committed
511
512
		ReduceData(tag, CELL, 0, OperationMinDistance);
		ExchangeData(tag, CELL, 0);
513
		
514
515
		//std::cout << "comput_equiv"+std::to_string(counter)+".pvtk" << std::endl;
		//Save("comput_equiv"+std::to_string(counter)+".pvtk");
516
517
518
519
		//file = "bequiv"+std::to_string(equiv)+".pvtk";
		//std::cout << "Save " << file << std::endl;
		//Save(file);
		//equiv++;
520
521
522

		CheckGhostSharedCount(__FILE__,__LINE__);
		CheckCentroids(__FILE__,__LINE__);
523
524
		
		ENTER_BLOCK();
525
526
527
528
529
530
531
532
533
534
535
536
		//TagInteger tag_new_owner = CreateTag("TEMPORARY_NEW_OWNER",DATA_INTEGER,CELL,NONE,1);
		//for(int k = 0; k < CellLastLocalID(); k++) if( isValidCell(k) )
		//{
		//	Cell c = CellByLocalID(k);
		//	if( !c.Hidden() && c.GetStatus() != Element::Owned )
		//	{
		//		assert( c.GetStatus() == Element::Shared || c.GetStatus() == Element::Ghost );
		//		tag_new_owner[c] = tag[c][0];
		//	}
		//}
		//ExchangeData(tag_new_owner,CELL,0);

Kirill Terekhov's avatar
Kirill Terekhov committed
537
		for(int k = 0; k < CellLastLocalID(); k++) if( isValidCell(k) )
Kirill Terekhov's avatar
Kirill Terekhov committed
538
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
539
540
			Cell c = CellByLocalID(k);
			if( !c.Hidden() && c.GetStatus() != Element::Owned )
Kirill Terekhov's avatar
Kirill Terekhov committed
541
			{
542
				assert( c.GetStatus() == Element::Shared || c.GetStatus() == Element::Ghost );
Kirill Terekhov's avatar
Kirill Terekhov committed
543
544
545
				//if ( !only_new || it->nbAdjElements(NODE | EDGE | FACE | CELL, NewMarker()) != 0)
				{
					int new_owner = tag[c][0];
546
547
548
549
550
551
552
553
554
555
556
					if( new_owner == -1 ) continue;
					//int new_owner = tag_new_owner[c];

					Storage::integer_array procs = c.IntegerArray(ProcessorsTag());
					if( !std::binary_search(procs.begin(),procs.end(),tag[c][0]) ) 
					{
						std::cout << "new owner " << tag[c][0] << " dist " << tag[c][1] << " is not among processors ";
						for(int k = 0; k < procs.size();++k) std::cout << procs[k] << " ";
						std::cout << " for cell " << c.LocalID() << " " << c.GlobalID() << std::endl;
					}
					
Kirill Terekhov's avatar
Kirill Terekhov committed
557
558
559
560
561
562
563
564
					c.IntegerDF(tag_owner) = new_owner;
					if (GetProcessorRank() == new_owner)
						c.SetStatus(Element::Shared);
					else
						c.SetStatus(Element::Ghost);
				}
			}
		}
565
566
567
		//DeleteTag(tag_new_owner);
		//ExchangeData(tag_owner,CELL,0);

568
569
		RecomputeParallelStorage(CELL);
		CheckGhostSharedCount(__FILE__,__LINE__,CELL);
570
		EXIT_BLOCK();
571
572
573
574
		DeleteTag(tag);
		
		
		
575
		ENTER_BLOCK();
576
577
		
		TagInteger new_owner = CreateTag("TEMPORARY_NEW_OWNER",DATA_INTEGER,NODE|EDGE|FACE,NODE|EDGE|FACE,1);
Kirill Terekhov's avatar
Kirill Terekhov committed
578
579
		for(ElementType etype = FACE; etype >= NODE; etype = PrevElementType(etype))
		{
580
581
			REPORT_VAL("etype ", ElementTypeName(etype));
			ENTER_BLOCK();
Kirill Terekhov's avatar
Kirill Terekhov committed
582
583
584
585
586
			for(int k = 0; k < LastLocalID(etype); k++) if( isValidElement(etype,k) )
			{
				Element e = ElementByLocalID(etype,k);
				if( !e.Hidden() && e.GetStatus() != Element::Owned )
				{
587
					assert( e.GetStatus() == Element::Shared || e.GetStatus() == Element::Ghost );
588
					//if( !only_new || e.nbAdjElements(NODE | EDGE | FACE | CELL,NewMarker()) )
Kirill Terekhov's avatar
Kirill Terekhov committed
589
590
					{
						Element::adj_type & hc = HighConn(e.GetHandle());
591
						new_owner[e] = INT_MAX;
Kirill Terekhov's avatar
Kirill Terekhov committed
592
593
594
						for(int l = 0; l < hc.size(); ++l)
						{
							if( !GetMarker(hc[l],HideMarker()) )
595
								new_owner[e] = std::min(new_owner[e],Integer(hc[l],tag_owner));
Kirill Terekhov's avatar
Kirill Terekhov committed
596
						}
597
598
599
					}
				}
			}
600
			EXIT_BLOCK();
601
602
			ReduceData(new_owner,etype,0,OperationMinOwner);
			ExchangeData(new_owner,etype);
603
			ENTER_BLOCK();
604
605
606
607
608
			for(int k = 0; k < LastLocalID(etype); k++) if( isValidElement(etype,k) )
			{
				Element e = ElementByLocalID(etype,k);
				if( !e.Hidden() && e.GetStatus() != Element::Owned )
				{
609
					assert( e.GetStatus() == Element::Shared || e.GetStatus() == Element::Ghost );
610
611
612
613
					//if( !only_new || e.nbAdjElements(NODE | EDGE | FACE | CELL,NewMarker()) )
					{
						if( new_owner[e] != INT_MAX &&
						   e.IntegerDF(tag_owner) != new_owner[e] )
Kirill Terekhov's avatar
Kirill Terekhov committed
614
						{
615
616
							e.IntegerDF(tag_owner) = new_owner[e];
							if (GetProcessorRank() == new_owner[e])
Kirill Terekhov's avatar
Kirill Terekhov committed
617
618
619
620
621
622
								e.SetStatus(Element::Shared);
							else
								e.SetStatus(Element::Ghost);
						}
					}
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
623
			}
624
625
626
			EXIT_BLOCK();
			RecomputeParallelStorage(etype);
			CheckGhostSharedCount(__FILE__,__LINE__,etype);
Kirill Terekhov's avatar
Kirill Terekhov committed
627
		}
628
		DeleteTag(new_owner);
629
630
631
		//ComputeSharedProcs();
		//std::cout << "after_equiv"+std::to_string(counter)+".pvtk" << std::endl;
		//Save("after_equiv"+std::to_string(counter)+".pvtk");
632
		EXIT_BLOCK();
633
		//RecomputeParallelStorage(CELL | EDGE | FACE | NODE);
634
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
635
		EXIT_FUNC();
636
		counter++;
Kirill Terekhov's avatar
Kirill Terekhov committed
637
	}
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
638
639
	
	void UnpackSyncMarkerOR(const Tag & tag, const Element & element, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
Kirill Terekhov's avatar
Kirill Terekhov committed
640
	{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
641
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
642
643
644
		element->Bulk(tag) |= *data;
	}

Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
645
	void UnpackSyncMarkerXOR(const Tag & tag, const Element & element, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
Kirill Terekhov's avatar
Kirill Terekhov committed
646
	{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
647
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
648
649
650
651
		element->Bulk(tag) ^= *data;
	}

	
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
652
	void UnpackSyncMarkerAND(const Tag & tag, const Element & element, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
Kirill Terekhov's avatar
Kirill Terekhov committed
653
	{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
654
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
655
656
657
		element->Bulk(tag) &= *data;
	}

Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
658
659
660
	//////////////////////////////
	/// REDUCTION FUNCTIONS END///
	//////////////////////////////
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
	bool Mesh::HaveGlobalID(ElementType type) const
	{
		assert(OneType(type));
		Tag test;
		if( GlobalIDTag().isValid() ) test = GlobalIDTag();
		//else if( HaveTag("GLOBAL_ID") ) test = GetTag("GLOBAL_ID") );
		if( test.isValid() )
		{
			//bool ret = true;
			//for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype) ) if( etype & types )
			//	ret &= test.isDefined(etype);
			//return ret;
			return test.isDefined(type);
		}
		else return false;
	}
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
677

Kirill Terekhov's avatar
Kirill Terekhov committed
678

Kirill Terekhov's avatar
Kirill Terekhov committed
679
	void Mesh::SynchronizeMarker(MarkerType marker, ElementType mask, SyncBitOp op)
Kirill Terekhov's avatar
Kirill Terekhov committed
680
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
681
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
682
683
684
685
#if defined(USE_MPI)
		if( m_state == Mesh::Parallel )
		{
			Tag t = CreateTag("TEMP_SYNC_MARKER",DATA_BULK,mask,mask,1);
Kirill Terekhov's avatar
Kirill Terekhov committed
686
			
Kirill Terekhov's avatar
Kirill Terekhov committed
687
688
689
			//workaround for old gcc compiler
			const Element::Status SGhost = Element::Ghost;
			const Element::Status SAny = Element::Any;
Kirill Terekhov's avatar
Kirill Terekhov committed
690
			Element::Status Expr = (Element::Shared | ((op != SYNC_BIT_SET) ? SGhost : SAny));
Kirill Terekhov's avatar
Kirill Terekhov committed
691
			
Kirill Terekhov's avatar
Kirill Terekhov committed
692
			for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
693
				if( it->GetMarker(marker) && (it->GetStatus() & Expr) )
Kirill Terekhov's avatar
Kirill Terekhov committed
694
					it->Bulk(t) = 1;
Kirill Terekhov's avatar
Kirill Terekhov committed
695
			
Kirill Terekhov's avatar
Kirill Terekhov committed
696
697
698
699
			
			
			switch(op)
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
700
701
702
				case SYNC_BIT_SET:
					ExchangeData(t,mask,0);
					for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
703
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
704
705
706
707
						if( it->GetStatus() == Element::Ghost )
						{
							if( it->HaveData(t) ) it->SetMarker(marker); else it->RemMarker(marker);
						}
Kirill Terekhov's avatar
Kirill Terekhov committed
708
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
709
710
711
712
					break;
				case SYNC_BIT_OR:
					ReduceData(t,mask,0,UnpackSyncMarkerOR);
					for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
713
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
714
715
716
717
						if( it->GetStatus() & (Element::Ghost | Element::Shared) )
						{
							if( !it->GetMarker(marker) && it->HaveData(t) ) it->SetMarker(marker);
						}
Kirill Terekhov's avatar
Kirill Terekhov committed
718
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
719
720
721
722
					break;
				case SYNC_BIT_AND:
					ReduceData(t,mask,0,UnpackSyncMarkerAND);
					for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
723
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
724
725
726
727
						if( it->GetStatus() & (Element::Ghost | Element::Shared))
						{
							if( it->HaveData(t) && it->Bulk(t) ) it->SetMarker(marker); else it->RemMarker(marker);
						}
Kirill Terekhov's avatar
Kirill Terekhov committed
728
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
729
730
731
732
					break;
				case SYNC_BIT_XOR:
					ReduceData(t,mask,0,UnpackSyncMarkerXOR);
					for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
733
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
734
735
736
737
						if( it->GetStatus() & (Element::Ghost | Element::Shared))
						{
							if( it->HaveData(t) && it->Bulk(t) ) it->SetMarker(marker); else it->RemMarker(marker);
						}
Kirill Terekhov's avatar
Kirill Terekhov committed
738
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
739
					break;
Kirill Terekhov's avatar
Kirill Terekhov committed
740
741
			}
			
Kirill Terekhov's avatar
Kirill Terekhov committed
742
			
Kirill Terekhov's avatar
Kirill Terekhov committed
743
744
			DeleteTag(t,mask);
		}
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
745
746
747
748
749
#else//USE_MPI
		(void) marker;
		(void) mask;
		(void) op;
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
750
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
751
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
752
	
Kirill Terekhov's avatar
Kirill Terekhov committed
753
754
	ElementType Mesh::SynchronizeElementType(ElementType etype)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
755
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
756
757
		ElementType etypeout = etype;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
758
		REPORT_MPI(MPI_Allreduce(&etype,&etypeout,1,INMOST_MPI_DATA_BULK_TYPE,MPI_BOR,GetCommunicator()));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
759
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
760
761
		return etypeout;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
762
763
	Storage::integer Mesh::TotalNumberOf(ElementType mask)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
764
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
765
766
767
768
769
		Storage::integer number = 0, ret = 0;
		for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); it++)
			if( it->GetStatus() != Element::Ghost ) number++;
		ret = number;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
770
		REPORT_MPI(MPI_Allreduce(&number,&ret,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
771
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
772
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
773
774
		return ret;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
775
	Storage::integer Mesh::EnumerateSet(const ElementSet & set, const Tag & num_tag, Storage::integer start, bool define_sparse)
Kirill Terekhov's avatar
Kirill Terekhov committed
776
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
777
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
778
779
780
781
		Storage::integer shift = 0, ret = 0;
		ElementType mask = CELL | FACE | EDGE | NODE;
#if defined(USE_MPI)
		Storage::integer number = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
782
783
		for(ElementSet::iterator it = set.Begin(); it != set.End(); it++)
			if( it->GetStatus() != Element::Ghost && (define_sparse || it->HaveData(num_tag)) )
Kirill Terekhov's avatar
Kirill Terekhov committed
784
				number++;
Kirill Terekhov's avatar
Kirill Terekhov committed
785
		REPORT_MPI(MPI_Scan(&number,&shift,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
786
		shift -= number;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
787
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
788
		shift += start;
Kirill Terekhov's avatar
Kirill Terekhov committed
789
		for(ElementSet::iterator it = set.Begin(); it != set.End(); it++)
790
			if( (it->GetStatus() == Element::Owned || it->GetStatus() == Element::Any) && (define_sparse || it->HaveData(num_tag)) )
Kirill Terekhov's avatar
Kirill Terekhov committed
791
				it->Integer(num_tag) = shift++;
Kirill Terekhov's avatar
Kirill Terekhov committed
792
793
		for(ElementSet::iterator it = set.Begin(); it != set.End(); it++)
			if( it->GetStatus() == Element::Shared && (define_sparse || it->HaveData(num_tag)) )
Kirill Terekhov's avatar
Kirill Terekhov committed
794
				it->Integer(num_tag) = shift++;
Kirill Terekhov's avatar
Kirill Terekhov committed
795
		ExchangeData(num_tag,mask,0);
Kirill Terekhov's avatar
Kirill Terekhov committed
796
797
		ret = shift;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
798
		REPORT_MPI(MPI_Bcast(&ret,1,INMOST_MPI_DATA_INTEGER_TYPE,GetProcessorsNumber()-1,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
799
		//MPI_Allreduce(&shift,&ret,1,INMOST_DATA_INTEGER_TYPE,MPI_MAX,comm);
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
800
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
801
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
802
803
		return ret;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
804
	Storage::integer Mesh::Enumerate(const HandleType * set, enumerator n, const Tag & num_tag, Storage::integer start, bool define_sparse)
Kirill Terekhov's avatar
Kirill Terekhov committed
805
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
806
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
807
808
809
810
		Storage::integer shift = 0, ret = 0;
		ElementType mask = CELL | FACE | EDGE | NODE;
#if defined(USE_MPI)
		Storage::integer number = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
811
812
		for(const HandleType * it = set; it != set+n; ++it)
			if( GetStatus(*it) != Element::Ghost && (define_sparse || HaveData(*it,num_tag))) number++;
Kirill Terekhov's avatar
Kirill Terekhov committed
813
		REPORT_MPI(MPI_Scan(&number,&shift,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
814
		shift -= number;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
815
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
816
		shift += start;
Kirill Terekhov's avatar
Kirill Terekhov committed
817
		for(const HandleType * it = set; it != set+n; ++it)
818
			if( (GetStatus(*it) == Element::Owned || GetStatus(*it) == Element::Any) && (define_sparse || HaveData(*it,num_tag))) Integer(*it,num_tag) = shift++;
Kirill Terekhov's avatar
Kirill Terekhov committed
819
		for(const HandleType * it = set; it != set+n; ++it)
820
			if( GetStatus(*it) == Element::Shared && (define_sparse || HaveData(*it,num_tag))) Integer(*it,num_tag) = shift++;
Kirill Terekhov's avatar
Kirill Terekhov committed
821
		ExchangeData(num_tag,mask,0);
Kirill Terekhov's avatar
Kirill Terekhov committed
822
823
		ret = shift;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
824
		REPORT_MPI(MPI_Bcast(&ret,1,INMOST_MPI_DATA_INTEGER_TYPE,GetProcessorsNumber()-1,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
825
		//MPI_Allreduce(&shift,&ret,1,INMOST_DATA_INTEGER_TYPE,MPI_MAX,comm);
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
826
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
827
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
828
829
		return ret;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
830
	Storage::integer Mesh::Enumerate(ElementType mask, Tag num_tag, Storage::integer start, bool define_sparse)
Kirill Terekhov's avatar
Kirill Terekhov committed
831
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
832
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
833
834
835
836
		Storage::integer shift = 0, ret = 0;
#if defined(USE_MPI)
		Storage::integer number = 0;
		for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
837
			if( it->GetStatus() != Element::Ghost && (define_sparse || it->HaveData(num_tag)) )
Kirill Terekhov's avatar
Kirill Terekhov committed
838
				number++;
Kirill Terekhov's avatar
Kirill Terekhov committed
839
		REPORT_MPI(MPI_Scan(&number,&shift,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
840
		shift -= number;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
841
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
842
843
		shift += start;
		for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); it++)
844
			if( (it->GetStatus() == Element::Owned || it->GetStatus() == Element::Any) && (define_sparse || it->HaveData(num_tag)) )
Kirill Terekhov's avatar
Kirill Terekhov committed
845
846
				it->Integer(num_tag) = shift++;
		for(Mesh::iteratorElement it = BeginElement(mask); it != EndElement(); it++)
847
			if( it->GetStatus() == Element::Shared && (define_sparse || it->HaveData(num_tag)) )
Kirill Terekhov's avatar
Kirill Terekhov committed
848
				it->Integer(num_tag) = shift++;
Kirill Terekhov's avatar
Kirill Terekhov committed
849
		ExchangeData(num_tag,mask,0);
Kirill Terekhov's avatar
Kirill Terekhov committed
850
851
		ret = shift;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
852
		REPORT_MPI(MPI_Bcast(&ret,1,INMOST_MPI_DATA_INTEGER_TYPE,GetProcessorsNumber()-1,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
853
		//MPI_Allreduce(&shift,&ret,1,INMOST_DATA_INTEGER_TYPE,MPI_MAX,comm);
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
854
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
855
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
856
857
858
859
860
		return ret;
	}
	
	Storage::real Mesh::Integrate(Storage::real input)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
861
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
862
863
		Storage::real output = input;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
864
		REPORT_MPI(MPI_Allreduce(&input,&output,1,INMOST_MPI_DATA_REAL_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
865
866
867
#else//USE_MPI
		(void) input;
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
868
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
869
870
		return output;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
871
872
	
	
Kirill Terekhov's avatar
Kirill Terekhov committed
873
	
Kirill Terekhov's avatar
Kirill Terekhov committed
874
875
876
	
	Storage::integer Mesh::Integrate(Storage::integer input)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
877
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
878
879
		Storage::integer output = input;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
880
		REPORT_MPI(MPI_Allreduce(&input,&output,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
881
882
883
#else//USE_MPI
		(void) input;
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
884
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
885
886
		return output;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
887
	
Kirill Terekhov's avatar
Kirill Terekhov committed
888
889
	void Mesh::Integrate(Storage::real * input, Storage::integer size)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
890
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
891
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
892
893
		static dynarray<Storage::real,64> temp;
		temp.resize(size);
Kirill Terekhov's avatar
Kirill Terekhov committed
894
		memcpy(temp.data(),input,sizeof(Storage::real)*size);
Kirill Terekhov's avatar
Kirill Terekhov committed
895
		REPORT_MPI(MPI_Allreduce(temp.data(),input,size,INMOST_MPI_DATA_REAL_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
896
#else//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
897
898
		(void) input;
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
899
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
900
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
901
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
902
	
Kirill Terekhov's avatar
Kirill Terekhov committed
903
904
	void Mesh::Integrate(Storage::integer * input, Storage::integer size)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
905
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
906
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
907
908
		static dynarray<Storage::integer,64> temp;
		temp.resize(size);
Kirill Terekhov's avatar
Kirill Terekhov committed
909
		memcpy(temp.data(),input,sizeof(Storage::integer)*size);
Kirill Terekhov's avatar
Kirill Terekhov committed
910
		REPORT_MPI(MPI_Allreduce(temp.data(),input,size,INMOST_MPI_DATA_INTEGER_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
911
912
#else//USE_MPI
		(void) input;
Kirill Terekhov's avatar
Kirill Terekhov committed
913
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
914
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
915
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
916
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
917
918
919
	
	Storage::integer Mesh::ExclusiveSum(Storage::integer input)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
920
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
921
922
		Storage::integer output = 0;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
923
		REPORT_MPI(MPI_Scan(&input,&output,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
924
		output -= input;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
925
926
927
#else//USE_MPI
		(void) input;
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
928
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
929
930
931
		return output;
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
932
	Storage::real Mesh::Integrate(const Tag & t, enumerator entry, ElementType mask)
Kirill Terekhov's avatar
Kirill Terekhov committed
933
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
934
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
935
936
		Storage::real output = 0, input = 0;
		for(iteratorElement it = BeginElement(mask); it != EndElement(); it++)
Kirill Terekhov's avatar
Kirill Terekhov committed
937
			if( GetStatus(*it) != Element::Ghost && HaveData(*it,t) )
Kirill Terekhov's avatar
Kirill Terekhov committed
938
939
940
941
			{
				real_array arr = RealArray(*it,t);
				if( arr.size() > entry ) input += arr[entry];
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
942
943
		output = input;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
944
		REPORT_MPI(MPI_Allreduce(&input,&output,1,INMOST_MPI_DATA_REAL_TYPE,MPI_SUM,comm));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
945
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
946
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
947
948
949
		return output;
	}
	
950
951
	Storage::real Mesh::AggregateMax(Storage::real input)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
952
		ENTER_FUNC();
953
954
		Storage::real output = input;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
955
		REPORT_MPI(MPI_Allreduce(&input,&output,1,INMOST_MPI_DATA_REAL_TYPE,MPI_MAX,comm));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
956
957
958
#else //USE_MPI
		(void) input;
#endif //USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
959
		EXIT_FUNC();
960
961
		return output;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
962
	
963
964
	Storage::integer Mesh::AggregateMax(Storage::integer input)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
965
		ENTER_FUNC();
966
967
		Storage::integer output = input;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
968
		REPORT_MPI(MPI_Allreduce(&input,&output,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_MAX,comm));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
969
970
971
#else //USE_MPI
		(void) input;
#endif //USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
972
		EXIT_FUNC();
973
974
		return output;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
975
	
Kirill Terekhov's avatar
Kirill Terekhov committed
976
977
	void Mesh::AggregateMax(Storage::real * input, Storage::integer size)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
978
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
979
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
980
981
		static dynarray<Storage::real,64> temp;
		temp.resize(size);
Kirill Terekhov's avatar
Kirill Terekhov committed
982
		memcpy(temp.data(),input,sizeof(Storage::real)*size);
Kirill Terekhov's avatar
Kirill Terekhov committed
983
		REPORT_MPI(MPI_Allreduce(temp.data(),input,size,INMOST_MPI_DATA_REAL_TYPE,MPI_MAX,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
984
985
#else//USE_MPI
		(void) input;
Kirill Terekhov's avatar
Kirill Terekhov committed
986
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
987
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
988
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
989
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
990
	
Kirill Terekhov's avatar
Kirill Terekhov committed
991
992
	void Mesh::AggregateMax(Storage::integer * input, Storage::integer size)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
993
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
994
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
995
996
		static dynarray<Storage::integer,64> temp;
		temp.resize(size);
Kirill Terekhov's avatar
Kirill Terekhov committed
997
		memcpy(temp.data(),input,sizeof(Storage::integer)*size);
Kirill Terekhov's avatar
Kirill Terekhov committed
998
		REPORT_MPI(MPI_Allreduce(temp.data(),input,size,INMOST_MPI_DATA_INTEGER_TYPE,MPI_MAX,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
999
1000
#else//USE_MPI
		(void) input;
Kirill Terekhov's avatar
Kirill Terekhov committed
1001
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
1002
#endif//USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
1003
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
1004
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
1005
	
Kirill Terekhov's avatar
Kirill Terekhov committed
1006
1007
	Storage::real Mesh::AggregateMin(Storage::real input)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1008
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
1009
1010
		Storage::real output = input;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
1011
		REPORT_MPI(MPI_Allreduce(&input,&output,1,INMOST_MPI_DATA_REAL_TYPE,MPI_MIN,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
1012
1013
1014
#else //USE_MPI
		(void) input;
#endif //USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
1015
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
1016
1017
1018
1019
1020
		return output;
	}
	
	Storage::integer Mesh::AggregateMin(Storage::integer input)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1021
		ENTER_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
1022
1023
		Storage::integer output = input;
#if defined(USE_MPI)
Kirill Terekhov's avatar
Kirill Terekhov committed
1024
		REPORT_MPI(MPI_Allreduce(&input,&output,1,INMOST_MPI_DATA_INTEGER_TYPE,MPI_MIN,comm));
Kirill Terekhov's avatar
Kirill Terekhov committed
1025
1026
1027
#else //USE_MPI
		(void) input;
#endif //USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
1028
		EXIT_FUNC();
Kirill Terekhov's avatar
Kirill Terekhov committed
1029
1030
		return output;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed