mesh.cpp 78.6 KB
Newer Older
Kirill Terekhov's avatar
Kirill Terekhov committed
1
2
3
4
5
#include "inmost.h"
#include <sstream>
#if defined(USE_MESH)
#define WAITNL 	{char c;scanf("%c",&c);}

Kirill Terekhov's avatar
Kirill Terekhov committed
6
7
8
9
10
11
12
13
14
15
16

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

Kirill Terekhov's avatar
Kirill Terekhov committed
17
18
namespace INMOST
{
19
  static std::vector<Mesh *> allocated_meshes;
Kirill Terekhov's avatar
Kirill Terekhov committed
20
21


22
#if defined(USE_PARALLEL_WRITE_TIME)
Kirill Terekhov's avatar
Kirill Terekhov committed
23
24
25
26
27
28
29
30
31
32
33
34
35
	void Mesh::AtExit(void)
	{
		while(!allocated_meshes.empty())
		{
			if( allocated_meshes.back() != NULL )
			{
				allocated_meshes.back()->FinalizeFile();
			}
			allocated_meshes.pop_back();
		}
	}
#endif //USE_PARALLEL_WRITE_TIME

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
	void Mesh::ReportConnection(HandleType h)
	{
		if( isValidElement(h) )
		{
			std::cout << ElementTypeName(GetHandleElementType(h)) << ":" << GetHandleID(h);
			if( HideMarker() && Hidden(h) )
				std::cout << " is hidden" << std::endl;
			else
				std::cout << " is visible" << std::endl;
			for(iteratorTag t = BeginTag(); t != EndTag(); ++t)
			{
				if( t->GetDataType() == DATA_REFERENCE )
				{
					for(ElementType etype = NODE; etype <= ESET; etype = NextElementType(etype))
					{
						if( t->isDefined(etype) )
						{
							for(Storage::integer kt = 0; kt < LastLocalID(etype); ++kt) if( isValidElement(etype,kt) )
							{
								Storage::reference_array a = ElementByLocalID(etype,kt).ReferenceArray(*t);
								for(Storage::reference_array::size_type lt = 0; lt < a.size(); ++lt)
								{
									if( a[lt].GetHandle() == h )
									{
										std::cout << ElementTypeName(GetHandleElementType(h)) << ":" << GetHandleID(h);
										std::cout << " handle " << h;
										std::cout << " found on ";
										std::cout << ElementTypeName(etype) << ":" << kt;
										if( HideMarker() && Hidden(ComposeHandle(etype,kt)) )
											std::cout << "(hidden)";
										else std::cout << "(visible)";
										std::cout << " tag " << t->GetTagName();
										std::cout << " position " << lt;
										std::cout << std::endl;
									}
									//prevent from checking deleted positions in the set
									if( etype == ESET && t->GetTagName() == "PROTECTED_HIGH_CONN" && lt == 2 )
										break;
								}
							}
						}
					}
				}
			}
		}
	}
	std::string Mesh::GetMeshName()
	{
		return name;
	}
	void Mesh::SetMeshName(std::string new_name)
	{
		name = new_name;
	}
	Mesh * Mesh::GetMesh(std::string name)
	{
		for(int q = 0; q < (int)allocated_meshes.size(); ++q)
			if( allocated_meshes[q]->GetMeshName() == name )
				return allocated_meshes[q];
		return NULL;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
97

Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
	const char * TopologyCheckNotifyString(TopologyCheck c)
	{
		switch(c)
		{
			case THROW_EXCEPTION:        return "exception thrown";
			case PRINT_NOTIFY:           return "print notify";
			case DELETE_ON_ERROR:        return "element should be deleted on error";
			case MARK_ON_ERROR:          return "element is marked on error";
			case DUPLICATE_EDGE:         return "search for duplicate edge";
			case DUPLICATE_FACE:         return "search for duplicate face";
			case DUPLICATE_CELL:         return "search for duplicate cell";
			case DEGENERATE_EDGE:        return "TOPOLOGY ERROR: curvilinear edge found"; 
			case DEGENERATE_FACE:        return "TOPOLOGY ERROR: degenerate face found";
			case DEGENERATE_CELL:        return "TOPOLOGY ERROR: degenerate cell found";
			case FACE_ORIENTATION:       return "TOPOLOGY ERROR: bad face orientation";
			case FACE_PLANARITY:         return "TOPOLOGY ERROR: non-planar face found";
			case INTERLEAVED_FACES:      return "TOPOLOGY ERROR: interleaving faces found";
			case TRIPLE_SHARED_FACE:     return "TOPOLOGY ERROR: face have more then two neighbours"; 
			case FLATTENED_CELL:         return "TOPOLOGY ERROR: flattened cell found"; 
			case ADJACENT_DUPLICATE:     return "TOPOLOGY ERROR: duplicates in adjacent elements";
			case ADJACENT_HIDDEN:        return "TOPOLOGY ERROR: hidden element is used as adjacent"; 
			case ADJACENT_VALID:         return "TOPOLOGY ERROR: invalid handle is used as adjacent"; 
			case ADJACENT_DIMENSION:     return "TOPOLOGY ERROR: wrong dimension of adjacent elements";
			case PROHIBIT_MULTILINE:     return "TOPOLOGY ERROR: multiline is prohibited"; 
			case PROHIBIT_POLYGON:       return "TOPOLOGY ERROR: polygon is prohibited"; 
			case PROHIBIT_MULTIPOLYGON:  return "TOPOLOGY ERROR: multipolygon is prohibited"; 
			case PROHIBIT_POLYHEDRON:    return "TOPOLOGY ERROR: polyhedron is prohibited"; 
			case FACE_EDGES_ORDER:       return "TOPOLOGY ERROR: no order in face edges"; 
			case PROHIBIT_CONCAVE_FACE:  return "TOPOLOGY ERROR: concave faces are prohibited"; 
			case PROHIBIT_CONCAVE_CELL:  return "TOPOLOGY ERROR: concave cells are prohibited"; 
			case PROHIBIT_NONSTAR_FACE:  return "TOPOLOGY ERROR: non star-shaped faces are prohibited"; 
			case PROHIBIT_NONSTAR_CELL:  return "TOPOLOGY ERROR: non star-shpaed cells are prohibited"; 
			case FACE_SELF_INTERSECTION: return "TOPOLOGY ERROR: self intersection of face edges detected"; 
			case CELL_SELF_INTERSECTION: return "TOPOLOGY ERROR: self intersection of cell faces detected"; 
			case DISABLE_2D:             return "TOPOLOGY ERROR: 2d mesh support is disabled"; 
			default: return "unknown";
		}
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
136
137

	const char * ElementTypeName(ElementType t)
Kirill Terekhov's avatar
Kirill Terekhov committed
138
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
139
140
141
142
143
144
145
146
147
148
149
150
		switch(t)
		{
			case NONE: return "NONE";
			case NODE: return "NODE";
			case EDGE: return "EDGE";
			case FACE: return "FACE";
			case CELL: return "CELL";
			case ESET: return "ESET";
			case MESH: return "MESH";
		}
		return "UNKNOWN";
	}
151

152
153
154
	void Mesh::Init(std::string name)
	{
#if defined(CHECKS_MARKERS)
155
156
		check_shared_mrk = true;
		check_private_mrk = true;
157
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
158
159
160
		m_link = this;
		integer selfid = 1;
		selfid = TieElement(5);
Kirill Terekhov's avatar
Kirill Terekhov committed
161
		assert(selfid == 0);
Kirill Terekhov's avatar
Kirill Terekhov committed
162
		dim = 3;
163
		//have_global_id = NONE;
Kirill Terekhov's avatar
Kirill Terekhov committed
164
165
166
167
		checkset = DEFAULT_CHECK;
		errorset = 0;
		new_element = hide_element = 0;

Kirill Terekhov's avatar
Kirill Terekhov committed
168
169
170
		memset(hidden_count,0,sizeof(integer)*6);
		memset(hidden_count_zero,0,sizeof(integer)*6);

Kirill Terekhov's avatar
Kirill Terekhov committed
171
		memset(remember,0,sizeof(remember));
Kirill Terekhov's avatar
Kirill Terekhov committed
172
173
174
175
176
177
178
		tag_coords        = CreateTag("PROTECTED_COORD",DATA_REAL, NODE,NONE,dim);
		tag_high_conn     = CreateTag("PROTECTED_HIGH_CONN",DATA_REFERENCE,ESET|CELL|FACE|EDGE|NODE,NONE);
		tag_low_conn      = CreateTag("PROTECTED_LOW_CONN",DATA_REFERENCE,ESET|CELL|FACE|EDGE|NODE,NONE);
		tag_markers       = CreateTag("PROTECTED_MARKERS",DATA_BULK,CELL|FACE|EDGE|NODE|ESET|MESH,NONE,MarkerFields);
		tag_geom_type     = CreateTag("PROTECTED_GEOM_TYPE",DATA_BULK,CELL|FACE|EDGE|NODE,NONE,1);
		tag_setname       = CreateTag("PROTECTED_SET_NAME",DATA_BULK,ESET,NONE);
		tag_setcomparator = CreateTag("PROTECTED_SET_COMPARATOR",DATA_BULK,ESET,NONE,1);
Kirill Terekhov's avatar
Kirill Terekhov committed
179
		AllocatePrivateMarkers();
180
		for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype))
Kirill Terekhov's avatar
Kirill Terekhov committed
181
			ReallocateData(ElementNum(etype),GetArrayCapacity(ElementNum(etype)));
Kirill Terekhov's avatar
Kirill Terekhov committed
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
		epsilon = 1.0e-8;
		m_state = Mesh::Serial;

#if defined(USE_MPI)
		{
			int test;
			MPI_Initialized(&test);
			if( test == 0 ) MPI_Init(NULL,NULL);
			comm = INMOST_MPI_COMM_WORLD;
		}
#endif

#if defined(USE_PARALLEL_WRITE_TIME)
		num_exchanges = 0;
		std::stringstream temp;
		temp << "time_" << GetProcessorRank() << ".xml";
		out_time.open(temp.str().c_str(),std::ios::out);
		out_time << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" << std::endl;
		out_time << "<?xml-stylesheet type=\"text/xsl\" href=\"style.xsl\"?>" << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
201
		out_time << "<Debug ProcessID=\"" << PROCESSID << "\">" << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
202
203
204
		tab = 1;
		func_id = 0;
#endif
205
206
207
208
209
210
    allocated_meshes.push_back(this);
  }
		
	Mesh::Mesh()
	:TagManager(), Storage(NULL,ComposeHandle(MESH,0))
	{
211
212
213
214
		std::stringstream tmp;
		tmp << "Mesh" << allocated_meshes.size();
		name = tmp.str();
		Init(name);
215
216
	}

