parallel.cpp 262 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
__INLINE std::string NameSlash(std::string input)
31
{
32
	for(size_t l = input.size(); l > 0; --l)
33
34
35
36
37
		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
#if defined(USE_MPI)
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
	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>
119
	void pack_data(Mesh::buffer_type & buf, const T & data, INMOST_MPI_Comm comm)
120
121
	{
		int ierr;
122
		POS_TYPE pack_size = 0, shift = 0;
123
		size_t write_pos = buf.size();
124
125
		ierr = MPI_Pack_size_call(1,MPIType<T>::Type(),comm,&pack_size); 
		if( ierr != MPI_SUCCESS ) MPI_Abort(comm,__LINE__);
126
		buf.resize(write_pos+pack_size);
127
128
		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__);
129
130
131
		buf.resize(write_pos+shift);
	}
	
132
133
134
135
	template<typename T>
	size_t pack_data_size(INMOST_MPI_Comm comm)
	{
		int ierr;
136
		POS_TYPE pack_size = 0;//, shift = 0;
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
		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;
			}
		}
	}
	
175
176
	
	template<typename T>
177
	void pack_data_vector(Mesh::buffer_type & buf, const std::vector<T> & data, INMOST_MPI_Comm comm)
178
	{
179
		//int ierr;
180
		pack_data(buf,data.size(),comm);
181
182
183
184
185
186
187
188
189
190
		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 )
191
		{
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
			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;
			}
208
		}
209
210
211
212
213
214
215
216
217
		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;
218
219
220
221
	}
	
	
	template<typename T>
222
	void unpack_data(Mesh::buffer_type & buf, size_t & buf_pos, T & data, INMOST_MPI_Comm comm)
223
	{
224
225
226
227
228
229
230
		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;
231
232
	}
	
233
	
234
	template<typename T>
235
	void unpack_data_array(Mesh::buffer_type & buf, size_t & buf_pos, T * data, size_t N, INMOST_MPI_Comm comm)
236
	{
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
		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)
	{
265
		//int ierr;
266
		size_t unpack_size;
267
		unpack_data(buf,buf_pos,unpack_size,comm);
268
		data.resize(unpack_size);
269
270
		if( !data.empty() )
			unpack_data_array(buf,buf_pos,&data[0],data.size(),comm);
271
	}
272
#endif
273
    
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
274
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
	//////////////////////////////
	/// 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 )
		{
317
			const Storage::integer * recv = static_cast<const Storage::integer *>(static_cast<const void *>(data));
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
318
			Storage::integer_array arr = e->IntegerArray(tag);
319
			//for(int k = 0; k < size; ++k)
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
320
321
322
323
324
325
326
327
328
			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
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
			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
348
349
350
351
352
353
354
355
356
		}
	}
	


	void DeleteUnpack(const Tag & tag, const Element & e, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size ) 
		{
357
			INMOST_DATA_ENUM_TYPE old_size;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
358
359
360
361
362
363
364
365
366
367
368
369
370
			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));
371
			dynarray<Storage::integer,64> result(static_cast<size_t>(p1.size())+size);
372
373
			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
374
375
376
377
378
379
380
		}
	}

	void UnpackLayersMarker(const Tag & tag, const Element & e, const INMOST_DATA_BULK_TYPE * data, INMOST_DATA_ENUM_TYPE size)
	{
		if( size )
		{
381
			INMOST_DATA_ENUM_TYPE old_size;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
382
383
384
385
386
387
			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
388
/*
389
390
    void Mesh::CheckFaces()
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
391
        //std::cout << "Check faces" << endl;
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

        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
408
409
            //if (suc) std::cout << "-=== Good face: " << setw(2) << it->LocalID();
            //else std::cout << "-=== Error face: " << setw(2) << it->LocalID();
410

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

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

		CheckGhostSharedCount(__FILE__,__LINE__);
		CheckCentroids(__FILE__,__LINE__);
522
523
		
		ENTER_BLOCK();
524
525
526
527
528
529
530
531
532
533
534
535
		//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);

536
		for(integer k = 0; k < CellLastLocalID(); k++) if( isValidCell(k) )
Kirill Terekhov's avatar
Kirill Terekhov committed
537
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
538
539
			Cell c = CellByLocalID(k);
			if( !c.Hidden() && c.GetStatus() != Element::Owned )
Kirill Terekhov's avatar
Kirill Terekhov committed
540
			{
541
				assert( c.GetStatus() == Element::Shared || c.GetStatus() == Element::Ghost );
Kirill Terekhov's avatar
Kirill Terekhov committed
542
543
				//if ( !only_new || it->nbAdjElements(NODE | EDGE | FACE | CELL, NewMarker()) != 0)
				{
544
					integer new_owner = tag[c][0];
545
546
547
548
549
550
551
					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 ";
552
						for(INMOST_DATA_ENUM_TYPE k = 0; k < procs.size();++k) std::cout << procs[k] << " ";
553
554
555
						std::cout << " for cell " << c.LocalID() << " " << c.GlobalID() << std::endl;
					}
					
Kirill Terekhov's avatar
Kirill Terekhov committed
556
557
558
559
560
561
562
563
					c.IntegerDF(tag_owner) = new_owner;
					if (GetProcessorRank() == new_owner)
						c.SetStatus(Element::Shared);
					else
						c.SetStatus(Element::Ghost);
				}
			}
		}
564
565
566
		//DeleteTag(tag_new_owner);
		//ExchangeData(tag_owner,CELL,0);

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

Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
644
	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
645
	{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
646
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
647
648
649
650
		element->Bulk(tag) ^= *data;
	}

	
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
651
	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
652
	{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
653
		(void) size;
Kirill Terekhov's avatar
Kirill Terekhov committed
654
655
656
		element->Bulk(tag) &= *data;
	}

Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
657
658
659
	//////////////////////////////
	/// REDUCTION FUNCTIONS END///
	//////////////////////////////
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
	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
676

Kirill Terekhov's avatar
Kirill Terekhov committed
677

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