217
	Mesh::Mesh(std::string name)
218
219
	:TagManager(), Storage(NULL,ComposeHandle(MESH,0))
	{
220
		Init(name);
Kirill Terekhov's avatar
Kirill Terekhov committed
221
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
222

Kirill Terekhov's avatar
Kirill Terekhov committed
223
224
225
226
  bool Mesh::GetPrivateMarker(HandleType h, MarkerType n) const
  {
    assert(isPrivate(n));
    n &= ~MarkerPrivateBit;
Kirill Terekhov's avatar
Kirill Terekhov committed
227
    int thread = GetLocalProcessorRank();
Kirill Terekhov's avatar
Kirill Terekhov committed
228
229
230
231
232
233
234
235
    const bulk * mem = static_cast<const bulk *>(MGetDenseLink(h,tag_private_markers[thread]));
    return (mem[n >> MarkerShift] & static_cast<bulk>(n & MarkerMask)) != 0;
  }

  void Mesh::SetPrivateMarker(HandleType h,MarkerType n)  
  {
    assert(isPrivate(n));
    n &= ~MarkerPrivateBit;
Kirill Terekhov's avatar
Kirill Terekhov committed
236
    int thread = GetLocalProcessorRank();
Kirill Terekhov's avatar
Kirill Terekhov committed
237
238
239
240
241
242
243
244
    bulk * mem = static_cast<bulk *>(MGetDenseLink(h,tag_private_markers[thread]));
    mem[n >> MarkerShift] |= static_cast<bulk>(n & MarkerMask);
  }

  void Mesh::RemPrivateMarker(HandleType h,MarkerType n) 
  {
    assert(isPrivate(n));
    n &= ~MarkerPrivateBit;
Kirill Terekhov's avatar
Kirill Terekhov committed
245
    int thread = GetLocalProcessorRank();
Kirill Terekhov's avatar
Kirill Terekhov committed
246
247
248
249
250
251
252
253
254
255
256
    bulk * mem = static_cast<bulk *>(MGetDenseLink(h,tag_private_markers[thread]));
    mem[n >> MarkerShift] &= ~static_cast<bulk>(n & MarkerMask);
  }

  void Mesh::AllocatePrivateMarkers()
  {
#if defined(USE_OMP)
#pragma omp parallel
    {
#pragma omp single
      {
Kirill Terekhov's avatar
Kirill Terekhov committed
257
		  tag_private_markers = new Tag[GetLocalProcessorNumber()];
Kirill Terekhov's avatar
Kirill Terekhov committed
258
259
260
261
      }
//#pragma omp ordered
      {
        std::stringstream name;
Kirill Terekhov's avatar
Kirill Terekhov committed
262
263
		name << "PROTECTED_PRIVATE_MARKERS_" << GetLocalProcessorRank();
        tag_private_markers[GetLocalProcessorRank()] = CreateTag(name.str(),DATA_BULK,CELL|FACE|EDGE|NODE|ESET|MESH,NONE,MarkerFieldsPrivate);
Kirill Terekhov's avatar
Kirill Terekhov committed
264
265
266
267
268
269
270
271
      }
    }
#else
    tag_private_markers = new Tag;
    tag_private_markers[0] = CreateTag("PROTECTED_PRIVATE_MARKERS_0",DATA_BULK,CELL|FACE|EDGE|NODE|ESET|MESH,NONE,MarkerFieldsPrivate);
#endif
  }

Kirill Terekhov's avatar
Kirill Terekhov committed
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  int Mesh::GetLocalProcessorNumber() const
  {
#if defined(USE_OMP)
	  return omp_get_num_threads();
#else
	  return 1;
#endif
  }

  int Mesh::GetLocalProcessorRank() const
  {
#if defined(USE_OMP)
	  return omp_get_thread_num();
#else
	  return 0;
#endif
  }

Kirill Terekhov's avatar
Kirill Terekhov committed
290
291
292
293
294
  void Mesh::DeallocatePrivateMarkers()
  {
#if defined(USE_OMP)
#pragma omp parallel
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
295
296
		//retrive tag before it was erased
		Tag del = tag_private_markers[GetLocalProcessorRank()];
Kirill Terekhov's avatar
Kirill Terekhov committed
297
#pragma omp barrier
Kirill Terekhov's avatar
Kirill Terekhov committed
298
299
		//delete tag, it will erase the tag
		DeleteTag(del);
Kirill Terekhov's avatar
Kirill Terekhov committed
300
#pragma omp barrier
Kirill Terekhov's avatar
Kirill Terekhov committed
301
		//deallocate space
Kirill Terekhov's avatar
Kirill Terekhov committed
302
#pragma omp single
Kirill Terekhov's avatar
Kirill Terekhov committed
303
304
305
		{
			delete [] tag_private_markers;
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
306
307
308
309
310
311
312
    }
#else
    DeleteTag(tag_private_markers[0]);
    delete tag_private_markers;
#endif
  }

Kirill Terekhov's avatar
Kirill Terekhov committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
	Storage::enumerator Mesh::MemoryUsage(HandleType h)
	{
		if( isValidHandle(h) )
		{
			integer etypenum = GetHandleElementNum(h);
			enumerator ret = 2*sizeof(integer); //link and address occupied
			for(Mesh::iteratorTag t = BeginTag(); t != EndTag(); ++t)
			{
				if( t->isDefinedByDim(etypenum) )
				{
					bool have_data = true;
					if( t->isSparseByDim(etypenum) )
					{
						have_data = HaveData(h,*t);
						if( have_data ) 
							ret += sizeof(sparse_sub_record); //size occupied for storage of data link
					}
					if( have_data )
					{
						ret += t->GetRecordSize(); //all utilized data for fixed data, size of support structure for variable data
						if( t->GetSize() == ENUMUNDEF )
Kirill Terekhov's avatar
Kirill Terekhov committed
334
							ret += GetDataCapacity(h,*t); //actually occupied size for sparse data
Kirill Terekhov's avatar
Kirill Terekhov committed
335
336
337
338
339
					}
				}
				if( !sparse_data[etypenum].empty() ) ret += sizeof(sparse_sub_type); //size needed to support sparse data
			}
			//Any additional impact of supporting huge structures over all elements may be added later
340
			return ret;
Kirill Terekhov's avatar
Kirill Terekhov committed
341
342
343
		}
		else return 0;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
344
345
	
	Mesh::Mesh(const Mesh & other)
Kirill Terekhov's avatar
Kirill Terekhov committed
346
	:TagManager(other),Storage(NULL,ComposeHandle(MESH,0))
Kirill Terekhov's avatar
Kirill Terekhov committed
347
	{
348
349
350
351
352
353
354
355
356
		{
			std::stringstream tmp;
			tmp << other.name << "_copy";
			name = tmp.str();
		}
#if defined(CHECKS_MARKERS)
		check_shared_mrk = other.check_shared_mrk;
		check_private_mrk = other.check_private_mrk;
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
357
		m_link = this;
Kirill Terekhov's avatar
Kirill Terekhov committed
358
359
		integer selfid = 1;
		selfid = TieElement(5);
Kirill Terekhov's avatar
Kirill Terekhov committed
360
361
362
363
		assert(selfid == 0);
		//TagManager constuctor copied only tags
		//copy links:
		for(int i = 0; i < 5; i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
364
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
365
366
367
			links[i] = other.links[i];
			empty_links[i] = other.empty_links[i];
			empty_space[i] = other.empty_space[i];
Kirill Terekhov's avatar
Kirill Terekhov committed
368
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
369
370
		//this should alocate space for data and copy it including markers and connections
		for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype))
Kirill Terekhov's avatar
Kirill Terekhov committed
371
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
372
373
374
375
			ReallocateData(ElementNum(etype),GetArrayCapacity(ElementNum(etype)));
			for(tag_array_type::size_type i = 0; i < tags.size(); ++i)
			{
				if( tags[i].isDefined(etype) )
Kirill Terekhov's avatar
Kirill Terekhov committed
376
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
					if( tags[i].isSparse(etype) )
					{
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) if( isValidElement(etype,lid) )
						{
							HandleType h = ComposeHandle(etype,lid);
							if( other.HaveData(h,tags[i]) )
								TagManager::CopyData(tags[i],MGetLink(h,tags[i]),other.MGetLink(h,other.tags[i]));
						}
					}
					else
					{
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) if( isValidElement(etype,lid) )
						{
							HandleType h = ComposeHandle(etype,lid);
							TagManager::CopyData(tags[i],MGetLink(h,tags[i]),other.MGetLink(h,other.tags[i]));
						}
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
394
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
395
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
396
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
397
398
		//setup system tags shortcuts
		dim = other.dim;
Kirill Terekhov's avatar
Kirill Terekhov committed
399
400
401
402
403
404
405
		tag_coords        = CreateTag("PROTECTED_COORD",DATA_REAL, NODE,NONE,dim);
		tag_high_conn     = CreateTag("PROTECTED_HIGH_CONN",DATA_REFERENCE,ESET|CELL|FACE|EDGE|NODE,NONE);
		tag_low_conn      = CreateTag("PROTECTED_LOW_CONN",DATA_REFERENCE,ESET|CELL|FACE|EDGE|NODE,NONE);
		tag_markers       = CreateTag("PROTECTED_MARKERS",DATA_BULK,CELL|FACE|EDGE|NODE|ESET|MESH,NONE,MarkerFields);
		tag_geom_type     = CreateTag("PROTECTED_GEOM_TYPE",DATA_BULK,CELL|FACE|EDGE|NODE,NONE,1);
		tag_setname       = CreateTag("PROTECTED_SET_NAME",DATA_BULK,ESET,NONE);
		tag_setcomparator = CreateTag("PROTECTED_SET_COMPARATOR",DATA_BULK,ESET,NONE,1);
406
		AllocatePrivateMarkers();
Kirill Terekhov's avatar
Kirill Terekhov committed
407
408
409
410
411
412
		//copy supplimentary values
		m_state = other.m_state;
		checkset = other.checkset;
		errorset = other.errorset;
		new_element = other.new_element;
		hide_element = other.hide_element;
Kirill Terekhov's avatar
Kirill Terekhov committed
413
		epsilon = other.epsilon;
414
		//have_global_id = other.have_global_id;
Kirill Terekhov's avatar
Kirill Terekhov committed
415
416
417
418
419
420
421
422
		// copy communicator
		if( m_state == Mesh::Parallel ) SetCommunicator(other.comm); else comm = INMOST_MPI_COMM_WORLD;
		// reestablish geometric tags and table
		memcpy(remember,other.remember,sizeof(remember));
		RestoreGeometricTags();
		//this is not needed as it was copied with all the other data
		//recompute global ids
		//AssignGlobalID(other.have_global_id);
423
		allocated_meshes.push_back(this);
Kirill Terekhov's avatar
Kirill Terekhov committed
424
425
426
427
428
	}
	
	Mesh & Mesh::operator =(Mesh const & other)
	{
		if( this == &other ) return *this; //don't do anything
429
430
431
432
433
434
435
436
437
		{
			std::stringstream tmp;
			tmp << other.name << "_copy";
			name = tmp.str();
		}
#if defined(CHECKS_MARKERS)
		check_shared_mrk = other.check_shared_mrk;
		check_private_mrk = other.check_private_mrk;
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
438
439
		//first delete everything
		//delete parallel vars
Kirill Terekhov's avatar
Kirill Terekhov committed
440
#if defined(USE_MPI)
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
441
#if defined(USE_MPI_P2P)
Kirill Terekhov's avatar
Kirill Terekhov committed
442
443
444
445
446
447
448
		if( m_state == Mesh::Parallel )
		{
			MPI_Free_mem(shared_space);
			MPI_Win_free(&window);
		}
#endif
#endif
449
		
Kirill Terekhov's avatar
Kirill Terekhov committed
450
451
		//clear all data fields
		for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype))
Kirill Terekhov's avatar
Kirill Terekhov committed
452
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
453
454
455
456
457
458
			for(tag_array_type::size_type i = 0; i < tags.size(); ++i)
			{
				if( tags[i].isDefined(etype) )
				{
					if( tags[i].isSparse(etype) )
					{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
459
460
461
462
#if defined(USE_OMP)
#pragma omp parallel for
#endif
						for(integer lid = 0; lid < LastLocalID(etype); ++lid)
Kirill Terekhov's avatar
Kirill Terekhov committed
463
464
465
466
467
							if( isValidElement(etype,lid) )
								DelSparseData(ComposeHandle(etype,lid),tags[i]);
					}
					else if( tags[i].GetSize() == ENUMUNDEF )
					{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
468
469
470
#if defined(USE_OMP)
#pragma omp parallel for
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
471
472
473
474
475
476
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) 
							if( isValidElement(etype,lid) )
								DelDenseData(ComposeHandle(etype,lid),tags[i]);
					}
				}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
477
		}
478
		
Kirill Terekhov's avatar
Kirill Terekhov committed
479
480
		//clear links
		for(int i = 0; i < 5; i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
481
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
482
483
484
			links[i].clear();
			empty_links[i].clear();
			empty_space[i].clear();
Kirill Terekhov's avatar
Kirill Terekhov committed
485
		}
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
486
		DeallocatePrivateMarkers();
487
		//while( !tags.empty() ) DeleteTag(tags.back(),CELL|FACE|EDGE|NODE|ESET|MESH);
Kirill Terekhov's avatar
Kirill Terekhov committed
488
489
490
491
		//this should copy tags, clear sparse data, set up dense links
		TagManager::operator =(other);
		//set up new links
		for(int i = 0; i < 5; i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
492
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
493
494
495
			links[i] = other.links[i];
			empty_links[i] = other.empty_links[i];
			empty_space[i] = other.empty_space[i];
Kirill Terekhov's avatar
Kirill Terekhov committed
496
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
497
498
		//this should alocate space for data and copy it including markers and connections
		for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype))
Kirill Terekhov's avatar
Kirill Terekhov committed
499
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
500
501
502
503
			ReallocateData(ElementNum(etype),GetArrayCapacity(ElementNum(etype)));
			for(tag_array_type::size_type i = 0; i < tags.size(); ++i)
			{
				if( tags[i].isDefined(etype) )
Kirill Terekhov's avatar
Kirill Terekhov committed
504
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
					if( tags[i].isSparse(etype) )
					{
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) if( isValidElement(etype,lid) )
						{
							HandleType h = ComposeHandle(etype,lid);
							if( other.HaveData(h,tags[i]) )
								TagManager::CopyData(tags[i],MGetLink(h,tags[i]),other.MGetLink(h,other.tags[i]));
						}
					}
					else
					{
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) if( isValidElement(etype,lid) )
						{
							HandleType h = ComposeHandle(etype,lid);
							TagManager::CopyData(tags[i],MGetLink(h,tags[i]),other.MGetLink(h,other.tags[i]));
						}
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
522
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
523
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
524
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
525
526
		//setup system tags shortcuts
		dim = other.dim;
Kirill Terekhov's avatar
Kirill Terekhov committed
527
528
529
530
531
532
533
		tag_coords        = CreateTag("PROTECTED_COORD",DATA_REAL, NODE,NONE,dim);
		tag_high_conn     = CreateTag("PROTECTED_HIGH_CONN",DATA_REFERENCE,ESET|CELL|FACE|EDGE|NODE,NONE);
		tag_low_conn      = CreateTag("PROTECTED_LOW_CONN",DATA_REFERENCE,ESET|CELL|FACE|EDGE|NODE,NONE);
		tag_markers       = CreateTag("PROTECTED_MARKERS",DATA_BULK,CELL|FACE|EDGE|NODE|ESET|MESH,NONE,MarkerFields);
		tag_geom_type     = CreateTag("PROTECTED_GEOM_TYPE",DATA_BULK,CELL|FACE|EDGE|NODE,NONE,1);
		tag_setname       = CreateTag("PROTECTED_SET_NAME",DATA_BULK,ESET,NONE);
		tag_setcomparator = CreateTag("PROTECTED_SET_COMPARATOR",DATA_BULK,ESET,NONE,1);
534
		AllocatePrivateMarkers();
Kirill Terekhov's avatar
Kirill Terekhov committed
535
536
537
538
539
540
		//copy supplimentary values
		m_state = other.m_state;
		checkset = other.checkset;
		errorset = other.errorset;
		new_element = other.new_element;
		hide_element = other.hide_element;
Kirill Terekhov's avatar
Kirill Terekhov committed
541
		epsilon = other.epsilon;
542
		//have_global_id = other.have_global_id;
Kirill Terekhov's avatar
Kirill Terekhov committed
543
544
545
546
547
548
549
550
		// copy communicator
		if( m_state == Mesh::Parallel ) SetCommunicator(other.comm); else comm = INMOST_MPI_COMM_WORLD;
		// reestablish geometric tags and table
		memcpy(remember,other.remember,sizeof(remember));
		RestoreGeometricTags();
		//this is not needed as it was copied with all the other data
		//recompute global ids
		//AssignGlobalID(other.have_global_id);
Kirill Terekhov's avatar
Kirill Terekhov committed
551
552
		return *this;
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
553
554
555

	void Mesh::Clear()
	{
556
557
		
		/*
Kirill Terekhov's avatar
Kirill Terekhov committed
558
559
560
561
562
563
564
565
		for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype))
		{
			for(tag_array_type::size_type i = 0; i < tags.size(); ++i)
			{
				if( tags[i].isDefined(etype) )
				{
					if( tags[i].isSparse(etype) )
					{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
566
567
568
#if defined(USE_OMP)
#pragma omp parallel for
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
569
570
571
572
573
574
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) 
							if( isValidElement(etype,lid) )
								DelSparseData(ComposeHandle(etype,lid),tags[i]);
					}
					else if( tags[i].GetSize() == ENUMUNDEF )
					{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
575
576
577
#if defined(USE_OMP)
#pragma omp parallel for
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
578
579
580
581
582
583
584
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) 
							if( isValidElement(etype,lid) )
								DelDenseData(ComposeHandle(etype,lid),tags[i]);
					}
				}
			}
		}
585
		*/
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
586
		DeallocatePrivateMarkers();
Kirill Terekhov's avatar
Kirill Terekhov committed
587
		memset(remember,0,sizeof(bool)*15);
588
		while( !tags.empty() ) DeleteTag(tags.back(),CELL|FACE|EDGE|NODE|ESET|MESH);
Kirill Terekhov's avatar
Kirill Terekhov committed
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
		tags.clear();
		//clear links
		dense_data.clear();
		for(int i = 0; i < 5; i++)
		{
			links[i].clear();
			empty_links[i].clear();
			empty_space[i].clear();
		}
		for(int i = 0; i < 6; i++)
		{
			sparse_data[i].clear();
			back_links[i].clear();
		}
		RemTopologyCheck(ENUMUNDEF);
		SetTopologyCheck(DEFAULT_CHECK);

	}
Kirill Terekhov's avatar
Kirill Terekhov committed
607
608
609
	
	Mesh::~Mesh()
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
610
		//clear all data fields
611
612
		//while( !tags.empty() ) DeleteTag(tags.back(),CELL|FACE|EDGE|NODE|ESET|MESH);
		/*
Kirill Terekhov's avatar
Kirill Terekhov committed
613
		for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype))
Kirill Terekhov's avatar
Kirill Terekhov committed
614
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
615
616
617
618
619
620
			for(tag_array_type::size_type i = 0; i < tags.size(); ++i)
			{
				if( tags[i].isDefined(etype) )
				{
					if( tags[i].isSparse(etype) )
					{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
621
622
623
#if defined(USE_OMP)
#pragma omp parallel for
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
624
625
626
627
628
629
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) 
							if( isValidElement(etype,lid) )
								DelSparseData(ComposeHandle(etype,lid),tags[i]);
					}
					else if( tags[i].GetSize() == ENUMUNDEF )
					{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
630
631
632
#if defined(USE_OMP)
#pragma omp parallel for
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
633
634
635
636
637
638
						for(integer lid = 0; lid < LastLocalID(etype); ++lid) 
							if( isValidElement(etype,lid) )
								DelDenseData(ComposeHandle(etype,lid),tags[i]);
					}
				}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
639
		}
640
		*/
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
641
		DeallocatePrivateMarkers();
642
		while( !tags.empty() ) DeleteTag(tags.back(),CELL|FACE|EDGE|NODE|ESET|MESH);
Kirill Terekhov's avatar
Kirill Terekhov committed
643
644
		//clear links
		for(int i = 0; i < 5; i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
645
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
646
647
648
			links[i].clear();
			empty_links[i].clear();
			empty_space[i].clear();
Kirill Terekhov's avatar
Kirill Terekhov committed
649
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
650
#if defined(USE_MPI)
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
651
#if defined(USE_MPI_P2P)
Kirill Terekhov's avatar
Kirill Terekhov committed
652
653
		if( m_state == Mesh::Parallel )
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
			int test = 0;
			MPI_Finalized(&test);
			if( !test )
			{
				MPI_Free_mem(shared_space);
				MPI_Win_free(&window);
			}
			else
			{
				std::cout << "Cannot release memory and window allocated by MPI" << std::endl;
				std::cout << "since MPI was already finalized. Most likely this" << std::endl;
				std::cout << "happens when you define class Mesh in main() function" << std::endl;
				std::cout << "so that destructor get called after Mesh::Finalize()" << std::endl;
				std::cout << "Please enclose area where you use Mesh class" << std::endl;
				std::cout << "with scopes, so that destructor get called when" << std::endl;
				std::cout << "execution goes out of the scope or dynamically" << std::endl;
				std::cout << "allocate and explicitly delete Mesh class." << std::endl;
				std::cout << "Thank you!" << std::endl;
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
673
674
			//~ MPI_Comm_free(&comm);
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
675
676
#endif //USE_MPI_P2P
#endif //USE_MPI
Kirill Terekhov's avatar
Kirill Terekhov committed
677
#if defined(USE_PARALLEL_WRITE_TIME)
Kirill Terekhov's avatar
Kirill Terekhov committed
678
679
		FinalizeFile();
#endif //USE_PARALLEL_WRITE_TIME
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
680
681
682
683
684
685
686
		{
			for(size_t q = 0; q < allocated_meshes.size(); ++q)
				if (allocated_meshes[q] == this)
					allocated_meshes[q] = NULL;
			std::sort(allocated_meshes.rbegin(), allocated_meshes.rend());
			while(!allocated_meshes.empty() && allocated_meshes.back() == NULL) allocated_meshes.pop_back();
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
687
		//arrays for data are deallocated inside ~TagManager()
Kirill Terekhov's avatar
Kirill Terekhov committed
688
689
690
691
692
693
694
695
696
697
698
	}
	
	
	
	Tag Mesh::CreateTag(std::string name, DataType dtype, ElementType etype,ElementType sparse, INMOST_DATA_ENUM_TYPE size)
	{
		Tag ret = TagManager::CreateTag(this,name,dtype,etype,sparse,size);
		return ret;
	}
	Tag Mesh::DeleteTag(Tag tag, ElementType type_mask)
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
699
		//std::cout << "Delete tag " << tag.GetTagName() << " type " << DataTypeName(tag.GetDataType()) << " on ";
Kirill Terekhov's avatar
Kirill Terekhov committed
700
701
		//for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype)) if( (etype & type_mask) && tag.isDefined(etype) ) std::cout << ElementTypeName(etype) << " ";
		//std::cout << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
702
703
		//deallocate data on elements
		for(ElementType etype = NODE; etype <= MESH; etype = NextElementType(etype))
Kirill Terekhov's avatar
Kirill Terekhov committed
704
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
705
706
707
708
			if( (etype & type_mask) && tag.isDefined(etype) )
			{
				if( tag.isSparse(etype) )
				{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
709
710
711
#if defined(USE_OMP)
#pragma omp parallel for
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
712
713
714
715
716
717
					for(integer lid = 0; lid < LastLocalID(etype); ++lid) 
						if( isValidElement(etype,lid) )
							DelSparseData(ComposeHandle(etype,lid),tag);
				}
				else if( tag.GetSize() == ENUMUNDEF )
				{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
718
719
720
#if defined(USE_OMP)
#pragma omp parallel for
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
721
722
723
724
725
					for(integer lid = 0; lid < LastLocalID(etype); ++lid) 
						if( isValidElement(etype,lid) )
							DelDenseData(ComposeHandle(etype,lid),tag);
				}
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
726
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
727
#if defined(USE_OMP)
728
#pragma omp critical (change_tags)
Kirill Terekhov's avatar
Kirill Terekhov committed
729
#endif
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
730
731
732
		{
			tag = TagManager::DeleteTag(tag,type_mask);
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
733
734
735
736
737
		return tag;
	}
	
	
	
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
738
	HandleType Mesh::FindSharedAdjacency(const HandleType * arr, enumerator s) const
Kirill Terekhov's avatar
Kirill Terekhov committed
739
	{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
740
		if( s == 0 ) return InvalidHandle();
Kirill Terekhov's avatar
Kirill Terekhov committed
741
742
743
		if( !HideMarker() )
		{
			{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
744
				enumerator flag0, flag1, i;
Kirill Terekhov's avatar
Kirill Terekhov committed
745
746
747
				dynarray<Element::adj_type const *, 64> hcarr(s);
				hcarr[0] = &HighConn(arr[0]);
				if( !hcarr[0]->empty() ) 
Kirill Terekhov's avatar
Kirill Terekhov committed
748
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
749
					for(i = 1; i < s; i++) hcarr[i] = &HighConn(arr[i]);
Kirill Terekhov's avatar
Kirill Terekhov committed
750
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
751
				else return InvalidHandle();
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
752
				enumerator it, iend = static_cast<enumerator>(hcarr[0]->size()), jt, jend;
Kirill Terekhov's avatar
Kirill Terekhov committed
753
				for(it = 0; it < iend; ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
754
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
755
					flag0 = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
756
					for(i = 1; i < s; ++i)
Kirill Terekhov's avatar
Kirill Terekhov committed
757
					{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
758
						jend = static_cast<enumerator>(hcarr[i]->size());
Kirill Terekhov's avatar
Kirill Terekhov committed
759
760
						flag1 = 0;
						for(jt = 0; jt < jend; ++jt)
Kirill Terekhov's avatar
Kirill Terekhov committed
761
						{
Kirill Terekhov's avatar
Kirill Terekhov committed
762
							if( hcarr[0]->at(it) == hcarr[i]->at(jt) )
Kirill Terekhov's avatar
Kirill Terekhov committed
763
764
							{
								flag0++;
Kirill Terekhov's avatar
Kirill Terekhov committed
765
								flag1 = 1;
Kirill Terekhov's avatar
Kirill Terekhov committed
766
767
768
								break;
							}
						}
Kirill Terekhov's avatar
Kirill Terekhov committed
769
						if( flag1 == 0 ) break;
Kirill Terekhov's avatar
Kirill Terekhov committed
770
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
771
					if( flag0 == s-1 ) 
Kirill Terekhov's avatar
Kirill Terekhov committed
772
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
773
						return hcarr[0]->at(it);
Kirill Terekhov's avatar
Kirill Terekhov committed
774
775
					}
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
776
777
778
779
			}
		}
		else
		{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
780
781
			enumerator ss = Count(arr,s,HideMarker()), nextk;
			enumerator k = ENUMUNDEF, i;
Kirill Terekhov's avatar
Kirill Terekhov committed
782
783
784
785
786
			k = getNext(arr,s,k,HideMarker());
			nextk = getNext(arr,s,k,HideMarker());
			Element::adj_type const & hc0 = HighConn(arr[k]);
			Element::adj_type::size_type it, iend = hc0.size(), jt, jend, flag0, flag1;
			for(it = 0; it < iend; ++it) if( !GetMarker(hc0[it],HideMarker()) )
Kirill Terekhov's avatar
Kirill Terekhov committed
787
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
788
789
790
				flag0 = 0;
				i = nextk;
				while( i < s )
Kirill Terekhov's avatar
Kirill Terekhov committed
791
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
792
793
794
795
					flag1 = 0;
					Element::adj_type const & ihc = HighConn(arr[i]);
					jend = ihc.size();
					for(jt = 0; jt < jend; ++jt) if( !GetMarker(ihc[jt],HideMarker()) )
Kirill Terekhov's avatar
Kirill Terekhov committed
796
					{
Kirill Terekhov's avatar
Kirill Terekhov committed
797
						if( hc0[it] == ihc[jt] )
Kirill Terekhov's avatar
Kirill Terekhov committed
798
799
						{
							flag0++;
Kirill Terekhov's avatar
Kirill Terekhov committed
800
							flag1 = 1;
Kirill Terekhov's avatar
Kirill Terekhov committed
801
802
803
							break;
						}
					}
Kirill Terekhov's avatar
Kirill Terekhov committed
804
805
					if( flag1 == 0 ) break;
					i = getNext(arr,s,i,HideMarker());
Kirill Terekhov's avatar
Kirill Terekhov committed
806
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
807
				if( flag0 == ss-1 ) return hc0[it];
Kirill Terekhov's avatar
Kirill Terekhov committed
808
809
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
810
		return InvalidHandle();
Kirill Terekhov's avatar
Kirill Terekhov committed
811
812
813
	}
	
	
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
814
	TopologyCheck Mesh::BeginTopologyCheck(ElementType etype, const HandleType * adj, enumerator s)
Kirill Terekhov's avatar
Kirill Terekhov committed
815
	{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
816
		enumerator i,j,d = ENUMUNDEF;
Kirill Terekhov's avatar
Kirill Terekhov committed
817
		TopologyCheck chk = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
818
		if( GetTopologyCheck(ADJACENT_VALID) )
Kirill Terekhov's avatar
Kirill Terekhov committed
819
820
		{
			for(i = 0; i < s; i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
821
				if( !isValidHandle(adj[i]) )
Kirill Terekhov's avatar
Kirill Terekhov committed
822
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
823
824
					chk |= ADJACENT_VALID;
					if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_VALID) << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
825
826
				}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
827
		if( GetTopologyCheck(ADJACENT_HIDDEN) )
Kirill Terekhov's avatar
Kirill Terekhov committed
828
829
		{
			for(i = 0; i < s; i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
830
				if( GetMarker(adj[i],HideMarker()) )
Kirill Terekhov's avatar
Kirill Terekhov committed
831
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
832
833
					chk |= ADJACENT_HIDDEN;
					if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_HIDDEN) << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
834
835
836
837
838
				}
		}
		if( GetTopologyCheck(ADJACENT_DUPLICATE) )
		{
			bool have_dup = false;
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
839
			MarkerType dup = CreatePrivateMarker();
Kirill Terekhov's avatar
Kirill Terekhov committed
840
841
			for(i = 0; i < s; i++)
			{
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
842
				if( GetPrivateMarker(adj[i],dup) )
Kirill Terekhov's avatar
Kirill Terekhov committed
843
844
845
846
				{
					have_dup = true; // duplication of element
					break;
				}
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
847
				else SetPrivateMarker(adj[i],dup);
Kirill Terekhov's avatar
Kirill Terekhov committed
848
			}
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
849
850
			for(i = 0; i < s; i++) RemPrivateMarker(adj[i],dup);
			ReleasePrivateMarker(dup);
Kirill Terekhov's avatar
Kirill Terekhov committed
851
852
853
854
855
856
857
858
859
860
861
862
863
			
			if( have_dup )
			{
				chk |= ADJACENT_DUPLICATE;
				if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_DUPLICATE) << std::endl;
			}
		}
		
		if( GetTopologyCheck(ADJACENT_DIMENSION | DEGENERATE_CELL | DEGENERATE_FACE | DEGENERATE_EDGE | DISABLE_2D) )
		{
			bool happen = false;
			for(i = 0; i < s; i++)
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
864
				j = ElementByHandle(adj[i])->GetElementDimension();
Kirill Terekhov's avatar
Kirill Terekhov committed
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
				if( j == ENUMUNDEF ) 
				{
					chk |= ADJACENT_DIMENSION;
					if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_DIMENSION) << std::endl;
					happen = true;
					break;
				}
				if( d == ENUMUNDEF ) d = j;
				if( d != j ) 
				{
					chk |= ADJACENT_DIMENSION;
					if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_DIMENSION) << std::endl;
					happen = true;
					break;
				}
			}
			if(!happen) switch(etype) //if happen = true, we cannot be sure about value in d
			{
				case EDGE: 
					if( GetTopologyCheck(DISABLE_2D) )
					{
						if( s == 1 && d == 0 ) 
						{
							chk |= DISABLE_2D;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DISABLE_2D) << std::endl;
						}
					}
					if( GetTopologyCheck(ADJACENT_DIMENSION) )
					{
						if( d > 0 ) 
						{
							chk |= ADJACENT_DIMENSION;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_DIMENSION) << std::endl;
						}
					}
					if( GetTopologyCheck(DEGENERATE_EDGE) )
					{
						if( s > 2 )
						{
							chk |= DEGENERATE_EDGE;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DEGENERATE_EDGE) << std::endl;
						}
					}
				break;
				case FACE:
					if( GetTopologyCheck(DISABLE_2D) )
					{
						if( s == 2 && d == 0 ) 
						{
							chk |= DISABLE_2D;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DISABLE_2D) << std::endl;
						}
					}
					if( GetTopologyCheck(ADJACENT_DIMENSION) )
					{
						if( d > 1 ) 
						{
							chk |= ADJACENT_DIMENSION;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_DIMENSION) << std::endl;
						}
					}
					if( GetTopologyCheck(DEGENERATE_EDGE) )
					{
						if(d == 0 && s != 2) //This should be Edge (2D)
						{
							chk |= DEGENERATE_EDGE;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DEGENERATE_EDGE) << std::endl;
						}
					}
					if( GetTopologyCheck() & DEGENERATE_FACE )
					{
						if(d == 1 && s < 3) // Should not be less then 3 Line or Curve
						{
							chk |= DEGENERATE_FACE;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DEGENERATE_FACE) << std::endl;
						}					
					}
				break;
				case CELL:
					if( GetTopologyCheck(DISABLE_2D) )
					{
						if( d == 1 ) 
						{
							chk |= DISABLE_2D;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DISABLE_2D) << std::endl;
						}
					}
					if( GetTopologyCheck(ADJACENT_DIMENSION) )
					{
						if( d > 2 || d == 0 ) 
						{
							chk |= ADJACENT_DIMENSION;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(ADJACENT_DIMENSION) << std::endl;
						}
					}
					if( GetTopologyCheck(DEGENERATE_FACE) )
					{
						if( d == 1 && s < 3 ) //Should not be less then 3 Line
						{
							chk |= DEGENERATE_FACE;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DEGENERATE_FACE) << std::endl;
						} 
					}
					if( GetTopologyCheck(DEGENERATE_CELL) )
					{
						if( d == 2 && s < 4 ) //Should not be less then 4 Tri, Quad, Polygon
						{
							chk |= DEGENERATE_CELL;
							if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DEGENERATE_CELL) << std::endl;
						} 
					}
				break;
			}
		}
		if( etype == CELL )
		{
			if( GetTopologyCheck(TRIPLE_SHARED_FACE) )
			{
				bool check = false;
				for(i = 0; i < s; i++)
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
986
					if( ElementByHandle(adj[i])->nbAdjElements(CELL) == 2 )
Kirill Terekhov's avatar
Kirill Terekhov committed
987
988
989
990
991
992
993
994
					{
						check = true;
						break;
					}
				}
				if( check )
				{
					bool happen = true;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
995
					if( (GetTopologyCheck(DUPLICATE_CELL)) && (FindSharedAdjacency(adj,s) != InvalidHandle()) ) happen = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
					if( happen )
					{
						chk |= TRIPLE_SHARED_FACE;
						if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(TRIPLE_SHARED_FACE) << std::endl;
					}
				}
			}
		}
		else if( etype == FACE )
		{
			if( GetTopologyCheck(INTERLEAVED_FACES) )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1008
1009
1010
				ElementArray<Node> allnodes(this);
				for(i = 0; i < s; i++) allnodes.Unite(ElementByHandle(adj[i])->getNodes());
				ElementArray<Face> faces = allnodes[0].getFaces();
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1011
1012
				for(i = 1; i < static_cast<enumerator>(allnodes.size()) && !faces.empty(); i++) faces.Intersect(allnodes[i].getFaces());
				for(i = 0; i < static_cast<enumerator>(faces.size()); i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1013
				{
Kirill Terekhov's avatar
Kirill Terekhov committed
1014
					if( faces[i]->nbAdjElements(NODE) != allnodes.size() )
Kirill Terekhov's avatar
Kirill Terekhov committed
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
					{
						chk |= INTERLEAVED_FACES;
						if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(INTERLEAVED_FACES) << std::endl;
					}
				}
			}
		}
		errorset |= chk;
		return chk;
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
1026
	TopologyCheck Mesh::EndTopologyCheck(HandleType he)
Kirill Terekhov's avatar
Kirill Terekhov committed
1027
1028
	{
		TopologyCheck chk = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
1029
		Element e = ElementByHandle(he);
Kirill Terekhov's avatar
Kirill Terekhov committed
1030
1031
1032
1033
1034
		switch(e->GetGeometricDimension(e->GetGeometricType()))
		{
		case 3:
			if( GetTopologyCheck(FLATTENED_CELL) )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1035
				ElementArray<Face> faces = e->getFaces();
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1036
1037
				enumerator num = e->nbAdjElements(NODE);
				for(enumerator i = 0; i < static_cast<enumerator>(faces.size()); i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
				{
					if( faces[i].nbAdjElements(NODE) == num )
					{
						chk |= FLATTENED_CELL;
						if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(FLATTENED_CELL) << std::endl;
					}
				}
			}
			if( GetTopologyCheck(FACE_ORIENTATION) )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1048
				ElementArray<Face> faces = e->getFaces();
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1049
				for(enumerator i = 0; i < static_cast<enumerator>(faces.size()); i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
				{
					if( faces[i].nbAdjElements(CELL) == 1 && !faces[i].CheckNormalOrientation() )
					{
						chk |= FACE_ORIENTATION;
						if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(FACE_ORIENTATION) << std::endl;
						break;
					}
				}
			}
			break;
		case 2:
			if( GetTopologyCheck(FACE_PLANARITY) )
			{
				if( (e->GetElementType() == FACE && !e->getAsFace()->Planarity()) || (e->GetElementType() == CELL && !e->getAsCell()->Planarity()) )
				{
					chk |= FACE_PLANARITY;
					if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(FACE_PLANARITY) << std::endl;
				}
			}
			if( GetTopologyCheck(FACE_EDGES_ORDER) )
			{
				if( (e->GetElementType() == FACE && !e->getAsFace()->CheckEdgeOrder()) || (e->GetElementType() == CELL && !e->getAsCell()->CheckEdgeOrder()) )
				{
					chk |= FACE_EDGES_ORDER;
					if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(FACE_EDGES_ORDER) << std::endl;
				}
			}
			break;
		}
		if( GetTopologyCheck(PROHIBIT_MULTILINE) )
		{
			if( e->GetGeometricType() == Element::MultiLine )
			{
				chk |= PROHIBIT_MULTILINE;
				if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(PROHIBIT_MULTILINE) << std::endl;
			}
		}
		if( GetTopologyCheck(PROHIBIT_MULTIPOLYGON) )
		{
			if( e->GetGeometricType() == Element::MultiPolygon )
			{
				chk |= PROHIBIT_MULTIPOLYGON;
				if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(PROHIBIT_MULTIPOLYGON) << std::endl;
			}
		}
		if( GetTopologyCheck(PROHIBIT_POLYGON) )
		{
			if( e->GetGeometricType() == Element::Polygon )
			{
				chk |= PROHIBIT_POLYGON;
				if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(PROHIBIT_POLYGON) << std::endl;
			}
		}
		if( GetTopologyCheck(PROHIBIT_POLYHEDRON) )
		{
			if( e->GetGeometricType() == Element::Polyhedron )
			{
				chk |= PROHIBIT_POLYHEDRON;
				if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(PROHIBIT_POLYHEDRON) << std::endl;
			}
		}
		errorset |= chk;
		return chk;
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
1115
1116
1117
	Node Mesh::CreateNode(const real * coords)
	{
		integer id = TieElement(0);
1118
		HandleType h = ComposeHandleNum(0,id);
Kirill Terekhov's avatar
Kirill Terekhov committed
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
		SetGeometricType(h,Element::Vertex);
		real * v = static_cast<Storage::real *>(MGetDenseLink(h,CoordsTag()));
		for(integer i = 0; i < dim; i++) v[i] = coords[i];
		SetMarker(h,NewMarker());
		return Node(this,h);
	}

	void PrintHandle(HandleType h)
	{
		std::cout << ElementTypeName(GetHandleElementType(h)) << " " << GetHandleID(h);
	}

	void PrintAdjElem(Element::adj_type const & arr)
	{
		for(Element::adj_type::size_type it = 0; it < arr.size(); ++it)
		{
			PrintHandle(arr[it]);
			std::cout << " ";
		}
		std::cout << std::endl;
	}

	void PrintHandles(const HandleType * beg, const HandleType * end)
Kirill Terekhov's avatar
Kirill Terekhov committed
1142
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1143
1144
1145
1146
1147
1148
		for(const HandleType * it = beg; it != end; ++it)
		{
			PrintHandle(*it);
			std::cout << " ";
		}
		std::cout << std::endl;
Kirill Terekhov's avatar
Kirill Terekhov committed
1149
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
1150
1151

	std::pair<Edge,bool> Mesh::CreateEdge(const ElementArray<Node> & nodes)
Kirill Terekhov's avatar
Kirill Terekhov committed
1152
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1153
1154
		HandleType he = InvalidHandle();
		if( !nodes.empty() )
Kirill Terekhov's avatar
Kirill Terekhov committed
1155
1156
		{
			TopologyCheck chk = 0;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1157
			chk |= BeginTopologyCheck(EDGE,nodes.data(),static_cast<enumerator>(nodes.size()));
Kirill Terekhov's avatar
Kirill Terekhov committed
1158
1159
1160
1161
1162
1163
			if( chk != 0 )
			{
				if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
			}
			if( GetTopologyCheck() & DUPLICATE_EDGE )
			{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1164
				HandleType test = FindSharedAdjacency(nodes.data(),static_cast<enumerator>(nodes.size()));
Kirill Terekhov's avatar
Kirill Terekhov committed
1165
1166
1167
				if (test != InvalidHandle()) return std::make_pair(Edge(this,test),false);
			}
			integer id = TieElement(1);
1168
			he = ComposeHandleNum(1,id);
Kirill Terekhov's avatar
Kirill Terekhov committed
1169
1170
1171
1172
1173
			for(ElementArray<Node>::size_type i = 0; i < nodes.size(); i++)
			{
				Element::adj_type & hc = HighConn(nodes.at(i));

				//PrintHandle(nodes.at(i)); std::cout << " current: "; PrintAdjElem(hc); 
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
1174
1175
1176
1177
1178
1179
#if defined(USE_OMP)
#pragma omp critical (node_high_conn)
#endif
				{
					hc.push_back(he);
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194

				//std::cout << "add "; PrintHandle(he); std::cout << " result: "; PrintAdjElem(hc);
			}
			Element::adj_type & lc = LowConn(he);

			//PrintHandle(he); std::cout << " current: "; PrintAdjElem(lc);
			
			lc.insert(lc.end(),nodes.data(),nodes.data()+nodes.size());

			//std::cout << "add "; PrintHandles(nodes.data(),nodes.data()+nodes.size());
			//std::cout << "result: "; PrintAdjElem(lc);
			//DEBUG
			/*
			bool halt = false;
			if(!Element(this,he)->CheckElementConnectivity()) 
Kirill Terekhov's avatar
Kirill Terekhov committed
1195
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1196
1197
				Element(this,he)->PrintElementConnectivity();
				halt = true;
Kirill Terekhov's avatar
Kirill Terekhov committed
1198
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
			for(ElementArray<Node>::size_type i = 0; i < nodes.size(); i++) 
				if(!nodes[i]->CheckElementConnectivity()) 
				{
					nodes[i]->PrintElementConnectivity();
					halt = true;
				}
			assert(!halt);
			*/
			//DEBUG END
			ComputeGeometricType(he);
			SetMarker(he,NewMarker());
			RecomputeGeometricData(he);
			chk |= EndTopologyCheck(he);
Kirill Terekhov's avatar
Kirill Terekhov committed
1212
1213
			if( chk != 0 )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1214
1215
				if( GetTopologyCheck(MARK_ON_ERROR) ) Integer(he,TopologyErrorTag()) = chk;
				if( GetTopologyCheck(DELETE_ON_ERROR) ) { Destroy(he); he = InvalidHandle();}
Kirill Terekhov's avatar
Kirill Terekhov committed
1216
1217
1218
				if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
1219
		return std::make_pair(Edge(this,he),true);
Kirill Terekhov's avatar
Kirill Terekhov committed
1220
1221
1222
	}
	
	
Kirill Terekhov's avatar
Kirill Terekhov committed
1223
	std::pair<Face,bool> Mesh::CreateFace(const ElementArray<Node> & f_nodes)
Kirill Terekhov's avatar
Kirill Terekhov committed
1224
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1225
1226
1227
		ElementArray<Edge> f_edges(this,f_nodes.size());
		ElementArray<Node> e_nodes(this,2);
		if( f_nodes.size() == 2 ) //This is an edge for 2d!
Kirill Terekhov's avatar
Kirill Terekhov committed
1228
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
1229
1230
1231
1232
1233
			e_nodes.resize(1);
			e_nodes.at(0) = f_nodes.at(0);
			f_edges.at(0) = CreateEdge(e_nodes).first->GetHandle();
			e_nodes.at(0) = f_nodes.at(1);
			f_edges.at(1) = CreateEdge(e_nodes).first->GetHandle();
Kirill Terekhov's avatar
Kirill Terekhov committed
1234
1235
1236
		}
		else
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
1237
			for(ElementArray<Node>::size_type i = 0; i < f_nodes.size(); i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1238
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1239
1240
1241
				e_nodes.at(0) = f_nodes.at(i);
				e_nodes.at(1) = f_nodes.at((i+1)%f_nodes.size());
				f_edges.at(i) = CreateEdge(e_nodes).first->GetHandle();
Kirill Terekhov's avatar
Kirill Terekhov committed
1242
1243
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
1244
		return CreateFace(f_edges);
Kirill Terekhov's avatar
Kirill Terekhov committed
1245
1246
	}
	
Kirill Terekhov's avatar
Kirill Terekhov committed
1247
	std::pair<Face,bool> Mesh::CreateFace(const ElementArray<Edge> & f_edges)
Kirill Terekhov's avatar
Kirill Terekhov committed
1248
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1249
1250
		HandleType he = InvalidHandle();
		if( !f_edges.empty() )
Kirill Terekhov's avatar
Kirill Terekhov committed
1251
1252
		{
			TopologyCheck chk = 0;
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1253
			chk |= BeginTopologyCheck(FACE,f_edges.data(),static_cast<enumerator>(f_edges.size()));
Kirill Terekhov's avatar
Kirill Terekhov committed
1254
1255
1256
1257
1258
1259
			if( chk != 0 )
			{
				if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
			}
			if( GetTopologyCheck(DUPLICATE_FACE) )
			{
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1260
				HandleType test = FindSharedAdjacency(f_edges.data(),static_cast<enumerator>(f_edges.size()));
Kirill Terekhov's avatar
Kirill Terekhov committed
1261
				if (test != InvalidHandle()) return std::make_pair(Face(this,test),false);
Kirill Terekhov's avatar
Kirill Terekhov committed
1262
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
1263
			integer id = TieElement(2);
1264
			he = ComposeHandleNum(2,id);
Kirill Terekhov's avatar
Kirill Terekhov committed
1265
1266
1267
1268
1269
			for(ElementArray<Edge>::size_type i = 0; i < f_edges.size(); i++)
			{
				Element::adj_type & hc = HighConn(f_edges.at(i));

				//PrintHandle(f_edges.at(i)); std::cout << " current: "; PrintAdjElem(hc); 
Kirill Terekhov's avatar
Updates    
Kirill Terekhov committed
1270
1271
1272
#if defined(USE_OMP)
#pragma omp critical (edge_high_conn)
#endif
Kirill Terekhov's avatar
Kirill Terekhov committed
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
				hc.push_back(he);

				//std::cout << "add "; PrintHandle(he); std::cout << " result: "; PrintAdjElem(hc);
			}
			Element::adj_type & lc = LowConn(he);

			//PrintHandle(he); std::cout << "current: "; PrintAdjElem(lc);

			lc.insert(lc.end(),f_edges.data(),f_edges.data()+f_edges.size());

			//std::cout << "add "; PrintHandles(f_edges.data(),f_edges.data()+f_edges.size());
			//std::cout << "result: "; PrintAdjElem(lc);
			//DEBUG
			/*
			bool halt = false;
			if(!Element(this,he)->CheckElementConnectivity())
Kirill Terekhov's avatar
Kirill Terekhov committed
1289
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
				Element(this,he)->PrintElementConnectivity();
				halt = true;
			}
			for(ElementArray<Edge>::size_type i = 0; i < f_edges.size(); i++) 
			{
				if(!f_edges[i]->CheckElementConnectivity())
				{
					f_edges[i]->PrintElementConnectivity();
					halt = true;
				}
Kirill Terekhov's avatar
Kirill Terekhov committed
1300
			}
Kirill Terekhov's avatar
Kirill Terekhov committed
1301
1302
1303
1304
1305
1306
1307
			assert(!halt);
			*/
			//DEBUG END
			ComputeGeometricType(he);
			SetMarker(he,NewMarker());
			RecomputeGeometricData(he);
			chk |= EndTopologyCheck(he);
Kirill Terekhov's avatar
Kirill Terekhov committed
1308
1309
			if( chk != 0 )
			{
Kirill Terekhov's avatar
Kirill Terekhov committed
1310
1311
				if( GetTopologyCheck(MARK_ON_ERROR)   ) Integer(he,TopologyErrorTag()) = chk;
				if( GetTopologyCheck(DELETE_ON_ERROR) ) { Destroy(he); he = InvalidHandle();}
Kirill Terekhov's avatar
Kirill Terekhov committed
1312
1313
1314
				if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
			}
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
1315
		return std::make_pair(Face(this,he),true);
Kirill Terekhov's avatar
Kirill Terekhov committed
1316
1317
1318
	}
	
	
Kirill Terekhov's avatar
Kirill Terekhov committed
1319
	std::pair<Cell,bool> Mesh::CreateCell(const ElementArray<Node> & c_f_nodes, const integer * c_f_sizes, integer s, const ElementArray<Node> & suggest_nodes_order)
Kirill Terekhov's avatar
Kirill Terekhov committed
1320
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1321
1322
1323
		ElementArray<Face> c_faces(this,s);
		ElementArray<Node>::size_type j = 0;
		for(integer i = 0; i < s; i++)
Kirill Terekhov's avatar
Kirill Terekhov committed
1324
		{
Kirill Terekhov's avatar
Kirill Terekhov committed
1325
			c_faces.at(i) = CreateFace(ElementArray<Node>(this, c_f_nodes.data()+j, c_f_nodes.data()+j + c_f_sizes[i])).first->GetHandle();
Kirill Terekhov's avatar
Kirill Terekhov committed
1326
1327
			j += c_f_sizes[i];
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
1328
		return CreateCell(c_faces,suggest_nodes_order);
Kirill Terekhov's avatar
Kirill Terekhov committed
1329
1330
1331
	}
	

Kirill Terekhov's avatar
Kirill Terekhov committed
1332
	std::pair<Cell, bool> Mesh::CreateCell(const ElementArray<Node> & c_f_nodes, const integer * c_f_nodeinds, const integer * c_f_numnodes, integer s, const ElementArray<Node> & suggest_nodes_order)
Kirill Terekhov's avatar
Kirill Terekhov committed
1333
	{
Kirill Terekhov's avatar
Kirill Terekhov committed
1334
1335
1336
1337
1338
1339
1340
1341
1342
		integer j = 0;
		ElementArray<Node> temp(this);
		ElementArray<Face> c_faces(this,s);
		for(integer i = 0; i < s; i++)
		{
			temp.resize(c_f_numnodes[i]);
			for(integer k = j; k < j+c_f_numnodes[i]; k++)
				temp.at(k-j) = c_f_nodes.at(c_f_nodeinds[k]);
			c_faces.at(i) = CreateFace(temp).first->GetHandle();
Kirill Terekhov's avatar
Kirill Terekhov committed
1343
1344
1345
			j += c_f_numnodes[i];
			temp.clear();
		}
Kirill Terekhov's avatar
Kirill Terekhov committed
1346
		return CreateCell(c_faces,suggest_nodes_order);
Kirill Terekhov's avatar
Kirill Terekhov committed
1347
1348
1349
	}
	
	
Kirill Terekhov's avatar
Kirill Terekhov committed
1350
	void Mesh::RestoreCellNodes(HandleType hc, ElementArray<Node> & ret)