diff --git a/contrib/Netgen/README b/contrib/Netgen/README index 37fb85051bd29845e57c8149554c2805a6d80d33..758926ba0fddcb4d6015a8ca1a8e5632c8acc319 100644 --- a/contrib/Netgen/README +++ b/contrib/Netgen/README @@ -2,16 +2,15 @@ This directory contains a (very) slightly modified version of Joachim Sch\"oberl's NETGEN mesh generator: -- only the libsrc directory was kept from the original distribution +- only (part of the) the libsrc directory was kept from the original + distribution -- libsrc/makefile.inc was replaced - -- libsrc/meshing/makefile was changed (removed some files from src) +- some of the makefiles were changed - parts of interface/nglib.cpp were #ifdef'd to remove the dependency towards netgen's CAD engine -All changed are marked with "MODIFIED FOR GMSH" in the source code +All the changes are marked with "MODIFIED FOR GMSH" in the source code See COPYING.LIB for license information diff --git a/contrib/Netgen/libsrc/general/Makefile b/contrib/Netgen/libsrc/general/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1a8ac9e29c130774bcb134d2e92a0674a1b8d0cf --- /dev/null +++ b/contrib/Netgen/libsrc/general/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for general purpose data types +# +src = array.cpp bitarray.cpp hashtabl.cpp symbolta.cpp table.cpp flags.cpp \ + spbita2d.cpp seti.cpp optmem.cpp sort.cpp mystring.cpp parthreads.cpp \ + moveablemem.cpp dynamicmem.cpp ngexception.cpp profiler.cpp +# +lib = gen +libpath = libsrc/general +# +include ../makefile.inc + diff --git a/contrib/Netgen/libsrc/general/array.cpp b/contrib/Netgen/libsrc/general/array.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95d711a96fc7d09fb2e65a28b9c9fd490ed3fae9 --- /dev/null +++ b/contrib/Netgen/libsrc/general/array.cpp @@ -0,0 +1,75 @@ +#ifndef FILE_NGSTD_ARRAYCPP +#define FILE_NGSTD_ARRAYCPP +// necessary for SGI ???? + +/**************************************************************************/ +/* File: array.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type ARRAY +*/ + +#include <mystdlib.h> +#include <myadt.hpp> +#include <assert.h> + + +namespace netgen +{ + //using namespace netgen; + +#ifdef NONE + void BASE_ARRAY :: ReSize (int minsize, int elementsize) + { + cout << "resize, minsize = " << minsize << endl; + + if (inc == -1) + throw Exception ("Try to resize fixed size array"); + + + void * p; + int nsize = (inc) ? allocsize + inc : 2 * allocsize; + if (nsize < minsize) nsize = minsize; + + if (data) + { + p = new char [nsize * elementsize]; + + int mins = (nsize < actsize) ? nsize : actsize; + memcpy (p, data, mins * elementsize); + + delete [] static_cast<char*> (data); + data = p; + } + else + { + data = new char[nsize * elementsize]; + } + + allocsize = nsize; + cout << "resize done" << endl; + } + + + + void BASE_ARRAY :: RangeCheck (int i) const + { + if (i < 0 || i >= actsize) + throw ArrayRangeException (); + } + + void BASE_ARRAY :: CheckNonEmpty () const + { + if (!actsize) + { + throw Exception ("Array should not be empty"); + // cerr << "Array souldn't be empty"; + } + } +#endif +} +#endif + diff --git a/contrib/Netgen/libsrc/general/array.hpp b/contrib/Netgen/libsrc/general/array.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3d90894edfacb5551297a3ee7bada29ec5f0991a --- /dev/null +++ b/contrib/Netgen/libsrc/general/array.hpp @@ -0,0 +1,632 @@ +#ifndef FILE_ARRAY +#define FILE_ARRAY + +/**************************************************************************/ +/* File: array.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + + + + +// template <class T, int B1, int B2> class IndirectArray; + + + +/** + A simple array container. + Array represented by size and data-pointer. + No memory allocation and deallocation, must be provided by user. + Helper functions for printing. + Optional range check by macro RANGE_CHECK + */ + +template <class T, int BASE = 0> +class FlatArray +{ +protected: + /// the size + int size; + /// the data + T * data; +public: + + /// provide size and memory + FlatArray (int asize, T * adata) + : size(asize), data(adata) { ; } + + /// the size + int Size() const { return size; } + + int Begin() const { return BASE; } + int End() const { return size+BASE; } + + /* + /// access array. + T & operator[] (int i) + { +#ifdef DEBUG + if (i-BASE < 0 || i-BASE >= size) + cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl; +#endif + + return data[i-BASE]; + } + */ + + /// Access array. BASE-based + T & operator[] (int i) const + { +#ifdef DEBUG + if (i-BASE < 0 || i-BASE >= size) + cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl; +#endif + + return data[i-BASE]; + } + + /* + template <int B2> + IndirectArray<T, BASE, B2> operator[] (const FlatArray<int, B2> & ind) + { return IndirectArray<T, BASE, B2> (*this, ind); } + */ + + /// Access array, one-based (old fashioned) + T & Elem (int i) + { +#ifdef DEBUG + if (i < 1 || i > size) + cout << "ARRAY<" << typeid(T).name() + << ">::Elem out of range, i = " << i + << ", s = " << size << endl; +#endif + + return ((T*)data)[i-1]; + } + + /// Access array, one-based (old fashioned) + const T & Get (int i) const + { +#ifdef DEBUG + if (i < 1 || i > size) + cout << "ARRAY<" << typeid(T).name() << ">::Get out of range, i = " << i + << ", s = " << size << endl; +#endif + + return ((const T*)data)[i-1]; + } + + /// Access array, one-based (old fashioned) + void Set (int i, const T & el) + { +#ifdef DEBUG + if (i < 1 || i > size) + cout << "ARRAY<" << typeid(T).name() << ">::Set out of range, i = " << i + << ", s = " << size << endl; +#endif + + ((T*)data)[i-1] = el; + } + + + + /// access first element + T & First () const + { + return data[0]; + } + + + /// access last element. check by macro CHECK_RANGE + T & Last () const + { + return data[size-1]; + } + + /// Fill array with value val + FlatArray & operator= (const T & val) + { + for (int i = 0; i < size; i++) + data[i] = val; + return *this; + } + + /// takes range starting from position start of end-start elements + const FlatArray<T> Range (int start, int end) + { + return FlatArray<T> (end-start, data+start); + } + + /// first position of element elem, returns -1 if element not contained in array + int Pos(const T & elem) const + { + int pos = -1; + for(int i=0; pos==-1 && i < this->size; i++) + if(elem == data[i]) pos = i; + return pos; + } + + /// does the array contain element elem ? + bool Contains(const T & elem) const + { + return ( Pos(elem) >= 0 ); + } +}; + + + +// print array +template <class T, int BASE> +inline ostream & operator<< (ostream & s, const FlatArray<T,BASE> & a) +{ + for (int i = a.Begin(); i < a.End(); i++) + s << i << ": " << a[i] << endl; + return s; +} + + + +/** + Dynamic array container. + + ARRAY<T> is an automatically increasing array container. + The allocated memory doubles on overflow. + Either the container takes care of memory allocation and deallocation, + or the user provides one block of data. +*/ +template <class T, int BASE = 0> +class ARRAY : public FlatArray<T, BASE> +{ +protected: + /// physical size of array + int allocsize; + /// memory is responsibility of container + bool ownmem; + +public: + + /// Generate array of logical and physical size asize + explicit ARRAY(int asize = 0) + : FlatArray<T, BASE> (asize, asize ? new T[asize] : 0) + { + allocsize = asize; + ownmem = 1; + } + + /// Generate array in user data + ARRAY(int asize, T* adata) + : FlatArray<T, BASE> (asize, adata) + { + allocsize = asize; + ownmem = 0; + } + + /// array copy + explicit ARRAY (const ARRAY<T> & a2) + : FlatArray<T, BASE> (a2.Size(), a2.Size() ? new T[a2.Size()] : 0) + { + allocsize = this->size; + ownmem = 1; + for (int i = BASE; i < this->size+BASE; i++) + (*this)[i] = a2[i]; + } + + + + /// if responsible, deletes memory + ~ARRAY() + { + if (ownmem) + delete [] this->data; + } + + /// Change logical size. If necessary, do reallocation. Keeps contents. + void SetSize(int nsize) + { + if (nsize > allocsize) + ReSize (nsize); + this->size = nsize; + } + + /// Change physical size. Keeps logical size. Keeps contents. + void SetAllocSize (int nallocsize) + { + if (nallocsize > allocsize) + ReSize (nallocsize); + } + + + /// Add element at end of array. reallocation if necessary. + int Append (const T & el) + { + if (this->size == allocsize) + ReSize (this->size+1); + this->data[this->size] = el; + this->size++; + return this->size; + } + + template <typename T2, int B2> + void Append (FlatArray<T2, B2> a2) + { + if (this->size+a2.Size() > allocsize) + ReSize (this->size+a2.Size()); + for (int i = 0; i < a2.Size(); i++) + this->data[this->size+i] = a2[i+B2]; + this->size += a2.Size(); + } + + + /* + template <int B1, int B2> + void Append (const IndirectArray<T,B1,B2> & a2) + { + if (this->size+a2.Size() > allocsize) + ReSize (this->size+a2.Size()); + for (int i = 0; i < a2.Size(); i++) + this->data[this->size+i] = a2[i+B2]; + this->size += a2.Size(); + } + */ + + /// Delete element i (0-based). Move last element to position i. + void Delete (int i) + { +#ifdef CHECK_ARRAY_RANGE + RangeCheck (i+1); +#endif + + this->data[i] = this->data[this->size-1]; + this->size--; + // DeleteElement (i+1); + } + + + /// Delete element i (1-based). Move last element to position i. + void DeleteElement (int i) + { +#ifdef CHECK_ARRAY_RANGE + RangeCheck (i); +#endif + + this->data[i-1] = this->data[this->size-1]; + this->size--; + } + + /// Delete last element. + void DeleteLast () + { + this->size--; + } + + /// Deallocate memory + void DeleteAll () + { + if (ownmem) + delete [] this->data; + this->data = 0; + this->size = allocsize = 0; + } + + /// Fill array with val + ARRAY & operator= (const T & val) + { + FlatArray<T, BASE>::operator= (val); + return *this; + } + + /// array copy + ARRAY & operator= (const ARRAY & a2) + { + SetSize (a2.Size()); + for (int i = BASE; i < this->size+BASE; i++) + (*this)[i] = a2[i]; + return *this; + } + + /// array copy + ARRAY & operator= (const FlatArray<T> & a2) + { + SetSize (a2.Size()); + for (int i = BASE; i < this->size+BASE; i++) + (*this)[i] = a2[i]; + return *this; + } + + +private: + + /// resize array, at least to size minsize. copy contents + void ReSize (int minsize) + { + int nsize = 2 * allocsize; + if (nsize < minsize) nsize = minsize; + + if (this->data) + { + T * p = new T[nsize]; + + int mins = (nsize < this->size) ? nsize : this->size; + memcpy (p, this->data, mins * sizeof(T)); + + if (ownmem) + delete [] this->data; + ownmem = 1; + this->data = p; + } + else + { + this->data = new T[nsize]; + ownmem = 1; + } + + allocsize = nsize; + } +}; + + + +template <class T, int S> +class ArrayMem : public ARRAY<T> +{ + // T mem[S]; // Intel C++ calls dummy constructor + // char mem[S*sizeof(T)]; + double mem[(S*sizeof(T)+7) / 8]; +public: + /// Generate array of logical and physical size asize + explicit ArrayMem(int asize = 0) + : ARRAY<T> (S, static_cast<T*> (static_cast<void*>(&mem[0]))) + { + this->SetSize (asize); + } + + ArrayMem & operator= (const T & val) + { + ARRAY<T>::operator= (val); + return *this; + } +}; + + + + + +/* +template <class T, int B1, int B2> +class IndirectArray +{ + const FlatArray<T, B1> & array; + const FlatArray<int, B2> & ia; + +public: + IndirectArray (const FlatArray<T,B1> & aa, const FlatArray<int, B2> & aia) + : array(aa), ia(aia) { ; } + int Size() const { return ia.Size(); } + const T & operator[] (int i) const { return array[ia[i]]; } +}; +*/ + + + + + + + + + + +/// +template <class T, int BASE = 0> +class MoveableArray +{ + int size; + int allocsize; + MoveableMem<T> data; + +public: + + MoveableArray() + { + size = allocsize = 0; + data.SetName ("MoveableArray"); + } + + MoveableArray(int asize) + : size(asize), allocsize(asize), data(asize) + { ; } + + ~MoveableArray () { ; } + + int Size() const { return size; } + + void SetSize(int nsize) + { + if (nsize > allocsize) + { + data.ReAlloc (nsize); + allocsize = nsize; + } + size = nsize; + } + + void SetAllocSize (int nallocsize) + { + data.ReAlloc (nallocsize); + allocsize = nallocsize; + } + + /// + T & operator[] (int i) + { return ((T*)data)[i-BASE]; } + + /// + const T & operator[] (int i) const + { return ((const T*)data)[i-BASE]; } + + /// + T & Elem (int i) + { return ((T*)data)[i-1]; } + + /// + const T & Get (int i) const + { return ((const T*)data)[i-1]; } + + /// + void Set (int i, const T & el) + { ((T*)data)[i-1] = el; } + + /// + T & Last () + { return ((T*)data)[size-1]; } + + /// + const T & Last () const + { return ((const T*)data)[size-1]; } + + /// + int Append (const T & el) + { + if (size == allocsize) + { + SetAllocSize (2*allocsize+1); + } + ((T*)data)[size] = el; + size++; + return size; + } + + /// + void Delete (int i) + { + DeleteElement (i+1); + } + + /// + void DeleteElement (int i) + { + ((T*)data)[i-1] = ((T*)data)[size-1]; + size--; + } + + /// + void DeleteLast () + { size--; } + + /// + void DeleteAll () + { + size = allocsize = 0; + data.Free(); + } + + /// + void PrintMemInfo (ostream & ost) const + { + ost << Size() << " elements of size " << sizeof(T) << " = " + << Size() * sizeof(T) << endl; + } + + MoveableArray & operator= (const T & el) + { + for (int i = 0; i < size; i++) + ((T*)data)[i] = el; + return *this; + } + + + MoveableArray & Copy (const MoveableArray & a2) + { + SetSize (a2.Size()); + for (int i = 0; i < this->size; i++) + data[i] = a2.data[i]; + return *this; + } + + /// array copy + MoveableArray & operator= (const MoveableArray & a2) + { + return Copy(a2); + } + + + void SetName (const char * aname) + { + data.SetName(aname); + } +private: + /// + //MoveableArray & operator= (MoveableArray &); //??? + /// + //MoveableArray (const MoveableArray &); //??? +}; + + +template <class T> +inline ostream & operator<< (ostream & ost, MoveableArray<T> & a) +{ + for (int i = 0; i < a.Size(); i++) + ost << i << ": " << a[i] << endl; + return ost; +} + + +/// bubble sort array +template <class T> +inline void BubbleSort (const FlatArray<T> & data) +{ + T hv; + for (int i = 0; i < data.Size(); i++) + for (int j = i+1; j < data.Size(); j++) + if (data[i] > data[j]) + { + hv = data[i]; + data[i] = data[j]; + data[j] = hv; + } +} +/// bubble sort array +template <class T, class S> +inline void BubbleSort (FlatArray<T> & data, FlatArray<S> & slave) +{ + T hv; + S hvs; + for (int i = 0; i < data.Size(); i++) + for (int j = i+1; j < data.Size(); j++) + if (data[i] > data[j]) + { + hv = data[i]; + data[i] = data[j]; + data[j] = hv; + + hvs = slave[i]; + slave[i] = slave[j]; + slave[j] = hvs; + } +} + + +template <class T> +void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, + ARRAY<T> & out) +{ + out.SetSize(0); + for(int i=0; i<in1.Size(); i++) + if(in2.Contains(in1[i])) + out.Append(in1[i]); +} +template <class T> +void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, const FlatArray<T> & in3, + ARRAY<T> & out) +{ + out.SetSize(0); + for(int i=0; i<in1.Size(); i++) + if(in2.Contains(in1[i]) && in3.Contains(in1[i])) + out.Append(in1[i]); +} + + + + +#endif + diff --git a/contrib/Netgen/libsrc/general/autoptr.hpp b/contrib/Netgen/libsrc/general/autoptr.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b90841408bcd5e8d597e10bee5473b1956ddfa85 --- /dev/null +++ b/contrib/Netgen/libsrc/general/autoptr.hpp @@ -0,0 +1,31 @@ +#ifndef FILE_AUTOPTR +#define FILE_AUTOPTR + +/**************************************************************************/ +/* File: autoptr.hpp */ +/* Author: STL, Joachim Schoeberl */ +/* Date: 29. Dec. 02 */ +/**************************************************************************/ + +template <typename T> +class AutoPtr +{ +private: + T * ptr; +public: + typedef T* pT; + explicit AutoPtr (T * p = 0) { ptr = p; } + ~AutoPtr () { delete ptr; } + + T & operator*() const { return *ptr; } + T* operator->() const { return ptr; } + T *& Ptr() { return ptr; } + T * Ptr() const { return ptr; } + void Reset(T * p = 0) { if (p != ptr) { delete ptr; ptr = p; } } + operator bool () { return ptr != 0; } +private: + AutoPtr (AutoPtr &) { ; } + AutoPtr & operator= (AutoPtr &) { ; } +}; + +#endif diff --git a/contrib/Netgen/libsrc/general/bitarray.cpp b/contrib/Netgen/libsrc/general/bitarray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c36e5fc043b42213f48bc8a06807a7f9b357762 --- /dev/null +++ b/contrib/Netgen/libsrc/general/bitarray.cpp @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* File: bitarray.cc */ +/* Autho: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + data type BitArray +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + + +namespace netgen +{ + //using namespace netgen; + + BitArray :: BitArray () + { + size = 0; + data = NULL; + } + + BitArray :: BitArray (int asize) + { + size = 0; + data = NULL; + SetSize (asize); + } + + BitArray :: ~BitArray () + { + delete [] data; + } + + void BitArray :: SetSize (int asize) + { + if (size == asize) return; + delete [] data; + + size = asize; + data = new unsigned char [Addr (size)+1]; + } + + void BitArray :: Set () + { + if (!size) return; + for (int i = 0; i <= Addr (size); i++) + data[i] = UCHAR_MAX; + } + + void BitArray :: Clear () + { + if (!size) return; + for (int i = 0; i <= Addr (size); i++) + data[i] = 0; + } + + + + void BitArray :: Invert () + { + if (!size) return; + for (int i = 0; i <= Addr (size); i++) + data[i] ^= 255; + } + + void BitArray :: And (const BitArray & ba2) + { + if (!size) return; + for (int i = 0; i <= Addr (size); i++) + data[i] &= ba2.data[i]; + } + + + void BitArray :: Or (const BitArray & ba2) + { + if (!size) return; + for (int i = 0; i <= Addr (size); i++) + data[i] |= ba2.data[i]; + } + + + + + + + + + + + + template <int BASE> + void BitArrayChar<BASE> :: Set () + { + data = 1; + } + + template <int BASE> + void BitArrayChar<BASE> :: Clear () + { + data = 0; + } + + + template <int BASE> + void BitArrayChar<BASE> :: Invert () + { + for (int i = BASE; i < data.Size()+BASE; i++) + data[i] = 1 - data[i]; + } + + template <int BASE> + void BitArrayChar<BASE> :: And (const BitArrayChar & ba2) + { + for (int i = BASE; i < data.Size()+BASE; i++) + data[i] &= ba2.data[i]; + } + + + template <int BASE> + void BitArrayChar<BASE> :: Or (const BitArrayChar & ba2) + { + for (int i = BASE; i < data.Size()+BASE; i++) + data[i] |= ba2.data[i]; + } + + + template class BitArrayChar<0>; + template class BitArrayChar<1>; +} diff --git a/contrib/Netgen/libsrc/general/bitarray.hpp b/contrib/Netgen/libsrc/general/bitarray.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ee3478da417f337e646c3c5c655f9de4694b95e7 --- /dev/null +++ b/contrib/Netgen/libsrc/general/bitarray.hpp @@ -0,0 +1,222 @@ +#ifndef FILE_BitArray +#define FILE_BitArray + +/**************************************************************************/ +/* File: bitarray.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +#include <limits.h> + +/** + data type BitArray + + BitArray is a compressed array of Boolean information. By Set and Clear + the whole array or one bit can be set or reset, respectively. + Test returns the state of the accoring bit. + No range checking is done. + + index ranges from 0 to size-1 +*/ +class BitArray +{ + INDEX size; + unsigned char * data; + +public: + BitArray (); + /// + BitArray (INDEX asize); + /// + ~BitArray (); + + /// + void SetSize (INDEX asize); + /// + INDEX Size () const + { + return size; + } + + /// + void Set (); + /// + void Set (INDEX i) + { + data[Addr(i)] |= Mask(i); + } + + void Clear (); + + + void Clear (INDEX i) + { + data[Addr(i)] &= ~Mask(i); + } + + bool Test (INDEX i) const + { + return (data[i / CHAR_BIT] & (char(1) << (i % CHAR_BIT) ) ) ? true : false; + } + + /// + void Invert (); + /// + void And (const BitArray & ba2); + /// + void Or (const BitArray & ba2); +private: + /// + inline unsigned char Mask (INDEX i) const + { + return char(1) << (i % CHAR_BIT); + } + /// + inline INDEX Addr (INDEX i) const + { + return (i / CHAR_BIT); + } + + /// + BitArray & operator= (BitArray &); + /// + BitArray (const BitArray &); +}; + + + +// print bitarray +inline ostream & operator<< (ostream & s, const BitArray & a) +{ + for (int i = 1; i <= a.Size(); i++) + { + s << int (a.Test(i)); + if (i % 40 == 0) s << "\n"; + } + if (a.Size() % 40 != 0) s << "\n"; + return s; +} + + +/* +inline +INDEX BitArray :: Size () const + { + return size; + } + +inline +unsigned char BitArray :: Mask (INDEX i) const + { + return char(1) << (i % CHAR_BIT); + } + +inline +INDEX BitArray :: Addr (INDEX i) const + { + return (i / CHAR_BIT); + } +inline +void BitArray :: Set (INDEX i) + { + data[Addr(i)] |= Mask(i); + } + +inline +void BitArray :: Clear (INDEX i) + { + data[Addr(i)] &= ~Mask(i); + } + + +inline +int BitArray :: Test (INDEX i) const + { + return (data[i / CHAR_BIT] & (char(1) << (i % CHAR_BIT) ) ) ? 1 : 0; + } + +*/ + + + + + + +/** + data type BitArrayChar + + BitArray is an array of Boolean information. By Set and Clear + the whole array or one bit can be set or reset, respectively. + Test returns the state of the accoring bit. + No range checking is done. +*/ +template <int BASE = 1> +class BitArrayChar +{ + /// + ARRAY<char,BASE> data; + +public: + /// + BitArrayChar () + { ; } + /// + BitArrayChar (int asize) + : data(asize) + { ; } + /// + ~BitArrayChar () + { ; } + + /// + void SetSize (int asize) + { data.SetSize(asize); } + + /// + inline int Size () const + { return data.Size(); } + + /// + void Set (); + /// + inline void Set (int i) + { data[i] = 1; } + /// + void Clear (); + /// + inline void Clear (int i) + { data[i] = 0; } + /// + inline int Test (int i) const + { return data[i]; } + /// + void Invert (); + /// + void And (const BitArrayChar & ba2); + /// + void Or (const BitArrayChar & ba2); +private: + /// copy bitarray is not supported + BitArrayChar & operator= (BitArrayChar &) { return *this; } + /// copy bitarray is not supported + BitArrayChar (const BitArrayChar &) { ; } +}; + + + + +template <int BASE> +inline ostream & operator<< (ostream & s, const BitArrayChar<BASE> & a) +{ + for (int i = BASE; i < a.Size()+BASE; i++) + { + s << a.Test(i); + if ( (i-BASE) % 40 == 39) s << "\n"; + } + if (a.Size() % 40 != 0) s << "\n"; + return s; +} + + +#endif diff --git a/contrib/Netgen/libsrc/general/dynamicmem.cpp b/contrib/Netgen/libsrc/general/dynamicmem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f41422f54c0cf13c881457981174712fe4261663 --- /dev/null +++ b/contrib/Netgen/libsrc/general/dynamicmem.cpp @@ -0,0 +1,202 @@ +#include <iostream> +#include <iomanip> + +#ifdef SSE +#include <emmintrin.h> +#endif + +#include <myadt.hpp> +using namespace std; + +namespace netgen +{ + + BaseDynamicMem * BaseDynamicMem::first = 0; + BaseDynamicMem * BaseDynamicMem::last = 0; + + + BaseDynamicMem :: BaseDynamicMem () + { + prev = last; + next = 0; + + if (last) last->next = this; + last = this; + if (!first) first = this; + + size = 0; + ptr = 0; + name = 0; + } + + BaseDynamicMem :: ~BaseDynamicMem () + { + Free(); + + if (next) next->prev = prev; + else last = prev; + if (prev) prev->next = next; + else first = next; + + delete [] name; + } + + void BaseDynamicMem :: SetName (const char * aname) + { + delete [] name; + if (aname) + { + name = new char[strlen(aname)+1]; + strcpy (name, aname); + } + } + + + void BaseDynamicMem :: Alloc (size_t s) + { + size = s; + ptr = new char[s]; + + if (!ptr) + { + cerr << "BaseynamicMem, cannot allocate " << s << " bytes" << endl; + Print (); + throw ("BaseDynamicMem::Alloc: out of memory"); + } + // ptr = (char*)malloc (s); + // ptr = (char*) _mm_malloc (s,16); + } + + void BaseDynamicMem :: ReAlloc (size_t s) + { + if (size == s) return; + + char * old = ptr; + ptr = new char[s]; + + if (!ptr) + { + cerr << "BaseynamicMem, cannot Reallocate " << s << " bytes" << endl; + Print (); + throw ("BaseDynamicMem::Alloc: out of memory"); + } + + + // ptr = (char*)malloc(s); + // ptr = (char*) _mm_malloc (s,16); + memmove (ptr, old, (s < size) ? s : size); + delete [] old; + // free (old); + // _mm_free (old); + size = s; + } + + void BaseDynamicMem :: Free () + { + delete [] ptr; + // free (ptr); + // _mm_free (ptr); + ptr = 0; + } + + void BaseDynamicMem :: Swap (BaseDynamicMem & m2) + { + size_t hi; + char * cp; + hi = size; size = m2.size; m2.size = hi; + cp = ptr; ptr = m2.ptr; m2.ptr = cp; + cp = name; name = m2.name; m2.name = cp; + } + + + void BaseDynamicMem :: Print () + { + cout << "****************** Dynamic Mem Report ****************" << endl; + BaseDynamicMem * p = first; + size_t mem = 0; + int cnt = 0; + while (p) + { + mem += p->size; + cnt++; + + cout << setw(10) << p->size << " Bytes"; + cout << ", addr = " << (void*)p->ptr; + if (p->name) + cout << " in block " << p->name; + cout << endl; + + p = p->next; + } + + if (mem > 100000000) + cout << "memory in dynamic memory: " << mem/1048576 << " MB" << endl; + else if (mem > 100000) + cout << "memory in dynamic memory: " << mem/1024 << " kB" << endl; + else + cout << "memory in dynamic memory: " << mem << " Bytes" << endl; + cout << "number of blocks: " << cnt << endl; + // cout << "******************************************************" << endl; + } + + +#pragma warning(push) +#ifdef __INTEL_COMPILER +#pragma warning(disable:1684) +#endif + + void BaseDynamicMem :: GetUsed (int nr, char * ch) + { + BaseDynamicMem * p = first; + + for (int i = 0; i < nr; i++) + ch[i] = '0'; + + while (p) + { + long unsigned hptr = (long unsigned) (p->ptr); + // uintptr_t hptr = reinterpret_cast<uintptr_t>(p->ptr); //?? + + hptr /= (1024*1024); + hptr /= (4096/nr); + + size_t blocks = p->size / (1024*1024); + blocks /= (4096/nr); + + // cout << "ptr = " << (void*)(p->ptr) << ", size = " << p->size << ", hptr = " << hptr << " blocks = " << blocks << endl; + + for (size_t i = 0; i <= blocks; i++) + ch[hptr+i] = '1'; + + p = p->next; + } + + { + + BaseMoveableMem * pm = BaseMoveableMem::first; + while (pm) + { + long unsigned hptr = (long unsigned) p->ptr; + // uintptr_t hptr = reinterpret_cast<uintptr_t>(pm->ptr); + + hptr /= (1024*1024); + hptr /= (4096/nr); + + size_t blocks = pm->size / (1024*1024); + blocks /= (4096/nr); + + // cout << "moveable, ptr = " << (void*)(pm->ptr) << ", size = " << pm->size << ", hptr = " << hptr << " blocks = " << blocks << endl; + + for (size_t i = 0; i <= blocks; i++) + ch[hptr+i] = '1'; + + pm = pm->next; + } + } + + + + } + +#pragma warning(pop) +} diff --git a/contrib/Netgen/libsrc/general/dynamicmem.hpp b/contrib/Netgen/libsrc/general/dynamicmem.hpp new file mode 100644 index 0000000000000000000000000000000000000000..483c9a7f17be91bf46974ffb2037c6fd9a098843 --- /dev/null +++ b/contrib/Netgen/libsrc/general/dynamicmem.hpp @@ -0,0 +1,95 @@ +#ifndef FILE_DYNAMICMEM +#define FILE_DYNAMICMEM + +/**************************************************************************/ +/* File: dynamicmem.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 12. Feb. 2003 */ +/**************************************************************************/ + + + + +class BaseDynamicMem +{ +private: + static BaseDynamicMem *first, *last; + + BaseDynamicMem *prev, *next; + size_t size; + char * ptr; + char * name; + +protected: + BaseDynamicMem (); + ~BaseDynamicMem (); + void Alloc (size_t s); + void ReAlloc (size_t s); + void Free (); + char * Ptr() { return ptr; } + const char * Ptr() const { return ptr; } + void Swap (BaseDynamicMem & m2); +public: + void SetName (const char * aname); + static void Print (); + static void GetUsed (int nr, char * ch); +}; + + +template <typename T> +class DynamicMem : public BaseDynamicMem +{ +public: + DynamicMem () + : BaseDynamicMem () + { + ; + } + DynamicMem (size_t s) + : BaseDynamicMem () + { + Alloc (s); + } + void Alloc (size_t s) + { + BaseDynamicMem::Alloc (sizeof(T) * s); + } + void ReAlloc (size_t s) + { + BaseDynamicMem::ReAlloc (sizeof(T) * s); + } + void Free () + { + BaseDynamicMem::Free (); + } + + const T * Ptr() const + { + return reinterpret_cast<const T*> (BaseDynamicMem::Ptr()); + } + + T * Ptr() + { + return reinterpret_cast<T*> (BaseDynamicMem::Ptr()); + } + + operator const T* () const + { + return reinterpret_cast<const T*> (BaseDynamicMem::Ptr()); + } + + operator T* () + { + return reinterpret_cast<T*> (BaseDynamicMem::Ptr()); + } + + void Swap (DynamicMem<T> & m2) + { + BaseDynamicMem::Swap (m2); + } +protected: + DynamicMem (const DynamicMem & m); + DynamicMem & operator= (const DynamicMem & m); +}; + +#endif diff --git a/contrib/Netgen/libsrc/general/flags.cpp b/contrib/Netgen/libsrc/general/flags.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6b5ccf26871420e6700590ed9318bff2ffbd7d6 --- /dev/null +++ b/contrib/Netgen/libsrc/general/flags.cpp @@ -0,0 +1,330 @@ +/**************************************************************************/ +/* File: flags.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 10. Oct. 96 */ +/**************************************************************************/ + +/* + Datatype Flags +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + Flags :: Flags () + { + ; + } + + Flags :: ~Flags () + { + DeleteFlags (); + } + + void Flags :: DeleteFlags () + { + for (int i = 0; i < strflags.Size(); i++) + delete [] strflags[i]; + for (int i = 0; i < numlistflags.Size(); i++) + delete numlistflags[i]; + strflags.DeleteAll(); + numflags.DeleteAll(); + defflags.DeleteAll(); + strlistflags.DeleteAll(); + numlistflags.DeleteAll(); + } + + void Flags :: SetFlag (const char * name, const char * val) + { + char * hval = new char[strlen (val) + 1]; + strcpy (hval, val); + strflags.Set (name, hval); + } + + void Flags :: SetFlag (const char * name, double val) + { + numflags.Set (name, val); + } + + void Flags :: SetFlag (const char * name) + { + defflags.Set (name, 1); + } + + + void Flags :: SetFlag (const char * name, const ARRAY<char*> & val) + { + ARRAY<char*> * strarray = new ARRAY<char*>; + for (int i = 1; i <= val.Size(); i++) + { + strarray->Append (new char[strlen(val.Get(i))+1]); + strcpy (strarray->Last(), val.Get(i)); + } + strlistflags.Set (name, strarray); + } + + void Flags :: SetFlag (const char * name, const ARRAY<double> & val) + { + ARRAY<double> * numarray = new ARRAY<double>; + for (int i = 1; i <= val.Size(); i++) + numarray->Append (val.Get(i)); + numlistflags.Set (name, numarray); + } + + + + + + const char * + Flags :: GetStringFlag (const char * name, const char * def) const + { + if (strflags.Used (name)) + return strflags.Get(name); + else + return def; + } + + double Flags :: GetNumFlag (const char * name, double def) const + { + if (numflags.Used (name)) + return numflags.Get(name); + else + return def; + } + + const double * Flags :: GetNumFlagPtr (const char * name) const + { + if (numflags.Used (name)) + return & ((SYMBOLTABLE<double>&)numflags).Elem(name); + else + return NULL; + } + + double * Flags :: GetNumFlagPtr (const char * name) + { + if (numflags.Used (name)) + return & ((SYMBOLTABLE<double>&)numflags).Elem(name); + else + return NULL; + } + + bool Flags :: GetDefineFlag (const char * name) const + { + return defflags.Used (name); + } + + + const ARRAY<char*> & + Flags :: GetStringListFlag (const char * name) const + { + if (strlistflags.Used (name)) + return *strlistflags.Get(name); + else + { + static ARRAY<char*> hstra(0); + return hstra; + } + } + + const ARRAY<double> & + Flags ::GetNumListFlag (const char * name) const + { + if (numlistflags.Used (name)) + return *numlistflags.Get(name); + else + { + static ARRAY<double> hnuma(0); + return hnuma; + } + } + + + bool Flags :: StringFlagDefined (const char * name) const + { + return strflags.Used (name); + } + + bool Flags :: NumFlagDefined (const char * name) const + { + return numflags.Used (name); + } + + bool Flags :: StringListFlagDefined (const char * name) const + { + return strlistflags.Used (name); + } + + bool Flags :: NumListFlagDefined (const char * name) const + { + return numlistflags.Used (name); + } + + + void Flags :: SaveFlags (const char * filename) const + { + int i; + ofstream outfile (filename); + + for (i = 1; i <= strflags.Size(); i++) + outfile << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + for (i = 1; i <= numflags.Size(); i++) + outfile << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + for (i = 1; i <= defflags.Size(); i++) + outfile << defflags.GetName(i) << endl; + } + + + + void Flags :: PrintFlags (ostream & ost) const + { + int i; + + for (i = 1; i <= strflags.Size(); i++) + ost << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + for (i = 1; i <= numflags.Size(); i++) + ost << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + for (i = 1; i <= defflags.Size(); i++) + ost << defflags.GetName(i) << endl; + } + + + void Flags :: LoadFlags (const char * filename) + { + char name[100], str[100]; + char ch; + double val; + ifstream infile(filename); + + // (*logout) << "Load flags from " << filename << endl << endl; + while (infile.good()) + { + infile >> name; + if (strlen (name) == 0) break; + + if (name[0] == '/' && name[1] == '/') + { + // (*logout) << "comment: "; + ch = 0; + while (ch != '\n' && infile.good()) + { + ch = infile.get(); + // (*logout) << ch; + } + continue; + } + + // (*logout) << name; + ch = 0; + infile >> ch; + if (ch != '=') + { + // (*logout) << endl; + infile.putback (ch); + SetFlag (name); + } + else + { + infile >> val; + if (!infile.good()) + { + infile.clear(); + infile >> str; + SetFlag (name, str); + // (*logout) << " = " << str << endl; + } + else + { + SetFlag (name, val); + // (*logout) << " = " << val << endl; + } + } + } + // (*logout) << endl; + } + + + void Flags :: SetCommandLineFlag (const char * st) + { + // cout << "clflag = " << st << endl; + istringstream inst( (char *)st); + // istrstream defined with char * (not const char * ?????) + + char name[100]; + double val; + + + if (st[0] != '-') + { + cerr << "flag must start with '-'" << endl; + return; + } + + const char * pos = strchr (st, '='); + + if (!pos) + { + // (cout) << "Add def flag: " << st+1 << endl; + SetFlag (st+1); + } + else + { + // cout << "pos = " << pos << endl; + + strncpy (name, st+1, (pos-st)-1); + name[pos-st-1] = 0; + + // cout << "name = " << name << endl; + + pos++; + char * endptr = NULL; + + val = strtod (pos, &endptr); + + // cout << "val = " << val << endl; + + if (endptr == pos) + { + // (cout) << "Add String Flag: " << name << " = " << pos << endl; + SetFlag (name, pos); + } + else + { + // (cout) << "Add Num Flag: " << name << " = " << val << endl; + SetFlag (name, val); + } + } + + + /* + inst >> name; + (*mycout) << "name = " << name << endl; + + ch = 0; + inst >> ch; + if (ch != '=') + { + SetFlag (name); + } + else + { + inst >> val; + if (!inst.good()) + { + inst.clear(); + inst >> str; + SetFlag (name, str); + (*mycout) << "str = " << str << endl; + } + else + { + SetFlag (name, val); + (*mycout) << "val = " << val << endl; + } + } + */ + } +} diff --git a/contrib/Netgen/libsrc/general/flags.hpp b/contrib/Netgen/libsrc/general/flags.hpp new file mode 100644 index 0000000000000000000000000000000000000000..59c365ee18ed0e7722214f30893b379233f7e48d --- /dev/null +++ b/contrib/Netgen/libsrc/general/flags.hpp @@ -0,0 +1,83 @@ +#ifndef FILE_FLAGS +#define FILE_FLAGS + + +/**************************************************************************/ +/* File: flags.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 10. Oct. 96 */ +/**************************************************************************/ + +/** + Flag - Table. + A flag table maintains string variables, numerical + variables and boolean flags. +*/ +class Flags +{ + /// + SYMBOLTABLE<char *> strflags; + /// + SYMBOLTABLE<double> numflags; + /// + SYMBOLTABLE<int> defflags; + /// + SYMBOLTABLE<ARRAY<char*>*> strlistflags; + /// + SYMBOLTABLE<ARRAY<double>*> numlistflags; +public: + /// + Flags (); + /// + ~Flags (); + + /// Deletes all flags + void DeleteFlags (); + /// Sets string flag, overwrite if exists + void SetFlag (const char * name, const char * val); + /// Sets numerical flag, overwrite if exists + void SetFlag (const char * name, double val); + /// Sets boolean flag + void SetFlag (const char * name); + /// Sets string arary falg + void SetFlag (const char * name, const ARRAY<char*> & val); + /// Sets double array flag + void SetFlag (const char * name, const ARRAY<double> & val); + + /// Save flags to file + void SaveFlags (const char * filename) const; + /// write flags to stream + void PrintFlags (ostream & ost) const; + /// Load flags from file + void LoadFlags (const char * filename); + /// set flag of form -name=hello -val=0.5 -defined + void SetCommandLineFlag (const char * st); + + /// Returns string flag, default value if not exists + const char * GetStringFlag (const char * name, const char * def) const; + /// Returns numerical flag, default value if not exists + double GetNumFlag (const char * name, double def) const; + /// Returns address of numerical flag, null if not exists + const double * GetNumFlagPtr (const char * name) const; + /// Returns address of numerical flag, null if not exists + double * GetNumFlagPtr (const char * name); + /// Returns boolean flag + bool GetDefineFlag (const char * name) const; + /// Returns string list flag, empty array if not exist + const ARRAY<char*> & GetStringListFlag (const char * name) const; + /// Returns num list flag, empty array if not exist + const ARRAY<double> & GetNumListFlag (const char * name) const; + + + /// Test, if string flag is defined + bool StringFlagDefined (const char * name) const; + /// Test, if num flag is defined + bool NumFlagDefined (const char * name) const; + /// Test, if string list flag is defined + bool StringListFlagDefined (const char * name) const; + /// Test, if num list flag is defined + bool NumListFlagDefined (const char * name) const; +}; + +#endif + diff --git a/contrib/Netgen/libsrc/general/hashtabl.cpp b/contrib/Netgen/libsrc/general/hashtabl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5b77f3cba0bd68a1141ca8aa16872af41525d42 --- /dev/null +++ b/contrib/Netgen/libsrc/general/hashtabl.cpp @@ -0,0 +1,327 @@ +/**************************************************************************/ +/* File: hashtabl.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type HASHTABLE +*/ + +#include <algorithm> +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + void INDEX_4 :: Sort () + { + if (i[0] > i[1]) Swap (i[0], i[1]); + if (i[2] > i[3]) Swap (i[2], i[3]); + if (i[0] > i[2]) Swap (i[0], i[2]); + if (i[1] > i[3]) Swap (i[1], i[3]); + if (i[1] > i[2]) Swap (i[1], i[2]); + } + + + + void INDEX_4Q :: Sort () + { + if (min2 (i[1], i[2]) < min2 (i[0], i[3])) + { Swap (i[0], i[1]); Swap (i[2], i[3]);} + if (i[3] < i[0]) + { Swap (i[0], i[3]); Swap (i[1], i[2]);} + if (i[3] < i[1]) + { Swap (i[1], i[3]); } + } + + + ostream & operator<<(ostream & s, const INDEX_2 & i2) + { + return s << i2.I1() << ", " << i2.I2(); + } + + ostream & operator<<(ostream & s, const INDEX_3 & i3) + { + return s << i3.I1() << ", " << i3.I2() << ", " << i3.I3(); + } + + ostream & operator<<(ostream & s, const INDEX_4 & i4) + { + return s << i4.I1() << ", " << i4.I2() << ", " << i4.I3() << ", " << i4.I4(); + } + + ostream & operator<<(ostream & s, const INDEX_4Q & i4) + { + return s << i4.I1() << ", " << i4.I2() << ", " << i4.I3() << ", " << i4.I4(); + } + + + int BASE_INDEX_HASHTABLE :: Position (int bnr, const INDEX & ind) const + { + int i; + for (i = 1; i <= hash.EntrySize (bnr); i++) + if (hash.Get(bnr, i) == ind) + return i; + return 0; + } + + + + /* + int BASE_INDEX_2_HASHTABLE :: Position (int bnr, const INDEX_2 & ind) const + { + int i; + for (i = 1; i <= hash.EntrySize (bnr); i++) + if (hash.Get(bnr, i) == ind) + return i; + return 0; + } + */ + + void BASE_INDEX_2_HASHTABLE :: PrintStat (ostream & ost) const + { + int n = hash.Size(); + int i; + int sumn = 0, sumnn = 0; + + for (i = 1; i <= n; i++) + { + sumn += hash.EntrySize(i); + sumnn += sqr (hash.EntrySize(i)); + } + + ost << "Hashtable: " << endl + << "size : " << n << endl + << "elements per row : " << (double(sumn) / double(n)) << endl + << "av. acces time : " + << (sumn ? (double (sumnn) / double(sumn)) : 0) << endl; + } + + + /* + int BASE_INDEX_3_HASHTABLE :: Position (int bnr, const INDEX_3 & ind) const + { + int i; + const INDEX_3 * pi = &hash.Get(bnr, 1); + int n = hash.EntrySize(bnr); + for (i = 1; i <= n; ++i, ++pi) + { + if (*pi == ind) + return i; + } + + return 0; + } + */ + + + + + + + + + + + + + + + + + + + + + BASE_INDEX_CLOSED_HASHTABLE :: + BASE_INDEX_CLOSED_HASHTABLE (int size) + : hash(size) + { + hash.SetName ("index-hashtable, hash"); + + invalid = -1; + for (int i = 1; i <= size; i++) + hash.Elem(i) = invalid; + } + + void BASE_INDEX_CLOSED_HASHTABLE :: + BaseSetSize (int size) + { + hash.SetSize(size); + for (int i = 1; i <= size; i++) + hash.Elem(i) = invalid; + } + + int BASE_INDEX_CLOSED_HASHTABLE :: + Position2 (const INDEX & ind) const + { + int i = HashValue(ind); + while (1) + { + i++; + if (i > hash.Size()) i = 1; + if (hash.Get(i) == ind) return i; + if (hash.Get(i) == invalid) return 0; + } + } + + int BASE_INDEX_CLOSED_HASHTABLE :: + PositionCreate2 (const INDEX & ind, int & apos) + { + int i = HashValue(ind); + int startpos = i; + while (1) + { + i++; + if (i > hash.Size()) i = 1; + if (hash.Get(i) == ind) + { + apos = i; + return 0; + } + if (hash.Get(i) == invalid) + { + hash.Elem(i) = ind; + apos = i; + return 1; + } + if (i == startpos) + throw NgException ("Try to set new element in full closed hashtable"); + } + } + + int BASE_INDEX_CLOSED_HASHTABLE :: UsedElements () const + { + int n = hash.Size(); + int cnt = 0; + for (int i = 1; i <= n; i++) + if (hash.Get(i) != invalid) + cnt++; + return cnt; + } + + + + + + + + + + + + BASE_INDEX_2_CLOSED_HASHTABLE :: + BASE_INDEX_2_CLOSED_HASHTABLE (int size) + : hash(size) + { + hash.SetName ("i2-hashtable, hash"); + + invalid = -1; + for (int i = 1; i <= size; i++) + hash.Elem(i).I1() = invalid; + } + + void BASE_INDEX_2_CLOSED_HASHTABLE :: + BaseSetSize (int size) + { + hash.SetSize(size); + for (int i = 1; i <= size; i++) + hash.Elem(i).I1() = invalid; + } + + + int BASE_INDEX_2_CLOSED_HASHTABLE :: + Position2 (const INDEX_2 & ind) const + { + int i = HashValue(ind); + while (1) + { + i++; + if (i > hash.Size()) i = 1; + if (hash.Get(i) == ind) return i; + if (hash.Get(i).I1() == invalid) return 0; + } + } + + int BASE_INDEX_2_CLOSED_HASHTABLE :: + PositionCreate2 (const INDEX_2 & ind, int & apos) + { + int i = HashValue(ind); + int startpos = i; + while (1) + { + i++; + if (i > hash.Size()) i = 1; + if (hash.Get(i) == ind) + { + apos = i; + return 0; + } + if (hash.Get(i).I1() == invalid) + { + hash.Elem(i) = ind; + apos = i; + return 1; + } + if (i == startpos) + throw NgException ("Try to set new element in full closed hashtable"); + } + } + + int BASE_INDEX_2_CLOSED_HASHTABLE :: UsedElements () const + { + int n = hash.Size(); + int cnt = 0; + for (int i = 1; i <= n; i++) + if (hash.Get(i).I1() != invalid) + cnt++; + return cnt; + } + + + + + + + + + void BASE_INDEX_3_CLOSED_HASHTABLE :: + BaseSetSize (int size) + { + hash.SetSize(size); + for (int i = 0; i < size; i++) + hash[i].I1() = invalid; + } + + bool BASE_INDEX_3_CLOSED_HASHTABLE :: + PositionCreate2 (const INDEX_3 & ind, int & apos) + { + int i = HashValue(ind); + int startpos = i; + while (1) + { + /* + i++; + if (i >= hash.Size()) i = 0; + */ + i = (i+1) % hash.Size(); + if (hash[i] == ind) + { + apos = i; + return false; + } + if (hash[i].I1() == invalid) + { + hash[i] = ind; + apos = i; + return true; + } + if (i == startpos) + throw NgException ("Try to set new element in full closed hashtable"); + } + } +} + diff --git a/contrib/Netgen/libsrc/general/hashtabl.hpp b/contrib/Netgen/libsrc/general/hashtabl.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bc1781b9650f110cd5cbcd44a74077e3839857ac --- /dev/null +++ b/contrib/Netgen/libsrc/general/hashtabl.hpp @@ -0,0 +1,1322 @@ +#ifndef FILE_HASHTABL +#define FILE_HASHTABL + +/**************************************************************************/ +/* File: hashtabl.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/** + Abstract data type HASHTABLE. + Hash is done by one INDEX +*/ +class BASE_INDEX_HASHTABLE +{ +protected: + /// keys are stored in this table + TABLE<INDEX> hash; + +public: + /// + BASE_INDEX_HASHTABLE (int size) + : hash (size) { }; + +protected: + /// + int HashValue (const INDEX & ind) const + { + return ind % hash.Size() + 1; + } + + /// + int Position (int bnr, const INDEX & ind) const; +}; + +/// +template <class T> +class INDEX_HASHTABLE : private BASE_INDEX_HASHTABLE +{ + /// + TABLE<T> cont; + +public: + /// + inline INDEX_HASHTABLE (int size); + /// + inline void Set (const INDEX & hash, const T & acont); + /// + inline const T & Get (const INDEX & ahash) const; + /// + inline bool Used (const INDEX & ahash) const; + /// + inline int GetNBags () const; + /// + inline int GetBagSize (int bnr) const; + /// + inline void GetData (int bnr, int colnr, INDEX & ahash, T & acont) const; + + /// + inline void PrintMemInfo (ostream & ost) const; +}; + + + + + + + + + + + +/// +class BASE_INDEX_2_HASHTABLE +{ +protected: + /// + TABLE<INDEX_2> hash; + +public: + /// + BASE_INDEX_2_HASHTABLE (int size) + : hash (size) { }; + + /// + void PrintStat (ostream & ost) const; + void BaseSetSize(int s) {hash.SetSize(s);} +protected: + /// + int HashValue (const INDEX_2 & ind) const + { + return (ind.I1() + ind.I2()) % hash.Size() + 1; + } + /// + int Position (int bnr, const INDEX_2 & ind) const + { + int i; + for (i = 1; i <= hash.EntrySize (bnr); i++) + if (hash.Get(bnr, i) == ind) + return i; + return 0; + } +}; + + +/// +template <class T> +class INDEX_2_HASHTABLE : public BASE_INDEX_2_HASHTABLE +{ + /// + TABLE<T> cont; + +public: + /// + INDEX_2_HASHTABLE (int size) + : BASE_INDEX_2_HASHTABLE (size), cont(size) + { ; } + + /// + void SetSize(int s) + { + cont.SetSize(s); + BaseSetSize(s); + } + + /// + void Set (const INDEX_2 & ahash, const T & acont) + { + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + if (pos) + cont.Set (bnr, pos, acont); + else + { + hash.Add1 (bnr, ahash); + cont.Add1 (bnr, acont); + } + } + + /// + const T & Get (const INDEX_2 & ahash) const + { + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + return cont.Get (bnr, pos); + } + + /// + bool Used (const INDEX_2 & ahash) const + { + return (Position (HashValue (ahash), ahash)) ? 1 : 0; + } + /// + int GetNBags () const + { + return cont.Size(); + } + + /// + int GetBagSize (int bnr) const + { + return cont.EntrySize (bnr); + } + + /// + void GetData (int bnr, int colnr, + INDEX_2 & ahash, T & acont) const + { + ahash = hash.Get(bnr, colnr); + acont = cont.Get(bnr, colnr); + } + + /// + void SetData (int bnr, int colnr, + const INDEX_2 & ahash, const T & acont) + { + hash.Set(bnr, colnr, ahash); + cont.Set(bnr, colnr, acont); + } + + /// + void PrintMemInfo (ostream & ost) const + { + ost << "Hash: " << endl; + hash.PrintMemInfo (ost); + ost << "Cont: " << endl; + cont.PrintMemInfo (ost); + } + + + void DeleteData () + { + int n = hash.Size(); + hash.SetSize (n); + cont.SetSize (n); + } + + + class Iterator + { + const INDEX_2_HASHTABLE & ht; + int bagnr, pos; + public: + Iterator (const INDEX_2_HASHTABLE & aht, + int abagnr, int apos) + : ht(aht), bagnr(abagnr), pos(apos) + { ; } + + int BagNr() const { return bagnr; } + int Pos() const { return pos; } + + void operator++ (int) + { + // cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; + pos++; + while (bagnr < ht.GetNBags() && + pos == ht.GetBagSize(bagnr+1)) + { + pos = 0; + bagnr++; + } + // cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; + } + + bool operator != (int i) const + { + return bagnr != i; + } + + }; + + Iterator Begin () const + { + Iterator it(*this, 0, -1); + it++; + return it; + } + + int End() const + { + return GetNBags(); + } + + void GetData (const Iterator & it, + INDEX_2 & ahash, T & acont) const + { + ahash = hash[it.BagNr()][it.Pos()]; + acont = cont[it.BagNr()][it.Pos()]; + } + + const INDEX_2 & GetHash (const Iterator & it) const + { return hash[it.BagNr()][it.Pos()]; } + + const T & GetData (const Iterator & it) const + { return cont[it.BagNr()][it.Pos()]; } +}; + + + +template <typename T> +inline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE<T> & ht) +{ + for (typename INDEX_2_HASHTABLE<T>::Iterator it = ht.Begin(); + it != ht.End(); it++) + { + ost << ht.GetHash(it) << ": " << ht.GetData(it) << endl; + } + + return ost; +} + + + + + + + +/// +class BASE_INDEX_3_HASHTABLE +{ +protected: + /// + TABLE<INDEX_3> hash; + +public: + /// + BASE_INDEX_3_HASHTABLE (int size) + : hash (size) { }; + +protected: + /// + int HashValue (const INDEX_3 & ind) const + { + return (ind.I1() + ind.I2() + ind.I3()) % hash.Size() + 1; + } + + /// + int Position (int bnr, const INDEX_3 & ind) const + { + const INDEX_3 * pi = &hash.Get(bnr, 1); + int n = hash.EntrySize(bnr); + for (int i = 1; i <= n; ++i, ++pi) + { + if (*pi == ind) + return i; + } + + return 0; + } + + +}; + + +/// +template <class T> +class INDEX_3_HASHTABLE : private BASE_INDEX_3_HASHTABLE +{ + /// + TABLE<T> cont; + +public: + /// + inline INDEX_3_HASHTABLE (int size); + /// + inline void Set (const INDEX_3 & ahash, const T & acont); + /// + inline const T & Get (const INDEX_3 & ahash) const; + /// + inline bool Used (const INDEX_3 & ahash) const; + /// + inline int GetNBags () const; + /// + inline int GetBagSize (int bnr) const; + /// + inline void SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont); + /// + inline void GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const; + /// returns position, if not existing, will create (create == return 1) + inline int PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr); + /// + inline void SetSize (int size); + + /// + inline void PrepareSet (const INDEX_3 & ahash); + /// + inline void AllocateElements (); + + /// + inline void PrintMemInfo (ostream & ost) const; + /// + inline void DeleteData (); + + + + + + + + + + class Iterator + { + const INDEX_3_HASHTABLE & ht; + int bagnr, pos; + public: + Iterator (const INDEX_3_HASHTABLE & aht, + int abagnr, int apos) + : ht(aht), bagnr(abagnr), pos(apos) + { ; } + + int BagNr() const { return bagnr; } + int Pos() const { return pos; } + + void operator++ (int) + { + // cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; + pos++; + while (bagnr < ht.GetNBags() && + pos == ht.GetBagSize(bagnr+1)) + { + pos = 0; + bagnr++; + } + // cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl; + } + + bool operator != (int i) const + { + return bagnr != i; + } + + }; + + Iterator Begin () const + { + Iterator it(*this, 0, -1); + it++; + return it; + } + + int End() const + { + return GetNBags(); + } + + void GetData (const Iterator & it, + INDEX_3 & ahash, T & acont) const + { + ahash = hash[it.BagNr()][it.Pos()]; + acont = cont[it.BagNr()][it.Pos()]; + } + + const INDEX_3 & GetHash (const Iterator & it) const + { return hash[it.BagNr()][it.Pos()]; } + + const T & GetData (const Iterator & it) const + { return cont[it.BagNr()][it.Pos()]; } + + + +}; + + + + + + +template <typename T> +inline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE<T> & ht) +{ + for (typename INDEX_3_HASHTABLE<T>::Iterator it = ht.Begin(); + it != ht.End(); it++) + { + ost << ht.GetHash(it) << ": " << ht.GetData(it) << endl; + } + + return ost; +} + + + + + + + + + + + + + + + + + + + + + + + + +/// Closed Hashing HT + +class BASE_INDEX_CLOSED_HASHTABLE +{ +protected: + /// + MoveableArray<INDEX> hash; + /// + int invalid; +public: + /// + BASE_INDEX_CLOSED_HASHTABLE (int size); + + int Size() const { return hash.Size(); } + int UsedPos (int pos) const { return ! (hash.Get(pos) == invalid); } + int UsedElements () const; + + /// + int HashValue (const INDEX & ind) const + { + return ind % hash.Size() + 1; + } + + + int Position (const INDEX & ind) const + { + int i = HashValue(ind); + while (1) + { + if (hash.Get(i) == ind) return i; + if (hash.Get(i) == invalid) return 0; + i++; + if (i > hash.Size()) i = 1; + } + } + + // returns 1, if new postion is created + int PositionCreate (const INDEX & ind, int & apos) + { + int i = HashValue (ind); + if (hash.Get(i) == ind) + { + apos = i; + return 0; + } + if (hash.Get(i) == invalid) + { + hash.Elem(i) = ind; + apos = i; + return 1; + } + return PositionCreate2 (ind, apos); + } + +protected: + int Position2 (const INDEX & ind) const; + int PositionCreate2 (const INDEX & ind, int & apos); + void BaseSetSize (int asize); +}; + + +template <class T> +class INDEX_CLOSED_HASHTABLE : public BASE_INDEX_CLOSED_HASHTABLE +{ + /// + MoveableArray<T> cont; + +public: + /// + INDEX_CLOSED_HASHTABLE (int size) + : BASE_INDEX_CLOSED_HASHTABLE(size), cont(size) + { + cont.SetName ("ind-hashtable, contents"); + } + + + void Set (const INDEX & ahash, const T & acont) + { + int pos; + PositionCreate (ahash, pos); + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; + } + + const T & Get (const INDEX & ahash) const + { + int pos = Position (ahash); + return cont.Get(pos); + } + + /// + bool Used (const INDEX & ahash) const + { + int pos = Position (ahash); + return (pos != 0); + } + + + /// + inline void SetData (int pos, const INDEX & ahash, const T & acont) + { + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; + } + + /// + void GetData (int pos, INDEX & ahash, T & acont) const + { + ahash = hash.Get(pos); + acont = cont.Get(pos); + } + + /// + inline void SetData (int pos, const T & acont) + { + cont.Elem(pos) = acont; + } + + /// + void GetData (int pos, T & acont) const + { + acont = cont.Get(pos); + } + + /// + const T & GetData (int pos) { return cont.Get(pos); } + /// + inline void SetSize (int size) + { + BaseSetSize(size); + cont.SetSize(size); + } + + /// + inline void DeleteData () + { SetSize (cont.Size()); } + + void SetName (const char * aname) + { + cont.SetName(aname); + hash.SetName(aname); + } +}; + + + + + + + +/// Closed Hashing HT + +class BASE_INDEX_2_CLOSED_HASHTABLE +{ +protected: + /// + MoveableArray<INDEX_2> hash; + /// + int invalid; +public: + /// + BASE_INDEX_2_CLOSED_HASHTABLE (int size); + + int Size() const { return hash.Size(); } + int UsedPos (int pos) const { return ! (hash.Get(pos).I1() == invalid); } + int UsedElements () const; + + /// + int HashValue (const INDEX_2 & ind) const + { + return (ind.I1() + 71 * ind.I2()) % hash.Size() + 1; + } + + + int Position (const INDEX_2 & ind) const + { + int i = HashValue(ind); + while (1) + { + if (hash.Get(i) == ind) return i; + if (hash.Get(i).I1() == invalid) return 0; + i++; + if (i > hash.Size()) i = 1; + } + } + + // returns 1, if new postion is created + int PositionCreate (const INDEX_2 & ind, int & apos) + { + int i = HashValue (ind); + if (hash.Get(i) == ind) + { + apos = i; + return 0; + } + if (hash.Get(i).I1() == invalid) + { + hash.Elem(i) = ind; + apos = i; + return 1; + } + return PositionCreate2 (ind, apos); + } + +protected: + /// + + int Position2 (const INDEX_2 & ind) const; + int PositionCreate2 (const INDEX_2 & ind, int & apos); + void BaseSetSize (int asize); +}; + + +template <class T> +class INDEX_2_CLOSED_HASHTABLE : public BASE_INDEX_2_CLOSED_HASHTABLE +{ + /// + MoveableArray<T> cont; + +public: + /// + inline INDEX_2_CLOSED_HASHTABLE (int size); + /// + inline void Set (const INDEX_2 & ahash, const T & acont); + /// + inline const T & Get (const INDEX_2 & ahash) const; + /// + inline bool Used (const INDEX_2 & ahash) const; + /// + inline void SetData (int pos, const INDEX_2 & ahash, const T & acont); + /// + inline void GetData (int pos, INDEX_2 & ahash, T & acont) const; + /// + inline void SetData (int pos, const T & acont); + /// + inline void GetData (int pos, T & acont) const; + /// + const T & GetData (int pos) { return cont.Get(pos); } + /// + inline void SetSize (int size); + /// + inline void PrintMemInfo (ostream & ost) const; + /// + inline void DeleteData () + { SetSize (cont.Size()); } + + void SetName (const char * aname) + { + cont.SetName(aname); + hash.SetName(aname); + } +}; + +class BASE_INDEX_3_CLOSED_HASHTABLE +{ +protected: + MoveableArray<INDEX_3> hash; + int invalid; + +protected: + // public: //SZ + BASE_INDEX_3_CLOSED_HASHTABLE (int size) + : hash(size) + { + hash.SetName ("i3-hashtable, hash"); + invalid = -1; + for (int i = 0; i < size; i++) + hash[i].I1() = invalid; + } + +public: + int Size() const + { + return hash.Size(); + } + + bool UsedPos (int pos) const + { + return ! (hash[pos].I1() == invalid); + } + + int UsedElements () const + { + int n = hash.Size(); + int cnt = 0; + for (int i = 0; i < n; i++) + if (hash[i].I1() != invalid) + cnt++; + return cnt; + } + + int HashValue (const INDEX_3 & ind) const + { + return (ind.I1() + 15 * ind.I2() + 41 * ind.I3()) % hash.Size(); + } + + int Position (const INDEX_3 & ind) const + { + int i = HashValue(ind); + while (1) + { + if (hash[i] == ind) return i; + if (hash[i].I1() == invalid) return -1; + i = (i+1) % hash.Size(); + } + } + + int Costs (const INDEX_3 & ind) const + { + int i = HashValue(ind); + int c = 1; + while (1) + { + if (hash[i] == ind) return c; + if (hash[i].I1() == invalid) return c; + i = (i+1) % hash.Size(); + c++; + } + } + + + + // returns true, if new postion is created + bool PositionCreate (const INDEX_3 & ind, int & apos) + { + int i = HashValue (ind); + if (hash[i] == ind) + { + apos = i; + return false; + } + if (hash[i].I1() == invalid) + { + hash[i] = ind; + apos = i; + return true; + } + return PositionCreate2 (ind, apos); + } + +protected: + bool PositionCreate2 (const INDEX_3 & ind, int & apos); + void BaseSetSize (int asize); +}; + + + +template <class T> +class INDEX_3_CLOSED_HASHTABLE : public BASE_INDEX_3_CLOSED_HASHTABLE +{ + MoveableArray<T,0> cont; + +public: + INDEX_3_CLOSED_HASHTABLE (int size) + : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(size) + { + cont.SetName ("i3-hashtable, contents"); + } + + void Set (const INDEX_3 & ahash, const T & acont) + { + int pos; + PositionCreate (ahash, pos); + hash[pos] = ahash; + cont[pos] = acont; + } + + const T & Get (const INDEX_3 & ahash) const + { + return cont[Position (ahash)]; + } + + bool Used (const INDEX_3 & ahash) const + { + return (Position (ahash) != -1); + } + + void SetData (int pos, const INDEX_3 & ahash, const T & acont) + { + hash[pos] = ahash; + cont[pos] = acont; + } + + void GetData (int pos, INDEX_3 & ahash, T & acont) const + { + ahash = hash[pos]; + acont = cont[pos]; + } + + void SetData (int pos, const T & acont) + { + cont[pos] = acont; + } + + void GetData (int pos, T & acont) const + { + acont = cont[pos]; + } + + const T & GetData (int pos) const + { + return cont[pos]; + } + + void SetSize (int size) + { + BaseSetSize(size); + cont.SetSize(size); + } + + void PrintMemInfo (ostream & ost) const + { + cout << "Hashtable: " << Size() + << " entries of size " << sizeof(INDEX_3) << " + " << sizeof(T) + << " = " << Size() * (sizeof(INDEX_3) + sizeof(T)) << " bytes" << endl; + + } + + void DeleteData () + { + SetSize (cont.Size()); + } + + void SetName (const char * aname) + { + cont.SetName(aname); + hash.SetName(aname); + } +}; + + + + + + + + + + + + + + + + + +template<class T> +inline INDEX_3_HASHTABLE<T> :: INDEX_3_HASHTABLE (int size) + : BASE_INDEX_3_HASHTABLE (size), cont(size) +{ + ; +} + +template<class T> +inline int INDEX_3_HASHTABLE<T> :: PositionCreate (const INDEX_3 & ahash, int & bnr, int & colnr) +{ + bnr = HashValue (ahash); + colnr = Position (bnr, ahash); + if (!colnr) + { + hash.Add (bnr, ahash); + cont.AddEmpty (bnr); + colnr = cont.EntrySize (bnr); + return 1; + } + return 0; +} + + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: Set (const INDEX_3 & ahash, const T & acont) +{ + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + if (pos) + cont.Set (bnr, pos, acont); + else + { + hash.Add1 (bnr, ahash); + cont.Add1 (bnr, acont); + } +} + +template<class T> +inline const T & INDEX_3_HASHTABLE<T> :: Get (const INDEX_3 & ahash) const +{ + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + return cont.Get (bnr, pos); +} + +template<class T> +inline bool INDEX_3_HASHTABLE<T> :: Used (const INDEX_3 & ahash) const +{ + return (Position (HashValue (ahash), ahash)) ? 1 : 0; +} + +template<class T> +inline int INDEX_3_HASHTABLE<T> :: GetNBags () const +{ + return cont.Size(); +} + +template<class T> +inline int INDEX_3_HASHTABLE<T> :: GetBagSize (int bnr) const +{ + return cont.EntrySize (bnr); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX_3 & ahash, T & acont) const +{ + ahash = hash.Get(bnr, colnr); + acont = cont.Get(bnr, colnr); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: SetData (int bnr, int colnr, const INDEX_3 & ahash, const T & acont) +{ + hash.Set(bnr, colnr, ahash); + cont.Set(bnr, colnr, acont); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: SetSize (int size) +{ + hash.SetSize (size); + cont.SetSize (size); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: DeleteData () +{ + int n = hash.Size(); + hash.SetSize (n); + cont.SetSize (n); +} + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: PrepareSet (const INDEX_3 & ahash) +{ + int bnr = HashValue (ahash); + hash.IncSizePrepare (bnr-1); + cont.IncSizePrepare (bnr-1); +} + + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: AllocateElements () +{ + hash.AllocateElementsOneBlock(); + cont.AllocateElementsOneBlock(); +} + + + +template<class T> +inline void INDEX_3_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const + { + ost << "Hash: " << endl; + hash.PrintMemInfo (ost); + ost << "Cont: " << endl; + cont.PrintMemInfo (ost); + } + + + + + +template<class T> +inline INDEX_HASHTABLE<T> :: INDEX_HASHTABLE (int size) + : BASE_INDEX_HASHTABLE (size), cont(size) + { + ; + } + +template<class T> +inline void INDEX_HASHTABLE<T> :: Set (const INDEX & ahash, const T & acont) + { + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + if (pos) + cont.Set (bnr, pos, acont); + else + { + hash.Add (bnr, ahash); + cont.Add (bnr, acont); + } + } + +template<class T> +inline const T & INDEX_HASHTABLE<T> :: Get (const INDEX & ahash) const + { + int bnr = HashValue (ahash); + int pos = Position (bnr, ahash); + return cont.Get (bnr, pos); + } + +template<class T> +inline bool INDEX_HASHTABLE<T> :: Used (const INDEX & ahash) const + { + return (Position (HashValue (ahash), ahash)) ? 1 : 0; + } + +template<class T> +inline int INDEX_HASHTABLE<T> :: GetNBags () const + { + return hash.Size(); + } + +template<class T> +inline int INDEX_HASHTABLE<T> :: GetBagSize (int bnr) const + { + return hash.EntrySize(bnr); + } + +template<class T> +inline void INDEX_HASHTABLE<T> :: GetData (int bnr, int colnr, INDEX & ahash, T & acont) const + { + ahash = hash.Get(bnr, colnr); + acont = cont.Get(bnr, colnr); + } + +template<class T> +inline void INDEX_HASHTABLE<T> :: PrintMemInfo (ostream & ost) const + { + ost << "Hash: " << endl; + hash.PrintMemInfo (ost); + ost << "Cont: " << endl; + cont.PrintMemInfo (ost); + } + + + + + + + + + + + + + + + +/* *********** Closed Hashing ************************* */ + + + +template<class T> +inline INDEX_2_CLOSED_HASHTABLE<T> :: +INDEX_2_CLOSED_HASHTABLE (int size) + : BASE_INDEX_2_CLOSED_HASHTABLE(size), cont(size) +{ + cont.SetName ("i2-hashtable, contents"); +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +Set (const INDEX_2 & ahash, const T & acont) +{ + int pos; + PositionCreate (ahash, pos); + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline const T & INDEX_2_CLOSED_HASHTABLE<T> :: +Get (const INDEX_2 & ahash) const +{ + int pos = Position (ahash); + return cont.Get(pos); +} + +template<class T> +inline bool INDEX_2_CLOSED_HASHTABLE<T> :: +Used (const INDEX_2 & ahash) const +{ + int pos = Position (ahash); + return (pos != 0); +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +SetData (int pos, const INDEX_2 & ahash, const T & acont) +{ + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +GetData (int pos, INDEX_2 & ahash, T & acont) const +{ + ahash = hash.Get(pos); + acont = cont.Get(pos); +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +SetData (int pos, const T & acont) +{ + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +GetData (int pos, T & acont) const +{ + acont = cont.Get(pos); +} + + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +SetSize (int size) +{ + BaseSetSize(size); + cont.SetSize(size); +} + + + +template<class T> +inline void INDEX_2_CLOSED_HASHTABLE<T> :: +PrintMemInfo (ostream & ost) const +{ + cout << "Hashtable: " << Size() + << " entries of size " << sizeof(INDEX_2) << " + " << sizeof(T) + << " = " << Size() * (sizeof(INDEX_2) + sizeof(T)) << " bytes." + << " Used els: " << UsedElements() + << endl; +} + + + + + + + + + + + + + + + + +/* +template<class T> +inline INDEX_3_CLOSED_HASHTABLE<T> :: +INDEX_3_CLOSED_HASHTABLE (int size) + : BASE_INDEX_3_CLOSED_HASHTABLE(size), cont(size) +{ + cont.SetName ("i3-hashtable, contents"); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +Set (const INDEX_3 & ahash, const T & acont) +{ + int pos; + PositionCreate (ahash, pos); + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline const T & INDEX_3_CLOSED_HASHTABLE<T> :: +Get (const INDEX_3 & ahash) const +{ + int pos = Position (ahash); + return cont[pos]; +} + +template<class T> +inline bool INDEX_3_CLOSED_HASHTABLE<T> :: +Used (const INDEX_3 & ahash) const +{ + int pos = Position (ahash); + return (pos != 0); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +SetData (int pos, const INDEX_3 & ahash, const T & acont) +{ + hash.Elem(pos) = ahash; + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +GetData (int pos, INDEX_3 & ahash, T & acont) const +{ + ahash = hash.Get(pos); + acont = cont.Get(pos); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +SetData (int pos, const T & acont) +{ + cont.Elem(pos) = acont; +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +GetData (int pos, T & acont) const +{ + acont = cont.Get(pos); +} + +template<class T> +inline const T & INDEX_3_CLOSED_HASHTABLE<T> :: +GetData (int pos) const +{ + return cont.Get(pos); +} + + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +SetSize (int size) +{ + BaseSetSize(size); + cont.SetSize(size); +} + +template<class T> +inline void INDEX_3_CLOSED_HASHTABLE<T> :: +PrintMemInfo (ostream & ost) const +{ + cout << "Hashtable: " << Size() + << " entries of size " << sizeof(INDEX_3) << " + " << sizeof(T) + << " = " << Size() * (sizeof(INDEX_3) + sizeof(T)) << " bytes" << endl; +} +*/ + + + + + + + + + + + + + + + + + +#endif diff --git a/contrib/Netgen/libsrc/general/moveablemem.cpp b/contrib/Netgen/libsrc/general/moveablemem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7f3c1dab6df0a8d8e32417fc28aeeee60271f42 --- /dev/null +++ b/contrib/Netgen/libsrc/general/moveablemem.cpp @@ -0,0 +1,271 @@ +#include <iostream> +#include <iomanip> + +#include <myadt.hpp> +using namespace std; +namespace netgen +{ + + NgMutex mem_mutex; + + size_t BaseMoveableMem::totalsize = 0; // 500000000; + size_t BaseMoveableMem::used = 0; + char * BaseMoveableMem::largeblock = 0; + + BaseMoveableMem * BaseMoveableMem::first = 0; + BaseMoveableMem * BaseMoveableMem::last = 0; + + + BaseMoveableMem :: BaseMoveableMem (size_t s) + { + // cout << "Construct object begin" << endl; + // Print (); + + prev = last; + next = 0; + + if (last) last->next = this; + last = this; + if (!first) first = this; + + size = 0; + + if (prev) + pos = prev->pos + prev->size; + else + pos = 0; + + ptr = 0; + name = NULL; + + if (s) Alloc(s); +} + +BaseMoveableMem :: ~BaseMoveableMem () throw() +{ + Free(); + + if (next) next->prev = prev; + else last = prev; + if (prev) prev->next = next; + else first = next; + + if(name != NULL) + { + delete [] name; + name = NULL; + } +} + +void BaseMoveableMem :: SetName (const char * aname) +{ + if(name != NULL) + { + delete [] name; + name = NULL; + } + if (aname) + { + name = new char[strlen(aname)+1]; + strcpy (name, aname); + } +} + + +void BaseMoveableMem :: Alloc (size_t s) +{ + if (totalsize == 0) + { + size = s; + //ptr = (char*) malloc(s); + ptr = new char[s]; + + if (!ptr) + { + cerr << "BaseynamicMem, cannot allocate " << s << " bytes" << endl; + Print (); + throw ("BaseDynamicMem::Alloc: out of memory"); + } + + return; + } + + + used += s - size; + + size_t r = s % 8; + if (r) s += 8-r; + if (prev) + pos = prev->pos + prev->size; + else + pos = 0; + size = s; + + if (next) + { + NgLock lock(mem_mutex); + lock.Lock(); + try + { + next->MoveTo (pos+size); + } + catch (NgException e) + { + lock.UnLock(); + throw NgException ("MoveableMem overflow"); + } + lock.UnLock(); + } + + if (size) + { + if (!largeblock) + { + cout << "moveable memory: allocate large block of " + << totalsize / 1048576 << " MB" << endl; + // largeblock = new char[totalsize]; + // largeblock = (char*)malloc (totalsize); + largeblock = new char[totalsize]; + } + ptr = largeblock+pos; + + if (pos + size > totalsize) + throw NgException ("MoveableMem overflow"); + } + else + ptr = 0; +} + +void BaseMoveableMem :: ReAlloc (size_t s) +{ + if (totalsize == 0) + { + if (size == s) return; + + char * old = ptr; + ptr = new char[s]; + + if (!ptr) + { + cerr << "BaseynamicMem, cannot Reallocate " << s << " bytes" << endl; + Print (); + throw ("BaseDynamicMem::Alloc: out of memory"); + } + + + + memmove (ptr, old, (s < size) ? s : size); + //free (old); + delete [] old; + size = s; + return; + } + + Alloc (s); +} + +void BaseMoveableMem :: MoveTo (size_t newpos) +{ + // cout << "move block, oldpos = " << pos << "; newpos = " << newpos + // << ", size = " << size << endl; + static size_t move = 0; + + if (newpos + size > totalsize) + throw NgException ("MoveableMem overflow"); + if (newpos > pos) + { + if (next) next->MoveTo (newpos+size); + memmove (largeblock+newpos, largeblock+pos, size); + move += size; + } + else if (newpos < pos) + { + // cout << "move down: " << size << endl; + memmove (largeblock+newpos, largeblock+pos, size); + if (next) next->MoveTo (newpos+size); + move += size; + } + pos = newpos; + ptr = largeblock+pos; + // cout << "total move: " << move << endl; +} + +void BaseMoveableMem :: Free () throw() +{ + if (totalsize == 0) + { + //free (ptr); + delete [] ptr; + ptr = 0; + return; + } + + /* + cout << "free block, pos = " << pos << "size = " << size << endl; + cout << "before: " << endl; + Print(); + */ + used -= size; + if (next) + { + NgLock lock(mem_mutex); + lock.Lock(); + next->MoveTo (pos); + lock.UnLock(); + } + + size = 0; + ptr = 0; + // pos = 0; +} + +void BaseMoveableMem :: Swap (BaseMoveableMem & m2) throw() +{ + size_t hi; + // BaseMoveableMem * hp; + char * cp; + hi = size; size = m2.size; m2.size = hi; + hi = pos; pos = m2.pos; m2.pos = hi; + /* + hp = prev; prev = m2.prev; m2.prev = hp; + hp = next; next = m2.next; m2.next = hp; + */ + cp = ptr; ptr = m2.ptr; m2.ptr = cp; + cp = name; name = m2.name; m2.name = cp; +} + + +void BaseMoveableMem :: Print () +{ + cout << "****************** Moveable Mem Report ****************" << endl; + BaseMoveableMem * p = first; + long int mem = 0; + int cnt = 0; + while (p) + { + mem += long(p->size); + cnt++; + + cout << setw(10) << p->size << " Bytes"; + cout << ", pos = " << p->pos; + cout << ", addr = " << (void*)p->ptr; + if (p->name) + cout << " in block " << p->name; + cout << endl; + + p = p->next; + } + + if (mem > 100000000) + cout << "memory in moveable arena: " << mem/1048576 << " MB" << endl; + else if (mem > 100000) + cout << "memory in moveable arena: " << mem/1024 << " kB" << endl; + else + cout << "memory in moveable arena: " << mem << " Bytes" << endl; + cout << "number of blocks: " << cnt << endl; + + cout << " used = " << used << endl; + // cout << "******************************************************" << endl; +} + +} diff --git a/contrib/Netgen/libsrc/general/moveablemem.hpp b/contrib/Netgen/libsrc/general/moveablemem.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b0761ee233ad51f40bfbece3e8913dd4157928a7 --- /dev/null +++ b/contrib/Netgen/libsrc/general/moveablemem.hpp @@ -0,0 +1,99 @@ +#ifndef FILE_MOVEABLEMEM +#define FILE_MOVEABLEMEM + +/**************************************************************************/ +/* File: moveablemem.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 12. Feb. 2003 */ +/**************************************************************************/ + + +extern NgMutex mem_mutex; + +class BaseMoveableMem +{ +public: + static size_t totalsize; + static size_t used; + +private: + static char * largeblock; + static BaseMoveableMem *first, *last; + + BaseMoveableMem *prev, *next; + size_t size, pos; + char * ptr; + char * name; + +protected: + BaseMoveableMem (size_t s = 0); + ~BaseMoveableMem () throw(); + void Alloc (size_t s); + void ReAlloc (size_t s); + void MoveTo (size_t newpos); + void Free () throw(); + char * Ptr() { return ptr; } + char * Ptr() const { return ptr; } + void Swap (BaseMoveableMem & m2) throw(); +public: + void SetName (const char * aname); + static void Print (); + + friend class BaseDynamicMem; +}; + + + + +template <typename T> +class MoveableMem : public BaseMoveableMem +{ +public: + MoveableMem (size_t s = 0) + : BaseMoveableMem (sizeof(T) * s) + { + ; + } + void Alloc (size_t s) + { + BaseMoveableMem::Alloc (sizeof(T) * s); + } + void ReAlloc (size_t s) + { + BaseMoveableMem::ReAlloc (sizeof(T) * s); + } + void Free () + { + BaseMoveableMem::Free (); + } + + const T * Ptr() const + { + return reinterpret_cast<const T*> (BaseMoveableMem::Ptr()); + } + + T * Ptr() + { + return reinterpret_cast<T*> (BaseMoveableMem::Ptr()); + } + + operator T* () const + { + return reinterpret_cast<T*> (BaseMoveableMem::Ptr()); + } + + operator T* () + { + return reinterpret_cast<T*> (BaseMoveableMem::Ptr()); + } + + void Swap (MoveableMem<T> & m2) + { + BaseMoveableMem::Swap (m2); + } +protected: + MoveableMem (const MoveableMem & m) { ; } + MoveableMem & operator= (const MoveableMem & m) { ; } +}; + +#endif diff --git a/contrib/Netgen/libsrc/general/myadt.hpp b/contrib/Netgen/libsrc/general/myadt.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ec0740296065f7934d8443f84b5a1de64b5332b7 --- /dev/null +++ b/contrib/Netgen/libsrc/general/myadt.hpp @@ -0,0 +1,46 @@ +#ifndef FILE_MYADT +#define FILE_MYADT + +/**************************************************************************/ +/* File: myadt.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + include for all abstract data types +*/ + + + +#include "../include/mystdlib.h" +#include "../include/mydefs.hpp" + + +namespace netgen +{ +#include "ngexception.hpp" +#include "parthreads.hpp" +#include "moveablemem.hpp" +#include "dynamicmem.hpp" + +#include "template.hpp" +#include "array.hpp" +#include "table.hpp" +#include "hashtabl.hpp" +#include "symbolta.hpp" +#include "bitarray.hpp" +#include "flags.hpp" +#include "spbita2d.hpp" +#include "seti.hpp" +#include "optmem.hpp" +#include "autoptr.hpp" +#include "sort.hpp" +#include "stack.hpp" +#include "mystring.hpp" +#include "profiler.hpp" +#include "netgenout.hpp" + +} + +#endif diff --git a/contrib/Netgen/libsrc/general/mystring.cpp b/contrib/Netgen/libsrc/general/mystring.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6538a460310e91d460230b09a6ea88022420059c --- /dev/null +++ b/contrib/Netgen/libsrc/general/mystring.cpp @@ -0,0 +1,437 @@ + +//************************************************************** +// +// filename: mystring.cpp +// +// project: doctoral thesis +// +// autor: Dipl.-Ing. Gerstmayr Johannes +// +// generated: 20.12.98 +// last change: 20.12.98 +// description: implementation for strings +// remarks: +// +//************************************************************** + +// string class +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <gprim.hpp> + +/* +#include <iostream.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <fstream.h> +#include "mystring.hh" + + */ + +namespace netgen +{ + + + void ReadEnclString(istream & in, string & str, const char encl) + { + char currchar; + str = ""; + + in.get(currchar); + while(in && currchar == ' ' || currchar == '\t' || currchar == '\n') + in.get(currchar); + + if(currchar == encl) + { + in.get(currchar); + while(in && currchar != encl) + { + str += currchar; + in.get(currchar); + } + } + else + { + in.putback(currchar); + in >> str; + } + } + + + + + + +void DefaultStringErrHandler() +{ + cerr << "Error : string operation out of range\n" << flush; +} + +void (*MyStr::ErrHandler)() = DefaultStringErrHandler; + + /* +MyStr::MyStr() +{ + length = 0; + str = shortstr; + str[0] = 0; +} + */ + +MyStr::MyStr(const char *s) +{ + length = unsigned(strlen(s)); + + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, s); +} + +/* +MyStr::MyStr(char s) +{ + length = 1; + str = shortstr; + str[0] = s; + str[1] = (char)0; +} +*/ + +MyStr::MyStr(const MyStr& s) +{ + length = s.length; + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, s.str); +} + +MyStr::MyStr(int i) +{ + char buffer[32]; + sprintf(buffer, "%d", i); + length = unsigned(strlen(buffer)); + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, buffer); +} + +MyStr::MyStr(void * p) +{ + char buffer[32]; + sprintf(buffer, "%p", p); + length = unsigned(strlen(buffer)); + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, buffer); +} + + +MyStr::MyStr(long l) +{ + char buffer[32]; + sprintf(buffer, "%ld", l); + length = unsigned(strlen(buffer)); + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, buffer); +} + +MyStr::MyStr(double d) +{ + char buffer[32]; + //if (fabs(d) < 1E-100) {d = 0;} + sprintf(buffer, "%g", d); + length = unsigned(strlen(buffer)); + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, buffer); +} + +MyStr::MyStr(const Point3d& p) +{ + char buffer[80]; + //if (fabs(d) < 1E-100) {d = 0;} + sprintf(buffer, "[%g, %g, %g]", p.X(), p.Y(), p.Z()); + length = unsigned(strlen(buffer)); + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, buffer); +} + +MyStr::MyStr(const Vec3d& p) +{ + char buffer[80]; + //if (fabs(d) < 1E-100) {d = 0;} + sprintf(buffer, "[%g, %g, %g]", p.X(), p.Y(), p.Z()); + length = unsigned(strlen(buffer)); + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, buffer); +} + +MyStr::MyStr(unsigned n, int) +{ + length = n; + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + str[n] = 0; +} + +MyStr::MyStr(const string & st) +{ + length = unsigned(st.length()); + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy (str, st.c_str()); +} + + + +MyStr MyStr::Left(unsigned r) +{ + if(r > length) + { + MyStr::ErrHandler(); + MyStr s; + return s; + } + else + { + MyStr tmp(r, 0); + strncpy(tmp.str, str, r); + return tmp; + } +} + +MyStr MyStr::Right(unsigned l) +{ + if(l > length) + { + MyStr::ErrHandler(); + MyStr s; + return s; + } + else + { + MyStr tmp(l, 0); + strncpy(tmp.str, str + length - l, l); + return tmp; + } +} + +MyStr& MyStr::InsertAt(unsigned pos, const MyStr& s) +{ + if(pos > length) + { + MyStr::ErrHandler(); + return *this; + } + int newLength = length + s.length; + char *tmp = new char[newLength + 1]; + strncpy(tmp, str, pos); + strcpy(tmp + pos, s.str); + strcpy(tmp + pos + s.length, str + pos); + + if (length > SHORTLEN) delete [] str; + length = newLength; + if (length > SHORTLEN) + str = tmp; + else + { + strcpy (shortstr, tmp); + delete [] tmp; + str = shortstr; + } + return *this; +} + +MyStr &MyStr::WriteAt(unsigned pos, const MyStr& s) +{ + if(pos > length) + { + MyStr::ErrHandler(); + return *this; + } + unsigned n = length - pos; + if(s.length < n) + n = s.length; + strncpy(str + pos, s.str, n); + return *this; +} + +void MyStr::ConvertTextToExcel() +{ + /* + for (int i = 0; i < Length(); i++) + { + if ((*this)[i]==',') {(*this)[i] = ';';} + else if ((*this)[i]=='.') {(*this)[i] = ',';} + } + */ +} + +void MyStr::ConvertExcelToText() +{ + /* + for (int i = 0; i < Length(); i++) + { + if ((*this)[i]==',') {(*this)[i] = '.';} + else if ((*this)[i]==';') {(*this)[i] = ',';} + } + */ +} + +MyStr& MyStr::operator = (const MyStr& s) +{ + if (length > SHORTLEN) delete [] str; + length = s.length; + if (length > SHORTLEN) + str = new char[length + 1]; + else + str = shortstr; + strcpy(str, s.str); + return *this; +} + +MyStr operator + (const MyStr& s1, const MyStr& s2) +{ + MyStr tmp(s1.length + s2.length, 0); + if (s1.length != 0) strcpy(tmp.str, s1.str); + if (s2.length != 0) strcpy(tmp.str + s1.length, s2.str); + return tmp; +} + +void MyStr::operator += (const MyStr& s) +{ + if (length+s.length <= SHORTLEN) + { + if (s.length != 0) strcpy(shortstr + length, s.str); + } + else + { + char *tmp = new char[length + s.length + 1]; + if (length != 0) strcpy(tmp, str); + if (s.length != 0) strcpy(tmp + length, s.str); + if (length > SHORTLEN) delete [] str; + length += s.length; + str = tmp; + } +} + +char& MyStr::operator [] (unsigned n) +{ + static char dummy; + if(n < length) + return str[n]; + else + { + MyStr::ErrHandler(); + return dummy; + } +} + +char MyStr::operator [] (unsigned n) const +{ + static char dummy; + if(n < length) + return str[n]; + else + { + MyStr::ErrHandler(); + return dummy; + } +} + +MyStr MyStr::operator () (unsigned l, unsigned r) +{ + if((l > r) || (r > length)) + { + MyStr::ErrHandler(); + MyStr s; + return s; + } + else + { + int n = r - l + 1; + MyStr tmp(n, 0); + strncpy(tmp.str, str + 1, n); + return tmp; + } +} + +string MyStr::cpp_string(void) const +{ + string aux(str,length); + return aux; +} + +/* +istream& operator >> (istream& is, MyStr& s) +{ + const int buflen = 1000; + char buffer[buflen+1]; + + int end = 0; + s = ""; + MyStr str; + + while (!end) + { + is.get(buffer, buflen); + str = MyStr(buffer); + s += str; + if (is.peek() == EOF) {end = 1;} + } + + return is; +} +*/ +/* +#ifdef __borland +::ifstream& operator >> (::ifstream& is, MyStr& s) // wb +{ // wb + const int buflen = 1000; // wb + char buffer[buflen+1]; // wb + // wb + int end = 0; // wb + s = ""; // wb + MyStr str; // wb + // wb + while (!end) // wb + { // wb + is.get(buffer, buflen); // wb + str = MyStr(buffer); // wb + s += str; // wb + if (is.peek() == EOF) {end = 1;} // wb + } // wb + // wb + return is; // wb +} + +#endif +*/ +} diff --git a/contrib/Netgen/libsrc/general/mystring.hpp b/contrib/Netgen/libsrc/general/mystring.hpp new file mode 100644 index 0000000000000000000000000000000000000000..434ba9a3cb8b06d7f72b1332572cfd8d00df7ee7 --- /dev/null +++ b/contrib/Netgen/libsrc/general/mystring.hpp @@ -0,0 +1,216 @@ + +//************************************************************** +// +// filename: mystring.h +// +// project: doctoral thesis, program smart +// +// autor: Dipl.-Ing. Gerstmayr Johannes +// +// generated: 20.12.98 +// last change: 20.12.98 +// description: base class for strings +// remarks: string with n characters has +// 0..n-1 characters and at pos n a 0 +// +//************************************************************** + + +#ifndef MYSTRING__H +#define MYSTRING__H + +class Point3d; +class Vec3d; + + +// extract string str which is enclosed by the given character encl from a given string in +void ReadEnclString(istream & in, string & str, const char encl); + + +class MyStr; + +MyStr operator + (const MyStr &, const MyStr &); +int operator == (const MyStr &, const MyStr &); +int operator < (const MyStr &, const MyStr &); +int operator <= (const MyStr &, const MyStr &); +int operator > (const MyStr &, const MyStr &); +int operator >= (const MyStr &, const MyStr &); +int operator != (const MyStr &, const MyStr &); +ostream& operator << (ostream &, const MyStr &); +istream& operator >> (istream &, MyStr &); + +class MyStr +{ +public: + MyStr(); + MyStr(const char *); + MyStr(char); + MyStr(const MyStr &); + MyStr(int); + MyStr(void *); + MyStr(long); + MyStr(double); + MyStr(const Point3d& p); + MyStr(const Vec3d& p); + MyStr(const string & st); + + ~MyStr(); + MyStr Left(unsigned); + MyStr Right(unsigned); + MyStr& InsertAt(unsigned, const MyStr &); + MyStr& WriteAt(unsigned, const MyStr &); + unsigned Length() const; + int Find(const char); + int Find(const char *); + int Find(const MyStr &); + MyStr& operator = (const MyStr &); + friend MyStr operator + (const MyStr &, const MyStr &); + void operator += (const MyStr &); + char* c_str(); + string cpp_string(void) const; + + //change every ',' -> ';', '.' -> ',' + void ConvertTextToExcel(); + //change every ','->'.', ';'->',' + void ConvertExcelToText(); + + MyStr operator () (unsigned, unsigned); + operator int(); + operator double(); + operator long(); + operator char *(); + char& operator [] (unsigned int); + char operator [] (unsigned int) const; + + friend int operator == (const MyStr &, const MyStr &); + friend int operator < (const MyStr &, const MyStr &); + friend int operator <= (const MyStr &, const MyStr &); + friend int operator > (const MyStr &, const MyStr &); + friend int operator >= (const MyStr &, const MyStr &); + friend int operator != (const MyStr &, const MyStr &); + friend ostream& operator << (ostream &, const MyStr &); + friend istream& operator >> (istream &, MyStr &); + static void SetToErrHandler(void (*)()); +private: + MyStr(unsigned, int); + char *str; + unsigned length; + enum { SHORTLEN = 24 }; + char shortstr[SHORTLEN+1]; + static void(*ErrHandler)(); +}; + + +inline MyStr::MyStr() +{ + length = 0; + str = shortstr; + str[0] = 0; +} + +inline MyStr::MyStr(char s) +{ + length = 1; + str = shortstr; + str[0] = s; + str[1] = (char)0; +} + +inline MyStr::~MyStr() +{ + if (length > SHORTLEN) + delete [] str; +} + +inline unsigned MyStr::Length() const +{ + return length; +} + +inline int MyStr::Find(const char c) +{ + char *pos = strchr(str, int(c)); + return pos ? int(pos - str) : -1; +} + +inline int MyStr::Find(const MyStr &s) +{ + char *pos = strstr(str, s.str); + return pos ? int(pos - str) : -1; +} + +inline int MyStr::Find(const char *s) +{ + char *pos = strstr(str, s); + return pos ? int(pos - str) : -1; +} + +inline MyStr::operator int() +{ + return atoi(str); +} + +inline MyStr::operator double() +{ + return atof(str); +} + +inline MyStr::operator long() +{ + return atol(str); +} + +inline MyStr::operator char *() +{ + return str; +} + +inline char* MyStr::c_str() +{ + return str; +} + + +inline int operator == (const MyStr &s1, const MyStr& s2) +{ + return strcmp(s1.str, s2.str) == 0; +} + +inline int operator < (const MyStr &s1, const MyStr& s2) +{ + return strcmp(s1.str, s2.str) < 0; +} + +inline int operator <= (const MyStr &s1, const MyStr& s2) +{ + return strcmp(s1.str, s2.str) <= 0; +} + +inline int operator > (const MyStr &s1, const MyStr& s2) +{ + return strcmp(s1.str, s2.str) > 0; +} + +inline int operator >= (const MyStr &s1, const MyStr& s2) +{ + return strcmp(s1.str, s2.str) >= 0; +} + +inline int operator != (const MyStr &s1, const MyStr& s2) +{ + return !(s1 == s2); +} + +inline ostream& operator << (ostream& os, const MyStr& s) +{ + return os << s.str; +} + +inline void MyStr::SetToErrHandler(void (*Handler)()) +{ + ErrHandler = Handler; +}; + +#endif + + diff --git a/contrib/Netgen/libsrc/general/netgenout.hpp b/contrib/Netgen/libsrc/general/netgenout.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2338445ad068ff10b1fbb648be05f86aead265b9 --- /dev/null +++ b/contrib/Netgen/libsrc/general/netgenout.hpp @@ -0,0 +1,184 @@ +#ifndef NETGEN_OUT_STREAM_HPP__ +#define NETGEN_OUT_STREAM_HPP__ + +// #include <ostream> +// #include <mystdlib.h> +// #include <meshing.hpp> + +#ifdef PARALLEL +extern int id; +extern int ntasks; +#endif +extern int printmessage_importance; + + + +class Imp +{ + int importance; +public: + Imp () : importance(0) { ; } + + Imp ( int aimportance ) : importance(aimportance) { ; } + + int GetImp () const { return importance; } +}; + + +class Proc +{ + int proc; +public: + Proc () : proc(0) { ; } + + Proc ( int aproc ) : proc(aproc) { ; } + + int GetProc () const { return proc; } +}; + +class Procs +{ + const netgen::FlatArray<int> procs; + +public: + + Procs ( const netgen::FlatArray<int> & aprocs ) : procs (aprocs) { ; } + + const netgen::FlatArray<int> & GetProcs () const { return procs; } +}; + + + +class NetgenOutStream +{ + ostream * out; + + bool print; + bool printheader; + + +public: + NetgenOutStream() : + out(&std::cout), + print(1), + printheader(1) + { + ; + } + + NetgenOutStream(ostream * aout, Imp imp ) : + out(aout), + printheader(1) + { + if ( netgen::printmessage_importance >= imp.GetImp() ) + print = true; + else + print = false; + } + + NetgenOutStream(ostream * aout, Proc proc ) : + out(aout), + printheader(1) + { +#ifdef PARALLEL + if ( netgen::id == proc.GetProc() ) + print = true; + else + print = false; +#else + if ( 0 == proc.GetProc() ) + print = true; + else + print = false; + +#endif + } + + NetgenOutStream(ostream * aout, Procs & procs ) : + out(aout), + printheader(1) + { +#ifdef PARALLEL + if ( procs.GetProcs().Contains(netgen::id) ) + print = true; + else + print = false; +#else + if ( procs.GetProcs().Contains(0) ) + print = true; + else + print = false; + +#endif + } + + ostream & OStream () + { + return *out; + } + + template <typename T> + NetgenOutStream & operator<< (T & var) + { + if ( print ) + { +#ifdef PARALLEL + if ( printheader ) + { + *out << "proc " << netgen::id << ": "; + printheader = false; + } +#endif + *out << var; + } + return (*this); + } + + NetgenOutStream& operator<< (ostream& ( *pf )(ostream&)) + { + if ( print ) + *out << (*pf) ; + + return (*this); + } + + NetgenOutStream& operator<< (ios& ( *pf )(ios&)) + { + if ( print) + *out << (*pf) ; + + printheader = 1; + + return (*this); + } + + NetgenOutStream& operator<< (ios_base& ( *pf )(ios_base&)) + { + if (print ) + *out << (*pf) ; + return (*this); + } + + +}; + + +NetgenOutStream operator<< ( ostream & ost, Imp imp ); +NetgenOutStream operator<< ( ostream & ost, Proc proc ); +NetgenOutStream operator<< ( ostream & ost, Procs & procs ); +// { +// return ( NetgenOutStream ( &ost, imp.GetImp() ) ); +// } + +// template <typename T> +// NetgenOutStream& operator<< (NetgenOutStream& out, T c ) +// { +// out.OStream() << c << endl; +// return out; +// } + + + + + +#endif diff --git a/contrib/Netgen/libsrc/general/ngexception.cpp b/contrib/Netgen/libsrc/general/ngexception.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2496f6b3be3b2b410727d4cd04234a3015d10df0 --- /dev/null +++ b/contrib/Netgen/libsrc/general/ngexception.cpp @@ -0,0 +1,33 @@ +/**************************************************************************/ +/* File: ngexception.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 16. Jan. 02 */ +/**************************************************************************/ + +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + + + NgException :: NgException (const string & s) + : what(s) + { + ; + } + + + NgException :: ~NgException () + { + ; + } + + /// append string to description + void NgException :: Append (const string & s) + { + what += s; + } + +} diff --git a/contrib/Netgen/libsrc/general/ngexception.hpp b/contrib/Netgen/libsrc/general/ngexception.hpp new file mode 100644 index 0000000000000000000000000000000000000000..56c561aa8cdd14eb038d9e728d114140cdbfb304 --- /dev/null +++ b/contrib/Netgen/libsrc/general/ngexception.hpp @@ -0,0 +1,30 @@ +#ifndef FILE_NGEXCEPTION +#define FILE_NGEXCEPTION + +/**************************************************************************/ +/* File: ngexception.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 16. Jan. 2002 */ +/**************************************************************************/ + + +/// Base class for all ng exceptions +class NgException +{ + /// verbal description of exception + string what; +public: + /// + NgException (const string & s); + /// + virtual ~NgException (); + + /// append string to description + void Append (const string & s); + // void Append (const char * s); + + /// verbal description of exception + const string & What() const { return what; } +}; + +#endif diff --git a/contrib/Netgen/libsrc/general/optmem.cpp b/contrib/Netgen/libsrc/general/optmem.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3f939ac1ae4453536490016806c929611d7590f --- /dev/null +++ b/contrib/Netgen/libsrc/general/optmem.cpp @@ -0,0 +1,64 @@ +/**************************************************************************/ +/* File: optmem.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 04. Apr. 97 */ +/**************************************************************************/ + +/* + Abstract data type ARRAY +*/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + BlockAllocator :: BlockAllocator (unsigned asize, unsigned ablocks) + : bablocks (0) + { + if (asize < sizeof(void*)) + asize = sizeof(void*); + size = asize; + blocks = ablocks; + freelist = NULL; + } + + BlockAllocator :: ~BlockAllocator () + { + //for (unsigned i = 0; i < bablocks.Size(); i++) + for (int i = 0; i < bablocks.Size(); i++) + delete [] bablocks[i]; + } + + void * BlockAllocator :: Alloc () + { + // return new char[size]; + if (!freelist) + { + // cout << "freelist = " << freelist << endl; + // cout << "BlockAlloc: " << size*blocks << endl; + char * hcp = new char [size * blocks]; + bablocks.Append (hcp); + bablocks.Last() = hcp; + for (unsigned i = 0; i < blocks-1; i++) + *(void**)&(hcp[i * size]) = &(hcp[ (i+1) * size]); + *(void**)&(hcp[(blocks-1)*size]) = NULL; + freelist = hcp; + } + + void * p = freelist; + freelist = *(void**)freelist; + return p; + } + + /* + void BlockAllocator :: Free (void * p) + { + *(void**)p = freelist; + freelist = p; + } + */ +} diff --git a/contrib/Netgen/libsrc/general/optmem.hpp b/contrib/Netgen/libsrc/general/optmem.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0015b20b783efb4f199df420efb9d4dab144447a --- /dev/null +++ b/contrib/Netgen/libsrc/general/optmem.hpp @@ -0,0 +1,59 @@ +#ifndef FILE_OPTMEM +#define FILE_OPTMEM + +/**************************************************************************/ +/* File: optmem.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 04. Apr. 97 */ +/**************************************************************************/ + +/** + Optimized Memory allocation classes +*/ + +class BlockAllocator +{ +private: + /// + unsigned size, blocks; + /// + void * freelist; + /// + ARRAY<char*> bablocks; +public: + /// + BlockAllocator (unsigned asize, unsigned ablocks = 100); + /// + ~BlockAllocator (); + /// + + void * Alloc (); + /* + { + if (!freelist) + Alloc2(); + + void * p = freelist; + // freelist = *(void**)freelist; + freelist = *static_cast<void**> (freelist); + + return p; + } + */ + + + /// + void Free (void * p) + { + *(void**)p = freelist; + freelist = p; + } + + +private: + // void Alloc2 (); +}; + + + +#endif diff --git a/contrib/Netgen/libsrc/general/parthreads.cpp b/contrib/Netgen/libsrc/general/parthreads.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81e9d0b6cce14da76c8e1cb196666a9fab2c3fc1 --- /dev/null +++ b/contrib/Netgen/libsrc/general/parthreads.cpp @@ -0,0 +1,40 @@ +/**************************************************************************/ +/* File: parthreads.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +/* + +namespace netgen +{ + using namespace netgen; + +#ifdef WIN32 + + NgLock :: NgLock (NgMutex & mut) + : sl(&mut.cs) + { + ; + } + + void NgLock :: Lock () + { + sl.Lock(); + } + void NgLock :: UnLock () + { + sl.Unlock(); + } + + +#else + +#endif +} + +*/ diff --git a/contrib/Netgen/libsrc/general/parthreads.hpp b/contrib/Netgen/libsrc/general/parthreads.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a00ff9e287caec8361d94da6a9193a6de8e576b0 --- /dev/null +++ b/contrib/Netgen/libsrc/general/parthreads.hpp @@ -0,0 +1,129 @@ +#ifndef FILE_PARTHREADS +#define FILE_PARTHREADS + +/**************************************************************************/ +/* File: parthreads.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 22. Nov. 2000 */ +/**************************************************************************/ + +/* + Parallel thread, Mutex, +*/ + +#ifdef NO_PARALLEL_THREADS + +class NgMutex { }; + +class NgLock +{ +public: + NgLock (NgMutex & mut, bool lock = 0) { ; } + void Lock () { ; } + void UnLock () { ; } +}; + + +#else + +#ifdef _MSC_VER + +class NgMutex +{ + CCriticalSection cs; + +public: + NgMutex () + { ; } + friend class NgLock; +}; + +class NgLock +{ + CSingleLock sl; + bool locked; +public: + NgLock (NgMutex & mut, bool lock = 0) + : sl(&mut.cs) + { + if (lock) sl.Lock(); + locked = lock; + } + + ~NgLock () + { + if (locked) sl.Unlock(); + } + + void Lock () + { + sl.Lock(); + locked = 1; + } + + void UnLock () + { + sl.Unlock(); + locked = 0; + } +}; + +#else + + +// #include <pthread.h> + +class NgMutex +{ + pthread_mutex_t mut; +public: + NgMutex () + { + pthread_mutex_init (&mut, NULL); + } + friend class NgLock; +}; + +class NgLock +{ + pthread_mutex_t & mut; + bool locked; +public: + NgLock (NgMutex & ngmut, bool lock = false) + : mut (ngmut.mut) + { + if (lock) + pthread_mutex_lock (&mut); + + locked = lock; + }; + + ~NgLock() + { + if (locked) + pthread_mutex_unlock (&mut); + } + + void Lock () + { + pthread_mutex_lock (&mut); + locked = true; + } + void UnLock () + { + pthread_mutex_unlock (&mut); + locked = false; + } + /* + int TryLock () + { + return pthread_mutex_trylock (&mut); + } + */ +}; + +#endif + +#endif + +#endif diff --git a/contrib/Netgen/libsrc/general/profiler.cpp b/contrib/Netgen/libsrc/general/profiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d61a7056bcb45bfb6edc549cab8a7cfc23c29fa --- /dev/null +++ b/contrib/Netgen/libsrc/general/profiler.cpp @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* File: profiler.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 19. Apr. 2002 */ +/**************************************************************************/ + + +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + long int NgProfiler::tottimes[SIZE]; + long int NgProfiler::starttimes[SIZE]; + long int NgProfiler::counts[SIZE]; + string NgProfiler::names[SIZE]; + int NgProfiler::usedcounter[SIZE]; + + + NgProfiler :: NgProfiler() + { + for (int i = 0; i < SIZE; i++) + { + tottimes[i] = 0; + usedcounter[i] = 0; + } + + total_timer = CreateTimer ("total CPU time"); + StartTimer (total_timer); + } + + NgProfiler :: ~NgProfiler() + { + StopTimer (total_timer); + + //ofstream prof; + //prof.open("ng.prof"); + + // ofstream-constructor may be called after STL-stuff is destructed, + // which leads to an "order of destruction"-problem, + // thus we use the C-variant: + + char filename[100]; +#ifdef PARALLEL + sprintf (filename, "netgen.prof.%d", id); +#else + sprintf (filename, "netgen.prof"); +#endif + + FILE *prof = fopen(filename,"w"); + Print (prof); + fclose(prof); + } + + +// void NgProfiler :: Print (ostream & prof) +// { +// for (int i = 0; i < SIZE; i++) +// if (counts[i] != 0 || usedcounter[i] != 0) +// { +// prof.setf (ios::fixed, ios::floatfield); +// prof.setf (ios::showpoint); + +// prof // << "job " << setw(3) << i +// << "calls " << setw(8) << counts[i] +// << ", time " << setprecision(2) << setw(6) << double(tottimes[i]) / CLOCKS_PER_SEC << " sec"; + +// if (usedcounter[i]) +// prof << " " << names[i]; +// else +// prof << " " << i; + +// prof << endl; +// } +// } + + + void NgProfiler :: Print (FILE * prof) + { + for (int i = 0; i < SIZE; i++) + if (counts[i] != 0 || usedcounter[i] != 0) + { + //fprintf(prof,"job %3i calls %8i, time %6.2f sec",i,counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); + fprintf(prof,"calls %8i, time %6.2f sec",counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); + if(usedcounter[i]) + fprintf(prof," %s",names[i].c_str()); + else + fprintf(prof," %i",i); + fprintf(prof,"\n"); + } + } + + int NgProfiler :: CreateTimer (const string & name) + { + for (int i = SIZE-1; i > 0; i--) + if(names[i] == name) + return i; + + for (int i = SIZE-1; i > 0; i--) + if (!usedcounter[i]) + { + usedcounter[i] = 1; + names[i] = name; + return i; + } + return -1; + } + + + NgProfiler prof; +} diff --git a/contrib/Netgen/libsrc/general/profiler.hpp b/contrib/Netgen/libsrc/general/profiler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b08708be83a056e6284e67c650b6373f708513b8 --- /dev/null +++ b/contrib/Netgen/libsrc/general/profiler.hpp @@ -0,0 +1,62 @@ +#ifndef FILE_NG_PROFILER +#define FILE_NG_PROFILER + +/**************************************************************************/ +/* File: profiler.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 5. Jan. 2005 */ +/**************************************************************************/ + + + +#ifdef VTRACE +#include "vt_user.h" +#else + #define VT_USER_START(n) + #define VT_USER_END(n) + #define VT_TRACER(n) +#endif + + + +class NgProfiler +{ + enum { SIZE = 1000 }; + + static long int tottimes[SIZE]; + static long int starttimes[SIZE]; + static long int counts[SIZE]; + static string names[SIZE]; + static int usedcounter[SIZE]; + + int total_timer; +public: + NgProfiler(); + ~NgProfiler(); + static int CreateTimer (const string & name); + + static void StartTimer (int nr) + { + starttimes[nr] = clock(); counts[nr]++; + VT_USER_START (const_cast<char*> (names[nr].c_str())); + } + static void StopTimer (int nr) + { + tottimes[nr] += clock()-starttimes[nr]; + VT_USER_END (const_cast<char*> (names[nr].c_str())); + } + + //static void Print (ostream & ost); + static void Print (FILE * prof); + + class RegionTimer + { + int nr; + public: + RegionTimer (int anr) : nr(anr) + { StartTimer (nr); } + ~RegionTimer () { StopTimer (nr); } + }; +}; + +#endif diff --git a/contrib/Netgen/libsrc/general/seti.cpp b/contrib/Netgen/libsrc/general/seti.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7f5b2ea74b1ee42c2f1299fd0a3a5b908eb1852 --- /dev/null +++ b/contrib/Netgen/libsrc/general/seti.cpp @@ -0,0 +1,70 @@ +#include <mystdlib.h> +#include <myadt.hpp> + + +namespace netgen +{ + //using namespace netgen; + + IndexSet :: IndexSet (int maxind) + { + SetMaxIndex (maxind); + } + + IndexSet :: ~IndexSet () + { + Clear(); + } + + + void IndexSet :: SetMaxIndex (int maxind) + { + if (maxind > flags.Size()) + { + flags.SetSize (2 * maxind); + flags.Clear(); + } + } + + /* + int IndexSet :: IsIn (int ind) const + { + return flags.Test (ind); + } + */ + + /* + void IndexSet :: Add (int ind) + { + if (ind > flags.Size()) + { + cerr << "out of range" << endl; + exit (1); + } + + if (!flags.Test(ind)) + { + set.Append (ind); + flags.Set (ind); + } + } + */ + + void IndexSet :: Del (int ind) + { + for (int i = 1; i <= set.Size(); i++) + if (set.Get(i) == ind) + { + set.DeleteElement (ind); + break; + } + flags.Clear (ind); + } + + void IndexSet :: Clear () + { + for (int i = 1; i <= set.Size(); i++) + flags.Clear (set.Get(i)); + set.SetSize (0); + } +} diff --git a/contrib/Netgen/libsrc/general/seti.hpp b/contrib/Netgen/libsrc/general/seti.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4ca0b8eb4ef2e25fec2e9c4a27bd5cd6731cf4a2 --- /dev/null +++ b/contrib/Netgen/libsrc/general/seti.hpp @@ -0,0 +1,45 @@ +#ifndef FILE_SETI +#define FILE_SETI + + +/**************************************************************************/ +/* File: seti.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Mar. 98 */ +/**************************************************************************/ + +/** + Set of Integers + */ +class IndexSet +{ + ARRAY<int> set; + BitArray flags; +public: + IndexSet (int maxind); + + ~IndexSet (); + /// increase range to maxind + void SetMaxIndex (int maxind); + int IsIn (int ind) const + { + return flags.Test (ind); + } + + void Add (int ind) + { + if (!flags.Test(ind)) + { + set.Append (ind); + flags.Set (ind); + } + } + + void Del (int ind); + void Clear (); + + const ARRAY<int> & Array() { return set; } +}; + +#endif + diff --git a/contrib/Netgen/libsrc/general/sort.cpp b/contrib/Netgen/libsrc/general/sort.cpp new file mode 100644 index 0000000000000000000000000000000000000000..264a132a748c4cd4be406ffa1d85b5f75ad0f1b7 --- /dev/null +++ b/contrib/Netgen/libsrc/general/sort.cpp @@ -0,0 +1,75 @@ +/**************************************************************************/ +/* File: sort.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 07. Jan. 00 */ +/**************************************************************************/ + +/* + Sorting +*/ + + +#include <algorithm> +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + +void Sort (const ARRAY<double> & values, + ARRAY<int> & order) +{ + int n = values.Size(); + int i, j; + + order.SetSize (n); + + for (i = 1; i <= n; i++) + order.Elem(i) = i; + for (i = 1; i <= n-1; i++) + for (j = 1; j <= n-1; j++) + if (values.Get(order.Elem(j)) > values.Get(order.Elem(j+1))) + { + Swap (order.Elem(j), order.Elem(j+1)); + } +} + + +void QickSortRec (const ARRAY<double> & values, + ARRAY<int> & order, + int left, int right) +{ + int i, j; + double midval; + + i = left; + j = right; + midval = values.Get(order.Get((i+j)/2)); + + do + { + while (values.Get(order.Get(i)) < midval) i++; + while (midval < values.Get(order.Get(j))) j--; + + if (i <= j) + { + Swap (order.Elem(i), order.Elem(j)); + i++; j--; + } + } + while (i <= j); + if (left < j) QickSortRec (values, order, left, j); + if (i < right) QickSortRec (values, order, i, right); +} + +void QickSort (const ARRAY<double> & values, + ARRAY<int> & order) +{ + int i, n = values.Size(); + order.SetSize (n); + for (i = 1; i <= n; i++) + order.Elem(i) = i; + + QickSortRec (values, order, 1, order.Size()); +} +} diff --git a/contrib/Netgen/libsrc/general/sort.hpp b/contrib/Netgen/libsrc/general/sort.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f65aa24fce073cadeab371ce71d3d4aa3b658ea9 --- /dev/null +++ b/contrib/Netgen/libsrc/general/sort.hpp @@ -0,0 +1,42 @@ +#ifndef FILE_SORT +#define FILE_SORT + +/**************************************************************************/ +/* File: sort.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 07. Jan. 00 */ +/**************************************************************************/ + + +// order(i) is sorted index of element i +extern void Sort (const ARRAY<double> & values, + ARRAY<int> & order); + +extern void QickSort (const ARRAY<double> & values, + ARRAY<int> & order); + + + + +template <class T> +inline void BubbleSort (int size, T * data) +{ + T hv; + for (int i = 0; i < size; i++) + for (int j = i+1; j < size; j++) + if (data[i] > data[j]) + { + hv = data[i]; + data[i] = data[j]; + data[j] = hv; + } +} + +template <class T> +inline void BubbleSort (ARRAY<T> & data) +{ + if(data.Size() > 0) + BubbleSort (data.Size(), &data[data.Begin()]); +} + +#endif diff --git a/contrib/Netgen/libsrc/general/spbita2d.cpp b/contrib/Netgen/libsrc/general/spbita2d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5badfe9a7c99b21254b7310024c4b92627f344f4 --- /dev/null +++ b/contrib/Netgen/libsrc/general/spbita2d.cpp @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* File: spbita2d.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Implementation of sparse 2 dimensional bitarray +*/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + SPARSE_BIT_ARRAY_2D :: SPARSE_BIT_ARRAY_2D (int ah, int aw) + { + lines = NULL; + SetSize (ah, aw); + } + + SPARSE_BIT_ARRAY_2D :: ~SPARSE_BIT_ARRAY_2D () + { + DeleteElements (); + delete lines; + } + + + void SPARSE_BIT_ARRAY_2D :: SetSize (int ah, int aw) + { + DeleteElements(); + if (lines) + { + delete lines; + lines = NULL; + } + + if (!aw) aw = ah; + + height = ah; + width = aw; + + if (!ah) return; + lines = new linestruct[ah]; + + if (lines) + { + for (int i = 0; i < ah; i++) + { + lines[i].size = 0; + lines[i].maxsize = 0; + lines[i].col = NULL; + } + } + else + { + height = width = 0; + MyError ("SPARSE_ARRAY::SetSize: Out of memory"); + } + } + + + + void SPARSE_BIT_ARRAY_2D :: DeleteElements () + { + if (lines) + { + for (int i = 0; i < height; i++) + { + if (lines[i].col) + { + delete [] lines[i].col; + lines[i].col = NULL; + lines[i].size = 0; + lines[i].maxsize = 0; + } + } + } + } + + + int SPARSE_BIT_ARRAY_2D :: Test (int i, int j) const + { + int k, max, *col; + + if (!lines) return 0; + if (i < 1 || i > height) return 0; + + col = lines[i-1].col; + max = lines[i-1].size; + + for (k = 0; k < max; k++, col++) + if (*col == j) return 1; + + return 0; + } + + + + void SPARSE_BIT_ARRAY_2D :: Set(int i, int j) + { + int k, max, *col; + + i--; + col = lines[i].col; + max = lines[i].size; + + for (k = 0; k < max; k++, col++) + if (*col == j) + return; + + if (lines[i].size) + { + if (lines[i].size == lines[i].maxsize) + { + col = new int[lines[i].maxsize+2]; + if (col) + { + lines[i].maxsize += 2; + memcpy (col, lines[i].col, sizeof (int) * lines[i].size); + delete [] lines[i].col; + lines[i].col = col; + } + else + { + MyError ("SPARSE_BIT_ARRAY::Set: Out of mem 1"); + return; + } + } + else + col = lines[i].col; + + if (col) + { + k = lines[i].size-1; + while (k >= 0 && col[k] > j) + { + col[k+1] = col[k]; + k--; + } + + k++; + lines[i].size++; + col[k] = j; + return; + } + else + { + MyError ("SPARSE_ARRAY::Set: Out of memory 2"); + } + } + else + { + lines[i].col = new int[4]; + if (lines[i].col) + { + lines[i].maxsize = 4; + lines[i].size = 1; + lines[i].col[0] = j; + return; + } + else + { + MyError ("SparseMatrix::Elem: Out of memory 3"); + } + } + } + +} diff --git a/contrib/Netgen/libsrc/general/spbita2d.hpp b/contrib/Netgen/libsrc/general/spbita2d.hpp new file mode 100644 index 0000000000000000000000000000000000000000..db656653b1799e747be24cc50d8ac3352f5b1381 --- /dev/null +++ b/contrib/Netgen/libsrc/general/spbita2d.hpp @@ -0,0 +1,56 @@ +#ifndef FILE_SPBITA2D +#define FILE_SPBITA2D + +/**************************************************************************/ +/* File: spbita2d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/** + Implementation of sparse 2 dimensional bitarray +*/ + + +class SPARSE_BIT_ARRAY_2D + { + class linestruct { public: INDEX size; INDEX maxsize; INDEX * col; }; + + /// + linestruct * lines; + /// + INDEX height, width; + + public: + + /// + SPARSE_BIT_ARRAY_2D (INDEX ah = 0, INDEX aw = 0); + /// + ~SPARSE_BIT_ARRAY_2D (); + + /// + void SetSize (INDEX ah, INDEX aw = 0); + /// + void DeleteElements (); + + /// + int Get (INDEX i, INDEX j) const; + + /// + INDEX Height () const { return height; } + /// + INDEX Width () const { return width; } + + /// + void Set (INDEX i, INDEX j); + /// + int Test (INDEX i, INDEX j) const; + + /// + INDEX BitsInLine (INDEX i) const { return lines[i-1].size; } + /// + INDEX GetIndex (INDEX i, INDEX nr) const { return lines[i-1].col[nr-1]; } + }; + + +#endif diff --git a/contrib/Netgen/libsrc/general/stack.hpp b/contrib/Netgen/libsrc/general/stack.hpp new file mode 100644 index 0000000000000000000000000000000000000000..db8dfad2666817a7694a0edfcceafdf3fdd68f1b --- /dev/null +++ b/contrib/Netgen/libsrc/general/stack.hpp @@ -0,0 +1,112 @@ +#ifndef FILE_STACK +#define FILE_STACK + +/*****************************************************************************/ +/* File: stack.hh */ +/* Author: Wolfram Muehlhuber */ +/* Date: September 98 */ +/*****************************************************************************/ + +/* + + Stack class, based on a resizable array + + */ + + +#include "array.hpp" + + +/// +template <class T> class STACK +{ +public: + /// + inline STACK (INDEX asize = 0, INDEX ainc = 0); + /// + inline ~STACK (); + + /// + inline void Push (const T & el); + /// + inline T & Pop (); + /// + const inline T & Top () const; + /// + inline int IsEmpty () const; + /// + inline void MakeEmpty (); + +private: + /// + ARRAY<T> elems; + /// + INDEX size; +}; + + + + +/* + + Stack class, based on a resizable array + + */ + +template <class T> +inline STACK<T> :: STACK (INDEX asize, INDEX ainc) + : elems(asize, ainc) +{ + size = 0; +} + + +template <class T> +inline STACK<T> :: ~STACK () +{ + ; +} + + +template <class T> +inline void STACK<T> :: Push (const T & el) +{ + if (size < elems.Size()) + elems.Elem(++size) = el; + else + { + elems.Append(el); + size++; + } +} + + +template <class T> +inline T & STACK<T> :: Pop () +{ + return elems.Elem(size--); +} + + +template <class T> +const inline T & STACK<T> :: Top () const +{ + return elems.Get(size); +} + +template <class T> +inline int STACK<T> :: IsEmpty () const +{ + return (size == 0); +} + + +template <class T> +inline void STACK<T> :: MakeEmpty () +{ + size = 0; +} + + + +#endif diff --git a/contrib/Netgen/libsrc/general/stack.icc b/contrib/Netgen/libsrc/general/stack.icc new file mode 100644 index 0000000000000000000000000000000000000000..c0182a564b73ca334e9ec60a7d73e3635e82a3fc --- /dev/null +++ b/contrib/Netgen/libsrc/general/stack.icc @@ -0,0 +1,67 @@ +/*****************************************************************************/ +/* File: stack.hh */ +/* Author: Wolfram Muehlhuber */ +/* Date: September 98 */ +/*****************************************************************************/ + +/* + + Stack class, based on a resizable array + + */ + +template <class T> +inline STACK<T> :: STACK (INDEX asize, INDEX ainc) + : elems(asize, ainc) +{ + size = 0; +} + + +template <class T> +inline STACK<T> :: ~STACK () +{ + ; +} + + +template <class T> +inline void STACK<T> :: Push (const T & el) +{ + if (size < elems.Size()) + elems.Elem(++size) = el; + else + { + elems.Append(el); + size++; + } +} + + +template <class T> +inline T & STACK<T> :: Pop () +{ + return elems.Elem(size--); +} + + +template <class T> +const inline T & STACK<T> :: Top () const +{ + return elems.Get(size); +} + +template <class T> +inline int STACK<T> :: IsEmpty () const +{ + return (size == 0); +} + + +template <class T> +inline void STACK<T> :: MakeEmpty () +{ + size = 0; +} + + diff --git a/contrib/Netgen/libsrc/general/symbolta.cpp b/contrib/Netgen/libsrc/general/symbolta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd35ac7cb229c6370d599e0d9e108f794eb0a5fd --- /dev/null +++ b/contrib/Netgen/libsrc/general/symbolta.cpp @@ -0,0 +1,52 @@ +/**************************************************************************/ +/* File: symbolta.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type Symbol Table +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + + +#ifndef FILE_SYMBOLTABLECC +#define FILE_SYMBOLTABLECC +// necessary for SGI ???? + + +namespace netgen +{ + //using namespace netgen; + + BASE_SYMBOLTABLE :: BASE_SYMBOLTABLE () + { + ; + } + + + BASE_SYMBOLTABLE :: ~BASE_SYMBOLTABLE() + { + DelNames(); + } + + + void BASE_SYMBOLTABLE :: DelNames() + { + for (int i = 0; i < names.Size(); i++) + delete [] names[i]; + names.SetSize (0); + } + + int BASE_SYMBOLTABLE :: Index (const char * name) const + { + if (!name) return 0; + for (int i = 0; i < names.Size(); i++) + if (strcmp (names[i], name) == 0) return i+1; + return 0; + } +} + +#endif diff --git a/contrib/Netgen/libsrc/general/symbolta.hpp b/contrib/Netgen/libsrc/general/symbolta.hpp new file mode 100644 index 0000000000000000000000000000000000000000..38895dee8e740abd1c5d48eb450d4a578d74f286 --- /dev/null +++ b/contrib/Netgen/libsrc/general/symbolta.hpp @@ -0,0 +1,158 @@ +#ifndef FILE_SYMBOLTA +#define FILE_SYMBOLTA + + +/**************************************************************************/ +/* File: symbolta.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/** + Base class for the generic SYMBOLTABLE. + An array of identifiers is maintained. +*/ +class BASE_SYMBOLTABLE +{ +protected: + /// identifiers + ARRAY <char*> names; + +public: + /// Constructor + BASE_SYMBOLTABLE (); + /// + ~BASE_SYMBOLTABLE (); + /// + void DelNames (); + /// Index of symbol name, returns 0 if not used. + int Index (const char * name) const; +}; + + +/** + Abstract data type Symbol Table. + + To a string an value of the generic type T is associated. + The string is not copied into the symbol table class! +*/ +template <class T> +class SYMBOLTABLE : public BASE_SYMBOLTABLE +{ +private: + /// Associated data + ARRAY <T> data; + +public: + /// Creates a symboltable + inline SYMBOLTABLE (); + /// Returns size of symboltable + inline INDEX Size() const; + /// Returns reference to element, error if not used + inline T & Elem (const char * name); + /// Returns reference to i-th element + inline T & Elem (int i) + { return data.Elem(i); } + /// Returns element, error if not used + inline const T & Get (const char * name) const; + /// Returns i-th element + inline const T & Get (int i) const; + /// Returns name of i-th element + inline const char* GetName (int i) const; + /// Associates el to the string name, overrides if name is used + inline void Set (const char * name, const T & el); + /// Checks whether name is used + inline bool Used (const char * name) const; + /// Deletes symboltable + inline void DeleteAll (); + + inline T & operator[] (int i) + { return data[i]; } + inline const T & operator[] (int i) const + { return data[i]; } + +private: + /// Prevents from copying symboltable by pointer assignment + SYMBOLTABLE<T> & operator= (SYMBOLTABLE<T> &); +}; + + + + +template <class T> +inline SYMBOLTABLE<T> :: SYMBOLTABLE () +{ + ; +} + + +template <class T> +inline INDEX SYMBOLTABLE<T> :: Size() const +{ + return data.Size(); +} + +template <class T> +inline T & SYMBOLTABLE<T> :: Elem (const char * name) +{ + int i = Index (name); + if (i) + return data.Elem (i); + else + return data.Elem(1); +} + +template <class T> +inline const T & SYMBOLTABLE<T> :: Get (const char * name) const +{ + int i; + i = Index (name); + if (i) + return data.Get(i); + else + return data.Get(1); +} + +template <class T> +inline const T & SYMBOLTABLE<T> :: Get (int i) const +{ + return data.Get(i); +} + +template <class T> +inline const char* SYMBOLTABLE<T> :: GetName (int i) const +{ + return names.Get(i); +} + +template <class T> +inline void SYMBOLTABLE<T> :: Set (const char * name, const T & el) +{ + int i; + i = Index (name); + if (i) + data.Set(i, el); + else + { + data.Append (el); + char * hname = new char [strlen (name) + 1]; + strcpy (hname, name); + names.Append (hname); + } +} + +template <class T> +inline bool SYMBOLTABLE<T> :: Used (const char * name) const +{ + return (Index(name)) ? true : false; +} + +template <class T> +inline void SYMBOLTABLE<T> :: DeleteAll () +{ + DelNames(); + data.DeleteAll(); +} + + +#endif diff --git a/contrib/Netgen/libsrc/general/table.cpp b/contrib/Netgen/libsrc/general/table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6168374bdb000aa175cc2ed55b540f264cf162a --- /dev/null +++ b/contrib/Netgen/libsrc/general/table.cpp @@ -0,0 +1,193 @@ +/**************************************************************************/ +/* File: table.cpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + Abstract data type TABLE +*/ + +#include <mystdlib.h> +#include <myadt.hpp> + +namespace netgen +{ + //using namespace netgen; + + BASE_TABLE :: BASE_TABLE (int size) + : data(size) + { + for (int i = 0; i < size; i++) + { + data[i].maxsize = 0; + data[i].size = 0; + data[i].col = NULL; + } + oneblock = NULL; + } + + BASE_TABLE :: BASE_TABLE (const FlatArray<int> & entrysizes, int elemsize) + : data(entrysizes.Size()) + { + int i, cnt = 0; + int n = entrysizes.Size(); + + for (i = 0; i < n; i++) + cnt += entrysizes[i]; + oneblock = new char[elemsize * cnt]; + // mem_total_alloc_table += elemsize * cnt; + + cnt = 0; + for (i = 0; i < n; i++) + { + data[i].maxsize = entrysizes[i]; + data[i].size = 0; + + data[i].col = &oneblock[elemsize * cnt]; + cnt += entrysizes[i]; + } + } + + BASE_TABLE :: ~BASE_TABLE () + { + if (oneblock) + delete [] oneblock; + else + { + for (int i = 0; i < data.Size(); i++) + delete [] (char*)data[i].col; + } + } + + void BASE_TABLE :: SetSize (int size) + { + for (int i = 0; i < data.Size(); i++) + delete [] (char*)data[i].col; + + data.SetSize(size); + for (int i = 0; i < size; i++) + { + data[i].maxsize = 0; + data[i].size = 0; + data[i].col = NULL; + } + } + + void BASE_TABLE :: ChangeSize (int size) + { + int oldsize = data.Size(); + if (size == oldsize) + return; + + if (size < oldsize) + for (int i = size; i < oldsize; i++) + delete [] (char*)data[i].col; + + data.SetSize(size); + + for (int i = oldsize; i < size; i++) + { + data[i].maxsize = 0; + data[i].size = 0; + data[i].col = NULL; + } + } + + void BASE_TABLE :: IncSize2 (int i, int elsize) + { +#ifdef DEBUG + if (i < 0 || i >= data.Size()) + { + MyError ("BASE_TABLE::Inc: Out of range"); + return; + } +#endif + + linestruct & line = data[i]; + if (line.size == line.maxsize) + { + void * p = new char [(line.maxsize+5) * elsize]; + + memcpy (p, line.col, line.maxsize * elsize); + delete [] (char*)line.col; + + line.col = p; + line.maxsize += 5; + } + + line.size++; + } + + + + /* + void BASE_TABLE :: DecSize (int i) + { +#ifdef DEBUG + if (i < 0 || i >= data.Size()) + { + MyError ("BASE_TABLE::Dec: Out of range"); + return; + } +#endif + + linestruct & line = data[i]; + +#ifdef DEBUG + if (line.size == 0) + { + MyError ("BASE_TABLE::Dec: EntrySize < 0"); + return; + } +#endif + + line.size--; + } + */ + + + + void BASE_TABLE :: AllocateElementsOneBlock (int elemsize) + { + int cnt = 0; + int n = data.Size(); + + for (int i = 0; i < n; i++) + cnt += data[i].maxsize; + oneblock = new char[elemsize * cnt]; + + cnt = 0; + for (int i = 0; i < n; i++) + { + data[i].size = 0; + data[i].col = &oneblock[elemsize * cnt]; + cnt += data[i].maxsize; + } + } + + + + int BASE_TABLE :: AllocatedElements () const + { + int els = 0; + for (int i = 0; i < data.Size(); i++) + els += data[i].maxsize; + return els; + } + + int BASE_TABLE :: UsedElements () const + { + int els = 0; + for (int i = 0; i < data.Size(); i++) + els += data[i].size; + return els; + } + + void BASE_TABLE :: SetElementSizesToMaxSizes () + { + for (int i = 0; i < data.Size(); i++) + data[i].size = data[i].maxsize; + } + +} diff --git a/contrib/Netgen/libsrc/general/table.hpp b/contrib/Netgen/libsrc/general/table.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f9ed02f18c4c893347a8468f972a86ddb02911a9 --- /dev/null +++ b/contrib/Netgen/libsrc/general/table.hpp @@ -0,0 +1,223 @@ +#ifndef FILE_TABLE +#define FILE_TABLE + +/**************************************************************************/ +/* File: table.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/// Base class to generic class TABLE. +class BASE_TABLE +{ +protected: + + /// + class linestruct + { + public: + /// + int size; + /// + int maxsize; + /// + void * col; + }; + + /// + ARRAY<linestruct> data; + char * oneblock; + +public: + /// + BASE_TABLE (int size); + /// + BASE_TABLE (const FlatArray<int> & entrysizes, int elemsize); + /// + ~BASE_TABLE (); + /// + void SetSize (int size); + /// + void ChangeSize (int size); + + /// increment size of entry i by one, i is 0-based + void IncSize (int i, int elsize) + { + if (data[i].size < data[i].maxsize) + data[i].size++; + else + IncSize2 (i, elsize); + } + /// + void IncSize2 (int i, int elsize); + + // void DecSize (int i); + + /// + void AllocateElementsOneBlock (int elemsize); + + int AllocatedElements () const; + int UsedElements () const; + + void SetElementSizesToMaxSizes (); +}; + + + + + + + +/** + Abstract data type TABLE. + + To an integer i in the range from 1 to size a set of elements of the + generic type T is associated. +*/ +template <class T, int BASE = 0> +class TABLE : public BASE_TABLE +{ +public: + /// Creates table. + inline TABLE () : BASE_TABLE(0) { ; } + + /// Creates table of size size + inline TABLE (int size) : BASE_TABLE (size) { ; } + + /// Creates fixed maximal element size table + inline TABLE (const FlatArray<int,BASE> & entrysizes) + : BASE_TABLE (FlatArray<int> (entrysizes.Size(), const_cast<int*>(&entrysizes[BASE])), + sizeof(T)) + { ; } + + /// Changes Size of table to size, deletes data + inline void SetSize (int size) + { + BASE_TABLE::SetSize (size); + } + + /// Changes Size of table to size, keep data + inline void ChangeSize (int size) + { + BASE_TABLE::ChangeSize (size); + } + + + /// Inserts element acont into row i, BASE-based. Does not test if already used. + inline void Add (int i, const T & acont) + { + IncSize (i-BASE, sizeof (T)); + ((T*)data[i-BASE].col)[data[i-BASE].size-1] = acont; + } + + + /// Inserts element acont into row i, 1-based. Does not test if already used. + inline void Add1 (int i, const T & acont) + { + IncSize (i-1, sizeof (T)); + ((T*)data.Elem(i).col)[data.Elem(i).size-1] = acont; + } + + /// + void IncSizePrepare (int i) + { + data[i-BASE].maxsize++; + } + + + /// Inserts element acont into row i. BASE-based. Does not test if already used, assumes to have enough memory + inline void AddSave (int i, const T & acont) + { + ((T*)data[i-BASE].col)[data[i-BASE].size] = acont; + data[i-BASE].size++; + } + + /// Inserts element acont into row i. 1-based. Does not test if already used, assumes to have mem + inline void AddSave1 (int i, const T & acont) + { + ((T*)data.Elem(i).col)[data.Elem(i).size] = acont; + data.Elem(i).size++; + } + + /// Inserts element acont into row i. Does not test if already used. + inline void AddEmpty (int i) + { + IncSize (i-BASE, sizeof (T)); + } + + /** Set the nr-th element in the i-th row to acont. + Does not check for overflow. */ + inline void Set (int i, int nr, const T & acont) + { ((T*)data.Get(i).col)[nr-1] = acont; } + /** Returns the nr-th element in the i-th row. + Does not check for overflow. */ + inline const T & Get (int i, int nr) const + { return ((T*)data.Get(i).col)[nr-1]; } + + + /** Returns pointer to the first element in row i. */ + inline const T * GetLine (int i) const + { + return ((const T*)data.Get(i).col); + } + + + /// Returns size of the table. + inline int Size () const + { + return data.Size(); + } + + /// Returns size of the i-th row. + inline int EntrySize (int i) const + { return data.Get(i).size; } + + /* + inline void DecEntrySize (int i) + { DecSize(i); } + */ + void AllocateElementsOneBlock () + { BASE_TABLE::AllocateElementsOneBlock (sizeof(T)); } + + + inline void PrintMemInfo (ostream & ost) const + { + int els = AllocatedElements(); + ost << "table: allocaed " << els + << " a " << sizeof(T) << " Byts = " + << els * sizeof(T) + << " bytes in " << Size() << " bags." + << " used: " << UsedElements() + << endl; + } + + /// Access entry. + FlatArray<T> operator[] (int i) const + { +#ifdef DEBUG + if (i-BASE < 0 || i-BASE >= data.Size()) + cout << "table out of range, i = " << i << ", s = " << data.Size() << endl; +#endif + + return FlatArray<T> (data[i-BASE].size, (T*)data[i-BASE].col); + } +}; + + +template <class T, int BASE> +inline ostream & operator<< (ostream & ost, const TABLE<T,BASE> & table) +{ + for (int i = BASE; i < table.Size()+BASE; i++) + { + ost << i << ": "; + FlatArray<T> row = table[i]; + ost << "(" << row.Size() << ") "; + for (int j = 0; j < row.Size(); j++) + ost << row[j] << " "; + ost << endl; + } + return ost; +} + +#endif + diff --git a/contrib/Netgen/libsrc/general/template.hpp b/contrib/Netgen/libsrc/general/template.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9fb378a7bc0648623902579ba96984cf5f37cc07 --- /dev/null +++ b/contrib/Netgen/libsrc/general/template.hpp @@ -0,0 +1,448 @@ +#ifndef FILE_TEMPLATE +#define FILE_TEMPLATE + +/**************************************************************************/ +/* File: template.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + +/* + templates, global types, defines and variables +*/ + +/// The following value may be adapted to the hardware ! +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC 1000000 +#endif + + +// #include <iostream> +/** output stream for testing. + testout is opened by main */ +extern ostream * testout; + +/** use instead of cout */ +extern ostream * mycout; + +/** error output stream */ +extern ostream * myerr; + +/** Error messages display. + Error messages are displayed by this function */ +extern void MyError (const char * ch); + + +/** Rings the bell. + Produces nr beeps. */ +extern void MyBeep (int nr = 1); + + +template <class T> +inline void Swap (T & a, T & b) +{ + T temp = a; + a = b; + b = temp; +} + +/* +template <class T> +inline void swap (T & a, T & b) +{ + T temp = a; + a = b; + b = temp; +} +*/ + + + +/** + INDEX is a typedef for (at least) 4-byte integer + */ +typedef int INDEX; + +/** + BOOL is a typedef for boolean variables + */ +// typedef int BOOL; + +typedef int ELIND; +typedef int PIND; + + +class twoint +{ +public: /// + int i1, i2; /// + twoint() {}; + /// + twoint(int ii1, int ii2) {i1 = ii1; i2 = ii2;} + friend int operator== (const twoint& t1, const twoint& t2); + /// + void Swap() {int x = i1; i1 = i2; i2 = x;} + void Sort() {if (i1 > i2) {Swap();}} +}; + +inline int operator== (const twoint& t1, const twoint& t2) +{ + return t1.i1 == t2.i1 && t1.i2 == t2.i2; +} + +class threeint +{ +public: /// + int i1, i2, i3; /// + threeint() {}; + /// + threeint(int ii1, int ii2, int ii3) {i1 = ii1; i2 = ii2; i3 = ii3;} +}; + +/// +class twodouble +{ +public: + /// + double d1, d2; + /// + twodouble() {d1 = 0; d2 = 0;}; + /// + twodouble(double id1, double id2) {d1 = id1; d2 = id2;} + /// + void Swap() {double x = d1; d1 = d2; d2 = x;} +}; + +class fourint { public: int i1, i2, i3, i4; fourint() {}; }; + + +/// +class INDEX_2; +ostream & operator<<(ostream & s, const INDEX_2 & i2); + + +class INDEX_2 +{ + /// + INDEX i[2]; + +public: + /// + INDEX_2 () { } + /// + INDEX_2 (INDEX ai1, INDEX ai2) + { i[0] = ai1; i[1] = ai2; } + + /// + INDEX_2 (const INDEX_2 & in2) + { i[0] = in2.i[0]; i[1] = in2.i[1]; } + + /// + int operator== (const INDEX_2 & in2) const + { return i[0] == in2.i[0] && i[1] == in2.i[1]; } + + /// + + + INDEX_2 Sort () + { + if (i[0] > i[1]) + { + INDEX hi = i[0]; + i[0] = i[1]; + i[1] = hi; + } + return *this; + } + + static INDEX_2 Sort (int i1, int i2) + { + if (i1 > i2) + return INDEX_2 (i2,i1); + else + return INDEX_2 (i1,i2); + } + + + /// + INDEX & I1 () { return i[0]; } + /// + INDEX & I2 () { return i[1]; } + /// + INDEX & I (int j) { return i[j-1]; } + /// + const INDEX & I1 () const { return i[0]; } + /// + const INDEX & I2 () const { return i[1]; } + /// + const INDEX & I (int j) const { return i[j-1]; } + /// + int & operator[] (int j) { return i[j]; } + /// + const int & operator[] (int j) const { return i[j]; } + /// + friend ostream & operator<<(ostream & s, const INDEX_2 & i2); +}; + + +/// +class INDEX_3 +{ + /// + INDEX i[3]; + +public: + /// + INDEX_3 () { } + /// + INDEX_3 (INDEX ai1, INDEX ai2, INDEX ai3) + { i[0] = ai1; i[1] = ai2; i[2] = ai3; } + + /// + INDEX_3 (const INDEX_3 & in2) + { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; } + + + static INDEX_3 Sort (INDEX_3 i3) + { + return i3.Sort(); + } + + static INDEX_3 Sort (int i1, int i2, int i3) + { + if (i1 > i2) Swap (i1, i2); + if (i2 > i3) Swap (i2, i3); + if (i1 > i2) Swap (i1, i2); + return INDEX_3 (i1, i2, i3); + } + + INDEX_3 Sort () + { + if (i[0] > i[1]) Swap (i[0], i[1]); + if (i[1] > i[2]) Swap (i[1], i[2]); + if (i[0] > i[1]) Swap (i[0], i[1]); + return *this; + } + + int operator== (const INDEX_3 & in2) const + { return i[0] == in2.i[0] && i[1] == in2.i[1] && i[2] == in2.i[2];} + + /// + INDEX & I1 () { return i[0]; } + /// + INDEX & I2 () { return i[1]; } + /// + INDEX & I3 () { return i[2]; } + /// + INDEX & I (int j) { return i[j-1]; } + /// + const INDEX & I1 () const { return i[0]; } + /// + const INDEX & I2 () const { return i[1]; } + /// + const INDEX & I3 () const { return i[2]; } + /// + const INDEX & I (int j) const { return i[j-1]; } + /// + int & operator[] (int j) { return i[j]; } + /// + const int & operator[] (int j) const { return i[j]; } + + /// + friend ostream & operator<<(ostream & s, const INDEX_3 & i3); +}; + + + +/// +class INDEX_4 +{ + /// + INDEX i[4]; + +public: + /// + INDEX_4 () { } + /// + INDEX_4 (INDEX ai1, INDEX ai2, INDEX ai3, INDEX ai4) + { i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; } + + /// + INDEX_4 (const INDEX_4 & in2) + { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; i[3] = in2.i[3]; } + + /// + void Sort (); + + /// + int operator== (const INDEX_4 & in2) const + { return + i[0] == in2.i[0] && i[1] == in2.i[1] && + i[2] == in2.i[2] && i[3] == in2.i[3]; } + + /// + INDEX & I1 () { return i[0]; } + /// + INDEX & I2 () { return i[1]; } + /// + INDEX & I3 () { return i[2]; } + /// + INDEX & I4 () { return i[3]; } + /// + INDEX & I (int j) { return i[j-1]; } + /// + const INDEX & I1 () const { return i[0]; } + /// + const INDEX & I2 () const { return i[1]; } + /// + const INDEX & I3 () const { return i[2]; } + /// + const INDEX & I4 () const { return i[3]; } + /// + const INDEX & I (int j) const { return i[j-1]; } + /// + int & operator[] (int j) { return i[j]; } + /// + const int & operator[] (int j) const { return i[j]; } + + /// + friend ostream & operator<<(ostream & s, const INDEX_4 & i4); +}; + + + + + + + + +/// The sort preserves quads !!! +class INDEX_4Q +{ + /// + INDEX i[4]; + +public: + /// + INDEX_4Q () { } + /// + INDEX_4Q (INDEX ai1, INDEX ai2, INDEX ai3, INDEX ai4) + { i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; } + + /// + INDEX_4Q (const INDEX_4Q & in2) + { i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; i[3] = in2.i[3]; } + + /// + void Sort (); + + /// + int operator== (const INDEX_4Q & in2) const + { return + i[0] == in2.i[0] && i[1] == in2.i[1] && + i[2] == in2.i[2] && i[3] == in2.i[3]; } + + /// + INDEX & I1 () { return i[0]; } + /// + INDEX & I2 () { return i[1]; } + /// + INDEX & I3 () { return i[2]; } + /// + INDEX & I4 () { return i[3]; } + /// + INDEX & I (int j) { return i[j-1]; } + /// + const INDEX & I1 () const { return i[0]; } + /// + const INDEX & I2 () const { return i[1]; } + /// + const INDEX & I3 () const { return i[2]; } + /// + const INDEX & I4 () const { return i[3]; } + /// + const INDEX & I (int j) const { return i[j-1]; } + /// + friend ostream & operator<<(ostream & s, const INDEX_4Q & i4); +}; + + + + + + + + + + + + +/// +template <class T> +inline T min2 (T a, T b) +{ + /// + return (a < b) ? a : b; +} +/// +template <class T> +inline T max2 (T a, T b) +{ + /// + return (a > b) ? a : b; +} +/// +template <class T> +inline T min3 (T a, T b, T c) +{ + /// + return (a < b) ? (a < c) ? a : c + : (b < c) ? b : c; +} +/// +template <class T> +inline T max3 (T a, T b, T c) +{ + /// + return (a > b) ? ((a > c) ? a : c) + : ((b > c) ? b : c); +} + +/// + +/// +template <class T> +inline int sgn (T a) +{ + return (a > 0) ? 1 : ( ( a < 0) ? -1 : 0 ); +} + +/// +template <class T> +inline T sqr (const T a) +{ + return a * a; +} + +/// +template <class T> +inline T pow3 (const T a) +{ + return a * a * a; +} + + + +/* +template <class T> +void BubbleSort (int size, T * data); + +template <class T> +void MergeSort (int size, T * data, T * help); +*/ + + + + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/Makefile b/contrib/Netgen/libsrc/gprim/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..608e522844a6a48099c593d915f4e11aa34df466 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for geometric library +# +src = geom2d.cpp geom3d.cpp \ + geomtest3d.cpp adtree.cpp transform3d.cpp geomfuncs.cpp + +# reftrans.cpp rot3d.cpp +# +lib = gprim +libpath = libsrc/gprim +# +# +include ../makefile.inc +# diff --git a/contrib/Netgen/libsrc/gprim/adtree.cpp b/contrib/Netgen/libsrc/gprim/adtree.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b5a319707bfce9923fbdec4d58f4eb712605061 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/adtree.cpp @@ -0,0 +1,2165 @@ +#include <mystdlib.h> + + +#include <myadt.hpp> +// class DenseMatrix; +#include <gprim.hpp> + +namespace netgen +{ + + + /* ******************************* ADTree ******************************* */ + + + ADTreeNode :: ADTreeNode(int adim) + { + pi = -1; + + left = NULL; + right = NULL; + father = NULL; + nchilds = 0; + dim = adim; + data = new float [dim]; + boxmin = NULL; + boxmax = NULL; + } + + + + + ADTreeNode :: ~ADTreeNode() + { + delete data; + } + + + ADTree :: ADTree (int adim, const float * acmin, + const float * acmax) + : ela(0), stack(1000), stackdir(1000) + { + dim = adim; + cmin = new float [dim]; + cmax = new float [dim]; + memcpy (cmin, acmin, dim * sizeof(float)); + memcpy (cmax, acmax, dim * sizeof(float)); + + root = new ADTreeNode (dim); + root->sep = (cmin[0] + cmax[0]) / 2; + root->boxmin = new float [dim]; + root->boxmax = new float [dim]; + memcpy (root->boxmin, cmin, dim * sizeof(float)); + memcpy (root->boxmax, cmax, dim * sizeof(float)); + } + + ADTree :: ~ADTree () + { + ; + } + + void ADTree :: Insert (const float * p, int pi) + { + ADTreeNode *node(NULL); + ADTreeNode *next; + int dir; + int lr(1); + + float * bmin = new float [dim]; + float * bmax = new float [dim]; + + memcpy (bmin, cmin, dim * sizeof(float)); + memcpy (bmax, cmax, dim * sizeof(float)); + + + next = root; + dir = 0; + while (next) + { + node = next; + + if (node->pi == -1) + { + memcpy (node->data, p, dim * sizeof(float)); + node->pi = pi; + + if (ela.Size() < pi+1) + ela.SetSize (pi+1); + ela[pi] = node; + + return; + } + + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + + dir++; + if (dir == dim) + dir = 0; + } + + + next = new ADTreeNode(dim); + memcpy (next->data, p, dim * sizeof(float)); + next->pi = pi; + next->sep = (bmin[dir] + bmax[dir]) / 2; + next->boxmin = bmin; + next->boxmax = bmax; + + if (ela.Size() < pi+1) + ela.SetSize (pi+1); + ela[pi] = next; + + + if (lr) + node->right = next; + else + node->left = next; + next -> father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree :: DeleteElement (int pi) + { + ADTreeNode * node = ela[pi]; + + node->pi = -1; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + + void ADTree :: SetCriterion (ADTreeCriterion & acriterion) + { + criterion = & acriterion; + } + + + void ADTree :: Reset () + { + stack.Elem(1) = root; + stackdir.Elem(1) = 0; + stackindex = 1; + } + + + int ADTree:: Next () + { + ADTreeNode *node; + int dir; + + if (stackindex == 0) + return -1; + + do + { + node = stack.Get(stackindex); + dir = stackdir.Get(stackindex); + stackindex --; + + if (criterion -> Eval(node)) + { + int ndir = dir + 1; + if (ndir == dim) + ndir = 0; + + if (node -> left && criterion -> Eval (node->left)) + { + stackindex ++; + stack.Elem(stackindex) = node -> left; + stackdir.Elem(stackindex) = ndir; + } + if (node->right && criterion -> Eval (node -> right)) + { + stackindex++; + stack.Elem(stackindex) = node->right; + stackdir.Elem(stackindex) = ndir; + } + + if (node -> pi != -1) + return node->pi; + } + } + while (stackindex > 0); + + return -1; + } + + + void ADTree :: GetMatch (ARRAY <int> & matches) + { + int nodenr; + + Reset(); + + while ( (nodenr = Next()) != -1) + matches.Append (nodenr); + } + + + void ADTree :: PrintRec (ostream & ost, const ADTreeNode * node) const + { + + if (node->data) + { + ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + for (int i = 0; i < dim; i++) + ost << node->data[i] << " "; + ost << endl; + } + if (node->left) + { + ost << "l "; + PrintRec (ost, node->left); + } + if (node->right) + { + ost << "r "; + PrintRec (ost, node->right); + } + } + + + /* ******************************* ADTree3 ******************************* */ + + + ADTreeNode3 :: ADTreeNode3() + { + pi = -1; + + left = NULL; + right = NULL; + father = NULL; + nchilds = 0; + } + + void ADTreeNode3 :: DeleteChilds () + { + if (left) + { + left->DeleteChilds(); + delete left; + left = NULL; + } + if (right) + { + right->DeleteChilds(); + delete right; + right = NULL; + } + } + + + BlockAllocator ADTreeNode3 :: ball(sizeof (ADTreeNode3)); + + + void * ADTreeNode3 :: operator new(size_t s) + { + return ball.Alloc(); + } + + void ADTreeNode3 :: operator delete (void * p) + { + ball.Free (p); + } + + + + + + + + ADTree3 :: ADTree3 (const float * acmin, + const float * acmax) + : ela(0) + { + memcpy (cmin, acmin, 3 * sizeof(float)); + memcpy (cmax, acmax, 3 * sizeof(float)); + + root = new ADTreeNode3; + root->sep = (cmin[0] + cmax[0]) / 2; + } + + ADTree3 :: ~ADTree3 () + { + root->DeleteChilds(); + delete root; + } + + + void ADTree3 :: Insert (const float * p, int pi) + { + ADTreeNode3 *node(NULL); + ADTreeNode3 *next; + int dir; + int lr(0); + + float bmin[3]; + float bmax[3]; + + memcpy (bmin, cmin, 3 * sizeof(float)); + memcpy (bmax, cmax, 3 * sizeof(float)); + + next = root; + dir = 0; + while (next) + { + node = next; + + if (node->pi == -1) + { + memcpy (node->data, p, 3 * sizeof(float)); + node->pi = pi; + + if (ela.Size() < pi+1) + ela.SetSize (pi+1); + ela[pi] = node; + + return; + } + + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + + dir++; + if (dir == 3) + dir = 0; + } + + + next = new ADTreeNode3; + memcpy (next->data, p, 3 * sizeof(float)); + next->pi = pi; + next->sep = (bmin[dir] + bmax[dir]) / 2; + + + if (ela.Size() < pi+1) + ela.SetSize (pi+1); + ela[pi] = next; + + + if (lr) + node->right = next; + else + node->left = next; + next -> father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree3 :: DeleteElement (int pi) + { + ADTreeNode3 * node = ela[pi]; + + node->pi = -1; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + void ADTree3 :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const + { + static ARRAY<ADTreeNode3*> stack(1000); + static ARRAY<int> stackdir(1000); + ADTreeNode3 * node; + int dir, stacks; + + stack.SetSize (1000); + stackdir.SetSize(1000); + pis.SetSize(0); + + stack.Elem(1) = root; + stackdir.Elem(1) = 0; + stacks = 1; + + while (stacks) + { + node = stack.Get(stacks); + dir = stackdir.Get(stacks); + stacks--; + + if (node->pi != -1) + { + if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && + node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && + node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) + + pis.Append (node->pi); + } + + + int ndir = dir+1; + if (ndir == 3) + ndir = 0; + + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack.Elem(stacks) = node->left; + stackdir.Elem(stacks) = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack.Elem(stacks) = node->right; + stackdir.Elem(stacks) = ndir; + } + } + } + + void ADTree3 :: PrintRec (ostream & ost, const ADTreeNode3 * node) const + { + + if (node->data) + { + ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + for (int i = 0; i < 3; i++) + ost << node->data[i] << " "; + ost << endl; + } + if (node->left) + PrintRec (ost, node->left); + if (node->right) + PrintRec (ost, node->right); + } + + + + + + + + +#ifdef ABC + + /* ******************************* ADTree3Div ******************************* */ + + + ADTreeNode3Div :: ADTreeNode3Div() + { + pi = 0; + + int i; + for (i = 0; i < ADTN_DIV; i++) + childs[i] = NULL; + + father = NULL; + nchilds = 0; + minx = 0; + dist = 1; + } + + void ADTreeNode3Div :: DeleteChilds () + { + int i; + for (i = 0; i < ADTN_DIV; i++) + if (childs[i]) + { + childs[i]->DeleteChilds(); + delete childs[i]; + childs[i] = NULL; + } + } + + + BlockAllocator ADTreeNode3Div :: ball(sizeof (ADTreeNode3Div)); + + void * ADTreeNode3Div :: operator new(size_t) + { + return ball.Alloc(); + } + + void ADTreeNode3Div :: operator delete (void * p) + { + ball.Free (p); + } + + + + + + + + ADTree3Div :: ADTree3Div (const float * acmin, + const float * acmax) + : ela(0) + { + memcpy (cmin, acmin, 3 * sizeof(float)); + memcpy (cmax, acmax, 3 * sizeof(float)); + + root = new ADTreeNode3Div; + + root->minx = cmin[0]; + root->dist = (cmax[0] - cmin[0]) / ADTN_DIV; + + // root->sep = (cmin[0] + cmax[0]) / 2; + } + + ADTree3Div :: ~ADTree3Div () + { + root->DeleteChilds(); + delete root; + } + + + void ADTree3Div :: Insert (const float * p, int pi) + { + ADTreeNode3Div *node; + ADTreeNode3Div *next; + int dir; + int bag; + + float bmin[3]; + float bmax[3]; + + memcpy (bmin, cmin, 3 * sizeof(float)); + memcpy (bmax, cmax, 3 * sizeof(float)); + + + next = root; + dir = 0; + while (next) + { + node = next; + + if (!node->pi) + { + memcpy (node->data, p, 3 * sizeof(float)); + node->pi = pi; + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = node; + + return; + } + + double dx = (bmax[dir] - bmin[dir]) / ADTN_DIV; + bag = int ((p[dir]-bmin[dir]) / dx); + + // (*testout) << "insert, bag = " << bag << endl; + + if (bag < 0) bag = 0; + if (bag >= ADTN_DIV) bag = ADTN_DIV-1; + + double nbmin = bmin[dir] + bag * dx; + double nbmax = bmin[dir] + (bag+1) * dx; + + /* + (*testout) << "bmin, max = " << bmin[dir] << "-" << bmax[dir] + << " p = " << p[dir]; + */ + next = node->childs[bag]; + bmin[dir] = nbmin; + bmax[dir] = nbmax; + + // (*testout) << "new bmin, max = " << bmin[dir] << "-" << bmax[dir] << endl; + + + /* + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + */ + + dir++; + if (dir == 3) + dir = 0; + } + + + next = new ADTreeNode3Div; + memcpy (next->data, p, 3 * sizeof(float)); + next->pi = pi; + + next->minx = bmin[dir]; + next->dist = (bmax[dir] - bmin[dir]) / ADTN_DIV; + // next->sep = (bmin[dir] + bmax[dir]) / 2; + + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = next; + + node->childs[bag] = next; + next -> father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree3Div :: DeleteElement (int pi) + { + ADTreeNode3Div * node = ela.Get(pi); + + node->pi = 0; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + void ADTree3Div :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const + { + static ARRAY<ADTreeNode3Div*> stack(1000); + static ARRAY<int> stackdir(1000); + ADTreeNode3Div * node; + int dir, i, stacks; + + stack.SetSize (1000); + stackdir.SetSize(1000); + pis.SetSize(0); + + stack.Elem(1) = root; + stackdir.Elem(1) = 0; + stacks = 1; + + while (stacks) + { + node = stack.Get(stacks); + dir = stackdir.Get(stacks); + stacks--; + + if (node->pi) + { + if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && + node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && + node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) + + pis.Append (node->pi); + } + + + int ndir = dir+1; + if (ndir == 3) + ndir = 0; + + int mini = int ( (bmin[dir] - node->minx) / node->dist ); + int maxi = int ( (bmax[dir] - node->minx) / node->dist ); + + // (*testout) << "get int, mini, maxi = " << mini << ", " << maxi << endl; + if (mini < 0) mini = 0; + if (maxi >= ADTN_DIV) maxi = ADTN_DIV-1; + + for (i = mini; i <= maxi; i++) + if (node->childs[i]) + { + stacks++; + stack.Elem(stacks) = node->childs[i]; + stackdir.Elem(stacks) = ndir; + } + + + /* + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack.Elem(stacks) = node->left; + stackdir.Elem(stacks) = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack.Elem(stacks) = node->right; + stackdir.Elem(stacks) = ndir; + } + */ + } + } + + void ADTree3Div :: PrintRec (ostream & ost, const ADTreeNode3Div * node) const + { + + if (node->data) + { + ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + ost << " from " << node->minx << " - " << node->minx + node->dist*ADTN_DIV << " "; + for (int i = 0; i < 3; i++) + ost << node->data[i] << " "; + ost << endl; + } + int i; + for (i = 0; i < ADTN_DIV; i++) + if (node->childs[i]) + PrintRec (ost, node->childs[i]); + } + + + + + + + + + + + + + /* ******************************* ADTree3M ******************************* */ + + + ADTreeNode3M :: ADTreeNode3M() + { + int i; + for (i = 0; i < ADTN_SIZE; i++) + pi[i] = 0; + + left = NULL; + right = NULL; + father = NULL; + nchilds = 0; + } + + void ADTreeNode3M :: DeleteChilds () + { + if (left) + { + left->DeleteChilds(); + delete left; + left = NULL; + } + if (right) + { + right->DeleteChilds(); + delete right; + right = NULL; + } + } + + + BlockAllocator ADTreeNode3M :: ball(sizeof (ADTreeNode3M)); + + void * ADTreeNode3M :: operator new(size_t) + { + return ball.Alloc(); + } + + void ADTreeNode3M :: operator delete (void * p) + { + ball.Free (p); + } + + + + + + + + ADTree3M :: ADTree3M (const float * acmin, + const float * acmax) + : ela(0) + { + memcpy (cmin, acmin, 3 * sizeof(float)); + memcpy (cmax, acmax, 3 * sizeof(float)); + + root = new ADTreeNode3M; + root->sep = (cmin[0] + cmax[0]) / 2; + } + + ADTree3M :: ~ADTree3M () + { + root->DeleteChilds(); + delete root; + } + + + void ADTree3M :: Insert (const float * p, int pi) + { + ADTreeNode3M *node; + ADTreeNode3M *next; + int dir; + int lr; + int i; + float bmin[3]; + float bmax[3]; + + memcpy (bmin, cmin, 3 * sizeof(float)); + memcpy (bmax, cmax, 3 * sizeof(float)); + + next = root; + dir = 0; + while (next) + { + node = next; + + for (i = 0; i < ADTN_SIZE; i++) + if (!node->pi[i]) + { + memcpy (node->data[i], p, 3 * sizeof(float)); + node->pi[i] = pi; + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = node; + + return; + } + + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + + dir++; + if (dir == 3) + dir = 0; + } + + + next = new ADTreeNode3M; + memcpy (next->data[0], p, 3 * sizeof(float)); + next->pi[0] = pi; + next->sep = (bmin[dir] + bmax[dir]) / 2; + + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = next; + + + if (lr) + node->right = next; + else + node->left = next; + next -> father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree3M :: DeleteElement (int pi) + { + ADTreeNode3M * node = ela.Get(pi); + + int i; + for (i = 0; i < ADTN_SIZE; i++) + if (node->pi[i] == pi) + node->pi[i] = 0; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + void ADTree3M :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const + { + static ARRAY<ADTreeNode3M*> stack(1000); + static ARRAY<int> stackdir(1000); + ADTreeNode3M * node; + int dir, i, stacks; + + stack.SetSize (1000); + stackdir.SetSize(1000); + pis.SetSize(0); + + stack.Elem(1) = root; + stackdir.Elem(1) = 0; + stacks = 1; + + while (stacks) + { + node = stack.Get(stacks); + dir = stackdir.Get(stacks); + stacks--; + + int * hpi = node->pi; + for (i = 0; i < ADTN_SIZE; i++) + if (hpi[i]) + { + float * datai = &node->data[i][0]; + if (datai[0] >= bmin[0] && datai[0] <= bmax[0] && + datai[1] >= bmin[1] && datai[1] <= bmax[1] && + datai[2] >= bmin[2] && datai[2] <= bmax[2]) + + pis.Append (node->pi[i]); + } + + + int ndir = dir+1; + if (ndir == 3) + ndir = 0; + + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack.Elem(stacks) = node->left; + stackdir.Elem(stacks) = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack.Elem(stacks) = node->right; + stackdir.Elem(stacks) = ndir; + } + } + } + + void ADTree3M :: PrintRec (ostream & ost, const ADTreeNode3M * node) const + { + + if (node->data) + { + // ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + for (int i = 0; i < 3; i++) + ost << node->data[i] << " "; + ost << endl; + } + if (node->left) + PrintRec (ost, node->left); + if (node->right) + PrintRec (ost, node->right); + } + + + + + + + + + + + + + /* ******************************* ADTree3F ******************************* */ + + + ADTreeNode3F :: ADTreeNode3F() + { + pi = 0; + father = NULL; + nchilds = 0; + int i; + for (i = 0; i < 8; i++) + childs[i] = NULL; + } + + void ADTreeNode3F :: DeleteChilds () + { + int i; + + for (i = 0; i < 8; i++) + { + if (childs[i]) + childs[i]->DeleteChilds(); + delete childs[i]; + childs[i] = NULL; + } + } + + + BlockAllocator ADTreeNode3F :: ball(sizeof (ADTreeNode3F)); + + void * ADTreeNode3F :: operator new(size_t) + { + return ball.Alloc(); + } + + void ADTreeNode3F :: operator delete (void * p) + { + ball.Free (p); + } + + + + + + + + ADTree3F :: ADTree3F (const float * acmin, + const float * acmax) + : ela(0) + { + memcpy (cmin, acmin, 3 * sizeof(float)); + memcpy (cmax, acmax, 3 * sizeof(float)); + + root = new ADTreeNode3F; + for (int i = 0; i < 3; i++) + root->sep[i] = (cmin[i] + cmax[i]) / 2; + } + + ADTree3F :: ~ADTree3F () + { + root->DeleteChilds(); + delete root; + } + + + void ADTree3F :: Insert (const float * p, int pi) + { + ADTreeNode3F *node; + ADTreeNode3F *next; + int lr; + + float bmin[3]; + float bmax[3]; + int i, dir; + + memcpy (bmin, cmin, 3 * sizeof(float)); + memcpy (bmax, cmax, 3 * sizeof(float)); + + + next = root; + while (next) + { + node = next; + + if (!node->pi) + { + memcpy (node->data, p, 3 * sizeof(float)); + node->pi = pi; + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = node; + + return; + } + + dir = 0; + for (i = 0; i < 3; i++) + { + if (node->sep[i] > p[i]) + { + bmax[i] = node->sep[i]; + } + else + { + bmin[i] = node->sep[i]; + dir += (1 << i); + } + } + next = node->childs[dir]; + + /* + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + */ + } + + + next = new ADTreeNode3F; + memcpy (next->data, p, 3 * sizeof(float)); + next->pi = pi; + + for (i = 0; i < 3; i++) + next->sep[i] = (bmin[i] + bmax[i]) / 2; + + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = next; + + node->childs[dir] = next; + next->father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree3F :: DeleteElement (int pi) + { + ADTreeNode3F * node = ela.Get(pi); + + node->pi = 0; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + void ADTree3F :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const + { + static ARRAY<ADTreeNode3F*> stack(1000); + ADTreeNode3F * node; + int dir, i, stacks; + + stack.SetSize (1000); + pis.SetSize(0); + + stack.Elem(1) = root; + stacks = 1; + + while (stacks) + { + node = stack.Get(stacks); + stacks--; + + if (node->pi) + { + if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && + node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && + node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) + + pis.Append (node->pi); + } + + + int i1min = (bmin[0] <= node->sep[0]) ? 0 : 1; + int i1max = (bmax[0] < node->sep[0]) ? 0 : 1; + int i2min = (bmin[1] <= node->sep[1]) ? 0 : 1; + int i2max = (bmax[1] < node->sep[1]) ? 0 : 1; + int i3min = (bmin[2] <= node->sep[2]) ? 0 : 1; + int i3max = (bmax[2] < node->sep[2]) ? 0 : 1; + + int i1, i2, i3; + for (i1 = i1min; i1 <= i1max; i1++) + for (i2 = i2min; i2 <= i2max; i2++) + for (i3 = i3min; i3 <= i3max; i3++) + { + i = i1+2*i2+4*i3; + if (node->childs[i]) + { + stacks++; + stack.Elem(stacks) = node->childs[i]; + } + } + + /* + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack.Elem(stacks) = node->left; + stackdir.Elem(stacks) = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack.Elem(stacks) = node->right; + stackdir.Elem(stacks) = ndir; + } + */ + } + } + + void ADTree3F :: PrintRec (ostream & ost, const ADTreeNode3F * node) const + { + int i; + if (node->data) + { + ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + for (i = 0; i < 3; i++) + ost << node->data[i] << " "; + ost << endl; + } + + for (i = 0; i < 8; i++) + if (node->childs[i]) + PrintRec (ost, node->childs[i]); + } + + + + + + + + + + + + + + /* ******************************* ADTree3FM ******************************* */ + + + ADTreeNode3FM :: ADTreeNode3FM() + { + father = NULL; + nchilds = 0; + int i; + + for (i = 0; i < ADTN_SIZE; i++) + pi[i] = 0; + + for (i = 0; i < 8; i++) + childs[i] = NULL; + } + + void ADTreeNode3FM :: DeleteChilds () + { + int i; + + for (i = 0; i < 8; i++) + { + if (childs[i]) + childs[i]->DeleteChilds(); + delete childs[i]; + childs[i] = NULL; + } + } + + + BlockAllocator ADTreeNode3FM :: ball(sizeof (ADTreeNode3FM)); + + void * ADTreeNode3FM :: operator new(size_t) + { + return ball.Alloc(); + } + + void ADTreeNode3FM :: operator delete (void * p) + { + ball.Free (p); + } + + + + + + + + ADTree3FM :: ADTree3FM (const float * acmin, + const float * acmax) + : ela(0) + { + memcpy (cmin, acmin, 3 * sizeof(float)); + memcpy (cmax, acmax, 3 * sizeof(float)); + + root = new ADTreeNode3FM; + for (int i = 0; i < 3; i++) + root->sep[i] = (cmin[i] + cmax[i]) / 2; + } + + ADTree3FM :: ~ADTree3FM () + { + root->DeleteChilds(); + delete root; + } + + + void ADTree3FM :: Insert (const float * p, int pi) + { + ADTreeNode3FM *node; + ADTreeNode3FM *next; + int lr; + + float bmin[3]; + float bmax[3]; + int i, dir; + + memcpy (bmin, cmin, 3 * sizeof(float)); + memcpy (bmax, cmax, 3 * sizeof(float)); + + next = root; + while (next) + { + node = next; + + for (i = 0; i < ADTN_SIZE; i++) + if (!node->pi[i]) + { + memcpy (node->data[i], p, 3 * sizeof(float)); + node->pi[i] = pi; + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = node; + + return; + } + + dir = 0; + for (i = 0; i < 3; i++) + { + if (node->sep[i] > p[i]) + { + bmax[i] = node->sep[i]; + } + else + { + bmin[i] = node->sep[i]; + dir += (1 << i); + } + } + next = node->childs[dir]; + + /* + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + */ + } + + + next = new ADTreeNode3FM; + memcpy (next->data[0], p, 3 * sizeof(float)); + next->pi[0] = pi; + + for (i = 0; i < 3; i++) + next->sep[i] = (bmin[i] + bmax[i]) / 2; + + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = next; + + node->childs[dir] = next; + next->father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree3FM :: DeleteElement (int pi) + { + ADTreeNode3FM * node = ela.Get(pi); + + int i; + for (i = 0; i < ADTN_SIZE; i++) + if (node->pi[i] == pi) + node->pi[i] = 0; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + void ADTree3FM :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const + { + static ARRAY<ADTreeNode3FM*> stack(1000); + ADTreeNode3FM * node; + int dir, i, stacks; + + stack.SetSize (1000); + pis.SetSize(0); + + stack.Elem(1) = root; + stacks = 1; + + while (stacks) + { + node = stack.Get(stacks); + stacks--; + + int * hpi = node->pi; + for (i = 0; i < ADTN_SIZE; i++) + if (hpi[i]) + { + float * datai = &node->data[i][0]; + if (datai[0] >= bmin[0] && datai[0] <= bmax[0] && + datai[1] >= bmin[1] && datai[1] <= bmax[1] && + datai[2] >= bmin[2] && datai[2] <= bmax[2]) + + pis.Append (node->pi[i]); + } + + /* + if (node->pi) + { + if (node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && + node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && + node->data[2] >= bmin[2] && node->data[2] <= bmax[2]) + + pis.Append (node->pi); + } + */ + + int i1min = (bmin[0] <= node->sep[0]) ? 0 : 1; + int i1max = (bmax[0] < node->sep[0]) ? 0 : 1; + int i2min = (bmin[1] <= node->sep[1]) ? 0 : 1; + int i2max = (bmax[1] < node->sep[1]) ? 0 : 1; + int i3min = (bmin[2] <= node->sep[2]) ? 0 : 1; + int i3max = (bmax[2] < node->sep[2]) ? 0 : 1; + + int i1, i2, i3; + for (i1 = i1min; i1 <= i1max; i1++) + for (i2 = i2min; i2 <= i2max; i2++) + for (i3 = i3min; i3 <= i3max; i3++) + { + i = i1+2*i2+4*i3; + if (node->childs[i]) + { + stacks++; + stack.Elem(stacks) = node->childs[i]; + } + } + + /* + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack.Elem(stacks) = node->left; + stackdir.Elem(stacks) = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack.Elem(stacks) = node->right; + stackdir.Elem(stacks) = ndir; + } + */ + } + } + + void ADTree3FM :: PrintRec (ostream & ost, const ADTreeNode3FM * node) const + { + int i; + if (node->data) + { + ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + for (i = 0; i < 3; i++) + ost << node->data[i] << " "; + ost << endl; + } + + for (i = 0; i < 8; i++) + if (node->childs[i]) + PrintRec (ost, node->childs[i]); + } + + + + +#endif + + + + + + + /* ******************************* ADTree6 ******************************* */ + + + ADTreeNode6 :: ADTreeNode6() + { + pi = -1; + + left = NULL; + right = NULL; + father = NULL; + nchilds = 0; + } + + void ADTreeNode6 :: DeleteChilds () + { + if (left) + { + left->DeleteChilds(); + delete left; + left = NULL; + } + if (right) + { + right->DeleteChilds(); + delete right; + right = NULL; + } + } + + + BlockAllocator ADTreeNode6 :: ball (sizeof (ADTreeNode6)); + void * ADTreeNode6 :: operator new(size_t) + { + return ball.Alloc(); + } + + void ADTreeNode6 :: operator delete (void * p) + { + ball.Free (p); + } + + + + + + ADTree6 :: ADTree6 (const float * acmin, + const float * acmax) + : ela(0) + { + memcpy (cmin, acmin, 6 * sizeof(float)); + memcpy (cmax, acmax, 6 * sizeof(float)); + + root = new ADTreeNode6; + root->sep = (cmin[0] + cmax[0]) / 2; + } + + ADTree6 :: ~ADTree6 () + { + root->DeleteChilds(); + delete root; + } + + void ADTree6 :: Insert (const float * p, int pi) + { + ADTreeNode6 *node(NULL); + ADTreeNode6 *next; + int dir; + int lr(0); + + float bmin[6]; + float bmax[6]; + + + memcpy (bmin, cmin, 6 * sizeof(float)); + memcpy (bmax, cmax, 6 * sizeof(float)); + + next = root; + dir = 0; + while (next) + { + node = next; + + if (node->pi == -1) + { + memcpy (node->data, p, 6 * sizeof(float)); + node->pi = pi; + + if (ela.Size() < pi+1) + ela.SetSize (pi+1); + ela[pi] = node; + + return; + } + + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + + dir++; + if (dir == 6) dir = 0; + } + + + next = new ADTreeNode6; + memcpy (next->data, p, 6 * sizeof(float)); + next->pi = pi; + next->sep = (bmin[dir] + bmax[dir]) / 2; + + if (ela.Size() < pi+1) + ela.SetSize (pi+1); + ela[pi] = next; + + if (lr) + node->right = next; + else + node->left = next; + next -> father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree6 :: DeleteElement (int pi) + { + ADTreeNode6 * node = ela[pi]; + + node->pi = -1; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + void ADTree6 :: PrintMemInfo (ostream & ost) const + { + ost << Elements() << " elements a " << sizeof(ADTreeNode6) + << " Bytes = " + << Elements() * sizeof(ADTreeNode6) << endl; + ost << "maxind = " << ela.Size() << " = " << sizeof(ADTreeNode6*) * ela.Size() << " Bytes" << endl; + } + + + + class inttn6 { + public: + int dir; + ADTreeNode6 * node; + }; + + + + + void ADTree6 :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const + { + static ARRAY<inttn6> stack(10000); + + stack.SetSize (10000); + pis.SetSize(0); + + stack[0].node = root; + stack[0].dir = 0; + int stacks = 0; + + while (stacks >= 0) + { + ADTreeNode6 * node = stack[stacks].node; + int dir = stack[stacks].dir; + + stacks--; + + if (node->pi != -1) + { + if (node->data[0] > bmax[0] || + node->data[1] > bmax[1] || + node->data[2] > bmax[2] || + node->data[3] < bmin[3] || + node->data[4] < bmin[4] || + node->data[5] < bmin[5]) + ; + else + pis.Append (node->pi); + } + + int ndir = (dir+1) % 6; + + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack[stacks].node = node->left; + stack[stacks].dir = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack[stacks].node = node->right; + stack[stacks].dir = ndir; + } + } + } + + void ADTree6 :: PrintRec (ostream & ost, const ADTreeNode6 * node) const + { + + if (node->data) + { + ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + for (int i = 0; i < 6; i++) + ost << node->data[i] << " "; + ost << endl; + } + if (node->left) + PrintRec (ost, node->left); + if (node->right) + PrintRec (ost, node->right); + } + + + int ADTree6 :: DepthRec (const ADTreeNode6 * node) const + { + int ldepth = 0; + int rdepth = 0; + + if (node->left) + ldepth = DepthRec(node->left); + if (node->right) + rdepth = DepthRec(node->right); + return 1 + max2 (ldepth, rdepth); + } + + int ADTree6 :: ElementsRec (const ADTreeNode6 * node) const + { + int els = 1; + if (node->left) + els += ElementsRec(node->left); + if (node->right) + els += ElementsRec(node->right); + return els; + } + + + + + + +#ifdef ABC + + /* ******************************* ADTree6F ******************************* */ + + + ADTreeNode6F :: ADTreeNode6F() + { + pi = 0; + father = NULL; + nchilds = 0; + int i; + for (i = 0; i < 64; i++) + childs[i] = NULL; + } + + void ADTreeNode6F :: DeleteChilds () + { + int i; + + for (i = 0; i < 64; i++) + { + if (childs[i]) + childs[i]->DeleteChilds(); + delete childs[i]; + childs[i] = NULL; + } + } + + + BlockAllocator ADTreeNode6F :: ball(sizeof (ADTreeNode6F)); + + void * ADTreeNode6F :: operator new(size_t) + { + return ball.Alloc(); + } + + void ADTreeNode6F :: operator delete (void * p) + { + ball.Free (p); + } + + + + + + + + ADTree6F :: ADTree6F (const float * acmin, + const float * acmax) + : ela(0) + { + memcpy (cmin, acmin, 6 * sizeof(float)); + memcpy (cmax, acmax, 6 * sizeof(float)); + + root = new ADTreeNode6F; + for (int i = 0; i < 6; i++) + root->sep[i] = (cmin[i] + cmax[i]) / 2; + } + + ADTree6F :: ~ADTree6F () + { + root->DeleteChilds(); + delete root; + } + + + void ADTree6F :: Insert (const float * p, int pi) + { + ADTreeNode6F *node; + ADTreeNode6F *next; + int lr; + + float bmin[6]; + float bmax[6]; + int i, dir; + + memcpy (bmin, cmin, 6 * sizeof(float)); + memcpy (bmax, cmax, 6 * sizeof(float)); + + next = root; + while (next) + { + node = next; + + if (!node->pi) + { + memcpy (node->data, p, 6 * sizeof(float)); + node->pi = pi; + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = node; + + return; + } + + dir = 0; + for (i = 0; i < 6; i++) + { + if (node->sep[i] > p[i]) + { + bmax[i] = node->sep[i]; + } + else + { + bmin[i] = node->sep[i]; + dir += (1 << i); + } + } + next = node->childs[dir]; + + /* + if (node->sep > p[dir]) + { + next = node->left; + bmax[dir] = node->sep; + lr = 0; + } + else + { + next = node->right; + bmin[dir] = node->sep; + lr = 1; + } + */ + } + + + next = new ADTreeNode6F; + memcpy (next->data, p, 6 * sizeof(float)); + next->pi = pi; + + for (i = 0; i < 6; i++) + next->sep[i] = (bmin[i] + bmax[i]) / 2; + + + if (ela.Size() < pi) + ela.SetSize (pi); + ela.Elem(pi) = next; + + node->childs[dir] = next; + next->father = node; + + while (node) + { + node->nchilds++; + node = node->father; + } + } + + void ADTree6F :: DeleteElement (int pi) + { + ADTreeNode6F * node = ela.Get(pi); + + node->pi = 0; + + node = node->father; + while (node) + { + node->nchilds--; + node = node->father; + } + } + + void ADTree6F :: GetIntersecting (const float * bmin, + const float * bmax, + ARRAY<int> & pis) const + { + static ARRAY<ADTreeNode6F*> stack(1000); + ADTreeNode6F * node; + int dir, i, stacks; + + stack.SetSize (1000); + pis.SetSize(0); + + stack.Elem(1) = root; + stacks = 1; + + while (stacks) + { + node = stack.Get(stacks); + stacks--; + + if (node->pi) + { + if ( + node->data[0] >= bmin[0] && node->data[0] <= bmax[0] && + node->data[1] >= bmin[1] && node->data[1] <= bmax[1] && + node->data[2] >= bmin[2] && node->data[2] <= bmax[2] && + node->data[3] >= bmin[3] && node->data[3] <= bmax[3] && + node->data[4] >= bmin[4] && node->data[4] <= bmax[4] && + node->data[5] >= bmin[5] && node->data[5] <= bmax[5] + ) + + pis.Append (node->pi); + } + + + int i1min = (bmin[0] <= node->sep[0]) ? 0 : 1; + int i1max = (bmax[0] < node->sep[0]) ? 0 : 1; + int i2min = (bmin[1] <= node->sep[1]) ? 0 : 1; + int i2max = (bmax[1] < node->sep[1]) ? 0 : 1; + int i3min = (bmin[2] <= node->sep[2]) ? 0 : 1; + int i3max = (bmax[2] < node->sep[2]) ? 0 : 1; + + int i4min = (bmin[3] <= node->sep[3]) ? 0 : 1; + int i4max = (bmax[3] < node->sep[3]) ? 0 : 1; + int i5min = (bmin[4] <= node->sep[4]) ? 0 : 1; + int i5max = (bmax[4] < node->sep[4]) ? 0 : 1; + int i6min = (bmin[5] <= node->sep[5]) ? 0 : 1; + int i6max = (bmax[5] < node->sep[5]) ? 0 : 1; + + int i1, i2, i3, i4, i5, i6; + for (i1 = i1min; i1 <= i1max; i1++) + for (i2 = i2min; i2 <= i2max; i2++) + for (i3 = i3min; i3 <= i3max; i3++) + for (i4 = i4min; i4 <= i4max; i4++) + for (i5 = i5min; i5 <= i5max; i5++) + for (i6 = i6min; i6 <= i6max; i6++) + { + i = i1 + 2*i2 + 4*i3 + 8*i4 + 16*i5 +32*i6; + if (node->childs[i]) + { + stacks++; + stack.Elem(stacks) = node->childs[i]; + } + } + + /* + if (node->left && bmin[dir] <= node->sep) + { + stacks++; + stack.Elem(stacks) = node->left; + stackdir.Elem(stacks) = ndir; + } + if (node->right && bmax[dir] >= node->sep) + { + stacks++; + stack.Elem(stacks) = node->right; + stackdir.Elem(stacks) = ndir; + } + */ + } + } + + void ADTree6F :: PrintRec (ostream & ost, const ADTreeNode6F * node) const + { + int i; + if (node->data) + { + ost << node->pi << ": "; + ost << node->nchilds << " childs, "; + for (i = 0; i < 6; i++) + ost << node->data[i] << " "; + ost << endl; + } + + for (i = 0; i < 64; i++) + if (node->childs[i]) + PrintRec (ost, node->childs[i]); + } + + + +#endif + + + + /* ************************************* Point3dTree ********************** */ + + + + Point3dTree :: Point3dTree (const Point3d & pmin, const Point3d & pmax) + { + float pmi[3], pma[3]; + for (int i = 0; i < 3; i++) + { + pmi[i] = pmin.X(i+1); + pma[i] = pmax.X(i+1); + } + tree = new ADTree3 (pmi, pma); + } + + Point3dTree :: ~Point3dTree () + { + delete tree; + } + + + + void Point3dTree :: Insert (const Point3d & p, int pi) + { + static float pd[3]; + pd[0] = p.X(); + pd[1] = p.Y(); + pd[2] = p.Z(); + tree->Insert (pd, pi); + } + + void Point3dTree :: GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const + { + float pmi[3], pma[3]; + for (int i = 0; i < 3; i++) + { + pmi[i] = pmin.X(i+1); + pma[i] = pmax.X(i+1); + } + tree->GetIntersecting (pmi, pma, pis); + } + + + + + + + + + + + Box3dTree :: Box3dTree (const Point3d & apmin, const Point3d & apmax) + { + boxpmin = apmin; + boxpmax = apmax; + float tpmin[6], tpmax[6]; + for (int i = 0; i < 3; i++) + { + tpmin[i] = tpmin[i+3] = boxpmin.X(i+1); + tpmax[i] = tpmax[i+3] = boxpmax.X(i+1); + } + tree = new ADTree6 (tpmin, tpmax); + } + + Box3dTree :: ~Box3dTree () + { + delete tree; + } + + void Box3dTree :: Insert (const Point3d & bmin, const Point3d & bmax, int pi) + { + static float tp[6]; + + for (int i = 0; i < 3; i++) + { + tp[i] = bmin.X(i+1); + tp[i+3] = bmax.X(i+1); + } + + tree->Insert (tp, pi); + } + + void Box3dTree ::GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const + { + float tpmin[6]; + float tpmax[6]; + + for (int i = 0; i < 3; i++) + { + tpmin[i] = boxpmin.X(i+1); + tpmax[i] = pmax.X(i+1); + + tpmin[i+3] = pmin.X(i+1); + tpmax[i+3] = boxpmax.X(i+1); + } + + tree->GetIntersecting (tpmin, tpmax, pis); + } + +} diff --git a/contrib/Netgen/libsrc/gprim/adtree.hpp b/contrib/Netgen/libsrc/gprim/adtree.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4cac0f2945d90707dd765cc17e78c707674cd822 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/adtree.hpp @@ -0,0 +1,481 @@ +#ifndef FILE_ADTREE +#define FILE_ADTREE + +/* *************************************************************************/ +/* File: adtree.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 16. Feb. 98 */ +/* Redesigned by Wolfram Muehlhuber, May 1998 */ +/* *************************************************************************/ + + + +/** + Alternating Digital Tree + */ + +#include "../include/mystdlib.h" +#include "../include/myadt.hpp" + +class ADTreeNode +{ +public: + ADTreeNode *left, *right, *father; + int dim; + float sep; + float *data; + float *boxmin; + float *boxmax; + int pi; + int nchilds; + + ADTreeNode (int adim); + ~ADTreeNode (); + + friend class ADTree; +}; + + +class ADTreeCriterion +{ +public: + ADTreeCriterion() { } + virtual int Eval (const ADTreeNode * node) const = 0; +}; + + +class ADTree +{ + int dim; + ADTreeNode * root; + float *cmin, *cmax; + ARRAY<ADTreeNode*> ela; + const ADTreeCriterion * criterion; + + ARRAY<ADTreeNode*> stack; + ARRAY<int> stackdir; + int stackindex; + +public: + ADTree (int adim, const float * acmin, + const float * acmax); + ~ADTree (); + + void Insert (const float * p, int pi); + // void GetIntersecting (const float * bmin, const float * bmax, + // ARRAY<int> & pis) const; + void SetCriterion (ADTreeCriterion & acriterion); + void Reset (); + int Next (); + void GetMatch (ARRAY<int> & matches); + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + + void PrintRec (ostream & ost, const ADTreeNode * node) const; +}; + + + +class ADTreeNode3 +{ +public: + ADTreeNode3 *left, *right, *father; + float sep; + float data[3]; + int pi; + int nchilds; + + ADTreeNode3 (); + void DeleteChilds (); + friend class ADTree3; + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + + +class ADTree3 +{ + ADTreeNode3 * root; + float cmin[3], cmax[3]; + ARRAY<ADTreeNode3*> ela; + +public: + ADTree3 (const float * acmin, + const float * acmax); + ~ADTree3 (); + + void Insert (const float * p, int pi); + void GetIntersecting (const float * bmin, const float * bmax, + ARRAY<int> & pis) const; + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + + void PrintRec (ostream & ost, const ADTreeNode3 * node) const; +}; + + +/* + +// divide each direction +#define ADTN_DIV 10 +class ADTreeNode3Div +{ +public: + ADTreeNode3Div *father; + ADTreeNode3Div *childs[ADTN_DIV]; + + float minx, dist; + float data[3]; + int pi; + int nchilds; + + ADTreeNode3Div (); + void DeleteChilds (); + friend class ADTree3Div; + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + + +class ADTree3Div +{ + ADTreeNode3Div * root; + float cmin[3], cmax[3]; + ARRAY<ADTreeNode3Div*> ela; + +public: + ADTree3Div (const float * acmin, + const float * acmax); + ~ADTree3Div (); + + void Insert (const float * p, int pi); + void GetIntersecting (const float * bmin, const float * bmax, + ARRAY<int> & pis) const; + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + + void PrintRec (ostream & ost, const ADTreeNode3Div * node) const; +}; + + + + +#define ADTN_SIZE 10 + +// multiple entries +class ADTreeNode3M +{ +public: + ADTreeNode3M *left, *right, *father; + float sep; + float data[ADTN_SIZE][3]; + int pi[ADTN_SIZE]; + int nchilds; + + ADTreeNode3M (); + void DeleteChilds (); + friend class ADTree3M; + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + + +class ADTree3M +{ + ADTreeNode3M * root; + float cmin[3], cmax[3]; + ARRAY<ADTreeNode3M*> ela; + +public: + ADTree3M (const float * acmin, + const float * acmax); + ~ADTree3M (); + + void Insert (const float * p, int pi); + void GetIntersecting (const float * bmin, const float * bmax, + ARRAY<int> & pis) const; + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + + void PrintRec (ostream & ost, const ADTreeNode3M * node) const; +}; + + + + + + +class ADTreeNode3F +{ +public: + ADTreeNode3F *father; + ADTreeNode3F *childs[8]; + float sep[3]; + float data[3]; + int pi; + int nchilds; + + ADTreeNode3F (); + void DeleteChilds (); + friend class ADTree3F; + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + +// fat tree +class ADTree3F +{ + ADTreeNode3F * root; + float cmin[3], cmax[3]; + ARRAY<ADTreeNode3F*> ela; + +public: + ADTree3F (const float * acmin, + const float * acmax); + ~ADTree3F (); + + void Insert (const float * p, int pi); + void GetIntersecting (const float * bmin, const float * bmax, + ARRAY<int> & pis) const; + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + + void PrintRec (ostream & ost, const ADTreeNode3F * node) const; +}; + + + + +class ADTreeNode3FM +{ +public: + ADTreeNode3FM *father; + ADTreeNode3FM *childs[8]; + float sep[3]; + float data[ADTN_SIZE][3]; + int pi[ADTN_SIZE]; + int nchilds; + + ADTreeNode3FM (); + void DeleteChilds (); + friend class ADTree3FM; + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + +// fat tree +class ADTree3FM +{ + ADTreeNode3FM * root; + float cmin[3], cmax[3]; + ARRAY<ADTreeNode3FM*> ela; + +public: + ADTree3FM (const float * acmin, + const float * acmax); + ~ADTree3FM (); + + void Insert (const float * p, int pi); + void GetIntersecting (const float * bmin, const float * bmax, + ARRAY<int> & pis) const; + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + + void PrintRec (ostream & ost, const ADTreeNode3FM * node) const; +}; + + + +*/ + + + + + +class ADTreeNode6 +{ +public: + ADTreeNode6 *left, *right, *father; + float sep; + float data[6]; + int pi; + int nchilds; + + ADTreeNode6 (); + void DeleteChilds (); + friend class ADTree6; + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + + +class ADTree6 +{ + ADTreeNode6 * root; + float cmin[6], cmax[6]; + ARRAY<ADTreeNode6*> ela; + +public: + ADTree6 (const float * acmin, + const float * acmax); + ~ADTree6 (); + + void Insert (const float * p, int pi); + void GetIntersecting (const float * bmin, const float * bmax, + ARRAY<int> & pis) const; + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + int Depth () const + { return DepthRec (root); } + int Elements () const + { return ElementsRec (root); } + + void PrintRec (ostream & ost, const ADTreeNode6 * node) const; + int DepthRec (const ADTreeNode6 * node) const; + int ElementsRec (const ADTreeNode6 * node) const; + + void PrintMemInfo (ostream & ost) const; +}; + + + + +/* + +class ADTreeNode6F +{ +public: + ADTreeNode6F * father; + ADTreeNode6F * childs[64]; + + float sep[6]; + float data[6]; + int pi; + int nchilds; + + ADTreeNode6F (); + void DeleteChilds (); + friend class ADTree6F; + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + + +class ADTree6F +{ + ADTreeNode6F * root; + float cmin[6], cmax[6]; + ARRAY<ADTreeNode6F*> ela; + +public: + ADTree6F (const float * acmin, + const float * acmax); + ~ADTree6F (); + + void Insert (const float * p, int pi); + void GetIntersecting (const float * bmin, const float * bmax, + ARRAY<int> & pis) const; + + void DeleteElement (int pi); + + + void Print (ostream & ost) const + { PrintRec (ost, root); } + int Depth () const + { return DepthRec (root); } + + void PrintRec (ostream & ost, const ADTreeNode6F * node) const; + int DepthRec (const ADTreeNode6F * node) const; +}; + + + + + + + +*/ + + + + + +class Point3dTree +{ + ADTree3 * tree; + +public: + Point3dTree (const Point3d & pmin, const Point3d & pmax); + ~Point3dTree (); + void Insert (const Point3d & p, int pi); + void DeleteElement (int pi) + { tree->DeleteElement(pi); } + void GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const; + const ADTree3 & Tree() const { return *tree; }; +}; + + + +class Box3dTree +{ + ADTree6 * tree; + Point3d boxpmin, boxpmax; +public: + Box3dTree (const Point3d & apmin, const Point3d & apmax); + ~Box3dTree (); + void Insert (const Point3d & bmin, const Point3d & bmax, int pi); + void Insert (const Box<3> & box, int pi) + { + Insert (box.PMin(), box.PMax(), pi); + } + void DeleteElement (int pi) + { tree->DeleteElement(pi); } + void GetIntersecting (const Point3d & pmin, const Point3d & pmax, + ARRAY<int> & pis) const; + + const ADTree6 & Tree() const { return *tree; }; +}; +#endif diff --git a/contrib/Netgen/libsrc/gprim/geom2d.cpp b/contrib/Netgen/libsrc/gprim/geom2d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34263348cc327ba2a652e6d7ec6c44c5af96018f --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom2d.cpp @@ -0,0 +1,489 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +namespace netgen +{ + +ostream & operator<<(ostream & s, const Point2d & p) +{ + return s << "(" << p.px << ", " << p.py << ")"; +} + +ostream & operator<<(ostream & s, const Vec2d & v) +{ + return s << "(" << v.vx << ", " << v.vy << ")"; +} + +#ifdef none +ostream & operator<<(ostream & s, const Line2d & l) + { + return s << l.p1 << "-" << l.p2; +} + +ostream & operator<<(ostream & s, const TRIANGLE2D & t) +{ + return s << t.p1 << "-" << t.p2 << "-" << t.p3; +} +#endif + + +double Fastatan2 (double x, double y) +{ + if (y > 0) + { + if (x > 0) + return y / (x+y); + else + return 1 - x / (y-x); + } + else if (y < 0) + { + if (x < 0) + return 2 + y / (x+y); + else + return 3 - x / (y-x); + } + else + { + if (x >= 0) + return 0; + else + return 2; + } +} + + +double Angle (const Vec2d & v) +{ + if (v.X() == 0 && v.Y() == 0) + return 0; + + double ang = atan2 (v.Y(), v.X()); + if (ang < 0) ang+= 2 * M_PI; + return ang; +} + +double FastAngle (const Vec2d & v) +{ + return Fastatan2 (v.X(), v.Y()); +} + +double Angle (const Vec2d & v1, const Vec2d & v2) +{ + double ang = Angle(v2) - Angle(v1); + if (ang < 0) ang += 2 * M_PI; + return ang; +} + +double FastAngle (const Vec2d & v1, const Vec2d & v2) +{ + double ang = FastAngle(v2) - FastAngle(v1); + if (ang < 0) ang += 4; + return ang; +} + +/* +int CW (const Point2d & p1,const Point2d & p2,const Point2d & p3) +{ + return Cross (p2 - p1, p3 - p2) < 0; +} + +int CCW (const Point2d & p1,const Point2d & p2,const Point2d & p3) +{ + return Cross (p2 - p1, p3 - p2) > 0; +} +*/ + +double Dist2(const Line2d & g, const Line2d & h ) + { + double dd = 0.0, d1,d2,d3,d4; + Point2d cp = CrossPoint(g,h); + + if ( Parallel(g,h) || !IsOnLine(g,cp) || !IsOnLine(h,cp) ) + { + d1 = Dist2(g.P1(),h.P1()); + d2 = Dist2(g.P1(),h.P2()); + d3 = Dist2(g.P2(),h.P1()); + d4 = Dist2(g.P2(),h.P2()); + if (d1<d2) d2 = d1; + if (d3<d4) d4 = d3; + dd = ( d2 < d4 ) ? d2 : d4; + } + return dd; +} + + +Point2d CrossPoint (const Line2d & l1, const Line2d & l2) + { + double den = Cross (l1.Delta(), l2.Delta()); + double num = Cross ( (l2.P1() - l1.P1()), l2.Delta()); + + if (den == 0) + return l1.P1(); + else + return l1.P1() + (num/den) * l1.Delta(); +} + + +int CrossPointBarycentric (const Line2d & l1, const Line2d & l2, + double & lam1, double & lam2) +{ + // p = l1.1 + lam1 (l1.2-l1.1) = l2.1 + lam2 (l2.2-l2.1) + double a11 = l1.p2.X() - l1.p1.X(); + double a21 = l1.p2.Y() - l1.p1.Y(); + double a12 = -(l2.p2.X() - l2.p1.X()); + double a22 = -(l2.p2.Y() - l2.p1.Y()); + + double b1 = l2.p1.X() - l1.p1.X(); + double b2 = l2.p1.Y() - l1.p1.Y(); + + double det = a11*a22 - a12 * a21; + if (det == 0) + return 1; + + lam1 = (a22 * b1 - a12 * b2) / det; + lam2 = (a11 * b2 - a21 * b1) / det; + return 0; +} + + + + +int Parallel (const Line2d & l1, const Line2d & l2, double peps) + { + double p = fabs (Cross (l1.Delta(), l2.Delta())); + // (*mycout) << endl << p << " " << l1.Length() << " " << l2.Length() << endl; + return p <= peps * l1.Length() * l2.Length(); +} + +int IsOnLine (const Line2d & l, const Point2d & p, double heps) + { + double c1 = (p - l.P1()) * l.Delta(); + double c2 = (p - l.P2()) * l.Delta(); + double d = fabs (Cross ( (p - l.P1()), l.Delta())); + double len2 = l.Length2(); + + return c1 >= -heps * len2 && c2 <= heps * len2 && d <= heps * len2; +} + +#ifdef none +int IsOnLine (const PLine2d & l, const Point2d & p, double heps) + { + double c1 = (p - l.P1()) * l.Delta(); + double c2 = (p - l.P2()) * l.Delta(); + double d = fabs (Cross ( (p - l.P1()), l.Delta())); + double len2 = l.Length2(); + + return c1 >= -heps * len2 && c2 <= heps * len2 && d <= heps * len2; +} + +int IsOnLongLine (const Line2d & l, const Point2d & p) + { + double d = fabs (Cross ( (p - l.P1()), l.Delta())); + return d <= EPSGEOM * l.Length(); +} + +int Hit (const Line2d & l1, const Line2d & l2, double heps) + { + double den = Cross ( (l1.P2() - l1.P1()), (l2.P1() - l2.P2())); + double num1 = Cross ( (l2.P1() - l1.P1()), (l2.P1() - l2.P2())); + double num2 = Cross ( (l1.P2() - l1.P1()), (l2.P1() - l1.P1())); + num1 *= sgn (den); + num2 *= sgn (den); + den = fabs (den); + + int ch = (-den * heps <= num1 && num1 <= den * (1 + heps) && + -den * heps <= num2 && num2 <= den * (1 + heps)); + return ch; +} + + +void Line2d :: GetNormal (Line2d & n) const +{ + double ax = P2().X()-P1().X(), + ay = P2().Y()-P1().Y(); + Point2d mid(P1().X()+.5*ax, P1().Y()+.5*ay); + + n=Line2d(mid,Point2d(mid.X()+ay,mid.Y()-ax)) ; +} + +Vec2d Line2d :: NormalDelta () const +{ + Line2d tmp; + GetNormal(tmp); + return tmp.Delta(); +} + +int TRIANGLE2D :: IsOn (const Point2d & p) const + { + return IsOnLine (Line2d (p1, p2), p) || + IsOnLine (Line2d (p1, p3), p) || + IsOnLine (Line2d (p2, p3), p); + } + + +int TRIANGLE2D :: IsIn (const Point2d & p) const +{ + return ::CW(p, p1, p2) == ::CW(p, p2, p3) && + ::CW(p, p1, p2) == ::CW(p, p3, p1); +} + + + +int PTRIANGLE2D :: IsOn (const Point2d & p) const +{ + return IsOnLine (Line2d (*p1, *p2), p) || + IsOnLine (Line2d (*p1, *p3), p) || + IsOnLine (Line2d (*p2, *p3), p); +} + + +int PTRIANGLE2D :: IsIn (const Point2d & p) const +{ + return ::CW(p, *p1, *p2) == ::CW(p, *p2, *p3) && + ::CW(p, *p1, *p2) == ::CW(p, *p3, *p1); +} + +#endif + + + + + + +Polygon2d :: Polygon2d () +{ + ; +} + +Polygon2d :: ~Polygon2d () +{ + ; +} + +void Polygon2d :: AddPoint (const Point2d & p) +{ + points.Append(p); +} + + +double Polygon2d :: HArea () const +{ + int i; + double ar = 0; + for (i = 1; i <= points.Size(); i++) + { + const Point2d & p1 = points.Get(i); + const Point2d & p2 = points.Get(i%points.Size()+1); + ar += + (p2.X()-p1.X()) * p1.Y() - + (p2.Y()-p1.Y()) * p1.X(); + } + return ar/2; + /* + CURSOR c; + double ar = 0; + Point2d * p1, * p2, p0 = Point2d(0, 0); + Vec2d v1, v2 = Vec2d(1, 0); + + p2 = points[points.Last()]; + for (c = points.First(); c != points.Head(); c++) + { + p1 = p2; + p2 = points[c]; + ar += Cross ( (*p2-*p1), (*p1 - p0)); + } + return ar / 2; + */ +} + + +int Polygon2d :: IsOn (const Point2d & p) const +{ + int i; + for (i = 1; i <= points.Size(); i++) + { + const Point2d & p1 = points.Get(i); + const Point2d & p2 = points.Get(i%points.Size()+1); + if (IsOnLine (Line2d(p1, p2), p)) return 1; + } + return 0; + /* + CURSOR c; + Point2d * p1, * p2; + + p2 = points[points.Last()]; + for (c = points.First(); c != points.Head(); c++) + { + p1 = p2; + p2 = points[c]; + if (IsOnLine (Line2d(*p1, *p2), p)) return 1; + } + return 0; + */ +} + + +int Polygon2d :: IsIn (const Point2d & p) const +{ + int i; + double sum = 0, ang; + for (i = 1; i <= points.Size(); i++) + { + const Point2d & p1 = points.Get(i); + const Point2d & p2 = points.Get(i%points.Size()+1); + ang = Angle ( (p1 - p), (p2 - p) ); + if (ang > M_PI) ang -= 2 * M_PI; + sum += ang; + } + return fabs(sum) > M_PI; + /* + CURSOR c; + Point2d * p1, * p2; + double sum = 0, ang; + + p2 = points[points.Last()]; + for (c = points.First(); c != points.Head(); c++) + { + p1 = p2; + p2 = points[c]; + ang = Angle ( (*p1 - p), (*p2 - p) ); + if (ang > M_PI) ang -= 2 * M_PI; + sum += ang; + } + + return fabs(sum) > M_PI; + */ +} + +int Polygon2d :: IsConvex () const + { + /* + Point2d *p, *pold, *pnew; + char cw; + CURSOR c; + + if (points.Length() < 3) return 0; + + c = points.Last(); + p = points[c]; + c--; + pold = points[c]; + pnew = points[points.First()]; + cw = ::CW (*pold, *p, *pnew); + + for (c = points.First(); c != points.Head(); c++) + { + pnew = points[c]; + if (cw != ::CW (*pold, *p, *pnew)) + return 0; + pold = p; + p = pnew; + } + */ + return 0; + } + + +int Polygon2d :: IsStarPoint (const Point2d & p) const + { + /* + Point2d *pnew, *pold; + char cw; + CURSOR c; + + if (points.Length() < 3) return 0; + + pold = points[points.Last()]; + pnew = points[points.First()]; + + cw = ::CW (p, *pold, *pnew); + + for (c = points.First(); c != points.Head(); c++) + { + pnew = points[c]; + if (cw != ::CW (p, *pold, *pnew)) + return 0; + pold = pnew; + } + return 1; + */ + return 0; + } + + +Point2d Polygon2d :: Center () const + { + /* + double ai, a = 0, x = 0, y = 0; + Point2d * p, *p2; + Point2d p0 = Point2d(0, 0); + CURSOR c; + + p2 = points[points.Last()]; + + for (c = points.First(); c != points.Head(); c++) + { + p = points[c]; + ai = Cross (*p2 - p0, *p - p0); + x += ai / 3 * (p2->X() + p->X()); + y += ai / 3 * (p2->Y() + p->Y()); + a+= ai; + p2 = p; + } + if (a != 0) + return Point2d (x / a, y / a); + else + return Point2d (0, 0); + */ + return Point2d (0, 0); + } + + + +Point2d Polygon2d :: EqualAreaPoint () const + { + /* + double a11 = 0, a12 = 0, a21= 0, a22 = 0; + double b1 = 0, b2 = 0, dx, dy; + double det; + Point2d * p, *p2; + CURSOR c; + + p = points[points.Last()]; + + for (c = points.First(); c != points.Head(); c++) + { + p2 = p; + p = points[c]; + + dx = p->X() - p2->X(); + dy = p->Y() - p2->Y(); + + a11 += sqr (dy); + a12 -= dx * dy; + a21 -= dx * dy; + a22 += sqr (dx); + b1 -= dy * (p->X() * p2->Y() - p2->X() * p->Y()); + b2 -= dx * (p->Y() * p2->X() - p2->Y() * p->X()); + } + + det = a11 * a22 - a21 * a12; + + if (det != 0) + return Point2d ( (b1 * a22 - b2 * a12) / det, + (a11 * b2 - a21 * b1) / det); + else + return Point2d (0, 0); +*/ + return Point2d (0, 0); + } + + +} diff --git a/contrib/Netgen/libsrc/gprim/geom2d.hpp b/contrib/Netgen/libsrc/gprim/geom2d.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0c4c616fac8686b8d54b9d79cb81f5778124cf01 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom2d.hpp @@ -0,0 +1,883 @@ +#ifndef FILE_GEOM2D +#define FILE_GEOM2D + +/* *************************************************************************/ +/* File: geom2d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 5. Aug. 95 */ +/* *************************************************************************/ + + + +/* Geometric Algorithms */ + +#define EPSGEOM 1E-5 + + +// extern void MyError (const char * ch); + +class Point2d; +class Vec2d; + +class LINE2D; +class Line2d; +class PLine2d; +class TRIANGLE2D; +class PTRIANGLE2D; + + +inline Vec2d operator- (const Point2d & p1, const Point2d & p2); +inline Point2d operator- (const Point2d & p1, const Vec2d & v); +inline Point2d operator+ (const Point2d & p1, const Vec2d & v); +inline Point2d Center (const Point2d & p1, const Point2d & p2); + +inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2); +inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v); +ostream & operator<<(ostream & s, const Point2d & p); +inline Vec2d operator- (const Point2d & p1, const Point2d & p2); +inline Point2d operator- (const Point2d & p1, const Vec2d & v); +inline Point2d operator+ (const Point2d & p1, const Vec2d & v); +inline Vec2d operator- (const Vec2d & p1, const Vec2d & v); +inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v); +inline Vec2d operator* (double scal, const Vec2d & v); +double Angle (const Vec2d & v); +double FastAngle (const Vec2d & v); +double Angle (const Vec2d & v1, const Vec2d & v2); +double FastAngle (const Vec2d & v1, const Vec2d & v2); +ostream & operator<<(ostream & s, const Vec2d & v); +double Dist2(const Line2d & g, const Line2d & h ); // GH +int Near (const Point2d & p1, const Point2d & p2, const double eps); + +int Parallel (const Line2d & l1, const Line2d & l2, double peps = EPSGEOM); +int IsOnLine (const Line2d & l, const Point2d & p, double heps = EPSGEOM); +int IsOnLongLine (const Line2d & l, const Point2d & p); +int Hit (const Line2d & l1, const Line2d & l2, double heps = EPSGEOM); +ostream & operator<<(ostream & s, const Line2d & l); +Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2); +int Parallel (const PLine2d & l1, const PLine2d & l2, double peps = EPSGEOM); +int IsOnLine (const PLine2d & l, const Point2d & p, double heps = EPSGEOM); +int IsOnLongLine (const PLine2d & l, const Point2d & p); +int Hit (const PLine2d & l1, const Line2d & l2, double heps = EPSGEOM); +ostream & operator<<(ostream & s, const Line2d & l); +ostream & operator<<(ostream & s, const TRIANGLE2D & t); +ostream & operator<<(ostream & s, const PTRIANGLE2D & t); + +/// +class Point2d +{ + /// + friend class Vec2d; + +protected: + /// + double px, py; + +public: + /// + Point2d() { /* px = py = 0; */ } + /// + Point2d(double ax, double ay) { px = ax; py = ay; } + /// + Point2d(const Point2d & p2) { px = p2.px; py = p2.py; } + + Point2d (const Point<2> & p2) + { + px = p2(0); + py = p2(1); + } + /// + Point2d & operator= (const Point2d & p2) + { px = p2.px; py = p2.py; return *this; } + + /// + int operator== (const Point2d & p2) const // GH + { return (px == p2.px && py == p2.py) ; } + + /// + double & X() { return px; } + /// + double & Y() { return py; } + /// + double X() const { return px; } + /// + double Y() const { return py; } + + operator Point<2> () const + { + return Point<2> (px, py); + } + + + /// + friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2); + /// + friend inline Point2d operator- (const Point2d & p1, const Vec2d & v); + /// + friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v); + + /// + friend inline Point2d Center (const Point2d & p1, const Point2d & p2); + + const Point2d & SetToMin (const Point2d & p2) + { + if (p2.px < px) px = p2.px; + if (p2.py < py) py = p2.py; + return *this; + } + + + /// + const Point2d & SetToMax (const Point2d & p2) + { + if (p2.px > px) px = p2.px; + if (p2.py > py) py = p2.py; + return *this; + } + + /// + friend double Dist (const Point2d & p1, const Point2d & p2) + { return sqrt ( (p1.px - p2.px) * (p1.px - p2.px) + + (p1.py - p2.py) * (p1.py - p2.py) ); } + // { return sqrt ( sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ); } + + /// + friend double Dist2 (const Point2d & p1, const Point2d & p2) + { return ( (p1.px - p2.px) * (p1.px - p2.px) + + (p1.py - p2.py) * (p1.py - p2.py) ); } + // { return sqr (p1.X()-p2.X()) + sqr (p1.Y()-p2.Y()) ; } + + + /** + Points clock-wise ? + Are the points (p1, p2, p3) clock-wise ? + */ + friend inline int CW (const Point2d & p1, const Point2d & p2, const Point2d & p3) + { + // return Cross (p2 - p1, p3 - p2) < 0; + return + (p2.px - p1.px) * (p3.py - p2.py) - + (p2.py - p1.py) * (p3.px - p2.px) < 0; + } + /** + Points counter-clock-wise ? + Are the points (p1, p2, p3) counter-clock-wise ? + */ + friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3) + { + // return Cross (p2 - p1, p3 - p2) > 0; + return + (p2.px - p1.px) * (p3.py - p2.py) - + (p2.py - p1.py) * (p3.px - p2.px) > 0; + } /** + Points counter-clock-wise ? + Are the points (p1, p2, p3) counter-clock-wise ? + */ + friend inline bool CCW (const Point2d & p1, const Point2d & p2, const Point2d & p3, double eps) + { + // return Cross (p2 - p1, p3 - p2) > 0; + double ax = p2.px - p1.px; + double ay = p2.py - p1.py; + double bx = p3.px - p2.px; + double by = p3.py - p2.py; + + return ax*by - ay*bx > eps*eps*max2(ax*ax+ay*ay,bx*bx+by*by); + } + + /// + friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2); + /// + friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v); + + /// + friend ostream & operator<<(ostream & s, const Point2d & p); +}; + + +inline int Near (const Point2d & p1, const Point2d & p2, + const double eps = 1e-4 ) +{ + return Dist2(p1,p2) <= eps*eps; +} + + + + + + +/// +class Vec2d + { +protected: + /// + double vx, vy; + +public: + /// + Vec2d() { /* vx = vy = 0; */ } + /// + Vec2d(double ax, double ay) + { vx = ax; vy = ay; } + /// + Vec2d(const Vec2d & v2) { vx = v2.vx; vy = v2.vy; } + + /// + explicit Vec2d(const Vec<2> & v2) { vx = v2(0); vy = v2(1); } + + /// + Vec2d(const Point2d & p1, const Point2d & p2) + { vx = p2.px - p1.px; vy = p2.py - p1.py; } + + /// + Vec2d & operator= (const Vec2d & p2) + { vx = p2.vx; vy = p2.vy; return *this; } + + /// + double & X() { return vx; } + /// + double & Y() { return vy; } + /// + double X() const { return vx; } + /// + double Y() const { return vy; } + + /// + double Length() const { return sqrt (vx * vx + vy * vy); } + /// + double Length2() const { return vx * vx + vy * vy; } + + void GetNormal (Vec2d & n) const { n.vx=-vy; n.vy=vx; } // GH + + /// + inline Vec2d & operator+= (const Vec2d & v2); + /// + inline Vec2d & operator-= (const Vec2d & v2); + /// + inline Vec2d & operator*= (double s); + /// + inline Vec2d & operator/= (double s); + + /// + friend inline Vec2d operator- (const Point2d & p1, const Point2d & p2); + /// + friend inline Point2d operator- (const Point2d & p1, const Vec2d & v); + /// + friend inline Point2d operator+ (const Point2d & p1, const Vec2d & v); + /// + friend inline Vec2d operator- (const Vec2d & p1, const Vec2d & v); + /// + friend inline Vec2d operator+ (const Vec2d & p1, const Vec2d & v); + /// + friend inline Vec2d operator* (double scal, const Vec2d & v); + + /// + friend double operator* (const Vec2d & v1, const Vec2d & v2) + { return v1.X() * v2.X() + v1.Y() * v2.Y(); } + + + /// + friend double Cross (const Vec2d & v1, const Vec2d & v2) + { return double(v1.X()) * double(v2.Y()) - + double(v1.Y()) * double(v2.X()); } + + /// + friend inline void PpSmV (const Point2d & p1, double s, const Vec2d & v, Point2d & p2); + /// + friend inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v); + +/// Angle in [0,2*PI) + + /// + friend double Angle (const Vec2d & v); + /// + friend double FastAngle (const Vec2d & v); + /// + friend double Angle (const Vec2d & v1, const Vec2d & v2); + /// + friend double FastAngle (const Vec2d & v1, const Vec2d & v2); + + /// + friend ostream & operator<<(ostream & s, const Vec2d & v); + }; + + + +/// +class Line2d + { +protected: + /// + Point2d p1, p2; + +public: + /// + Line2d() : p1(), p2() { }; + /// + Line2d(const Point2d & ap1, const Point2d & ap2) + { p1 = ap1; p2 = ap2; } + + /// + Line2d & operator= (const Line2d & l2) + { p1 = l2.p1; p2 = l2.p2; return *this;} + + /// + Point2d & P1() { return p1; } + /// + Point2d & P2() { return p2; } + /// + const Point2d & P1() const { return p1; } + /// + const Point2d & P2() const { return p2; } + + /// + double XMax() const { return max2 (p1.X(), p2.X()); } + /// + double YMax() const { return max2 (p1.Y(), p2.Y()); } + /// + double XMin() const { return min2 (p1.X(), p2.X()); } + /// + double YMin() const { return min2 (p1.Y(), p2.Y()); } + + /// + Vec2d Delta () const { return Vec2d (p2.X()-p1.X(), p2.Y()-p1.Y()); } + /// + double Length () const { return Delta().Length(); } + /// + double Length2 () const + { return sqr (p1.X() - p2.X()) + + sqr (p1.Y() - p2.Y()); } + + void GetNormal (Line2d & n) const; // GH + Vec2d NormalDelta () const; // GH + + /// square of the distance between two 2d-lines. + friend double Dist2(const Line2d & g, const Line2d & h ); // GH + + /// + friend Point2d CrossPoint (const Line2d & l1, const Line2d & l2); + /// returns 1 iff parallel + friend int CrossPointBarycentric (const Line2d & l1, const Line2d & l2, + double & lam1, double & lam2); + + /// + friend int Parallel (const Line2d & l1, const Line2d & l2, double peps); + /// + friend int IsOnLine (const Line2d & l, const Point2d & p, double heps); + /// + friend int IsOnLongLine (const Line2d & l, const Point2d & p); + /// + friend int Hit (const Line2d & l1, const Line2d & l2, double heps); + + /// + friend ostream & operator<<(ostream & s, const Line2d & l); + }; + + +#ifdef NONE +/// +class PLine2d + { +protected: + /// + Point2d const * p1, *p2; + +public: + /// + PLine2d() { }; + /// + PLine2d(Point2d const * ap1, Point2d const * ap2) + { p1 = ap1; p2 = ap2; } + + /// + PLine2d & operator= (const PLine2d & l2) + { p1 = l2.p1; p2 = l2.p2; return *this;} + + /// + const Point2d *& P1() { return p1; } + /// + const Point2d *& P2() { return p2; } + /// + const Point2d & P1() const { return *p1; } + /// + const Point2d & P2() const { return *p2; } + + /// + double XMax() const { return max2 (p1->X(), p2->X()); } + /// + double YMax() const { return max2 (p1->Y(), p2->Y()); } + /// + double XMin() const { return min2 (p1->X(), p2->X()); } + /// + double YMin() const { return min2 (p1->Y(), p2->Y()); } + + + /// + Vec2d Delta () const { return Vec2d (p2->X()-p1->X(), p2->Y()-p1->Y()); } + /// + double Length () const { return Delta().Length(); } + /// + double Length2 () const + { return sqr (p1->X() - p2->X()) + + sqr (p1->Y() - p2->Y()); } + + + + /// + friend Point2d CrossPoint (const PLine2d & l1, const PLine2d & l2); + /// + friend int Parallel (const PLine2d & l1, const PLine2d & l2, double peps); + /// + friend int IsOnLine (const PLine2d & l, const Point2d & p, double heps); + /// + friend int IsOnLongLine (const PLine2d & l, const Point2d & p); + /// + friend int Hit (const PLine2d & l1, const Line2d & l2, double heps); + + /// + friend ostream & operator<<(ostream & s, const Line2d & l); + }; + + + +/// +class ILINE + { + /// + INDEX i[2]; + + public: + /// + ILINE() {}; + /// + ILINE(INDEX i1, INDEX i2) { i[0] = i1; i[1] = i2; } + /// + ILINE(const ILINE & l) { i[0] = l.i[0]; i[1] = l.i[1]; } + + /// + ILINE & operator= (const ILINE & l) + { i[0] = l.i[0]; i[1] = l.i[1]; return *this; } + + /// + const INDEX & I(int ai) const { return i[ai-1]; } + /// + const INDEX & X() const { return i[0]; } + /// + const INDEX & Y() const { return i[1]; } + /// + const INDEX & I1() const { return i[0]; } + /// + const INDEX & I2() const { return i[1]; } + + /// + INDEX & I(int ai) { return i[ai-1]; } + /// + INDEX & X() { return i[0]; } + /// + INDEX & Y() { return i[1]; } + /// + INDEX & I1() { return i[0]; } + /// + INDEX & I2() { return i[1]; } + }; + + + + +/// +class TRIANGLE2D + { +private: + /// + Point2d p1, p2, p3; + +public: + /// + TRIANGLE2D() { }; + /// + TRIANGLE2D (const Point2d & ap1, const Point2d & ap2, + const Point2d & ap3) + { p1 = ap1; p2 = ap2; p3 = ap3;} + + /// + TRIANGLE2D & operator= (const TRIANGLE2D & t2) + { p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; } + + /// + Point2d & P1() { return p1; } + /// + Point2d & P2() { return p2; } + /// + Point2d & P3() { return p3; } + /// + const Point2d & P1() const { return p1; } + /// + const Point2d & P2() const { return p2; } + /// + const Point2d & P3() const { return p3; } + + /// + double XMax() const { return max3 (p1.X(), p2.X(), p3.X()); } + /// + double YMax() const { return max3 (p1.Y(), p2.Y(), p3.Y()); } + /// + double XMin() const { return min3 (p1.X(), p2.X(), p3.X()); } + /// + double YMin() const { return min3 (p1.Y(), p2.Y(), p3.Y()); } + + /// + inline Point2d Center () const + { return Point2d( (p1.X()+p2.X()+p3.X())/3, (p1.Y()+p2.Y()+p3.Y())/3); } + + /// + int Regular() const; + /// + int CW () const; + /// + int CCW () const; + + /// + int IsOn (const Point2d & p) const; + /// + int IsIn (const Point2d & p) const; + /// + friend ostream & operator<<(ostream & s, const TRIANGLE2D & t); + }; + + +/// +class PTRIANGLE2D + { +private: + /// + Point2d const *p1, *p2, *p3; + +public: + /// + PTRIANGLE2D() { }; + /// + PTRIANGLE2D (const Point2d * ap1, const Point2d * ap2, + const Point2d * ap3) + { p1 = ap1; p2 = ap2; p3 = ap3;} + + /// + PTRIANGLE2D & operator= (const PTRIANGLE2D & t2) + { p1 = t2.p1; p2 = t2.p2; p3 = t2.p3; return *this; } + + /// + const Point2d *& P1() { return p1; } + /// + const Point2d *& P2() { return p2; } + /// + const Point2d *& P3() { return p3; } + /// + const Point2d * P1() const { return p1; } + /// + const Point2d * P2() const { return p2; } + /// + const Point2d * P3() const { return p3; } + + /// + double XMax() const { return max3 (p1->X(), p2->X(), p3->X()); } + /// + double YMax() const { return max3 (p1->Y(), p2->Y(), p3->Y()); } + /// + double XMin() const { return min3 (p1->X(), p2->X(), p3->X()); } + /// + double YMin() const { return min3 (p1->Y(), p2->Y(), p3->Y()); } + + /// + Point2d Center () const + { return Point2d( (p1->X()+p2->X()+p3->X())/3, (p1->Y()+p2->Y()+p3->Y())/3); } + + + /// + int Regular() const; + /// + int CW () const; + /// + int CCW () const; + + /// + int IsOn (const Point2d & p) const; + /// + int IsIn (const Point2d & p) const; + /// + friend ostream & operator<<(ostream & s, const PTRIANGLE2D & t); + }; +#endif + + + +class Polygon2d +{ +protected: + ARRAY<Point2d> points; + +public: + Polygon2d (); + ~Polygon2d (); + + void AddPoint (const Point2d & p); + int GetNP() const { return points.Size(); } + void GetPoint (int i, Point2d & p) const + { p = points.Get(i); } + void GetLine (int i, Point2d & p1, Point2d & p2) const + { p1 = points.Get(i); p2 = points.Get(i%points.Size()+1); } + + double Area () const { return fabs (HArea()); } + int CW () const { return HArea() > 0; } + int CCW () const { return HArea() < 0; } + + int IsOn (const Point2d & p) const; + int IsIn (const Point2d & p) const; + + int IsConvex () const; + + int IsStarPoint (const Point2d & p) const; + Point2d Center() const; + Point2d EqualAreaPoint () const; +private: + double HArea () const; +}; + + +/** Cheap approximation to atan2. + A monotone function of atan2(x,y) is computed. + */ +extern double Fastatan2 (double x, double y); + + +inline Vec2d & Vec2d :: operator+= (const Vec2d & v2) + { + vx += v2.vx; + vy += v2.vy; + return *this; + } + +inline Vec2d & Vec2d :: operator-= (const Vec2d & v2) + { + vx -= v2.vx; + vy -= v2.vy; + return *this; + } + +inline Vec2d & Vec2d :: operator*= (double s) + { + vx *= s; + vy *= s; + return *this; + } + + +inline Vec2d & Vec2d :: operator/= (double s) +{ + if (s != 0) + { + vx /= s; + vy /= s; + } + else + { + MyError ("Vec2d::operator /=: Division by zero"); + } + return *this; +} + + + +inline Vec2d operator- (const Point2d & p1, const Point2d & p2) + { + return Vec2d (p1.X() - p2.X(), p1.Y() - p2.Y()); + } + + +inline Point2d operator- (const Point2d & p1, const Vec2d & v) + { + return Point2d (p1.X() - v.X(), p1.Y() - v.Y()); + } + + +inline Point2d operator+ (const Point2d & p1, const Vec2d & v) + { + return Point2d (p1.X() + v.X(), p1.Y() + v.Y()); + } + + +inline Point2d Center (const Point2d & p1, const Point2d & p2) + { + return Point2d ((p1.X() + p2.X()) / 2, (p1.Y() + p2.Y()) / 2); + } + + +inline Vec2d operator- (const Vec2d & v1, const Vec2d & v2) + { + return Vec2d (v1.X() - v2.X(), v1.Y() - v2.Y()); + } + + +inline Vec2d operator+ (const Vec2d & v1, const Vec2d & v2) + { + return Vec2d (v1.X() + v2.X(), v1.Y() + v2.Y()); + } + + +inline Vec2d operator* (double scal, const Vec2d & v) + { + return Vec2d (scal * v.X(), scal * v.Y()); + } + + +inline void PpSmV (const Point2d & p1, double s, + const Vec2d & v, Point2d & p2) + { + p2.X() = p1.X() + s * v.X(); + p2.Y() = p1.Y() + s * v.Y(); + } + + +inline void PmP (const Point2d & p1, const Point2d & p2, Vec2d & v) + { + v.X() = p1.X() - p2.X(); + v.Y() = p1.Y() - p2.Y(); + } + + + + + +#ifdef none +inline int TRIANGLE2D :: Regular() const + { + return fabs(Cross ( p2 - p1, p3 - p2)) > EPSGEOM; + } + + +inline int TRIANGLE2D :: CW () const + { + return Cross ( p2 - p1, p3 - p2) < 0; + } + + +inline int TRIANGLE2D :: CCW () const + { + return Cross ( p2 - p1, p3 - p2) > 0; + } + + + + +inline int PTRIANGLE2D :: Regular() const + { + return fabs(Cross ( *p2 - *p1, *p3 - *p2)) > EPSGEOM; + } + + +inline int PTRIANGLE2D :: CW () const + { + return Cross ( *p2 - *p1, *p3 - *p2) < 0; + } + + +inline int PTRIANGLE2D :: CCW () const + { + return Cross ( *p2 - *p1, *p3 - *p2) > 0; + } + + +#endif + + +/// +class Mat2d +{ +protected: + /// + double coeff[4]; + +public: + /// + Mat2d() { coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0; } + /// + Mat2d(double a11, double a12, double a21, double a22) + { coeff[0] = a11; coeff[1] = a12; coeff[2] = a21; coeff[3] = a22; } + /// + Mat2d(const Mat2d & m2) + { for (int i = 0; i < 4; i++) coeff[i] = m2.Get(i); } + + /// + double & Elem (INDEX i, INDEX j) { return coeff[2*(i-1)+j-1]; } + /// + double & Elem (INDEX i) {return coeff[i]; } + /// + double Get (INDEX i, INDEX j) const { return coeff[2*(i-1)+j-1]; } + /// + double Get (INDEX i) const {return coeff[i]; } + + /// + double Det () const { return coeff[0] * coeff[3] - coeff[1] * coeff[2]; } + + /// + void Mult (const Vec2d & v, Vec2d & prod) const; + /// + void MultTrans (const Vec2d & v , Vec2d & prod) const; + /// + void Solve (const Vec2d & rhs, Vec2d & x) const; + /// Solves mat * x = rhs, but using a positive definite matrix instead of mat + void SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const; + /// add a term \alpha * v * v^T + void AddDiadicProduct (double alpha, Vec2d & v); +}; + + + +inline void Mat2d :: Mult (const Vec2d & v, Vec2d & prod) const +{ + prod.X() = coeff[0] * v.X() + coeff[1] * v.Y(); + prod.Y() = coeff[2] * v.X() + coeff[3] * v.Y(); +} + + +inline void Mat2d :: MultTrans (const Vec2d & v, Vec2d & prod) const +{ + prod.X() = coeff[0] * v.X() + coeff[2] * v.Y(); + prod.Y() = coeff[1] * v.X() + coeff[3] * v.Y(); +} + + + +inline void Mat2d :: Solve (const Vec2d & rhs, Vec2d & x) const +{ + double det = Det(); + + if (det == 0) + MyError ("Mat2d::Solve: zero determinant"); + else + { + x.X() = (coeff[3] * rhs.X() - coeff[1] * rhs.Y()) / det; + x.Y() = (-coeff[2] * rhs.X() + coeff[0] * rhs.Y()) / det; + } +} + + +inline void Mat2d :: SolvePositiveDefinite (const Vec2d & rhs, Vec2d & x) const +{ + double a = max2(coeff[0], 1e-8); + double b = coeff[1] / a; + double c = coeff[2] / a; + double d = max2(coeff[3] - a *b * c, 1e-8); + + x.X() = (rhs.X() - b * rhs.Y()) / a; + x.Y() = rhs.Y() / d - c * x.X(); +} + + +inline void Mat2d :: AddDiadicProduct (double alpha, Vec2d & v) +{ + coeff[0] += alpha * v.X() * v.X(); + coeff[1] += alpha * v.X() * v.Y(); + coeff[2] += alpha * v.Y() * v.X(); + coeff[3] += alpha * v.Y() * v.Y(); +} + + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/geom3d.cpp b/contrib/Netgen/libsrc/gprim/geom3d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71970ffee39d81ca921f7f3d08c8030ed0e8905a --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom3d.cpp @@ -0,0 +1,731 @@ +#include <algorithm> +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> + +namespace netgen +{ +ostream & operator<<(ostream & s, const Point3d & p) + { + return s << "(" << p.x[0] << ", " << p.x[1] << ", " << p.x[2] << ")"; + } + +ostream & operator<<(ostream & s, const Vec3d & v) + { + return s << "(" << v.x[0] << ", " << v.x[1] << ", " << v.x[2] << ")"; + } + +double Angle (const Vec3d & v1, const Vec3d & v2) +{ + double co = (v1 * v2) / (v1.Length() * v2.Length()); + if (co > 1) co = 1; + if (co < -1) co = -1; + return acos ( co ); +} + + +void Vec3d :: GetNormal (Vec3d & n) const + { + if (fabs (X()) > fabs (Z())) + { + n.X() = -Y(); + n.Y() = X(); + n.Z() = 0; + } + else + { + n.X() = 0; + n.Y() = Z(); + n.Z() = -Y(); + } + double len = n.Length(); + if (len == 0) + { + n.X() = 1; + n.Y() = n.Z() = 0; + } + else + n /= len; + } + +/* +ostream & operator<<(ostream & s, const ROTDenseMatrix3D & r) + { + return s << "{ (" << r.txx << ", " << r.txy << ", " << r.txz << ") , (" + << r.tyx << ", " << r.tyy << ", " << r.tyz << ") , (" + << r.tzx << ", " << r.tzy << ", " << r.tzz << ") }"; + } +*/ + +/* +Vec3d operator- (const Point3d & p1, const Point3d & p2) + { + return Vec3d (p1.X() - p2.X(), p1.Y() - p2.Y(),p1.Z() - p2.Z()); + } + +Point3d operator- (const Point3d & p1, const Vec3d & v) + { + return Point3d (p1.X() - v.X(), p1.Y() - v.Y(),p1.Z() - v.Z()); + } + +Point3d operator+ (const Point3d & p1, const Vec3d & v) + { + return Point3d (p1.X() + v.X(), p1.Y() + v.Y(),p1.Z() + v.Z()); + } + +Vec3d operator- (const Vec3d & v1, const Vec3d & v2) + { + return Vec3d (v1.X() - v2.X(), v1.Y() - v2.Y(),v1.Z() - v2.Z()); + } + +Vec3d operator+ (const Vec3d & v1, const Vec3d & v2) + { + return Vec3d (v1.X() + v2.X(), v1.Y() + v2.Y(),v1.Z() + v2.Z()); + } + +Vec3d operator* (double scal, const Vec3d & v) + { + return Vec3d (scal * v.X(), scal * v.Y(), scal * v.Z()); + } +*/ +/* +double operator* (const Vec3d & v1, const Vec3d & v2) + { + return v1.X() * v2.X() + v1.Y() * v2.Y() + v1.Z() * v2.Z(); + } + +double Cross (const Vec3d & v1, const Vec3d & v2) + { + return v1.X() * v2.Y() - v1.Y() * v2.X(); + } +*/ + +/* +void ROTDenseMatrix3D :: CalcRotMat(double ag, double bg, double lg, double size2, Vec3d r) + { + size = size2; + txx=size * ( cos(bg) * cos(lg) ); + txy=size * ( cos(bg) * sin(lg) ); + txz=size * (-sin(bg) ); + + tyx=size * ( sin(ag) * sin(bg) * cos(lg) - cos(ag) * sin(lg) ); + tyy=size * ( sin(ag) * sin(bg) * sin(lg) + cos(ag) * cos(lg) ); + tyz=size * ( sin(ag) * cos(bg) ); + + tzx=size * ( cos(ag) * sin(bg) * cos(lg) + sin(ag) * sin(lg) ); + tzy=size * ( cos(ag) * sin(bg) * sin(lg) - sin(ag) * cos(lg) ); + tzz=size * ( cos(ag) * cos(bg) ); + + deltaR=r; + } +ROTDenseMatrix3D :: ROTDenseMatrix3D(double ag, double bg, double lg, double size2, Vec3d r) + {CalcRotMat(ag, bg, lg, size2, r); } + +ROTDenseMatrix3D :: ROTDenseMatrix3D(Vec3d rot2) + { + Vec3d r2(0,0,0); + CalcRotMat(rot2.X(), rot2.Y(), rot2.Z(), 1, r2); + } + +ROTDenseMatrix3D ROTDenseMatrix3D :: INV() + { + ROTDenseMatrix3D rinv(txx/sqr(size),tyx/sqr(size),tzx/sqr(size), + txy/sqr(size),tyy/sqr(size),tzy/sqr(size), + txz/sqr(size),tyz/sqr(size),tzz/sqr(size), + 1/size,deltaR); + return rinv; + } + +Vec3d operator* (const ROTDenseMatrix3D & r, const Vec3d & v) + { + return Vec3d (r.XX() * v.X() + r.XY() * v.Y() + r.XZ() * v.Z(), + r.YX() * v.X() + r.YY() * v.Y() + r.YZ() * v.Z(), + r.ZX() * v.X() + r.ZY() * v.Y() + r.ZZ() * v.Z() ); + } + +Point3d operator* (const ROTDenseMatrix3D & r, const Point3d & p) + { + return Point3d (r.XX() * p.X() + r.XY() * p.Y() + r.XZ() * p.Z(), + r.YX() * p.X() + r.YY() * p.Y() + r.YZ() * p.Z(), + r.ZX() * p.X() + r.ZY() * p.Y() + r.ZZ() * p.Z() ); + } +*/ + + + + + + + +Box3d :: Box3d ( double aminx, double amaxx, + double aminy, double amaxy, + double aminz, double amaxz ) +{ + minx[0] = aminx; maxx[0] = amaxx; + minx[1] = aminy; maxx[1] = amaxy; + minx[2] = aminz; maxx[2] = amaxz; +} + +Box3d :: Box3d ( const Box3d & b2 ) +{ + for (int i = 0; i < 3; i++) + { + minx[i] = b2.minx[i]; + maxx[i] = b2.maxx[i]; + } +} + +Box3d :: Box3d ( const Box<3> & b2 ) +{ + for (int i = 0; i < 3; i++) + { + minx[i] = b2.PMin()(i); + maxx[i] = b2.PMax()(i); + } +} + + +/* +int Box3d :: Intersect (const Box3d & box2) const +{ + int i; + for (i = 0; i <= 2; i++) + if (minx[i] > box2.maxx[i] || maxx[i] < box2.minx[i]) + return 0; + return 1; +} +*/ + +/* +void Box3d :: SetPoint (const Point3d & p) +{ + minx[0] = maxx[0] = p.X(); + minx[1] = maxx[1] = p.Y(); + minx[2] = maxx[2] = p.Z(); +} + +void Box3d :: AddPoint (const Point3d & p) +{ + if (p.X() < minx[0]) minx[0] = p.X(); + if (p.X() > maxx[0]) maxx[0] = p.X(); + if (p.Y() < minx[1]) minx[1] = p.Y(); + if (p.Y() > maxx[1]) maxx[1] = p.Y(); + if (p.Z() < minx[2]) minx[2] = p.Z(); + if (p.Z() > maxx[2]) maxx[2] = p.Z(); +} +*/ + +void Box3d :: GetPointNr (int i, Point3d & point) const +{ + i--; + point.X() = (i & 1) ? maxx[0] : minx[0]; + point.Y() = (i & 2) ? maxx[1] : minx[1]; + point.Z() = (i & 4) ? maxx[2] : minx[2]; +} + + +void Box3d :: Increase (double d) +{ + for (int i = 0; i <= 2; i++) + { + minx[i] -= d; + maxx[i] += d; + } +} + +void Box3d :: IncreaseRel (double /* rel */) +{ + for (int i = 0; i <= 2; i++) + { + double d = 0.5 * (maxx[i] - minx[i]); + minx[i] -= d; + maxx[i] += d; + } +} + + +Box3d :: Box3d (const Point3d& p1, const Point3d& p2) +{ + minx[0] = min2 (p1.X(), p2.X()); + minx[1] = min2 (p1.Y(), p2.Y()); + minx[2] = min2 (p1.Z(), p2.Z()); + maxx[0] = max2 (p1.X(), p2.X()); + maxx[1] = max2 (p1.Y(), p2.Y()); + maxx[2] = max2 (p1.Z(), p2.Z()); +} + +const Box3d& Box3d :: operator+=(const Box3d& b) +{ + minx[0] = min2 (minx[0], b.minx[0]); + minx[1] = min2 (minx[1], b.minx[1]); + minx[2] = min2 (minx[2], b.minx[2]); + maxx[0] = max2 (maxx[0], b.maxx[0]); + maxx[1] = max2 (maxx[1], b.maxx[1]); + maxx[2] = max2 (maxx[2], b.maxx[2]); + + return *this; +} + +Point3d Box3d :: MaxCoords() const +{ + return Point3d(maxx[0], maxx[1], maxx[2]); +} + +Point3d Box3d :: MinCoords() const +{ + return Point3d(minx[0], minx[1], minx[2]); +} + +/* +void Box3d :: CreateNegMinMaxBox() +{ + minx[0] = MAXDOUBLE; + minx[1] = MAXDOUBLE; + minx[2] = MAXDOUBLE; + maxx[0] = MINDOUBLE; + maxx[1] = MINDOUBLE; + maxx[2] = MINDOUBLE; + +} +*/ + +void Box3d :: WriteData(ofstream& fout) const +{ + for(int i = 0; i < 3; i++) + { + fout << minx[i] << " " << maxx[i] << " "; + } + fout << "\n"; +} + +void Box3d :: ReadData(ifstream& fin) +{ + for(int i = 0; i < 3; i++) + { + fin >> minx[i]; + fin >> maxx[i]; + } +} + + + + +Box3dSphere :: Box3dSphere ( double aminx, double amaxx, + double aminy, double amaxy, + double aminz, double amaxz ) + : Box3d (aminx, amaxx, aminy, amaxy, aminz, amaxz) +{ + CalcDiamCenter (); +} + + +void Box3dSphere :: CalcDiamCenter () +{ + diam = sqrt( sqr (maxx[0] - minx[0]) + + sqr (maxx[1] - minx[1]) + + sqr (maxx[2] - minx[2])); + + c.X() = 0.5 * (minx[0] + maxx[0]); + c.Y() = 0.5 * (minx[1] + maxx[1]); + c.Z() = 0.5 * (minx[2] + maxx[2]); + + inner = min2 ( min2 (maxx[0] - minx[0], maxx[1] - minx[1]), maxx[2] - minx[2]) / 2; +} + + +void Box3dSphere :: GetSubBox (int i, Box3dSphere & sbox) const +{ + i--; + if (i & 1) + { + sbox.minx[0] = c.X(); + sbox.maxx[0] = maxx[0]; + } + else + { + sbox.minx[0] = minx[0]; + sbox.maxx[0] = c.X(); + } + if (i & 2) + { + sbox.minx[1] = c.Y(); + sbox.maxx[1] = maxx[1]; + } + else + { + sbox.minx[1] = minx[1]; + sbox.maxx[1] = c.Y(); + } + if (i & 4) + { + sbox.minx[2] = c.Z(); + sbox.maxx[2] = maxx[2]; + } + else + { + sbox.minx[2] = minx[2]; + sbox.maxx[2] = c.Z(); + } + + // sbox.CalcDiamCenter (); + + sbox.c.X() = 0.5 * (sbox.minx[0] + sbox.maxx[0]); + sbox.c.Y() = 0.5 * (sbox.minx[1] + sbox.maxx[1]); + sbox.c.Z() = 0.5 * (sbox.minx[2] + sbox.maxx[2]); + sbox.diam = 0.5 * diam; + sbox.inner = 0.5 * inner; +} + + + + +/* +double Determinant (const Vec3d & col1, + const Vec3d & col2, + const Vec3d & col3) +{ + return + col1.x[0] * ( col2.x[1] * col3.x[2] - col2.x[2] * col3.x[1]) + + col1.x[1] * ( col2.x[2] * col3.x[0] - col2.x[0] * col3.x[2]) + + col1.x[2] * ( col2.x[0] * col3.x[1] - col2.x[1] * col3.x[0]); +} +*/ + +void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3) +{ + Swap (v1.Y(), v2.X()); + Swap (v1.Z(), v3.X()); + Swap (v2.Z(), v3.Y()); +} + + +int SolveLinearSystem (const Vec3d & col1, const Vec3d & col2, + const Vec3d & col3, const Vec3d & rhs, + Vec3d & sol) +{ + // changed by MW + double matrix[3][3]; + double locrhs[3]; + int retval = 0; + + for(int i=0; i<3; i++) + { + matrix[i][0] = col1.X(i+1); + matrix[i][1] = col2.X(i+1); + matrix[i][2] = col3.X(i+1); + locrhs[i] = rhs.X(i+1); + } + + for(int i=0; i<2; i++) + { + int pivot = i; + double maxv = fabs(matrix[i][i]); + for(int j=i+1; j<3; j++) + if(fabs(matrix[j][i]) > maxv) + { + maxv = fabs(matrix[j][i]); + pivot = j; + } + + if(fabs(maxv) > 1e-40) + { + if(pivot != i) + { + swap(matrix[i][0],matrix[pivot][0]); + swap(matrix[i][1],matrix[pivot][1]); + swap(matrix[i][2],matrix[pivot][2]); + swap(locrhs[i],locrhs[pivot]); + } + for(int j=i+1; j<3; j++) + { + double fac = matrix[j][i] / matrix[i][i]; + + for(int k=i+1; k<3; k++) + matrix[j][k] -= fac*matrix[i][k]; + locrhs[j] -= fac*locrhs[i]; + } + } + else + retval = 1; + } + + if(fabs(matrix[2][2]) < 1e-40) + retval = 1; + + if(retval != 0) + return retval; + + + for(int i=2; i>=0; i--) + { + double sum = locrhs[i]; + for(int j=2; j>i; j--) + sum -= matrix[i][j]*sol.X(j+1); + + sol.X(i+1) = sum/matrix[i][i]; + } + + return 0; + + + + + + /* + double det = Determinant (col1, col2, col3); + if (fabs (det) < 1e-40) + return 1; + + sol.X() = Determinant (rhs, col2, col3) / det; + sol.Y() = Determinant (col1, rhs, col3) / det; + sol.Z() = Determinant (col1, col2, rhs) / det; + + return 0; + */ + /* + Vec3d cr; + Cross (col1, col2, cr); + double det = cr * col3; + + if (fabs (det) < 1e-40) + return 1; + + if (fabs(cr.Z()) > 1e-12) + { + // solve for 3. component + sol.Z() = (cr * rhs) / det; + + // 2x2 system for 1. and 2. component + double res1 = rhs.X() - sol.Z() * col3.X(); + double res2 = rhs.Y() - sol.Z() * col3.Y(); + + sol.X() = (col2.Y() * res1 - col2.X() * res2) / cr.Z(); + sol.Y() = (col1.X() * res2 - col1.Y() * res1) / cr.Z(); + + } + else + { + det = Determinant (col1, col2, col3); + if (fabs (det) < 1e-40) + return 1; + + sol.X() = Determinant (rhs, col2, col3) / det; + sol.Y() = Determinant (col1, rhs, col3) / det; + sol.Z() = Determinant (col1, col2, rhs) / det; + } + + return 0; + */ +} + + +int SolveLinearSystemLS (const Vec3d & col1, + const Vec3d & col2, + const Vec2d & rhs, + Vec3d & sol) +{ + double a11 = col1 * col1; + double a12 = col1 * col2; + double a22 = col2 * col2; + + double det = a11 * a22 - a12 * a12; + + if (det*det <= 1e-24 * a11 * a22) + { + sol = Vec3d (0, 0, 0); + return 1; + } + + Vec2d invrhs; + invrhs.X() = ( a22 * rhs.X() - a12 * rhs.Y()) / det; + invrhs.Y() = (-a12 * rhs.X() + a11 * rhs.Y()) / det; + + sol.X() = invrhs.X() * col1.X() + invrhs.Y() * col2.X(); + sol.Y() = invrhs.X() * col1.Y() + invrhs.Y() * col2.Y(); + sol.Z() = invrhs.X() * col1.Z() + invrhs.Y() * col2.Z(); + + return 0; + + /* + Vec3d inv1, inv2; + int err = + PseudoInverse (col1, col2, inv1, inv2); + + sol = rhs.X() * inv1 + rhs.Y() * inv2; + return err; + */ +} + +int SolveLinearSystemLS2 (const Vec3d & col1, + const Vec3d & col2, + const Vec2d & rhs, + Vec3d & sol, double & x, double & y) +{ + double a11 = col1 * col1; + double a12 = col1 * col2; + double a22 = col2 * col2; + + double det = a11 * a22 - a12 * a12; + + if (fabs (det) <= 1e-12 * col1.Length() * col2.Length() || + col1.Length2() == 0 || col2.Length2() == 0) + { + sol = Vec3d (0, 0, 0); + x = 0; y = 0; + return 1; + } + + Vec2d invrhs; + invrhs.X() = ( a22 * rhs.X() - a12 * rhs.Y()) / det; + invrhs.Y() = (-a12 * rhs.X() + a11 * rhs.Y()) / det; + + sol.X() = invrhs.X() * col1.X() + invrhs.Y() * col2.X(); + sol.Y() = invrhs.X() * col1.Y() + invrhs.Y() * col2.Y(); + sol.Z() = invrhs.X() * col1.Z() + invrhs.Y() * col2.Z(); + + x = invrhs.X(); + y = invrhs.Y(); + + return 0; + + /* + Vec3d inv1, inv2; + int err = + PseudoInverse (col1, col2, inv1, inv2); + + sol = rhs.X() * inv1 + rhs.Y() * inv2; + return err; + */ +} + +int PseudoInverse (const Vec3d & col1, + const Vec3d & col2, + Vec3d & inv1, + Vec3d & inv2) +{ + double a11 = col1 * col1; + double a12 = col1 * col2; + double a22 = col2 * col2; + + double det = a11 * a22 - a12 * a12; + + if (fabs (det) < 1e-12 * col1.Length() * col2.Length()) + { + inv1 = Vec3d (0, 0, 0); + inv2 = Vec3d (0, 0, 0); + return 1; + } + + double ia11 = a22 / det; + double ia12 = -a12 / det; + double ia22 = a11 / det; + + inv1 = ia11 * col1 + ia12 * col2; + inv2 = ia12 * col1 + ia22 * col2; + + return 0; +} + + + + +QuadraticFunction3d :: +QuadraticFunction3d (const Point3d & p, const Vec3d & v) +{ + Vec3d hv(v); + hv /= (hv.Length() + 1e-12); + Vec3d t1, t2; + hv.GetNormal (t1); + Cross (hv, t1, t2); + + double t1p = t1.X() * p.X() + t1.Y() * p.Y() + t1.Z() * p.Z(); + double t2p = t2.X() * p.X() + t2.Y() * p.Y() + t2.Z() * p.Z(); + c0 = sqr (t1p) + sqr (t2p); + cx = -2 * (t1p * t1.X() + t2p * t2.X()); + cy = -2 * (t1p * t1.Y() + t2p * t2.Y()); + cz = -2 * (t1p * t1.Z() + t2p * t2.Z()); + + cxx = t1.X() * t1.X() + t2.X() * t2.X(); + cyy = t1.Y() * t1.Y() + t2.Y() * t2.Y(); + czz = t1.Z() * t1.Z() + t2.Z() * t2.Z(); + + cxy = 2 * t1.X() * t1.Y() + 2 * t2.X() * t2.Y(); + cxz = 2 * t1.X() * t1.Z() + 2 * t2.X() * t2.Z(); + cyz = 2 * t1.Y() * t1.Z() + 2 * t2.Y() * t2.Z(); + + /* + (*testout) << "c0 = " << c0 + << " clin = " << cx << " " << cy << " " << cz + << " cq = " << cxx << " " << cyy << " " << czz + << cxy << " " << cyz << " " << cyz << endl; + */ +} + +// QuadraticFunction3d gqf (Point3d (0,0,0), Vec3d (1, 0, 0)); + + + + + +void referencetransform :: Set (const Point3d & p1, const Point3d & p2, + const Point3d & p3, double ah) +{ + ex = p2 - p1; + ex /= ex.Length(); + ey = p3 - p1; + ey -= (ex * ey) * ex; + ey /= ey.Length(); + ez = Cross (ex, ey); + rp = p1; + h = ah; + + exh = ah * ex; + eyh = ah * ey; + ezh = ah * ez; + ah = 1 / ah; + ex_h = ah * ex; + ey_h = ah * ey; + ez_h = ah * ez; +} + +void referencetransform :: ToPlain (const Point3d & p, Point3d & pp) const +{ + Vec3d v; + v = p - rp; + pp.X() = (ex_h * v); + pp.Y() = (ey_h * v); + pp.Z() = (ez_h * v); +} + +void referencetransform :: ToPlain (const ARRAY<Point3d> & p, + ARRAY<Point3d> & pp) const +{ + Vec3d v; + int i; + + pp.SetSize (p.Size()); + for (i = 1; i <= p.Size(); i++) + { + v = p.Get(i) - rp; + pp.Elem(i).X() = (ex_h * v); + pp.Elem(i).Y() = (ey_h * v); + pp.Elem(i).Z() = (ez_h * v); + } +} + +void referencetransform :: FromPlain (const Point3d & pp, Point3d & p) const +{ + Vec3d v; + // v = (h * pp.X()) * ex + (h * pp.Y()) * ey + (h * pp.Z()) * ez; + // p = rp + v; + v.X() = pp.X() * exh.X() + pp.Y() * eyh.X() + pp.Z() * ezh.X(); + v.Y() = pp.X() * exh.Y() + pp.Y() * eyh.Y() + pp.Z() * ezh.Y(); + v.Z() = pp.X() * exh.Z() + pp.Y() * eyh.Z() + pp.Z() * ezh.Z(); + p.X() = rp.X() + v.X(); + p.Y() = rp.Y() + v.Y(); + p.Z() = rp.Z() + v.Z(); +} + + +} diff --git a/contrib/Netgen/libsrc/gprim/geom3d.hpp b/contrib/Netgen/libsrc/gprim/geom3d.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c5e8eecbda12398f6cf2a18ed8735db500df2f08 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geom3d.hpp @@ -0,0 +1,731 @@ +#ifndef FILE_GEOM3D +#define FILE_GEOM3D + +/* *************************************************************************/ +/* File: geom3d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 5. Aug. 95 */ +/* *************************************************************************/ + + + + +extern void MyError (const char * ch); + +class Point3d; +class Vec3d; + +inline Vec3d operator- (const Point3d & p1, const Point3d & p2); +inline Point3d operator- (const Point3d & p1, const Vec3d & v); +inline Point3d operator+ (const Point3d & p1, const Vec3d & v); +Point3d & Add (double d, const Vec3d & v); +Point3d & Add2 (double d, const Vec3d & v, + double d2, const Vec3d & v2); +inline Point3d Center (const Point3d & p1, const Point3d & p2); +inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3); +inline Point3d Center (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4); +ostream & operator<<(ostream & s, const Point3d & p); +inline Vec3d operator- (const Vec3d & p1, const Vec3d & v); +inline Vec3d operator+ (const Vec3d & p1, const Vec3d & v); +inline Vec3d operator* (double scal, const Vec3d & v); +inline double operator* (const Vec3d & v1, const Vec3d & v2); +inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2); +inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod); +double Angle (const Vec3d & v); +double FastAngle (const Vec3d & v); +double Angle (const Vec3d & v1, const Vec3d & v2); +double FastAngle (const Vec3d & v1, const Vec3d & v2); +ostream & operator<<(ostream & s, const Vec3d & v); +void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3); +int SolveLinearSystem (const Vec3d & col1, + const Vec3d & col2, + const Vec3d & col3, + const Vec3d & rhs, + Vec3d & sol); +int SolveLinearSystemLS (const Vec3d & col1, + const Vec3d & col2, + const Vec2d & rhs, + Vec3d & sol); +int SolveLinearSystemLS2 (const Vec3d & col1, + const Vec3d & col2, + const Vec2d & rhs, + Vec3d & sol, + double & x, double & y); +int PseudoInverse (const Vec3d & col1, + const Vec3d & col2, + Vec3d & inv1, + Vec3d & inv2); +double Determinant (const Vec3d & col1, + const Vec3d & col2, + const Vec3d & col3); + +/// Point in R3 +class Point3d +{ +protected: + /// + double x[3]; + +public: + /// + Point3d () { x[0] = x[1] = x[2] = 0; } + /// + Point3d(double ax, double ay, double az) + { x[0] = ax; x[1] = ay; x[2] = az; } + /// + Point3d(double ax[3]) + { x[0] = ax[0]; x[1] = ax[1]; x[2] = ax[2]; } + + /// + Point3d(const Point3d & p2) + { x[0] = p2.x[0]; x[1] = p2.x[1]; x[2] = p2.x[2]; } + + Point3d (const Point<3> & p2) + { + for (int i = 0; i < 3; i++) + x[i] = p2(i); + } + + /// + Point3d & operator= (const Point3d & p2) + { x[0] = p2.x[0]; x[1] = p2.x[1]; x[2] = p2.x[2]; return *this; } + + /// + int operator== (const Point3d& p) const + { return (x[0] == p.x[0] && x[1] == p.x[1] && x[2] == p.x[2]); } + + /// + double & X() { return x[0]; } + /// + double & Y() { return x[1]; } + /// + double & Z() { return x[2]; } + /// + double X() const { return x[0]; } + /// + double Y() const { return x[1]; } + /// + double Z() const { return x[2]; } + /// + double & X(int i) { return x[i-1]; } + /// + double X(int i) const { return x[i-1]; } + /// + const Point3d & SetToMin (const Point3d & p2) + { + if (p2.x[0] < x[0]) x[0] = p2.x[0]; + if (p2.x[1] < x[1]) x[1] = p2.x[1]; + if (p2.x[2] < x[2]) x[2] = p2.x[2]; + return *this; + } + + /// + const Point3d & SetToMax (const Point3d & p2) + { + if (p2.x[0] > x[0]) x[0] = p2.x[0]; + if (p2.x[1] > x[1]) x[1] = p2.x[1]; + if (p2.x[2] > x[2]) x[2] = p2.x[2]; + return *this; + } + + /// + friend inline Vec3d operator- (const Point3d & p1, const Point3d & p2); + /// + friend inline Point3d operator- (const Point3d & p1, const Vec3d & v); + /// + friend inline Point3d operator+ (const Point3d & p1, const Vec3d & v); + /// + inline Point3d & operator+= (const Vec3d & v); + inline Point3d & operator-= (const Vec3d & v); + /// + inline Point3d & Add (double d, const Vec3d & v); + /// + inline Point3d & Add2 (double d, const Vec3d & v, + double d2, const Vec3d & v2); + /// + friend inline double Dist (const Point3d & p1, const Point3d & p2) + { return sqrt ( (p1.x[0]-p2.x[0]) * (p1.x[0]-p2.x[0]) + + (p1.x[1]-p2.x[1]) * (p1.x[1]-p2.x[1]) + + (p1.x[2]-p2.x[2]) * (p1.x[2]-p2.x[2])); } + /// + inline friend double Dist2 (const Point3d & p1, const Point3d & p2) + { return ( (p1.x[0]-p2.x[0]) * (p1.x[0]-p2.x[0]) + + (p1.x[1]-p2.x[1]) * (p1.x[1]-p2.x[1]) + + (p1.x[2]-p2.x[2]) * (p1.x[2]-p2.x[2])); } + + /// + friend inline Point3d Center (const Point3d & p1, const Point3d & p2); + /// + friend inline Point3d Center (const Point3d & p1, const Point3d & p2, const Point3d & p3); + /// + friend inline Point3d Center (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4); + /// + friend ostream & operator<<(ostream & s, const Point3d & p); + + /// + friend class Vec3d; + /// + friend class Box3d; + + + operator Point<3> () const + { + return Point<3> (x[0], x[1], x[2]); + } +}; + + +/// +class Vec3d +{ +protected: + /// + double x[3]; + +public: + /// + inline Vec3d() { x[0] = x[1] = x[2] = 0; } + /// + inline Vec3d(double ax, double ay, double az) + { x[0] = ax; x[1] = ay; x[2] = az; } + /// + Vec3d(double ax[3]) + { x[0] = ax[0]; x[1] = ax[1]; x[2] = ax[2]; } + /// + inline Vec3d(const Vec3d & v2) + { x[0] = v2.x[0]; x[1] = v2.x[1]; x[2] = v2.x[2]; } + /// + inline Vec3d(const Point3d & p1, const Point3d & p2) + { + x[0] = p2.x[0] - p1.x[0]; + x[1] = p2.x[1] - p1.x[1]; + x[2] = p2.x[2] - p1.x[2]; + } + /// + inline Vec3d(const Point3d & p1) + { + x[0] = p1.x[0]; + x[1] = p1.x[1]; + x[2] = p1.x[2]; + } + + Vec3d (const Vec<3> & v2) + { + for (int i = 0; i < 3; i++) + x[i] = v2(i); + } + + operator Vec<3> () const + { + return Vec<3> (x[0], x[1], x[2]); + } + + + Vec3d & operator= (const Vec3d & v2) + { x[0] = v2.x[0]; x[1] = v2.x[1]; x[2] = v2.x[2]; return *this; } + /// + Vec3d & operator= (double val) + { x[0] = x[1] = x[2] = val; return *this; } + /// + double & X() { return x[0]; } + /// + double & Y() { return x[1]; } + /// + double & Z() { return x[2]; } + /// + double & X(int i) { return x[i-1]; } + + /// + double X() const { return x[0]; } + /// + double Y() const { return x[1]; } + /// + double Z() const { return x[2]; } + /// + double X(int i) const { return x[i-1]; } + + /// + double Length() const + { return sqrt (x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); } + /// + double Length2() const + { return x[0] * x[0] + x[1] * x[1] + x[2] * x[2]; } + + /// + Vec3d & operator+= (const Vec3d & v2); + /// + Vec3d & operator-= (const Vec3d & v2); + /// + Vec3d & operator*= (double s); + /// + Vec3d & operator/= (double s); + /// + inline Vec3d & Add (double d, const Vec3d & v); + /// + inline Vec3d & Add2 (double d, const Vec3d & v, + double d2, const Vec3d & v2); + + /// + friend inline Vec3d operator- (const Point3d & p1, const Point3d & p2); + /// + friend inline Point3d operator- (const Point3d & p1, const Vec3d & v); + /// + friend inline Point3d operator+ (const Point3d & p1, const Vec3d & v); + /// + friend inline Vec3d operator- (const Vec3d & p1, const Vec3d & v); + /// + friend inline Vec3d operator+ (const Vec3d & p1, const Vec3d & v); + /// + friend inline Vec3d operator* (double scal, const Vec3d & v); + + /// + friend inline double operator* (const Vec3d & v1, const Vec3d & v2); + /// + friend inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2); + /// + friend inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod); + + /// Returns one normal-vector to n + void GetNormal (Vec3d & n) const; + /// + friend double Angle (const Vec3d & v); + /// + friend double FastAngle (const Vec3d & v); + /// + friend double Angle (const Vec3d & v1, const Vec3d & v2); + /// + friend double FastAngle (const Vec3d & v1, const Vec3d & v2); + + void Normalize() + { + double len = (x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); + if (len == 0) return; + len = sqrt (len); + x[0] /= len; x[1] /= len; x[2] /= len; + } + + /// + friend ostream & operator<<(ostream & s, const Vec3d & v); + + /// + friend class Point3d; + friend void Transpose (Vec3d & v1, Vec3d & v2, Vec3d & v3); + friend int SolveLinearSystem (const Vec3d & col1, + const Vec3d & col2, + const Vec3d & col3, + const Vec3d & rhs, + Vec3d & sol); + friend int SolveLinearSystemLS (const Vec3d & col1, + const Vec3d & col2, + const Vec2d & rhs, + Vec3d & sol); + friend int SolveLinearSystemLS2 (const Vec3d & col1, + const Vec3d & col2, + const Vec2d & rhs, + Vec3d & sol, + double & x, double & y); + friend int PseudoInverse (const Vec3d & col1, + const Vec3d & col2, + Vec3d & inv1, + Vec3d & inv2); + friend double Determinant (const Vec3d & col1, + const Vec3d & col2, + const Vec3d & col3); +}; + + + +class QuadraticFunction3d +{ + double c0, cx, cy, cz; + double cxx, cyy, czz, cxy, cxz, cyz; + +public: + QuadraticFunction3d (const Point3d & p, const Vec3d & v); + double Eval (const Point3d & p) + { + return + c0 + + p.X() * (cx + cxx * p.X() + cxy * p.Y() + cxz * p.Z()) + + p.Y() * (cy + cyy * p.Y() + cyz * p.Z()) + + p.Z() * (cz + czz * p.Z()); + } +}; + + + +inline Point3d Center (const Point3d & p1, const Point3d & p2) +{ + return Point3d (0.5 * (p1.x[0] + p2.x[0]), + 0.5 * (p1.x[1] + p2.x[1]), + 0.5 * (p1.x[2] + p2.x[2])); +} + + +inline Point3d Center (const Point3d & p1, const Point3d & p2, + const Point3d & p3) +{ + return Point3d (1.0/3.0 * (p1.x[0] + p2.x[0] + p3.x[0]), + 1.0/3.0 * (p1.x[1] + p2.x[1] + p3.x[1]), + 1.0/3.0 * (p1.x[2] + p2.x[2] + p3.x[2])); +} + +inline Point3d Center (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4) +{ + return Point3d (0.25 * (p1.x[0] + p2.x[0] + p3.x[0] + p4.x[0]), + 0.25 * (p1.x[1] + p2.x[1] + p3.x[1] + p4.x[1]), + 0.25 * (p1.x[2] + p2.x[2] + p3.x[2] + p4.x[2])); +} + + + +inline Vec3d & Vec3d :: operator+= (const Vec3d & v2) +{ + x[0] += v2.x[0]; + x[1] += v2.x[1]; + x[2] += v2.x[2]; + return *this; +} + +inline Vec3d & Vec3d :: operator-= (const Vec3d & v2) +{ + x[0] -= v2.x[0]; + x[1] -= v2.x[1]; + x[2] -= v2.x[2]; + return *this; +} + + +inline Vec3d & Vec3d :: operator*= (double s) +{ + x[0] *= s; + x[1] *= s; + x[2] *= s; + return *this; +} + + +inline Vec3d & Vec3d :: operator/= (double s) +{ + if (s != 0) + { + x[0] /= s; + x[1] /= s; + x[2] /= s; + } +#ifdef DEBUG + else + { + cerr << "Vec div by 0, v = " << (*this) << endl; + // MyError ("Vec3d::operator /=: Divisioin by zero"); + } +#endif + return *this; +} + +inline Vec3d & Vec3d::Add (double d, const Vec3d & v) +{ + x[0] += d * v.x[0]; + x[1] += d * v.x[1]; + x[2] += d * v.x[2]; + return *this; +} + +inline Vec3d & Vec3d::Add2 (double d, const Vec3d & v, + double d2, const Vec3d & v2) +{ + x[0] += d * v.x[0] + d2 * v2.x[0]; + x[1] += d * v.x[1] + d2 * v2.x[1]; + x[2] += d * v.x[2] + d2 * v2.x[2]; + return *this; +} + + + + + + + + +inline Vec3d operator- (const Point3d & p1, const Point3d & p2) +{ + return Vec3d (p1.x[0] - p2.x[0], p1.x[1] - p2.x[1],p1.x[2] - p2.x[2]); +} + + +inline Point3d operator- (const Point3d & p1, const Vec3d & v) +{ + return Point3d (p1.x[0] - v.x[0], p1.x[1] - v.x[1],p1.x[2] - v.x[2]); +} + + +inline Point3d operator+ (const Point3d & p1, const Vec3d & v) +{ + return Point3d (p1.x[0] + v.x[0], p1.x[1] + v.x[1],p1.x[2] + v.x[2]); +} + +inline Point3d & Point3d::operator+= (const Vec3d & v) +{ + x[0] += v.x[0]; + x[1] += v.x[1]; + x[2] += v.x[2]; + return *this; +} + +inline Point3d & Point3d::operator-= (const Vec3d & v) +{ + x[0] -= v.x[0]; + x[1] -= v.x[1]; + x[2] -= v.x[2]; + return *this; +} + +inline Point3d & Point3d::Add (double d, const Vec3d & v) +{ + x[0] += d * v.x[0]; + x[1] += d * v.x[1]; + x[2] += d * v.x[2]; + return *this; +} + +inline Point3d & Point3d::Add2 (double d, const Vec3d & v, + double d2, const Vec3d & v2) +{ + x[0] += d * v.x[0] + d2 * v2.x[0]; + x[1] += d * v.x[1] + d2 * v2.x[1]; + x[2] += d * v.x[2] + d2 * v2.x[2]; + return *this; +} + + +inline Vec3d operator- (const Vec3d & v1, const Vec3d & v2) +{ + return Vec3d (v1.x[0] - v2.x[0], v1.x[1] - v2.x[1],v1.x[2] - v2.x[2]); +} + + +inline Vec3d operator+ (const Vec3d & v1, const Vec3d & v2) +{ + return Vec3d (v1.x[0] + v2.x[0], v1.x[1] + v2.x[1],v1.x[2] + v2.x[2]); +} + + +inline Vec3d operator* (double scal, const Vec3d & v) +{ + return Vec3d (scal * v.x[0], scal * v.x[1], scal * v.x[2]); +} + + + +inline double operator* (const Vec3d & v1, const Vec3d & v2) +{ + return v1.x[0] * v2.x[0] + v1.x[1] * v2.x[1] + v1.x[2] * v2.x[2]; +} + + + +inline Vec3d Cross (const Vec3d & v1, const Vec3d & v2) +{ + return Vec3d + ( v1.x[1] * v2.x[2] - v1.x[2] * v2.x[1], + v1.x[2] * v2.x[0] - v1.x[0] * v2.x[2], + v1.x[0] * v2.x[1] - v1.x[1] * v2.x[0]); +} + +inline void Cross (const Vec3d & v1, const Vec3d & v2, Vec3d & prod) +{ + prod.x[0] = v1.x[1] * v2.x[2] - v1.x[2] * v2.x[1]; + prod.x[1] = v1.x[2] * v2.x[0] - v1.x[0] * v2.x[2]; + prod.x[2] = v1.x[0] * v2.x[1] - v1.x[1] * v2.x[0]; +} + +inline double Determinant (const Vec3d & col1, + const Vec3d & col2, + const Vec3d & col3) +{ + return + col1.x[0] * ( col2.x[1] * col3.x[2] - col2.x[2] * col3.x[1]) + + col1.x[1] * ( col2.x[2] * col3.x[0] - col2.x[0] * col3.x[2]) + + col1.x[2] * ( col2.x[0] * col3.x[1] - col2.x[1] * col3.x[0]); +} + + +/// +class Box3d +{ +protected: + /// + double minx[3], maxx[3]; + +public: + /// + Box3d () { }; + /// + Box3d ( double aminx, double amaxx, + double aminy, double amaxy, + double aminz, double amaxz ); + /// + Box3d ( const Box3d & b2 ); + /// + Box3d (const Point3d& p1, const Point3d& p2); + /// + Box3d (const Box<3> & b2); + /// + double MinX () const { return minx[0]; } + /// + double MaxX () const { return maxx[0]; } + /// + double MinY () const { return minx[1]; } + /// + double MaxY () const { return maxx[1]; } + /// + double MinZ () const { return minx[2]; } + /// + double MaxZ () const { return maxx[2]; } + + /// + double Mini (int i) const { return minx[i-1]; } + /// + double Maxi (int i) const { return maxx[i-1]; } + + /// + Point3d PMin () const { return Point3d(minx[0], minx[1], minx[2]); } + /// + Point3d PMax () const { return Point3d(maxx[0], maxx[1], maxx[2]); } + + /// + void GetPointNr (int i, Point3d & point) const; + /// increase Box at each side with dist + void Increase (double dist); + /// increase Box by factor rel + void IncreaseRel (double rel); + /// return 1 if closures are intersecting + int Intersect (const Box3d & box2) const + { + if (minx[0] > box2.maxx[0] || maxx[0] < box2.minx[0] || + minx[1] > box2.maxx[1] || maxx[1] < box2.minx[1] || + minx[2] > box2.maxx[2] || maxx[2] < box2.minx[2]) + return 0; + return 1; + } + /// return 1 if point p in closure + int IsIn (const Point3d & p) const + { + if (minx[0] <= p.x[0] && maxx[0] >= p.x[0] && + minx[1] <= p.x[1] && maxx[1] >= p.x[1] && + minx[2] <= p.x[2] && maxx[2] >= p.x[2]) + return 1; + return 0; + } + /// + inline void SetPoint (const Point3d & p) + { + minx[0] = maxx[0] = p.X(); + minx[1] = maxx[1] = p.Y(); + minx[2] = maxx[2] = p.Z(); + } + + /// + inline void AddPoint (const Point3d & p) + { + if (p.x[0] < minx[0]) minx[0] = p.x[0]; + if (p.x[0] > maxx[0]) maxx[0] = p.x[0]; + if (p.x[1] < minx[1]) minx[1] = p.x[1]; + if (p.x[1] > maxx[1]) maxx[1] = p.x[1]; + if (p.x[2] < minx[2]) minx[2] = p.x[2]; + if (p.x[2] > maxx[2]) maxx[2] = p.x[2]; + } + + /// + const Box3d& operator+=(const Box3d& b); + + /// + Point3d MaxCoords() const; + /// + Point3d MinCoords() const; + + /// Make a negative sized box; + // void CreateNegMinMaxBox(); + + /// + Point3d CalcCenter () const { return Point3d(0.5*(minx[0] + maxx[0]), + 0.5*(minx[1] + maxx[1]), + 0.5*(minx[2] + maxx[2])); } + /// + double CalcDiam () const { return sqrt(sqr(maxx[0]-minx[0])+ + sqr(maxx[1]-minx[1])+ + sqr(maxx[2]-minx[2])); } + + /// + void WriteData(ofstream& fout) const; + /// + void ReadData(ifstream& fin); +}; + + +class Box3dSphere : public Box3d +{ +protected: + /// + double diam, inner; + /// + Point3d c; +public: + /// + Box3dSphere () { }; + /// + Box3dSphere ( double aminx, double amaxx, + double aminy, double amaxy, + double aminz, double amaxz); + /// + const Point3d & Center () const { return c; } + + /// + double Diam () const { return diam; } + /// + double Inner () const { return inner; } + /// + void GetSubBox (int i, Box3dSphere & sbox) const; + + // private: + /// + void CalcDiamCenter (); +}; + + + + +/// +class referencetransform +{ + /// + Vec3d ex, ey, ez; + /// + Vec3d exh, eyh, ezh; + /// + Vec3d ex_h, ey_h, ez_h; + /// + Point3d rp; + /// + double h; + +public: + + /// + void Set (const Point3d & p1, const Point3d & p2, + const Point3d & p3, double ah); + + /// + void ToPlain (const Point3d & p, Point3d & pp) const; + /// + void ToPlain (const ARRAY<Point3d> & p, ARRAY<Point3d> & pp) const; + /// + void FromPlain (const Point3d & pp, Point3d & p) const; +}; + + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/geomfuncs.cpp b/contrib/Netgen/libsrc/gprim/geomfuncs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b2ac83824a8908e1e2a5be3417ad5e79057f3f72 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomfuncs.cpp @@ -0,0 +1,111 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> + +namespace netgen +{ + + /* + // template <> +inline void CalcInverse (const Mat<2,2> & m, Mat<2,2> & inv) +{ + double det = m(0,0) * m(1,1) - m(0,1) * m(1,0); + if (det == 0) + { + inv = 0; + return; + } + + double idet = 1.0 / det; + inv(0,0) = idet * m(1,1); + inv(0,1) = -idet * m(0,1); + inv(1,0) = -idet * m(1,0); + inv(1,1) = idet * m(0,0); +} + */ + + + + // template <> +void CalcInverse (const Mat<3,3> & m, Mat<3,3> & inv) +{ + double det = Det (m); + if (det == 0) + { + inv = 0; + return; + } + + double idet = 1.0 / det; + inv(0,0) = idet * (m(1,1) * m(2,2) - m(1,2) * m(2,1)); + inv(1,0) = -idet * (m(1,0) * m(2,2) - m(1,2) * m(2,0)); + inv(2,0) = idet * (m(1,0) * m(2,1) - m(1,1) * m(2,0)); + + inv(0,1) = -idet * (m(0,1) * m(2,2) - m(0,2) * m(2,1)); + inv(1,1) = idet * (m(0,0) * m(2,2) - m(0,2) * m(2,0)); + inv(2,1) = -idet * (m(0,0) * m(2,1) - m(0,1) * m(2,0)); + + inv(0,2) = idet * (m(0,1) * m(1,2) - m(0,2) * m(1,1)); + inv(1,2) = -idet * (m(0,0) * m(1,2) - m(0,2) * m(1,0)); + inv(2,2) = idet * (m(0,0) * m(1,1) - m(0,1) * m(1,0)); +} + +/* +// template <> +void CalcInverse (const Mat<2,3> & m, Mat<3,2> & inv) +{ + Mat<2,2> a = m * Trans (m); + Mat<2,2> ainv; + CalcInverse (a, ainv); + inv = Trans (m) * ainv; +} +*/ + + + +double Det (const Mat<2,2> & m) +{ + return m(0,0) * m(1,1) - m(0,1) * m(1,0); +} + +double Det (const Mat<3,3> & m) +{ + return + m(0,0) * m(1,1) * m(2,2) + + m(1,0) * m(2,1) * m(0,2) + + m(2,0) * m(0,1) * m(1,2) + - m(0,0) * m(2,1) * m(1,2) + - m(1,0) * m(0,1) * m(2,2) + - m(2,0) * m(1,1) * m(0,2); +} + + +void EigenValues (const Mat<3,3> & m, Vec<3> & ev) +{ + const double pi = 3.141592; + double a, b, c, d; + double p, q; + double arg; + + a = -1.; + b = m(0,0) + m(1,1) + m(2,2); + c = -( m(0,0)*m(2,2) + m(1,1)*m(2,2) + m(0,0)*m(1,1) - sqr(m(0,1)) - sqr(m(0,2)) - sqr(m(1,2)) ); + d = Det (m); + p = 3.*a*c - sqr(b); + q = 27.*sqr(a)*d - 9.*a*b*c + 2.*sqr(b)*b; + + + arg = acos((-q/2)/sqrt(-(p*p*p))); + + + ev(0) = (2. * sqrt(-p) * cos(arg/3.) - b) / 3.*a; + ev(1) = (-2. * sqrt(-p) * cos(arg/3.+pi/3) - b) / 3.*a; + ev(2) = (-2. * sqrt(-p) * cos(arg/3.-pi/3)- b) / 3.*a; + + + +} + + +} diff --git a/contrib/Netgen/libsrc/gprim/geomfuncs.hpp b/contrib/Netgen/libsrc/gprim/geomfuncs.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4c8a51ee439ad968c895736e42a4f4199b253463 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomfuncs.hpp @@ -0,0 +1,157 @@ +#ifndef FILE_GEOMFUNCS +#define FILE_GEOMFUNCS + +/* *************************************************************************/ +/* File: geomfuncs.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +template <int D> +inline double Abs (const Vec<D> & v) +{ + double sum = 0; + for (int i = 0; i < D; i++) + sum += v(i) * v(i); + return sqrt (sum); +} + + +template <int D> +inline double Abs2 (const Vec<D> & v) +{ + double sum = 0; + for (int i = 0; i < D; i++) + sum += v(i) * v(i); + return sum; +} + + + +template <int D> +inline double Dist (const Point<D> & a, const Point<D> & b) +{ + return Abs (a-b); +} + +template <int D> +inline double Dist2 (const Point<D> & a, const Point<D> & b) +{ + return Abs2 (a-b); +} + + +template <int D> +inline Point<D> Center (const Point<D> & a, const Point<D> & b) +{ + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = 0.5 * (a(i) + b(i)); + return res; +} + +template <int D> +inline Point<D> Center (const Point<D> & a, const Point<D> & b, const Point<D> & c) +{ + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = (1.0/3.0) * (a(i) + b(i) + c(i)); + return res; +} + +template <int D> +inline Point<D> Center (const Point<D> & a, const Point<D> & b, const Point<D> & c, const Point<D> & d) +{ + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = (1.0/4.0) * (a(i) + b(i) + c(i) + d(i)); + return res; +} + + + +inline Vec<3> Cross (const Vec<3> & v1, const Vec<3> & v2) +{ + return Vec<3> + ( v1(1) * v2(2) - v1(2) * v2(1), + v1(2) * v2(0) - v1(0) * v2(2), + v1(0) * v2(1) - v1(1) * v2(0) ); +} + + +inline double Determinant (const Vec<3> & col1, + const Vec<3> & col2, + const Vec<3> & col3) +{ + return + col1(0) * ( col2(1) * col3(2) - col2(2) * col3(1)) + + col1(1) * ( col2(2) * col3(0) - col2(0) * col3(2)) + + col1(2) * ( col2(0) * col3(1) - col2(1) * col3(0)); +} + + + +template <> +inline Vec<2> Vec<2> :: GetNormal () const +{ + return Vec<2> (-x[1], x[0]); +} + +template <> +inline Vec<3> Vec<3> :: GetNormal () const +{ + if (fabs (x[0]) > fabs (x[2])) + return Vec<3> (-x[1], x[0], 0); + else + return Vec<3> (0, x[2], -x[1]); +} + + + +// template <int H, int W> +inline void CalcInverse (const Mat<2,2> & m, Mat<2,2> & inv) +{ + double det = m(0,0) * m(1,1) - m(0,1) * m(1,0); + if (det == 0) + { + inv = 0; + return; + } + + double idet = 1.0 / det; + inv(0,0) = idet * m(1,1); + inv(0,1) = -idet * m(0,1); + inv(1,0) = -idet * m(1,0); + inv(1,1) = idet * m(0,0); +} + +void CalcInverse (const Mat<3,3> & m, Mat<3,3> & inv); + +inline void CalcInverse (const Mat<2,3> & m, Mat<3,2> & inv) +{ + Mat<2,2> a = m * Trans (m); + Mat<2,2> ainv; + CalcInverse (a, ainv); + inv = Trans (m) * ainv; +} + +void CalcInverse (const Mat<3,2> & m, Mat<2,3> & inv); + +inline void CalcInverse (const Mat<3,2> & m, Mat<2,3> & inv) +{ + Mat<2,2> a = Trans (m) * m; + Mat<2,2> ainv; + CalcInverse (a, ainv); + inv = ainv * Trans (m); +} + + +double Det (const Mat<2,2> & m); +double Det (const Mat<3,3> & m); + +// eigenvalues of a symmetric matrix +void EigenValues (const Mat<3,3> & m, Vec<3> & ev); +void EigenValues (const Mat<2,2> & m, Vec<3> & ev); + +#endif diff --git a/contrib/Netgen/libsrc/gprim/geomobjects.hpp b/contrib/Netgen/libsrc/gprim/geomobjects.hpp new file mode 100644 index 0000000000000000000000000000000000000000..87c38d9bffb2cacb984d747d34707ae9c827e1dc --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomobjects.hpp @@ -0,0 +1,359 @@ +#ifndef FILE_OBJECTS +#define FILE_OBJECTS + +/* *************************************************************************/ +/* File: geomobjects.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + + +template <int D> class Vec; +template <int D> class Point; + + +template <int D> +class Point +{ + +protected: + double x[D]; + +public: + Point () { ; } + Point (double ax) { x[0] = ax; } + Point (double ax, double ay) { x[0] = ax; x[1] = ay; } + Point (double ax, double ay, double az) + { x[0] = ax; x[1] = ay; x[2] = az; } + Point (double ax, double ay, double az, double au) + { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au;} + + Point (const Point<D> & p2) + { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } + + explicit Point (const Vec<D> & v) + { for (int i = 0; i < D; i++) x[i] = v(i); } + + + Point & operator= (const Point<D> & p2) + { + for (int i = 0; i < D; i++) x[i] = p2.x[i]; + return *this; + } + + Point & operator= (double val) + { + for (int i = 0; i < D; i++) x[i] = val; + return *this; + } + + double & operator() (int i) { return x[i]; } + const double & operator() (int i) const { return x[i]; } + + operator const double* () const { return x; } +}; + + + + + +template <int D> +class Vec +{ + +protected: + double x[D]; + +public: + Vec () { ; } // for (int i = 0; i < D; i++) x[i] = 0; } + Vec (double ax) { for (int i = 0; i < D; i++) x[i] = ax; } + Vec (double ax, double ay) { x[0] = ax; x[1] = ay; } + Vec (double ax, double ay, double az) + { x[0] = ax; x[1] = ay; x[2] = az; } + Vec (double ax, double ay, double az, double au) + { x[0] = ax; x[1] = ay; x[2] = az; x[3] = au; } + + Vec (const Vec<D> & p2) + { for (int i = 0; i < D; i++) x[i] = p2.x[i]; } + + explicit Vec (const Point<D> & p) + { for (int i = 0; i < D; i++) x[i] = p(i); } + + Vec (const Vec<D> & p1, const Vec<D> & p2) + { for(int i=0; i<D; i++) x[i] = p2(i)-p1(1); } + + + + Vec & operator= (const Vec<D> & p2) + { + for (int i = 0; i < D; i++) x[i] = p2.x[i]; + return *this; + } + + Vec & operator= (double s) + { + for (int i = 0; i < D; i++) x[i] = s; + return *this; + } + + double & operator() (int i) { return x[i]; } + const double & operator() (int i) const { return x[i]; } + + operator const double* () const { return x; } + + double Length () const + { + double l = 0; + for (int i = 0; i < D; i++) + l += x[i] * x[i]; + return sqrt (l); + } + + double Length2 () const + { + double l = 0; + for (int i = 0; i < D; i++) + l += x[i] * x[i]; + return l; + } + + const Vec<D> & Normalize () + { + double l = Length(); + if (l != 0) + for (int i = 0; i < D; i++) + x[i] /= l; + return *this; + } + + Vec<D> GetNormal () const; +}; + + + + + +template <int H, int W=H> +class Mat +{ + +protected: + double x[H*W]; + +public: + Mat () { ; } + Mat (const Mat & b) + { for (int i = 0; i < H*W; i++) x[i] = b.x[i]; } + + Mat & operator= (double s) + { + for (int i = 0; i < H*W; i++) x[i] = s; + return *this; + } + + Mat & operator= (const Mat & b) + { + for (int i = 0; i < H*W; i++) x[i] = b.x[i]; + return *this; + } + + double & operator() (int i, int j) { return x[i*W+j]; } + const double & operator() (int i, int j) const { return x[i*W+j]; } + double & operator() (int i) { return x[i]; } + const double & operator() (int i) const { return x[i]; } + + Vec<H> Col (int i) const + { + Vec<H> hv; + for (int j = 0; j < H; j++) + hv(j) = x[j*W+i]; + return hv; + } + + Vec<W> Row (int i) const + { + Vec<W> hv; + for (int j = 0; j < W; j++) + hv(j) = x[i*W+j]; + return hv; + } + + void Solve (const Vec<H> & rhs, Vec<W> & sol) const + { + Mat<W,H> inv; + CalcInverse (*this, inv); + sol = inv * rhs; + } +}; + + + + +template <int D> +class Box +{ +protected: + Point<D> pmin, pmax; +public: + Box () { ; } + Box ( const Point<D> & p1, const Point<D> & p2) + { + for (int i = 0; i < D; i++) + { + pmin(i) = min2(p1(i), p2(i)); + pmax(i) = max2(p1(i), p2(i)); + } + } + + enum EB_TYPE { EMPTY_BOX = 1 }; + Box ( EB_TYPE et ) + { + pmin = Point<3> (1e99, 1e99, 1e99); + pmax = Point<3> (-1e99, -1e99, -1e99); + } + + const Point<D> & PMin () const { return pmin; } + const Point<D> & PMax () const { return pmax; } + + void Set (const Point<D> & p) + { pmin = pmax = p; } + + void Add (const Point<D> & p) + { + for (int i = 0; i < D; i++) + { + if (p(i) < pmin(i)) pmin(i) = p(i); + else if (p(i) > pmax(i)) pmax(i) = p(i); + } + } + + Point<D> Center () const + { + Point<D> c; + for (int i = 0; i < D; i++) + c(i) = 0.5 * (pmin(i)+pmax(i)); + return c; + } + double Diam () const { return Abs (pmax-pmin); } + + Point<D> GetPointNr (int nr) const + { + Point<D> p; + for (int i = 0; i < D; i++) + { + p(i) = (nr & 1) ? pmax(i) : pmin(i); + nr >>= 1; + } + return p; + } + + + bool Intersect (const Box<D> & box2) const + { + for (int i = 0; i < D; i++) + if (pmin(i) > box2.pmax(i) || + pmax(i) < box2.pmin(i)) return 0; + return 1; + } + + + bool IsIn (const Point<D> & p) const + { + for (int i = 0; i < D; i++) + if (p(i) < pmin(i) || p(i) > pmax(i)) return 0; + return 1; + } + + + void Increase (double dist) + { + for (int i = 0; i < D; i++) + { + pmin(i) -= dist; + pmax(i) += dist; + } + } +}; + + + + +template <int D> +class BoxSphere : public Box<D> +{ +protected: + /// + Point<D> c; + /// + double diam; + /// + double inner; +public: + /// + BoxSphere () { }; + /// + BoxSphere (const Box<D> & box) + : Box<D> (box) + { + CalcDiamCenter(); + }; + + /// + BoxSphere ( Point<D> apmin, Point<D> apmax ) + : Box<D> (apmin, apmax) + { + CalcDiamCenter(); + } + + /// + const Point<D> & Center () const { return c; } + /// + double Diam () const { return diam; } + /// + double Inner () const { return inner; } + + + /// + void GetSubBox (int nr, BoxSphere & sbox) const + { + for (int i = 0; i < D; i++) + { + if (nr & 1) + { + sbox.pmin(i) = c(i); + sbox.pmax(i) = this->pmax(i); + } + else + { + sbox.pmin(i) = this->pmin(i); + sbox.pmax(i) = c(i); + } + sbox.c(i) = 0.5 * (sbox.pmin(i) + sbox.pmax(i)); + nr >>= 1; + } + sbox.diam = 0.5 * diam; + sbox.inner = 0.5 * inner; + } + + + /// + void CalcDiamCenter () + { + c = Box<D>::Center (); + diam = Dist (this->pmin, this->pmax); + + inner = this->pmax(0) - this->pmin(0); + for (int i = 1; i < D; i++) + if (this->pmax(i) - this->pmin(i) < inner) + inner = this->pmax(i) - this->pmin(i); + } + +}; + + + + + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/geomops.hpp b/contrib/Netgen/libsrc/gprim/geomops.hpp new file mode 100644 index 0000000000000000000000000000000000000000..755f35a87886bf237e01893549f4dd5d6cc04aae --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomops.hpp @@ -0,0 +1,391 @@ +#ifndef FILE_GEOMOPS +#define FILE_GEOMOPS + +/* *************************************************************************/ +/* File: geomops.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Jul. 02 */ +/* *************************************************************************/ + + +/* + +Point - Vector operations + + */ + + +template <int D> +inline Vec<D> operator+ (const Vec<D> & a, const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) + b(i); + return res; +} + + + +template <int D> +inline Point<D> operator+ (const Point<D> & a, const Vec<D> & b) +{ + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) + b(i); + return res; +} + + + +template <int D> +inline Vec<D> operator- (const Point<D> & a, const Point<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; +} + +template <int D> +inline Point<D> operator- (const Point<D> & a, const Vec<D> & b) +{ + Point<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; +} + +template <int D> +inline Vec<D> operator- (const Vec<D> & a, const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = a(i) - b(i); + return res; +} + + + +template <int D> +inline Vec<D> operator* (double s, const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = s * b(i); + return res; +} + + +template <int D> +inline double operator* (const Vec<D> & a, const Vec<D> & b) +{ + double sum = 0; + for (int i = 0; i < D; i++) + sum += a(i) * b(i); + return sum; +} + + + +template <int D> +inline Vec<D> operator- (const Vec<D> & b) +{ + Vec<D> res; + for (int i = 0; i < D; i++) + res(i) = -b(i); + return res; +} + + +template <int D> +inline Point<D> & operator+= (Point<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) += b(i); + return a; +} + +template <int D> +inline Vec<D> & operator+= (Vec<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) += b(i); + return a; +} + + +template <int D> +inline Point<D> & operator-= (Point<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) -= b(i); + return a; +} + +template <int D> +inline Vec<D> & operator-= (Vec<D> & a, const Vec<D> & b) +{ + for (int i = 0; i < D; i++) + a(i) -= b(i); + return a; +} + + + +template <int D> +inline Vec<D> & operator*= (Vec<D> & a, double s) +{ + for (int i = 0; i < D; i++) + a(i) *= s; + return a; +} + + +template <int D> +inline Vec<D> & operator/= (Vec<D> & a, double s) +{ + for (int i = 0; i < D; i++) + a(i) /= s; + return a; +} + + + + +// Matrix - Vector operations + +/* +template <int H, int W> +inline Vec<H> operator* (const Mat<H,W> & m, const Vec<W> & v) +{ + Vec<H> res; + for (int i = 0; i < H; i++) + { + res(i) = 0; + for (int j = 0; j < W; j++) + res(i) += m(i,j) * v(j); + } + return res; +} +*/ + +// thanks to VC60 partial template specialization features !!! + +inline Vec<2> operator* (const Mat<2,2> & m, const Vec<2> & v) +{ + Vec<2> res; + for (int i = 0; i < 2; i++) + { + res(i) = 0; + for (int j = 0; j < 2; j++) + res(i) += m(i,j) * v(j); + } + return res; +} + +inline Vec<2> operator* (const Mat<2,3> & m, const Vec<3> & v) +{ + Vec<2> res; + for (int i = 0; i < 2; i++) + { + res(i) = 0; + for (int j = 0; j < 3; j++) + res(i) += m(i,j) * v(j); + } + return res; +} + + +inline Vec<3> operator* (const Mat<3,2> & m, const Vec<2> & v) +{ + Vec<3> res; + for (int i = 0; i < 3; i++) + { + res(i) = 0; + for (int j = 0; j < 2; j++) + res(i) += m(i,j) * v(j); + } + return res; +} + + +inline Vec<3> operator* (const Mat<3,3> & m, const Vec<3> & v) +{ + Vec<3> res; + for (int i = 0; i < 3; i++) + { + res(i) = 0; + for (int j = 0; j < 3; j++) + res(i) += m(i,j) * v(j); + } + return res; +} + + + + + + + +/* +template <int H1, int W1, int H2, int W2> +inline Mat<H1,W2> operator* (const Mat<H1,W1> & a, const Mat<H2,W2> & b) +{ + Mat<H1,W2> m; + for (int i = 0; i < H1; i++) + for (int j = 0; j < W2; j++) + { + double sum = 0; + for (int k = 0; k < W1; k++) + sum += a(i,k) * b(k, j); + m(i,j) = sum; + } + return m; +} +*/ + +inline Mat<2,2> operator* (const Mat<2,2> & a, const Mat<2,2> & b) +{ + Mat<2,2> m; + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + { + double sum = 0; + for (int k = 0; k < 2; k++) + sum += a(i,k) * b(k, j); + m(i,j) = sum; + } + return m; +} + +inline Mat<2,2> operator* (const Mat<2,3> & a, const Mat<3,2> & b) +{ + Mat<2,2> m; + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + { + double sum = 0; + for (int k = 0; k < 3; k++) + sum += a(i,k) * b(k, j); + m(i,j) = sum; + } + return m; +} + + +inline Mat<3,2> operator* (const Mat<3,2> & a, const Mat<2,2> & b) +{ + Mat<3,2> m; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + { + double sum = 0; + for (int k = 0; k < 2; k++) + sum += a(i,k) * b(k, j); + m(i,j) = sum; + } + return m; +} + + + +inline Mat<2,3> operator* (const Mat<2,2> & a, const Mat<2,3> & b) +{ + Mat<2,3> m; + for (int i = 0; i < 2; i++) + for (int j = 0; j < 3; j++) + { + double sum = 0; + for (int k = 0; k < 2; k++) + sum += a(i,k) * b(k, j); + m(i,j) = sum; + } + return m; +} + + +inline Mat<3,3> operator* (const Mat<3,3> & a, const Mat<3,3> & b) +{ + Mat<3,3> m; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + { + double sum = 0; + for (int k = 0; k < 3; k++) + sum += a(i,k) * b(k, j); + m(i,j) = sum; + } + return m; +} + + + + + + + + +template <int H, int W> +inline Mat<W,H> Trans (const Mat<H,W> & m) +{ + Mat<W,H> res; + for (int i = 0; i < H; i++) + for (int j = 0; j < W; j++) + res(j,i) = m(i,j); + return res; +} + + + + + + + + + + + +template <int D> +inline ostream & operator<< (ostream & ost, const Vec<D> & a) +{ + ost << "("; + for (int i = 0; i < D-1; i++) + ost << a(i) << ", "; + ost << a(D-1) << ")"; + return ost; +} + +template <int D> +inline ostream & operator<< (ostream & ost, const Point<D> & a) +{ + ost << "("; + for (int i = 0; i < D-1; i++) + ost << a(i) << ", "; + ost << a(D-1) << ")"; + return ost; +} + +template <int D> +inline ostream & operator<< (ostream & ost, const Box<D> & b) +{ + ost << b.PMin() << " - " << b.PMax(); + return ost; +} + +template <int H, int W> +inline ostream & operator<< (ostream & ost, const Mat<H,W> & m) +{ + ost << "("; + for (int i = 0; i < H; i++) + { + for (int j = 0; j < W; j++) + ost << m(i,j) << " "; + ost << endl; + } + return ost; +} + + + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/geomtest3d.cpp b/contrib/Netgen/libsrc/gprim/geomtest3d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..20a3be0b349734219799ab428cfd11286e9fcaed --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomtest3d.cpp @@ -0,0 +1,1150 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include <gprim.hpp> + +namespace netgen +{ +int +IntersectTriangleLine (const Point<3> ** tri, const Point<3> ** line) +{ + Vec3d vl(*line[0], *line[1]); + Vec3d vt1(*tri[0], *tri[1]); + Vec3d vt2(*tri[0], *tri[2]); + Vec3d vrs(*tri[0], *line[0]); + + static DenseMatrix a(3), ainv(3); + static Vector rs(3), lami(3); + int i; + + /* + (*testout) << "Tri-Line inters: " << endl + << "tri = " << *tri[0] << ", " << *tri[1] << ", " << *tri[2] << endl + << "line = " << *line[0] << ", " << *line[1] << endl; + */ + for (i = 1; i <= 3; i++) + { + a.Elem(i, 1) = -vl.X(i); + a.Elem(i, 2) = vt1.X(i); + a.Elem(i, 3) = vt2.X(i); + rs.Elem(i) = vrs.X(i); + } + + double det = a.Det(); + + double arel = vl.Length() * vt1.Length() * vt2.Length(); + /* + double amax = 0; + for (i = 1; i <= 9; i++) + if (fabs (a.Get(i)) > amax) + amax = fabs(a.Get(i)); + */ + // new !!!! + if (fabs (det) <= 1e-10 * arel) + { +#ifdef DEVELOP + // line parallel to triangle ! + // cout << "ERROR: IntersectTriangleLine degenerated" << endl; + // (*testout) << "WARNING: IntersectTriangleLine degenerated\n"; + /* + (*testout) << "lin-tri intersection: " << endl + << "line = " << *line[0] << " - " << *line[1] << endl + << "tri = " << *tri[0] << " - " << *tri[1] << " - " << *tri[2] << endl + << "lami = " << lami << endl + << "pc = " << ( *line[0] + lami.Get(1) * vl ) << endl + << " = " << ( *tri[0] + lami.Get(2) * vt1 + lami.Get(3) * vt2) << endl + << " a = " << a << endl + << " ainv = " << ainv << endl + << " det(a) = " << det << endl + << " rs = " << rs << endl; + */ +#endif + return 0; + } + + CalcInverse (a, ainv); + ainv.Mult (rs, lami); + + // (*testout) << "lami = " << lami << endl; + + double eps = 1e-6; + if ( + (lami.Get(1) >= -eps && lami.Get(1) <= 1+eps && + lami.Get(2) >= -eps && lami.Get(3) >= -eps && + lami.Get(2) + lami.Get(3) <= 1+eps) && ! + (lami.Get(1) >= eps && lami.Get(1) <= 1-eps && + lami.Get(2) >= eps && lami.Get(3) >= eps && + lami.Get(2) + lami.Get(3) <= 1-eps) ) + + + { +#ifdef DEVELOP + // cout << "WARNING: IntersectTriangleLine degenerated" << endl; + (*testout) << "WARNING: IntersectTriangleLine numerical inexact" << endl; + + (*testout) << "lin-tri intersection: " << endl + << "line = " << *line[0] << " - " << *line[1] << endl + << "tri = " << *tri[0] << " - " << *tri[1] << " - " << *tri[2] << endl + << "lami = " << lami << endl + << "pc = " << ( *line[0] + lami.Get(1) * vl ) << endl + << " = " << ( *tri[0] + lami.Get(2) * vt1 + lami.Get(3) * vt2) << endl + << " a = " << a << endl + << " ainv = " << ainv << endl + << " det(a) = " << det << endl + << " rs = " << rs << endl; +#endif + } + + + if (lami.Get(1) >= 0 && lami.Get(1) <= 1 && + lami.Get(2) >= 0 && lami.Get(3) >= 0 && lami.Get(2) + lami.Get(3) <= 1) + { + + return 1; + } + + return 0; +} + + + + + +int IntersectTetTriangle (const Point<3> ** tet, const Point<3> ** tri, + const int * tetpi, const int * tripi) +{ + int i, j; + double diam = Dist (*tri[0], *tri[1]); + double epsrel = 1e-8; + double eps = diam * epsrel; + + double eps2 = eps * eps; + int cnt = 0; + + int tetp1 = -1, tetp2 = -1; + int trip1 = -1, trip2 = -1; + int tetp3, tetp4, trip3; + + /* + for (i = 0; i < 4; i++) + loctetpi[i] = -1; + */ + + + if (!tetpi) + { + for (i = 0; i <= 2; i++) + { + // loctripi[i] = -1; + for (j = 0; j <= 3; j++) + { + if (Dist2 (*tet[j], *tri[i]) < eps2) + { + // loctripi[i] = j; + // loctetpi[j] = i; + cnt++; + tetp2 = tetp1; + tetp1 = j; + trip2 = trip1; + trip1 = i; + break; + } + } + } + } + else + { + for (i = 0; i <= 2; i++) + { + // loctripi[i] = -1; + for (j = 0; j <= 3; j++) + { + if (tetpi[j] == tripi[i]) + { + // loctripi[i] = j; + // loctetpi[j] = i; + cnt++; + tetp2 = tetp1; + tetp1 = j; + trip2 = trip1; + trip1 = i; + break; + } + } + } + } + + // (*testout) << "cnt = " << cnt << endl; + + + // (*testout) << "tet-trig inters, cnt = " << cnt << endl; + + // cnt .. number of common points + switch (cnt) + { + case 0: + { + Vec3d no, n; + int inpi[3]; + + // check, if some trigpoint is in tet: + + for (j = 0; j < 3; j++) + inpi[j] = 1; + + for (i = 1; i <= 4; i++) + { + int pi1 = i % 4; + int pi2 = (i+1) % 4; + int pi3 = (i+2) % 4; + int pi4 = (i+3) % 4; + + Vec3d v1 (*tet[pi1], *tet[pi2]); + Vec3d v2 (*tet[pi1], *tet[pi3]); + Vec3d v3 (*tet[pi1], *tet[pi4]); + Cross (v1, v2, n); + + // n /= n.Length(); + double nl = n.Length(); + + if (v3 * n > 0) + n *= -1; + + int outeri = 1; + for (j = 0; j < 3; j++) + { + Vec3d v(*tet[pi1], *tri[j]); + if ( v * n < eps * nl) + outeri = 0; + else + inpi[j] = 0; + } + + if (outeri) + return 0; + } + + if (inpi[0] || inpi[1] || inpi[2]) + { + return 1; + } + + + // check, if some tet edge intersects triangle: + const Point<3> * line[2], *tetf[3]; + for (i = 0; i <= 2; i++) + for (j = i+1; j <= 3; j++) + { + line[0] = tet[i]; + line[1] = tet[j]; + + if (IntersectTriangleLine (tri, &line[0])) + return 1; + } + + // check, if triangle line intersects tet face: + for (i = 0; i <= 3; i++) + { + for (j = 0; j <= 2; j++) + tetf[j] = tet[(i+j) % 4]; + + for (j = 0; j <= 2; j++) + { + line[0] = tri[j]; + line[1] = tri[(j+1) % 3]; + + if (IntersectTriangleLine (&tetf[0], &line[0])) + return 1; + } + } + + + return 0; +//GH break; + } + case 1: + { + trip2 = 0; + while (trip2 == trip1) + trip2++; + trip3 = 3 - trip1 - trip2; + + tetp2 = 0; + while (tetp2 == tetp1) + tetp2++; + tetp3 = 0; + while (tetp3 == tetp1 || tetp3 == tetp2) + tetp3++; + tetp4 = 6 - tetp1 - tetp2 - tetp3; + + Vec3d vtri1 = *tri[trip2] - *tri[trip1]; + Vec3d vtri2 = *tri[trip3] - *tri[trip1]; + Vec3d ntri; + Cross (vtri1, vtri2, ntri); + + // tri durch tet ? + // fehlt noch + + + // test 3 tet-faces: + for (i = 1; i <= 3; i++) + { + Vec3d vtet1, vtet2; + switch (i) + { + case 1: + { + vtet1 = *tet[tetp2] - *tet[tetp1]; + vtet2 = *tet[tetp3] - *tet[tetp1]; + break; + } + case 2: + { + vtet1 = *tet[tetp3] - *tet[tetp1]; + vtet2 = *tet[tetp4] - *tet[tetp1]; + break; + } + case 3: + { + vtet1 = *tet[tetp4] - *tet[tetp1]; + vtet2 = *tet[tetp2] - *tet[tetp1]; + break; + } + } + + Vec3d ntet; + Cross (vtet1, vtet2, ntet); + + Vec3d crline = Cross (ntri, ntet); + + double lcrline = crline.Length(); + + if (lcrline < eps * eps * eps * eps) // new change ! + continue; + + if (vtri1 * crline + vtri2 * crline < 0) + crline *= -1; + + crline /= lcrline; + + double lam1, lam2, lam3, lam4; + LocalCoordinates (vtri1, vtri2, crline, lam1, lam2); + LocalCoordinates (vtet1, vtet2, crline, lam3, lam4); + + if (lam1 > -epsrel && lam2 > -epsrel && + lam3 > -epsrel && lam4 > -epsrel) + { + + /* + (*testout) << "lcrline = " << lcrline + << " eps = " << eps << " diam = " << diam << endl; + + (*testout) << "hit, cnt == 1 " + << "lam1,2,3,4 = " << lam1 << ", " + << lam2 << ", " << lam3 << ", " << lam4 + << "\n"; + */ + return 1; + } + } + return 0; +//GH break; + } + case 2: + { + // common edge + tetp3 = 0; + while (tetp3 == tetp1 || tetp3 == tetp2) + tetp3++; + tetp4 = 6 - tetp1 - tetp2 - tetp3; + trip3 = 3 - trip1 - trip2; + + // (*testout) << "trip1,2,3 = " << trip1 << ", " << trip2 << ", " << trip3 << endl; + // (*testout) << "tetp1,2,3,4 = " << tetp1 << ", " << tetp2 + // << ", " << tetp3 << ", " << tetp4 << endl; + + Vec3d vtri = *tri[trip3] - *tri[trip1]; + Vec3d vtet1 = *tet[tetp3] - *tri[trip1]; + Vec3d vtet2 = *tet[tetp4] - *tri[trip1]; + + Vec3d n = *tri[trip2] - *tri[trip1]; + n /= n.Length(); + + vtet1 -= (n * vtet1) * n; + vtet2 -= (n * vtet2) * n; + + + double lam1, lam2; + LocalCoordinates (vtet1, vtet2, vtri, lam1, lam2); + + if (lam1 < -epsrel || lam2 < -epsrel) + return 0; + else + { + /* + + (*testout) << "vtet1 = " << vtet1 << endl; + (*testout) << "vtet2 = " << vtet2 << endl; + (*testout) << "vtri = " << vtri << endl; + (*testout) << "lam1 = " << lam1 << " lam2 = " << lam2 << endl; + (*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2)) + << " = " << (vtet1 * vtri) << endl; + (*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2)) + << " = " << (vtet2 * vtri) << endl; + + (*testout) << "tet = "; + for (j = 0; j < 4; j++) + (*testout) << (*tet[j]) << " "; + (*testout) << endl; + (*testout) << "tri = "; + for (j = 0; j < 3; j++) + (*testout) << (*tri[j]) << " "; + (*testout) << endl; + + (*testout) << "hit, cnt == 2" << endl; + */ + + return 1; + } + + break; + } + case 3: + { + // common face + return 0; + } + } + + (*testout) << "hit, cnt = " << cnt << endl; + return 1; +} + + + + + +int IntersectTetTriangleRef (const Point<3> ** tri, const int * tripi) +{ + int i, j; + double eps = 1e-8; + double eps2 = eps * eps; + + static Point<3> rtetp1(0, 0, 0); + static Point<3> rtetp2(1, 0, 0); + static Point<3> rtetp3(0, 1, 0); + static Point<3> rtetp4(0, 0, 1); + + static const Point<3> * tet[] = { &rtetp1, &rtetp2, &rtetp3, &rtetp4 }; + static int tetpi[] = { 1, 2, 3, 4 }; + + + // return IntersectTetTriangle (tet, tri, tetpi, tripi); + + + int cnt = 0; + + int tetp1 = -1, tetp2 = -1; + int trip1 = -1, trip2 = -1; + int tetp3, tetp4, trip3; + + /* + if (!tetpi) + { + for (i = 0; i <= 2; i++) + { + for (j = 0; j <= 3; j++) + { + if (Dist2 (*tet[j], *tri[i]) < eps2) + { + cnt++; + tetp2 = tetp1; + tetp1 = j; + trip2 = trip1; + trip1 = i; + break; + } + } + } + } + else + */ + { + for (i = 0; i <= 2; i++) + { + for (j = 0; j <= 3; j++) + { + if (tetpi[j] == tripi[i]) + { + cnt++; + tetp2 = tetp1; + tetp1 = j; + trip2 = trip1; + trip1 = i; + break; + } + } + } + } + + // (*testout) << "cnt = " << cnt << endl; + + + switch (cnt) + { + case 0: + { + Vec3d no, n; + // int inpi[3]; + int pside[3][4]; + + for (j = 0; j < 3; j++) + { + pside[j][0] = (*tri[j])(0) > -eps; + pside[j][1] = (*tri[j])(1) > -eps; + pside[j][2] = (*tri[j])(2) > -eps; + pside[j][3] = (*tri[j])(0) + (*tri[j])(1) + (*tri[j])(2) < 1+eps; + } + + + for (j = 0; j < 4; j++) + { + if (!pside[0][j] && !pside[1][j] && !pside[2][j]) + return 0; + } + + for (j = 0; j < 3; j++) + { + if (pside[j][0] && pside[j][1] && pside[j][2] && pside[j][3]) + return 1; + } + + + const Point<3> * line[2], *tetf[3]; + for (i = 0; i <= 2; i++) + for (j = i+1; j <= 3; j++) + { + line[0] = tet[i]; + line[1] = tet[j]; + + if (IntersectTriangleLine (tri, &line[0])) + return 1; + } + + for (i = 0; i <= 3; i++) + { + for (j = 0; j <= 2; j++) + tetf[j] = tet[(i+j) % 4]; + + for (j = 0; j <= 2; j++) + { + line[0] = tri[j]; + line[1] = tri[(j+1) % 3]; + + if (IntersectTriangleLine (&tetf[0], &line[0])) + return 1; + } + } + + + return 0; + break; + } + case 1: + { + trip2 = 0; + if (trip2 == trip1) + trip2++; + trip3 = 3 - trip1 - trip2; + + tetp2 = 0; + while (tetp2 == tetp1) + tetp2++; + tetp3 = 0; + while (tetp3 == tetp1 || tetp3 == tetp2) + tetp3++; + tetp4 = 6 - tetp1 - tetp2 - tetp3; + + Vec3d vtri1 = *tri[trip2] - *tri[trip1]; + Vec3d vtri2 = *tri[trip3] - *tri[trip1]; + Vec3d ntri; + Cross (vtri1, vtri2, ntri); + + // tri durch tet ? + + /* + Vec3d vtet1(*tet[tetp1], *tet[tetp2]); + Vec3d vtet2(*tet[tetp1], *tet[tetp3]); + Vec3d vtet3(*tet[tetp1], *tet[tetp4]); + Vec3d sol; + + SolveLinearSystem (vtet1, vtet2, vtet3, vtri1, sol); + if (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0) + return 1; + + SolveLinearSystem (vtet1, vtet2, vtet3, vtri2, sol); + if (sol.X() > 0 && sol.Y() > 0 && sol.Z() > 0) + return 1; + */ + + // test 3 tet-faces: + for (i = 1; i <= 3; i++) + { + Vec3d vtet1, vtet2; + switch (i) + { + case 1: + { + vtet1 = *tet[tetp2] - *tet[tetp1]; + vtet2 = *tet[tetp3] - *tet[tetp1]; + break; + } + case 2: + { + vtet1 = *tet[tetp3] - *tet[tetp1]; + vtet2 = *tet[tetp4] - *tet[tetp1]; + break; + } + case 3: + { + vtet1 = *tet[tetp4] - *tet[tetp1]; + vtet2 = *tet[tetp2] - *tet[tetp1]; + break; + } + } + + Vec3d ntet; + Cross (vtet1, vtet2, ntet); + + Vec3d crline = Cross (ntri, ntet); + + double lcrline = crline.Length(); + if (lcrline < eps * eps) + continue; + + + if (vtri1 * crline + vtri2 * crline < 0) + crline *= -1; + + double lam1, lam2, lam3, lam4; + LocalCoordinates (vtri1, vtri2, crline, lam1, lam2); + LocalCoordinates (vtet1, vtet2, crline, lam3, lam4); + + if (lam1 > -eps && lam2 > -eps && + lam3 > -eps && lam4 > -eps) + { + // (*testout) << "hit, cnt == 1" << "\n"; + return 1; + } + } + + return 0; + break; + } + case 2: + { + // common edge + tetp3 = 0; + while (tetp3 == tetp1 || tetp3 == tetp2) + tetp3++; + tetp4 = 6 - tetp1 - tetp2 - tetp3; + trip3 = 3 - trip1 - trip2; + + // (*testout) << "trip1,2,3 = " << trip1 << ", " << trip2 << ", " << trip3 << endl; + // (*testout) << "tetp1,2,3,4 = " << tetp1 << ", " << tetp2 + // << ", " << tetp3 << ", " << tetp4 << endl; + + Vec3d vtri = *tri[trip3] - *tri[trip1]; + Vec3d vtet1 = *tet[tetp3] - *tri[trip1]; + Vec3d vtet2 = *tet[tetp4] - *tri[trip1]; + + Vec3d n = *tri[trip2] - *tri[trip1]; + n /= n.Length(); + + vtet1 -= (n * vtet1) * n; + vtet2 -= (n * vtet2) * n; + + + double lam1, lam2; + LocalCoordinates (vtet1, vtet2, vtri, lam1, lam2); + + if (lam1 < -eps || lam2 < -eps) + return 0; + else + { + +// (*testout) << "vtet1 = " << vtet1 << endl; +// (*testout) << "vtet2 = " << vtet2 << endl; +// (*testout) << "vtri = " << vtri << endl; +// (*testout) << "lam1 = " << lam1 << " lam2 = " << lam2 << endl; + +// (*testout) << (lam1 * (vtet1 * vtet1) + lam2 * (vtet1 * vtet2)) +// << " = " << (vtet1 * vtri) << endl; +// (*testout) << (lam1 * (vtet1 * vtet2) + lam2 * (vtet2 * vtet2)) +// << " = " << (vtet2 * vtri) << endl; + +// (*testout) << "tet = "; +// for (j = 0; j < 4; j++) +// (*testout) << (*tet[j]) << " "; +// (*testout) << endl; +// (*testout) << "tri = "; +// for (j = 0; j < 3; j++) +// (*testout) << (*tri[j]) << " "; +// (*testout) << endl; + +// (*testout) << "hit, cnt == 2" << endl; + + return 1; + } + + break; + } + case 3: + { + // common face + return 0; + } + } + + (*testout) << "hit, cnt = " << cnt << endl; + return 1; +} + + + + + + + + + + + +int IntersectTriangleTriangle (const Point<3> ** tri1, const Point<3> ** tri2) +{ + int i, j; + double diam = Dist (*tri1[0], *tri1[1]); + double epsrel = 1e-8; + double eps = diam * epsrel; + double eps2 = eps * eps; + + + + int cnt = 0; + /* + int tri1pi[3]; + int tri2pi[3]; + */ + + // int tri1p1 = -1; + /// int tri1p2 = -1; + // int tri2p1 = -1; + // int tri2p2 = -1; + // int tri1p3, tri2p3; + + /* + for (i = 0; i < 3; i++) + tri1pi[i] = -1; + */ + for (i = 0; i <= 2; i++) + { + // tri2pi[i] = -1; + for (j = 0; j <= 2; j++) + { + if (Dist2 (*tri1[j], *tri2[i]) < eps2) + { + // tri2pi[i] = j; + // tri1pi[j] = i; + cnt++; + // tri1p2 = tri1p1; + // tri1p1 = j; + // tri2p2 = tri2p1; + // tri2p1 = i; + break; + } + } + } + + switch (cnt) + { + case 0: + { + const Point<3> * line[2]; + + for (i = 0; i <= 2; i++) + { + line[0] = tri2[i]; + line[1] = tri2[(i+1)%3]; + + if (IntersectTriangleLine (tri1, &line[0])) + { + (*testout) << "int1, line = " << *line[0] << " - " << *line[1] << endl; + return 1; + } + } + + for (i = 0; i <= 2; i++) + { + line[0] = tri1[i]; + line[1] = tri1[(i+1)%3]; + + if (IntersectTriangleLine (tri2, &line[0])) + { + (*testout) << "int2, line = " << *line[0] << " - " << *line[1] << endl; + return 1; + } + } + break; + } + default: + return 0; + } + + return 0; +} + + + +void +LocalCoordinates (const Vec3d & e1, const Vec3d & e2, + const Vec3d & v, double & lam1, double & lam2) +{ + double m11 = e1 * e1; + double m12 = e1 * e2; + double m22 = e2 * e2; + double rs1 = v * e1; + double rs2 = v * e2; + + double det = m11 * m22 - m12 * m12; + lam1 = (rs1 * m22 - rs2 * m12)/det; + lam2 = (m11 * rs2 - m12 * rs1)/det; +} + + + + + +int CalcSphereCenter (const Point<3> ** pts, Point<3> & c) +{ + Vec3d row1 (*pts[0], *pts[1]); + Vec3d row2 (*pts[0], *pts[2]); + Vec3d row3 (*pts[0], *pts[3]); + + Vec3d rhs(0.5 * (row1*row1), + 0.5 * (row2*row2), + 0.5 * (row3*row3)); + Transpose (row1, row2, row3); + + Vec3d sol; + if (SolveLinearSystem (row1, row2, row3, rhs, sol)) + { + (*testout) << "CalcSphereCenter: degenerated" << endl; + return 1; + } + + c = *pts[0] + sol; + return 0; +} + + + + + +int CalcTriangleCenter (const Point3d ** pts, Point3d & c) +{ + static DenseMatrix a(2), inva(2); + static Vector rs(2), sol(2); + double h = Dist(*pts[0], *pts[1]); + + Vec3d v1(*pts[0], *pts[1]); + Vec3d v2(*pts[0], *pts[2]); + + rs.Elem(1) = v1 * v1; + rs.Elem(2) = v2 * v2; + + a.Elem(1,1) = 2 * rs.Get(1); + a.Elem(1,2) = a.Elem(2,1) = 2 * (v1 * v2); + a.Elem(2,2) = 2 * rs.Get(2); + + if (fabs (a.Det()) <= 1e-12 * h * h) + { + (*testout) << "CalcTriangleCenter: degenerated" << endl; + return 1; + } + + CalcInverse (a, inva); + inva.Mult (rs, sol); + + c = *pts[0]; + v1 *= sol.Get(1); + v2 *= sol.Get(2); + + c += v1; + c += v2; + + return 0; +} + + + +double ComputeCylinderRadius (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Point3d & p4) +{ + Vec3d v12(p1, p2); + Vec3d v13(p1, p3); + Vec3d v14(p1, p4); + + Vec3d n1 = Cross (v12, v13); + Vec3d n2 = Cross (v14, v12); + + double n1l = n1.Length(); + double n2l = n2.Length(); + n1 /= n1l; + n2 /= n2l; + + double v12len = v12.Length(); + double h1 = n1l / v12len; + double h2 = n2l / v12len; + + /* + (*testout) << "n1 = " << n1 << " n2 = " << n2 + << "h1 = " << h1 << " h2 = " << h2 << endl; + */ + return ComputeCylinderRadius (n1, n2, h1, h2); +} + + + + +/* + Two triangles T1 and T2 have normals n1 and n2. + The height over the common edge is h1, and h2. + */ +double ComputeCylinderRadius (const Vec3d & n1, const Vec3d & n2, + double h1, double h2) +{ + Vec3d t1, t2; + double n11 = n1 * n1; + double n12 = n1 * n2; + double n22 = n2 * n2; + double det = n11 * n22 - n12 * n12; + + if (fabs (det) < 1e-14 * n11 * n22) + return 1e20; + + // a biorthogonal bases (ti * nj) = delta_ij: + t1 = (n22/det) * n1 + (-n12/det) * n2; + t2 = (-n12/det) * n1 + (n11/det) * n2; + + // normalize: + t1 /= t1.Length(); + t2 /= t2.Length(); + + /* + vector to center point has form + v = lam1 n1 + lam2 n2 + and fulfills + t2 v = h1/2 + t1 v = h2/2 + */ + + double lam1 = 0.5 * h2 / (n1 * t1); + double lam2 = 0.5 * h1 / (n2 * t2); + + double rad = (lam1 * n1 + lam2 * n2).Length(); + /* + (*testout) << "n1 = " << n1 + << " n2 = " << n2 + << " t1 = " << t1 + << " t2 = " << t2 + << " rad = " << rad << endl; + */ + return rad; +} + + + + + + +double MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p) +{ + Vec2d v(lp1, lp2); + Vec2d vlp(lp1, p); + + // dist(lam) = \| vlp \|^2 - 2 lam (v1p, v) + lam^2 \| v \|^2 + + // lam = (v * vlp) / (v * v); + // if (lam < 0) lam = 0; + // if (lam > 1) lam = 1; + + double num = v*vlp; + double den = v*v; + + if (num <= 0) + return Dist2 (lp1, p); + + if (num >= den) + return Dist2 (lp2, p); + + if (den > 0) + { + return vlp.Length2() - num * num /den; + } + else + return vlp.Length2(); +} + + + + +double MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p) +{ + Vec3d v(lp1, lp2); + Vec3d vlp(lp1, p); + + // dist(lam) = \| vlp \|^2 - 2 lam (v1p, v) + lam^2 \| v \|^2 + + // lam = (v * vlp) / (v * v); + // if (lam < 0) lam = 0; + // if (lam > 1) lam = 1; + + double num = v*vlp; + double den = v*v; + + if (num <= 0) + return Dist2 (lp1, p); + + if (num >= den) + return Dist2 (lp2, p); + + if (den > 0) + { + return vlp.Length2() - num * num /den; + } + else + return vlp.Length2(); +} + + + +double MinDistTP2 (const Point3d & tp1, const Point3d & tp2, + const Point3d & tp3, const Point3d & p) +{ + double lam1, lam2; + double res; + + LocalCoordinates (Vec3d (tp1, tp2), Vec3d (tp1, tp3), + Vec3d (tp1, p), lam1, lam2); + int in1 = lam1 >= 0; + int in2 = lam2 >= 0; + int in3 = lam1+lam2 <= 1; + + if (in1 && in2 && in3) + { + Point3d pp = tp1 + lam1 * Vec3d(tp1, tp2) + lam2 * Vec3d (tp1, tp3); + res = Dist2 (p, pp); + } + else + { + res = Dist2 (tp1, p); + if (!in1) + { + double hv = MinDistLP2 (tp1, tp3, p); + if (hv < res) res = hv; + } + if (!in2) + { + double hv = MinDistLP2 (tp1, tp2, p); + if (hv < res) res = hv; + } + if (!in3) + { + double hv = MinDistLP2 (tp2, tp3, p); + if (hv < res) res = hv; + } + /* + double d1 = MinDistLP2 (tp1, tp2, p); + double d2 = MinDistLP2 (tp1, tp3, p); + double d3 = MinDistLP2 (tp2, tp3, p); + res = min3 (d1, d2, d3); + */ + } + + return res; + + Vec3d pp1(tp1, p); + Vec3d v1(tp1, tp2), v2(tp1, tp3); + + double c = pp1.Length2(); + double cx = -2 * (pp1 * v1); + double cy = -2 * (pp1 * v2); + double cxx = v1.Length2(); + double cxy = 2 * (v1 * v2); + double cyy = v2.Length2(); + + QuadraticPolynomial2V pol (-c, -cx, -cy, -cxx, -cxy, -cyy); + double res2 = - pol.MaxUnitTriangle (); + + if (fabs (res - res2) > 1e-8) + cout << "res and res2 differ: " << res << " != " << res2 << endl; + return res2; +} + + +// 0 checks !!! +double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2, + const Point3d & l2p1, const Point3d & l2p2) +{ + // dist(lam1,lam2) = \| l2p1+lam2v2 - (l1p1+lam1 v1) \| + // min ! + + Vec3d l1l2 (l1p1, l2p1); + Vec3d v1 (l1p1, l1p2); + Vec3d v2 (l2p1, l2p2); + + double a11, a12, a22, rs1, rs2; + double lam1, lam2, det; + + a11 = v1*v1; + a12 = -(v1*v2); + a22 = v2*v2; + rs1 = l1l2 * v1; + rs2 = - (l1l2 * v2); + + det = a11 * a22 - a12 * a12; + if (det < 1e-14 * a11 * a22) + det = 1e-14 * a11 * a22; // regularization should be stable + + if (det < 1e-20) + det = 1e-20; + + + lam1 = (a22 * rs1 - a12 * rs2) / det; + lam2 = (-a12 * rs1 + a11 * rs2) / det; + + if (lam1 >= 0 && lam2 >= 0 && lam1 <= 1 && lam2 <= 1) + { + Vec3d v = l1l2 + (-lam1) * v1 + lam2 * v2; + return v.Length2(); + } + + double minv, hv; + minv = MinDistLP2 (l1p1, l1p2, l2p1); + hv = MinDistLP2 (l1p1, l1p2, l2p2); + if (hv < minv) minv = hv; + + hv = MinDistLP2 (l2p1, l2p2, l1p1); + if (hv < minv) minv = hv; + hv = MinDistLP2 (l2p1, l2p2, l1p2); + if (hv < minv) minv = hv; + + return minv; +} + +} + + diff --git a/contrib/Netgen/libsrc/gprim/geomtest3d.hpp b/contrib/Netgen/libsrc/gprim/geomtest3d.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7ce362d05222c857288ea0e8d9c8fc1f25fc90e6 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/geomtest3d.hpp @@ -0,0 +1,80 @@ +#ifndef FILE_GEOMTEST3D +#define FILE_GEOMTEST3D + +/* *************************************************************************/ +/* File: geomtest3d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 13. Feb. 98 */ +/* *************************************************************************/ + + + +extern int +IntersectTriangleLine (const Point<3> ** tri, const Point<3> ** line); + + + +/** + Returns 0, iff + closure (tet) cup closure (tri) is empty, one corner point of tet, + one edge of tet or one face of tet + */ +extern int +IntersectTetTriangle (const Point<3> ** tet, const Point<3> ** tri, + const int * tetpi = NULL, const int * tripi = NULL); + +/** + Same test as above, but tet int reference position (0, ex, ey, ez), + tetpi = 1, 2, 4, 5 + */ +extern int +IntersectTetTriangleRef (const Point3d ** tri, const int * tripi = NULL); + + +// 1, iff not regular triangulation +extern int +IntersectTriangleTriangle (const Point<3> ** tri1, const Point<3> ** tri2); + + +extern void +LocalCoordinates (const Vec3d & e1, const Vec3d & e2, + const Vec3d & v, double & lam1, double & lam2); + +/// return 1 = degenerated sphere +extern int +CalcSphereCenter (const Point<3> ** pts, Point<3> & c); + +/// return 1 = degenerated triangle +extern int +CalcTriangleCenter (const Point3d ** pts, Point3d & c); + + + +/* + Compute radius of cylinder fitting 4 points. + cylinder axis is in the direction of p1-p2 +*/ +extern double ComputeCylinderRadius (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4); + +/* + Two triangles T1 and T2 have normals n1 and n2. + The height over the common edge is h1, and h2. + Radius of cylinder fitting both triangles +*/ +extern double ComputeCylinderRadius (const Vec3d & n1, const Vec3d & n2, + double h1, double h2); + + +extern double MinDistLP2 (const Point2d & lp1, const Point2d & lp2, const Point2d & p); + +extern double MinDistLP2 (const Point3d & lp1, const Point3d & lp2, const Point3d & p); + +extern double MinDistTP2 (const Point3d & tp1, const Point3d & tp2, + const Point3d & tp3, const Point3d & p); + +extern double MinDistLL2 (const Point3d & l1p1, const Point3d & l1p2, + const Point3d & l2p1, const Point3d & l2p2); + + +#endif diff --git a/contrib/Netgen/libsrc/gprim/gprim.hpp b/contrib/Netgen/libsrc/gprim/gprim.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0f57ebac869366f0bb1eeefe4c65ca93c1ab4526 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/gprim.hpp @@ -0,0 +1,26 @@ +#ifndef FILE_GPRIM +#define FILE_GPRIM + +/* *************************************************************************/ +/* File: gprim.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 14. Aug. 97 */ +/* *************************************************************************/ + + +namespace netgen +{ +#include "geomobjects.hpp" +#include "geomops.hpp" +#include "geomfuncs.hpp" + +#include "geom2d.hpp" +#include "geom3d.hpp" +#include "geomtest3d.hpp" +// #include "rot3d.hpp" +#include "transform3d.hpp" +// #include "reftrans.hpp" +#include "adtree.hpp" +} + +#endif diff --git a/contrib/Netgen/libsrc/gprim/transform3d.cpp b/contrib/Netgen/libsrc/gprim/transform3d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea62fffe5a0e9563644b0428f822ca1bbf2cac77 --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/transform3d.cpp @@ -0,0 +1,173 @@ +#include <mystdlib.h> + +#include <myadt.hpp> +#include <gprim.hpp> +#include <linalg.hpp> + +namespace netgen +{ + +Transformation3d :: Transformation3d () +{ + int i, j; + for (i = 0; i < 3; i++) + { + offset[i] = 0; + for (j = 0; j < 3; j++) + lin[i][j] = 0; + } +} + +Transformation3d :: Transformation3d (const Vec3d & translate) +{ + int i, j; + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + lin[i][j] = 0; + for (i = 0; i < 3; i++) + { + offset[i] = translate.X(i+1); + lin[i][i] = 1; + } +} + + +Transformation3d :: +Transformation3d (const Point3d & c, double alpha, + double beta, double gamma) +{ + // total = T_c x Rot_0 x T_c^{-1} + // Use Euler angles, see many books from tech mech, e.g. + // Shabana "multibody systems" + + Transformation3d tc(c); + Transformation3d tcinv; + tc.CalcInverse (tcinv); + + Transformation3d r1, r2, r3, ht, ht2; + r1.SetAxisRotation (3, alpha); + r2.SetAxisRotation (1, beta); + r3.SetAxisRotation (3, gamma); + + ht.Combine (tc, r3); + ht2.Combine (ht, r2); + ht.Combine (ht2, r1); + Combine (ht, tcinv); + + cout << "Rotation - Transformation:" << (*this) << endl; + // (*testout) << "Rotation - Transformation:" << (*this) << endl; +} + + + + +Transformation3d :: Transformation3d (const Point3d ** pp) +{ + int i, j; + for (i = 1; i <= 3; i++) + { + offset[i-1] = (*pp[0]).X(i); + for (j = 1; j <= 3; j++) + lin[i-1][j-1] = (*pp[j]).X(i) - (*pp[0]).X(i); + } +} + +Transformation3d :: Transformation3d (const Point3d pp[]) +{ + int i, j; + for (i = 1; i <= 3; i++) + { + offset[i-1] = pp[0].X(i); + for (j = 1; j <= 3; j++) + lin[i-1][j-1] = pp[j].X(i) - pp[0].X(i); + } +} + + +void Transformation3d :: CalcInverse (Transformation3d & inv) const +{ + static DenseMatrix a(3), inva(3); + static Vector b(3), sol(3); + int i, j; + + for (i = 1; i <= 3; i++) + { + b.Elem(i) = offset[i-1]; + for (j = 1; j <= 3; j++) + a.Elem(i, j) = lin[i-1][j-1]; + } + + ::netgen::CalcInverse (a, inva); + inva.Mult (b, sol); + + for (i = 1; i <= 3; i++) + { + inv.offset[i-1] = -sol.Get(i); + for (j = 1; j <= 3; j++) + inv.lin[i-1][j-1] = inva.Elem(i, j); + } +} + + +void Transformation3d:: +Combine (const Transformation3d & ta, const Transformation3d & tb) +{ + int i, j, k; + + // o = o_a+ m_a o_b + // m = m_a m_b + + for (i = 0; i <= 2; i++) + { + offset[i] = ta.offset[i]; + for (j = 0; j <= 2; j++) + offset[i] += ta.lin[i][j] * tb.offset[j]; + } + + for (i = 0; i <= 2; i++) + for (j = 0; j <= 2; j++) + { + lin[i][j] = 0; + for (k = 0; k <= 2; k++) + lin[i][j] += ta.lin[i][k] * tb.lin[k][j]; + } +} +void Transformation3d :: SetAxisRotation (int dir, double alpha) +{ + double co = cos(alpha); + double si = sin(alpha); + dir--; + int pos1 = (dir+1) % 3; + int pos2 = (dir+2) % 3; + + int i, j; + for (i = 0; i <= 2; i++) + { + offset[i] = 0; + for (j = 0; j <= 2; j++) + lin[i][j] = 0; + } + + lin[dir][dir] = 1; + lin[pos1][pos1] = co; + lin[pos2][pos2] = co; + lin[pos1][pos2] = si; + lin[pos2][pos1] = -si; +} + +ostream & operator<< (ostream & ost, Transformation3d & trans) +{ + int i, j; + ost << "offset = "; + for (i = 0; i <= 2; i++) + ost << trans.offset[i] << " "; + ost << endl << "linear = " << endl; + for (i = 0; i <= 2; i++) + { + for (j = 0; j <= 2; j++) + ost << trans.lin[i][j] << " "; + ost << endl; + } + return ost; +} +} diff --git a/contrib/Netgen/libsrc/gprim/transform3d.hpp b/contrib/Netgen/libsrc/gprim/transform3d.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2754173e2469ebf5e2df1823abb6a03ddf17e26f --- /dev/null +++ b/contrib/Netgen/libsrc/gprim/transform3d.hpp @@ -0,0 +1,190 @@ +#ifndef FILE_TRANSFORM3D +#define FILE_TRANSFORM3D + +/* *************************************************************************/ +/* File: transform3d.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 22. Mar. 98 */ +/* *************************************************************************/ + +/* + Affine - Linear mapping in 3D space + */ + +class Transformation3d; +ostream & operator<< (ostream & ost, Transformation3d & trans); + +class Transformation3d +{ + double lin[3][3]; + double offset[3]; +public: + /// + Transformation3d (); + /// Unit tet is mapped to tet descibed by pp + Transformation3d (const Point3d ** pp); + /// Unit tet is mapped to tet descibed by pp + Transformation3d (const Point3d pp[]); + /// translation + Transformation3d (const Vec3d & translate); + /// rotation with ... + Transformation3d (const Point3d & c, double alpha, double beta, double gamma); + /// + void CalcInverse (Transformation3d & inv) const; + /// this = ta x tb + void Combine (const Transformation3d & ta, const Transformation3d & tb); + /// dir = 1..3 (== x..z) + void SetAxisRotation (int dir, double alpha); + /// + void Transform (const Point3d & from, Point3d & to) const + { + for (int i = 1; i <= 3; i++) + { + to.X(i) = offset[i-1] + lin[i-1][0] * from.X(1) + + lin[i-1][1] * from.X(2) + lin[i-1][2] * from.X(3); + } + } + + /// + void Transform (Point3d & p) const + { + Point3d hp; + Transform (p, hp); + p = hp; + } + + /// transform vector, apply only linear part, not offset + void Transform (const Vec3d & from, Vec3d & to) const + { + for (int i = 1; i <= 3; i++) + { + to.X(i) = lin[i-1][0] * from.X(1) + + lin[i-1][1] * from.X(2) + lin[i-1][2] * from.X(3); + } + } + friend ostream & operator<< (ostream & ost, Transformation3d & trans); +}; + + + + + + + + + + + + + + +template <int D> +class Transformation +{ + Mat<D> m; + Vec<D> v; +public: + /// + Transformation () { m = 0; v = 0; } + + /// Unit tet is mapped to tet descibed by pp + Transformation (const Point<D> * pp); + + /// translation + Transformation (const Vec<D> & translate) + { + v = translate; + m = 0; + for (int i = 0; i < D; i++) + m(i,i) = 1; + } + + // rotation with ... + Transformation (const Point<D> & c, double alpha, double beta, double gamma) + { + // total = T_c x Rot_0 x T_c^{-1} + // Use Euler angles, see many books from tech mech, e.g. + // Shabana "multibody systems" + + Vec<D> vc(c); + Transformation<D> tc(vc); + Transformation<D> tcinv(-vc); + // tc.CalcInverse (tcinv); + + Transformation<D> r1, r2, r3, ht, ht2; + r1.SetAxisRotation (3, alpha); + r2.SetAxisRotation (1, beta); + r3.SetAxisRotation (3, gamma); + + ht.Combine (tc, r3); + ht2.Combine (ht, r2); + ht.Combine (ht2, r1); + Combine (ht, tcinv); + + // cout << "Rotation - Transformation:" << (*this) << endl; + // (*testout) << "Rotation - Transformation:" << (*this) << endl; + } + + /// + void CalcInverse (Transformation & inv) const; + + /// this = ta x tb + void Combine (const Transformation & ta, const Transformation & tb) + { + v = ta.v + ta.m * tb.v; + m = ta.m * tb.m; + } + + + + /// dir = 1..3 (== x..z) + void SetAxisRotation (int dir, double alpha) + { + double co = cos(alpha); + double si = sin(alpha); + dir--; + int pos1 = (dir+1) % 3; + int pos2 = (dir+2) % 3; + + int i, j; + for (i = 0; i <= 2; i++) + { + v(i) = 0; + for (j = 0; j <= 2; j++) + m(i,j) = 0; + } + + m(dir,dir) = 1; + m(pos1, pos1) = co; + m(pos2, pos2) = co; + m(pos1, pos2) = si; + m(pos2, pos1) = -si; + } + + /// + void Transform (const Point<D> & from, Point<D> & to) const + { + to = Point<D> (v + m * Vec<D>(from)); + } + + void Transform (Point<D> & p) const + { + p = Point<D> (v + m * Vec<D>(p)); + } + + + + /// transform vector, apply only linear part, not offset + void Transform (const Vec<D> & from, Vec<D> & to) const + { + to = m * from; + } +}; + +template <int D> +ostream & operator<< (ostream & ost, Transformation<D> & trans); + + + + +#endif diff --git a/contrib/Netgen/libsrc/include/FlexLexer.h b/contrib/Netgen/libsrc/include/FlexLexer.h new file mode 100644 index 0000000000000000000000000000000000000000..f6120759597d8b5aae428f7f8940481a6fa40fd5 --- /dev/null +++ b/contrib/Netgen/libsrc/include/FlexLexer.h @@ -0,0 +1,184 @@ +// $Header: /cvsroot/gmsh/contrib/Netgen/libsrc/include/FlexLexer.h,v 1.3 2008-09-24 18:04:44 geuzaine Exp $ + +// FlexLexer.h -- define interfaces for lexical analyzer classes generated +// by flex + +// Copyright (c) 1993 The Regents of the University of California. +// All rights reserved. +// +// This code is derived from software contributed to Berkeley by +// Kent Williams and Tom Epperly. +// +// Redistribution and use in source and binary forms are permitted provided +// that: (1) source distributions retain this entire copyright notice and +// comment, and (2) distributions including binaries display the following +// acknowledgement: ``This product includes software developed by the +// University of California, Berkeley and its contributors'' in the +// documentation or other materials provided with the distribution and in +// all advertising materials mentioning features or use of this software. +// Neither the name of the University nor the names of its contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +// This file defines FlexLexer, an abstract class which specifies the +// external interface provided to flex C++ lexer objects, and yyFlexLexer, +// which defines a particular lexer class. +// +// If you want to create multiple lexer classes, you use the -P flag +// to rename each yyFlexLexer to some other xxFlexLexer. You then +// include <FlexLexer.h> in your other sources once per lexer class: +// +// #undef yyFlexLexer +// #define yyFlexLexer xxFlexLexer +// #include <FlexLexer.h> +// +// #undef yyFlexLexer +// #define yyFlexLexer zzFlexLexer +// #include <FlexLexer.h> +// ... + +#ifndef __FLEX_LEXER_H +// Never included before - need to define base class. +#define __FLEX_LEXER_H + + +extern "C++" { +struct yy_buffer_state; +typedef int yy_state_type; + +class FlexLexer { +public: + virtual ~FlexLexer() { } + + const char* YYText() { return yytext; } + int YYLeng() { return yyleng; } + + virtual void + yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0; + virtual struct yy_buffer_state* + yy_create_buffer( istream* s, int size ) = 0; + virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0; + virtual void yyrestart( istream* s ) = 0; + + virtual int yylex() = 0; + + // Call yylex with new input/output sources. + int yylex( istream* new_in, ostream* new_out = 0 ) + { + switch_streams( new_in, new_out ); + return yylex(); + } + + // Switch to new input/output streams. A nil stream pointer + // indicates "keep the current one". + virtual void switch_streams( istream* new_in = 0, + ostream* new_out = 0 ) = 0; + + int lineno() const { return yylineno; } + + int debug() const { return yy_flex_debug; } + void set_debug( int flag ) { yy_flex_debug = flag; } + +protected: + char* yytext; + int yyleng; + int yylineno; // only maintained if you use %option yylineno + int yy_flex_debug; // only has effect with -d or "%option debug" +}; + +} +#endif + +#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce) +// Either this is the first time through (yyFlexLexerOnce not defined), +// or this is a repeated include to define a different flavor of +// yyFlexLexer, as discussed in the flex man page. +#define yyFlexLexerOnce + +class yyFlexLexer : public FlexLexer { +public: + // arg_yyin and arg_yyout default to the cin and cout, but we + // only make that assignment when initializing in yylex(). + yyFlexLexer( istream* arg_yyin = 0, ostream* arg_yyout = 0 ); + + virtual ~yyFlexLexer(); + + void yy_switch_to_buffer( struct yy_buffer_state* new_buffer ); + struct yy_buffer_state* yy_create_buffer( istream* s, int size ); + void yy_delete_buffer( struct yy_buffer_state* b ); + void yyrestart( istream* s ); + + virtual int yylex(); + virtual void switch_streams( istream* new_in, ostream* new_out ); + +protected: + virtual int LexerInput( char* buf, int max_size ); + virtual void LexerOutput( const char* buf, int size ); + virtual void LexerError( const char* msg ); + + void yyunput( int c, char* buf_ptr ); + int yyinput(); + + void yy_load_buffer_state(); + void yy_init_buffer( struct yy_buffer_state* b, istream* s ); + void yy_flush_buffer( struct yy_buffer_state* b ); + + int yy_start_stack_ptr; + int yy_start_stack_depth; + int* yy_start_stack; + + void yy_push_state( int new_state ); + void yy_pop_state(); + int yy_top_state(); + + yy_state_type yy_get_previous_state(); + yy_state_type yy_try_NUL_trans( yy_state_type current_state ); + int yy_get_next_buffer(); + + istream* yyin; // input source for default LexerInput + ostream* yyout; // output sink for default LexerOutput + + struct yy_buffer_state* yy_current_buffer; + + // yy_hold_char holds the character lost when yytext is formed. + char yy_hold_char; + + // Number of characters read into yy_ch_buf. + int yy_n_chars; + + // Points to current character in buffer. + char* yy_c_buf_p; + + int yy_init; // whether we need to initialize + int yy_start; // start state number + + // Flag which is used to allow yywrap()'s to do buffer switches + // instead of setting up a fresh yyin. A bit of a hack ... + int yy_did_buffer_switch_on_eof; + + // The following are not always needed, but may be depending + // on use of certain flex features (like REJECT or yymore()). + + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + yy_state_type* yy_state_buf; + yy_state_type* yy_state_ptr; + + char* yy_full_match; + int* yy_full_state; + int yy_full_lp; + + int yy_lp; + int yy_looking_for_trail_begin; + + int yy_more_flag; + int yy_more_len; + int yy_more_offset; + int yy_prev_more_offset; +}; + +#endif diff --git a/contrib/Netgen/libsrc/include/acisgeom.hpp b/contrib/Netgen/libsrc/include/acisgeom.hpp new file mode 100644 index 0000000000000000000000000000000000000000..491b7720dbdb18f49b2fce4530708f0c890170f0 --- /dev/null +++ b/contrib/Netgen/libsrc/include/acisgeom.hpp @@ -0,0 +1,3 @@ +#ifdef ACIS +#include "../acisgeom/acisgeom.hpp" +#endif diff --git a/contrib/Netgen/libsrc/include/csg.hpp b/contrib/Netgen/libsrc/include/csg.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ffd45ef0bf4fb948a3efd2432eb8e7b6c111900c --- /dev/null +++ b/contrib/Netgen/libsrc/include/csg.hpp @@ -0,0 +1 @@ +#include "../csg/csg.hpp" diff --git a/contrib/Netgen/libsrc/include/geometry2d.hpp b/contrib/Netgen/libsrc/include/geometry2d.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bf0965c228fc36935a9c2a539aa8d1ea133ad158 --- /dev/null +++ b/contrib/Netgen/libsrc/include/geometry2d.hpp @@ -0,0 +1 @@ +#include "../geom2d/geometry2d.hpp" diff --git a/contrib/Netgen/libsrc/include/gprim.hpp b/contrib/Netgen/libsrc/include/gprim.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1e827aaf8c01c9b7296876c16309c3462e772ac8 --- /dev/null +++ b/contrib/Netgen/libsrc/include/gprim.hpp @@ -0,0 +1 @@ +#include "../gprim/gprim.hpp" diff --git a/contrib/Netgen/libsrc/include/incvis.hpp b/contrib/Netgen/libsrc/include/incvis.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0f2b1026a0670f49b5976cd82249dea3e1815f6c --- /dev/null +++ b/contrib/Netgen/libsrc/include/incvis.hpp @@ -0,0 +1,31 @@ +// libraries for User interface: + + +#ifndef NOTCL + +#include <tcl.h> +#include <tk.h> + +#if TK_MAJOR_VERSION==8 && TK_MINOR_VERSION>=4 +#define tcl_const const +#else +#define tcl_const +#endif + +#endif + +#include <GL/gl.h> +#include <GL/glu.h> +#ifndef NOTCL +#include "../../togl/togl.h" +#endif + + + + +// part of OpenGL 1.2, but not in Microsoft's OpenGL 1.1 header: +// GL version sould be checked at runtime +#ifndef GL_CLAMP_TO_EDGE +#define GL_CLAMP_TO_EDGE 0x812F +#endif + diff --git a/contrib/Netgen/libsrc/include/linalg.hpp b/contrib/Netgen/libsrc/include/linalg.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e96bd036c3ed3606d458b2db3275fb273d27d138 --- /dev/null +++ b/contrib/Netgen/libsrc/include/linalg.hpp @@ -0,0 +1 @@ +#include "../linalg/linalg.hpp" diff --git a/contrib/Netgen/libsrc/include/meshing.hpp b/contrib/Netgen/libsrc/include/meshing.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e41a88f9f221c969e56923d95d5dc9c5214b98f3 --- /dev/null +++ b/contrib/Netgen/libsrc/include/meshing.hpp @@ -0,0 +1 @@ +#include <../meshing/meshing.hpp> diff --git a/contrib/Netgen/libsrc/include/myadt.hpp b/contrib/Netgen/libsrc/include/myadt.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d36bef05c12d28b9aa35e9c1de6fcd8df749dcc9 --- /dev/null +++ b/contrib/Netgen/libsrc/include/myadt.hpp @@ -0,0 +1 @@ +#include <../general/myadt.hpp> diff --git a/contrib/Netgen/libsrc/include/mydefs.hpp b/contrib/Netgen/libsrc/include/mydefs.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c34ce56a8e03cd621577d526e57b65ce358346a6 --- /dev/null +++ b/contrib/Netgen/libsrc/include/mydefs.hpp @@ -0,0 +1,29 @@ +#ifndef FILE_MYDEFS +#define FILE_MYDEFS + +/**************************************************************************/ +/* File: mydefs.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 10. Mar. 98 */ +/**************************************************************************/ + +/* + defines for graphics, testmodes, ... +*/ + + +// #define DEBUG + + +#define noDEMOVERSION +#define noDEVELOP +#define noSTEP +#define noSOLIDGEOM + +#define noDEMOAPP +#define noMODELLER + +#define noSTAT_STREAM +#define noLOG_STREAM + +#endif diff --git a/contrib/Netgen/libsrc/include/mystdlib.h b/contrib/Netgen/libsrc/include/mystdlib.h new file mode 100644 index 0000000000000000000000000000000000000000..939a268e6ea1eebe0d3c8d7235a75c256f0b5abb --- /dev/null +++ b/contrib/Netgen/libsrc/include/mystdlib.h @@ -0,0 +1,104 @@ +#ifndef FILE_MYSTDLIB +#define FILE_MYSTDLIB + + +#include <iostream> +#include <iomanip> +#include <fstream> +#include <sstream> + +#ifdef OLDCINCLUDE + +// e.g., CC compiler on SGI +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <malloc.h> +#include <ctype.h> +#include <time.h> + +#else + +// new standard +#include <cstdlib> +#include <cstdio> +#include <cmath> +#include <cctype> +#include <ctime> +#include <cstring> +#include <climits> +#endif + + + +#include <new> +#include <string> +#include <typeinfo> + +#ifdef PARALLEL +#undef SEEK_SET +#undef SEEK_CUR +#undef SEEK_END +#include <mpi.h> +#endif + +#ifdef _OPENMP +#include <omp.h> +#endif + + +#ifdef METIS +namespace metis { extern "C" { +#include <metis.h> +} } +#endif + + + +#ifndef NO_PARALLEL_THREADS +#ifndef WIN32 +#include <pthread.h> +#endif +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + + +/*** Windows headers ***/ +#ifdef _MSC_VER +# define WIN32_LEAN_AND_MEAN +# ifndef NO_PARALLEL_THREADS +# include <afxwin.h> +# include <afxmt.h> +# endif +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN +# include <winnt.h> + +#else +# ifndef NO_PARALLEL_THREADS +# include <pthread.h> +# endif +#endif + +/* +extern void* operator new(std::size_t) throw (std::bad_alloc); +extern void* operator new[](std::size_t) throw (std::bad_alloc); +extern void operator delete(void*) throw(); +extern void operator delete[](void*) throw(); +*/ + +/* +extern int mem_alloc; +extern int mem_total_alloc; +extern int mem_max_alloc; +extern int mem_total_alloc_array; +extern int mem_total_alloc_table; +*/ + +using namespace std; + +#endif + diff --git a/contrib/Netgen/libsrc/include/occgeom.hpp b/contrib/Netgen/libsrc/include/occgeom.hpp new file mode 100644 index 0000000000000000000000000000000000000000..af258e0df032193ef448a72102d8c7215ec9d9b0 --- /dev/null +++ b/contrib/Netgen/libsrc/include/occgeom.hpp @@ -0,0 +1 @@ +#include "../occ/occgeom.hpp" diff --git a/contrib/Netgen/libsrc/include/opti.hpp b/contrib/Netgen/libsrc/include/opti.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6b8a0b61c8d1eb081531c9351ab2a7b3ba85fbe8 --- /dev/null +++ b/contrib/Netgen/libsrc/include/opti.hpp @@ -0,0 +1 @@ +#include "../opti/opti.hpp" diff --git a/contrib/Netgen/libsrc/include/parallel.hpp b/contrib/Netgen/libsrc/include/parallel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4ba662f810ea4c6240c57cf64608803abc18f602 --- /dev/null +++ b/contrib/Netgen/libsrc/include/parallel.hpp @@ -0,0 +1 @@ +#include "../parallel/parallel.hpp" diff --git a/contrib/Netgen/libsrc/include/stepgeom.hpp b/contrib/Netgen/libsrc/include/stepgeom.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d2c5c5e41e9683fe5f8537c4fae9337306c1d02a --- /dev/null +++ b/contrib/Netgen/libsrc/include/stepgeom.hpp @@ -0,0 +1,10 @@ +#include "../stepgeom/geomanif.hh" +#include "../stepgeom/geopac2d.hh" +#include "../stepgeom/geopac3d.hh" +#include "../stepgeom/geosplinesurf.hh" +#include "../stepgeom/algprim.hh" +#include "../stepgeom/scenery.hh" +#include "../stepgeom/brep.hh" +#include "../stepgeom/adtcrit.hh" +#include "../stepgeom/STEPgeom.hh" +#include "../stepgeom/visapprox.hh" diff --git a/contrib/Netgen/libsrc/include/stepreader.hpp b/contrib/Netgen/libsrc/include/stepreader.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0214d58d9dcf3297ee09ef74abd6a03af3e72390 --- /dev/null +++ b/contrib/Netgen/libsrc/include/stepreader.hpp @@ -0,0 +1 @@ +#include "../stepgeom/STEPread.hh" diff --git a/contrib/Netgen/libsrc/include/stlgeom.hpp b/contrib/Netgen/libsrc/include/stlgeom.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f1eea264e11281071ae2ae1235bc098ff3352ce6 --- /dev/null +++ b/contrib/Netgen/libsrc/include/stlgeom.hpp @@ -0,0 +1 @@ +#include <../stlgeom/stlgeom.hpp> diff --git a/contrib/Netgen/libsrc/include/visual.hpp b/contrib/Netgen/libsrc/include/visual.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f026f5a458c6c131b65b0b1d616d42eefae015a5 --- /dev/null +++ b/contrib/Netgen/libsrc/include/visual.hpp @@ -0,0 +1 @@ +#include "../visualization/visual.hpp" diff --git a/contrib/Netgen/libsrc/interface/Makefile b/contrib/Netgen/libsrc/interface/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..8c8cfcc69ac4168b896925f83e74ee06ec9a638f --- /dev/null +++ b/contrib/Netgen/libsrc/interface/Makefile @@ -0,0 +1,9 @@ +# MODIFIED FOR GMSH +#src = nginterface.cpp writeuser.cpp writediffpack.cpp writeabaqus.cpp writefluent.cpp writepermas.cpp writetochnog.cpp writetecplot.cpp wuchemnitz.cpp writetochnog.cpp writefeap.cpp writeelmer.cpp writegmsh.cpp writejcm.cpp writetet.cpp writedolfin.cpp readuser.cpp importsolution.cpp readtetmesh.cpp +src = nglib.cpp +# +lib = nginterface +libpath = libsrc/interface +# +include ../makefile.inc +# diff --git a/contrib/Netgen/libsrc/interface/importsolution.cpp b/contrib/Netgen/libsrc/interface/importsolution.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f9d3e6727658f295aacf6fee57333d4a414a834 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/importsolution.cpp @@ -0,0 +1,129 @@ +// +// Read solution file +// + + +#include <mystdlib.h> + + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +#include "nginterface.h" + +namespace netgen +{ +#include "writeuser.hpp" + + +void ImportSolution (const char * filename) +{ + ifstream inf (filename); + char buf[100], name[1000]; + int i, size, comps, order; + bool iscomplex; + const char * type; + Flags flags; + + while (1) + { + buf[0] = 0; + inf >> buf; + if (strcmp (buf, "solution") == 0) + { + inf >> name; + + inf >> buf[0]; + flags.DeleteFlags (); + while (buf[0] == '-') + { + inf >> buf[1]; + inf.putback (buf[1]); + if (!isalpha (buf[1])) + { + break; + } + inf >> (buf+1); + flags.SetCommandLineFlag (buf); + buf[0] = 0; + inf >> buf[0]; + } + inf.putback (buf[0]); + + (*testout) << "Flags: " << endl; + flags.PrintFlags (*testout); + (*testout) << "done" << endl; + + size = int(flags.GetNumFlag ("size", Ng_GetNP())); + comps = int(flags.GetNumFlag ("components", 1)); + type = flags.GetStringFlag ("type", "nodal"); + order = int(flags.GetNumFlag ("order", 1)); + iscomplex = flags.GetDefineFlag ("complex"); + + double * sol = new double[size*comps]; + + (*testout) << "import solution " << name << " size = " << size << " comps = " << comps << " order = " << order << endl; + + for (i = 0; i < size*comps; i++) + { + inf >> sol[i]; + // (*testout) << "sol: " << sol[i] << endl; + } + + Ng_SolutionData soldata; + Ng_InitSolutionData (&soldata); + soldata.name = name; + soldata.data = sol; + soldata.dist = comps; + soldata.components = comps; + soldata.order = order; + soldata.iscomplex = iscomplex; + soldata.soltype = NG_SOLUTION_NODAL; + soldata.draw_surface = 1; + soldata.draw_volume = 1; + if (strcmp (type, "element") == 0) + { + soldata.soltype = NG_SOLUTION_ELEMENT; + soldata.draw_surface = 0; + } + if (strcmp (type, "surfaceelement") == 0) + { + soldata.soltype = NG_SOLUTION_SURFACE_ELEMENT; + soldata.draw_volume = 0; + } + if (strcmp (type, "noncontinuous") == 0) + soldata.soltype = NG_SOLUTION_NONCONTINUOUS; + if (strcmp (type, "surfacenoncontinuous") == 0) + soldata.soltype = NG_SOLUTION_SURFACE_NONCONTINUOUS; + + Ng_SetSolutionData (&soldata); + } + else + { + // cout << "kw = (" << buf << ")" << endl; + (*testout) << "kw = (" << buf << ")" << endl; + break; + } + } + /* + struct Ng_SolutionData + { + char * name; // name of gridfunction + double * data; // solution values + int components; // used components in solution vector + int dist; // num of doubles per entry (alignment!) + Ng_SolutionType soltype; // type of solution function + }; + + // initialize solution data with default arguments + void Ng_InitSolutionData (Ng_SolutionData * soldata); + // set solution data + void Ng_SetSolutionData (Ng_SolutionData * soldata); + */ +} + + + +} diff --git a/contrib/Netgen/libsrc/interface/nginterface.cpp b/contrib/Netgen/libsrc/interface/nginterface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..400a7a19eb9c5ad4b610659db2d7b749d91b9496 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/nginterface.cpp @@ -0,0 +1,2412 @@ +#include <mystdlib.h> + + +#include <meshing.hpp> +#include <csg.hpp> +#include <geometry2d.hpp> +#include <stlgeom.hpp> + + +#ifdef OCCGEOMETRY +#include <occgeom.hpp> +#endif + +#ifdef ACIS +#include <acisgeom.hpp> +#endif + +#ifdef SOCKETS +#include "../sockets/sockets.hpp" +#endif + +#ifndef NOTCL +#include <visual.hpp> +#endif + + +#include "nginterface.h" + +// #include <FlexLexer.h> + + +// #include <mystdlib.h> + + +namespace netgen +{ +#include "writeuser.hpp" + + extern AutoPtr<Mesh> mesh; +#ifndef NOTCL + extern VisualSceneMesh vsmesh; + extern Tcl_Interp * tcl_interp; +#endif + + extern AutoPtr<SplineGeometry2d> geometry2d; + extern AutoPtr<CSGeometry> geometry; + extern STLGeometry * stlgeometry; + +#ifdef OCCGEOMETRY + extern OCCGeometry * occgeometry; +#endif +#ifdef ACIS + extern ACISGeometry * acisgeometry; +#endif + +#ifdef OPENGL + extern VisualSceneSolution vssolution; +#endif + extern CSGeometry * ParseCSG (istream & istr); + +#ifdef SOCKETS + extern AutoPtr<ClientSocket> clientsocket; + //extern ARRAY< AutoPtr < ServerInfo > > servers; + extern ARRAY< ServerInfo* > servers; +#endif +} + + +using namespace netgen; + +/* + extern void * operator new (size_t s); + extern void * operator new [] (size_t s); + extern void operator delete (void * p); + extern void operator delete [] (void * p); +*/ + +// extern FlexLexer * lexer; + + + +void Ng_LoadGeometry (const char * filename) +{ + + + if (printmessage_importance>0) + cout << "CALLED NG LOAD GEOMETRY" << endl; + + geometry.Reset (new CSGeometry ()); + geometry2d.Reset (); + +#ifdef OCCGEOMETRY + delete occgeometry; + occgeometry = 0; +#endif +#ifdef ACIS + delete acisgeometry; + acisgeometry = 0; +#endif + + // he: if filename is empty, return + // can be used to reset geometry + if (strcmp(filename,"")==0) + return; + + ifstream infile (filename); + + if ((strcmp (&filename[strlen(filename)-3], "geo") == 0) || + (strcmp (&filename[strlen(filename)-3], "GEO") == 0) || + (strcmp (&filename[strlen(filename)-3], "Geo") == 0)) + { + + + geometry.Reset( netgen::ParseCSG(infile) ); + + if (!geometry) + { + geometry.Reset (new CSGeometry ()); + //throw NgException ("input file not found"); + cerr << "Error: input file \"" << filename << "\" not found" << endl; + } + + geometry -> FindIdenticSurfaces(1e-6); + +#ifdef PARALLEL + int id, rc, ntasks; + MPI_Comm_size(MPI_COMM_WORLD, &ntasks); + MPI_Comm_rank(MPI_COMM_WORLD, &id); + if ( id > 0 ) + { + geometry->CalcTriangleApproximation ( geometry->BoundingBox(), 0.001, 20 ); + return; + } +#endif + + Box<3> box (geometry->BoundingBox()); +#ifdef NOTCL + double detail = 0.001; + double facets = 20; + geometry->CalcTriangleApproximation(box, detail, facets); + +#else + double detail = atof (Tcl_GetVar (tcl_interp, "::geooptions.detail", 0)); + double facets = atof (Tcl_GetVar (tcl_interp, "::geooptions.facets", 0)); + + if (atoi (Tcl_GetVar (tcl_interp, "::geooptions.drawcsg", 0))) + geometry->CalcTriangleApproximation(box, detail, facets); +#endif + } + + else if (strcmp (&filename[strlen(filename)-4], "in2d") == 0) + { + geometry2d.Reset (new SplineGeometry2d()); + geometry2d -> Load (filename); + } + + else if ((strcmp (&filename[strlen(filename)-3], "stl") == 0) || + (strcmp (&filename[strlen(filename)-3], "STL") == 0) || + (strcmp (&filename[strlen(filename)-3], "Stl") == 0)) + { + stlgeometry = STLGeometry :: Load (infile); + stlgeometry->edgesfound = 0; + Mesh meshdummy; + stlgeometry->Clear(); + stlgeometry->BuildEdges(); + stlgeometry->MakeAtlas(meshdummy); + stlgeometry->CalcFaceNums(); + stlgeometry->AddFaceEdges(); + stlgeometry->LinkEdges(); + } + +#ifdef OCCGEOMETRY + else if ((strcmp (&filename[strlen(filename)-4], "iges") == 0) || + (strcmp (&filename[strlen(filename)-3], "igs") == 0) || + (strcmp (&filename[strlen(filename)-3], "IGS") == 0) || + (strcmp (&filename[strlen(filename)-4], "IGES") == 0)) + { + PrintMessage (1, "Load IGES geometry file ", filename); + occgeometry = LoadOCC_IGES (filename); + } + else if ((strcmp (&filename[strlen(filename)-4], "step") == 0) || + (strcmp (&filename[strlen(filename)-3], "stp") == 0) || + (strcmp (&filename[strlen(filename)-3], "STP") == 0) || + (strcmp (&filename[strlen(filename)-4], "STEP") == 0)) + { + PrintMessage (1, "Load STEP geometry file ", filename); + occgeometry = LoadOCC_STEP (filename); + } +#endif + +#ifdef ACIS + else if ( + strcmp (&filename[strlen(filename)-3], "sat") == 0 || + ( strlen(filename) >= 7 && strcmp ( &filename[ strlen( filename)-7 ], "sat.tet" ) == 0 ) + ) + { + PrintMessage (1, "Load ACIS geometry file ", filename); + acisgeometry = LoadACIS_SAT (filename); + } +#endif + else + { + //throw NgException("Unknown geometry extension"); + cerr << "Error: Unknown geometry extension \"" << filename[strlen(filename)-3] << "\"" << endl; + } + + +} + + +void Ng_LoadMeshFromStream ( istream & input ) +{ + mesh.Reset (new Mesh()); + mesh -> Load(input); + if(input.good()) + { + string auxstring; + input >> auxstring; + if(auxstring == "csgsurfaces") + { + if (geometry) + { + geometry.Reset (new CSGeometry ("")); + } + if (stlgeometry) + { + delete stlgeometry; + stlgeometry = NULL; + } +#ifdef OCCGEOMETRY + if (occgeometry) + { + delete occgeometry; + occgeometry = NULL; + } +#endif +#ifdef ACIS + if (acisgeometry) + { + delete acisgeometry; + acisgeometry = NULL; + } +#endif + geometry2d.Reset (0); + + geometry -> LoadSurfaces(input); + } + } + +} + + +void Ng_LoadMesh (const char * filename) +{ + if ( (strlen (filename) > 4) && + strcmp (filename + (strlen (filename)-4), ".vol") != 0 ) + { + mesh.Reset (new Mesh()); + ReadFile(*mesh,filename); + + //mesh->SetGlobalH (mparam.maxh); + //mesh->CalcLocalH(); + return; + } + + ifstream infile(filename); + Ng_LoadMeshFromStream(infile); +} + +void Ng_LoadMeshFromString (char * mesh_as_string) +{ + istringstream instream(mesh_as_string); + Ng_LoadMeshFromStream(instream); +} + + + + +int Ng_GetDimension () +{ + return (mesh) ? mesh->GetDimension() : -1; +} + +int Ng_GetNP () +{ + return (mesh) ? mesh->GetNP() : 0; +} + +int Ng_GetNV () +{ + return (mesh) ? mesh->GetNV() : 0; +} + +int Ng_GetNE () +{ + if(!mesh) return 0; + if (mesh->GetDimension() == 3) + return mesh->GetNE(); + else + return mesh->GetNSE(); +} + +int Ng_GetNSE () +{ + if(!mesh) return 0; + if (mesh->GetDimension() == 3) + return mesh->GetNSE(); + else + return mesh->GetNSeg(); +} + +void Ng_GetPoint (int pi, double * p) +{ + if (pi < 1 || pi > mesh->GetNP()) + { + if (printmessage_importance>0) + cout << "Ng_GetPoint: illegal point " << pi << endl; + return; + } + + const Point3d & hp = mesh->Point (pi); + p[0] = hp.X(); + p[1] = hp.Y(); + if (mesh->GetDimension() == 3) + p[2] = hp.Z(); +} + + +NG_ELEMENT_TYPE Ng_GetElement (int ei, int * epi, int * np) +{ + if (mesh->GetDimension() == 3) + { + int i; + const Element & el = mesh->VolumeElement (ei); + for (i = 0; i < el.GetNP(); i++) + epi[i] = el.PNum(i+1); + + if (np) + *np = el.GetNP(); + + if (el.GetType() == PRISM) + { + // degenerated prism, (should be obsolete) + const int map1[] = { 3, 2, 5, 6, 1 }; + const int map2[] = { 1, 3, 6, 4, 2 }; + const int map3[] = { 2, 1, 4, 5, 3 }; + + const int * map = NULL; + int deg1 = 0, deg2 = 0, deg3 = 0; + //int deg = 0; + if (el.PNum(1) == el.PNum(4)) { map = map1; deg1 = 1; } + if (el.PNum(2) == el.PNum(5)) { map = map2; deg2 = 1; } + if (el.PNum(3) == el.PNum(6)) { map = map3; deg3 = 1; } + + switch (deg1+deg2+deg3) + { + { + case 1: + if (printmessage_importance>0) + cout << "degenerated prism found, deg = 1" << endl; + for (i = 0; i < 5; i++) + epi[i] = el.PNum (map[i]); + + if (np) *np = 5; + return NG_PYRAMID; + break; + } + case 2: + { + if (printmessage_importance>0) + cout << "degenerated prism found, deg = 2" << endl; + if (!deg1) epi[3] = el.PNum(4); + if (!deg2) epi[3] = el.PNum(5); + if (!deg3) epi[3] = el.PNum(6); + + if (np) *np = 4; + return NG_TET; + break; + } + default: + ; + } + + } + + return NG_ELEMENT_TYPE (el.GetType()); + } + else + { + int i; + const Element2d & el = mesh->SurfaceElement (ei); + for (i = 0; i < el.GetNP(); i++) + epi[i] = el.PNum(i+1); + + if (np) *np = el.GetNP(); + return NG_ELEMENT_TYPE (el.GetType()); + /* + switch (el.GetNP()) + { + case 3: return NG_TRIG; + case 4: return NG_QUAD; + case 6: return NG_TRIG6; + } + */ + } + + // should not occur + return NG_TET; +} + + +NG_ELEMENT_TYPE Ng_GetElementType (int ei) +{ + if (mesh->GetDimension() == 3) + { + return NG_ELEMENT_TYPE (mesh->VolumeElement (ei).GetType()); + } + else + { + const Element2d & el = mesh->SurfaceElement (ei); + switch (el.GetNP()) + { + case 3: return NG_TRIG; + case 4: return NG_QUAD; + case 6: return NG_TRIG6; + } + } + + // should not occur + return NG_TET; +} + + + +int Ng_GetElementIndex (int ei) +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(ei).GetIndex(); + else + { + int ind = mesh->SurfaceElement(ei).GetIndex(); + ind = mesh->GetFaceDescriptor(ind).BCProperty(); + return ind; + } +} + +void Ng_SetElementIndex(const int ei, const int index) +{ + mesh->VolumeElement(ei).SetIndex(index); +} + +char * Ng_GetElementMaterial (int ei) +{ + static char empty[] = ""; + if (mesh->GetDimension() == 3) + { + int ind = mesh->VolumeElement(ei).GetIndex(); + // cout << "ind = " << ind << endl; + const char * mat = mesh->GetMaterial (ind); + if (mat) + return const_cast<char*> (mat); + else + return empty; + } + // add astrid + else + { + int ind = mesh->SurfaceElement(ei).GetIndex(); + ind = mesh->GetFaceDescriptor(ind).BCProperty(); + const char * mat = mesh->GetMaterial ( ind ); + if (mat) + return const_cast<char*> (mat); + else + return empty; + } + return 0; +} + +char * Ng_GetDomainMaterial (int dom) +{ + static char empty[] = ""; + // astrid + if ( 1 ) // mesh->GetDimension() == 3) + { + const char * mat = mesh->GetMaterial(dom); + if (mat) + return const_cast<char*> (mat); + else + return empty; + } + + return 0; +} + + +NG_ELEMENT_TYPE Ng_GetSurfaceElement (int ei, int * epi, int * np) +{ + if (mesh->GetDimension() == 3) + { + const Element2d & el = mesh->SurfaceElement (ei); + for (int i = 0; i < el.GetNP(); i++) + epi[i] = el[i]; + + if (np) *np = el.GetNP(); + + return NG_ELEMENT_TYPE (el.GetType()); + } + else + { + const Segment & seg = mesh->LineSegment (ei); + + if (seg.pmid < 0) + { + epi[0] = seg.p1; + epi[1] = seg.p2; + + if (np) *np = 2; + return NG_SEGM; + } + else + { + epi[0] = seg.p1; + epi[1] = seg.p2; + epi[2] = seg.pmid; + + if (np) *np = 3; + return NG_SEGM3; + } + } + + return NG_TRIG; +} + +int Ng_GetSurfaceElementIndex (int ei) +{ + if (mesh->GetDimension() == 3) + return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).BCProperty(); + else + return mesh->LineSegment(ei).si; +} + +int Ng_GetSurfaceElementSurfaceNumber (int ei) +{ + if (mesh->GetDimension() == 3) + return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).SurfNr(); + else + return mesh->LineSegment(ei).si; +} +int Ng_GetSurfaceElementFDNumber (int ei) +{ + if (mesh->GetDimension() == 3) + return mesh->SurfaceElement(ei).GetIndex(); + else + return -1; +} + + +char * Ng_GetSurfaceElementBCName (int ei) +{ + if ( mesh->GetDimension() == 3 ) + return const_cast<char *>(mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).GetBCName().c_str()); + else + return const_cast<char *>(mesh->LineSegment(ei).GetBCName().c_str()); +} + + +// Inefficient (but maybe safer) version: +//void Ng_GetSurfaceElementBCName (int ei, char * name) +//{ +// if ( mesh->GetDimension() == 3 ) +// strcpy(name,mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).GetBCName().c_str()); +// else +// strcpy(name,mesh->LineSegment(ei).GetBCName().c_str()); +//} + +char * Ng_GetBCNumBCName (int bcnr) +{ + return const_cast<char *>(mesh->GetBCName(bcnr).c_str()); +} + + +// Inefficient (but maybe safer) version: +//void Ng_GetBCNumBCName (int bcnr, char * name) +//{ +// strcpy(name,mesh->GetBCName(bcnr).c_str()); +//} + +void Ng_GetNormalVector (int sei, int locpi, double * nv) +{ + nv[0] = 0; + nv[1] = 0; + nv[2] = 1; + + (*testout) << "Ng_GetNormalVector (sei = " << sei << ", locpi = " << locpi << ")" << endl; + + if (mesh->GetDimension() == 3) + { + Vec<3> n; + Point<3> p; + p = mesh->Point (mesh->SurfaceElement(sei).PNum(locpi)); + + int surfi = mesh->GetFaceDescriptor(mesh->SurfaceElement(sei).GetIndex()).SurfNr(); + + (*testout) << "surfi = " << surfi << endl; +#ifdef OCCGEOMETRY + if (occgeometry) + { + PointGeomInfo gi = mesh->SurfaceElement(sei).GeomInfoPi(locpi); + occgeometry->GetSurface (surfi).GetNormalVector(p, gi, n); + nv[0] = n(0); + nv[1] = n(1); + nv[2] = n(2); + } + else +#endif + if (geometry) + { + (*testout) << "geometry defined" << endl; + n = geometry->GetSurface (surfi) -> GetNormalVector(p); + (*testout) << "aus is" << endl; + nv[0] = n(0); + nv[1] = n(1); + nv[2] = n(2); + } + } +} + + + +void Ng_SetPointSearchStartElement(const int el) +{ + mesh->SetPointSearchStartElement(el); +} + + +int Ng_FindElementOfPoint (double * p, double * lami, int build_searchtree, + const int * const indices, const int numind) + +{ + ARRAY<int> * dummy(NULL); + int ind = -1; + + if(indices != NULL) + { + dummy = new ARRAY<int>(numind); + for(int i=0; i<numind; i++) (*dummy)[i] = indices[i]; + } + + if (mesh->GetDimension() == 3) + { + Point3d p3d(p[0], p[1], p[2]); + ind = + mesh->GetElementOfPoint(p3d, lami, dummy, build_searchtree != 0); + } + else + { + double lam3[3]; + Point3d p2d(p[0], p[1], 0); + ind = + mesh->GetElementOfPoint(p2d, lam3, dummy, build_searchtree != 0); + + + if(mesh->SurfaceElement(ind).GetType()==QUAD) + { + lami[0] = lam3[0]; + lami[1] = lam3[1]; + } + else + { + lami[0] = 1-lam3[0]-lam3[1]; + lami[1] = lam3[0]; + } + } + + delete dummy; + + return ind; +} + +int Ng_FindSurfaceElementOfPoint (double * p, double * lami, int build_searchtree, + const int * const indices, const int numind) + +{ + ARRAY<int> * dummy(NULL); + int ind = -1; + + if(indices != NULL) + { + dummy = new ARRAY<int>(numind); + for(int i=0; i<numind; i++) (*dummy)[i] = indices[i]; + } + + if (mesh->GetDimension() == 3) + { + Point3d p3d(p[0], p[1], p[2]); + ind = + mesh->GetSurfaceElementOfPoint(p3d, lami, dummy, build_searchtree != 0); + } + else + { + //throw NgException("FindSurfaceElementOfPoint for 2D meshes not yet implemented"); + cerr << "FindSurfaceElementOfPoint for 2D meshes not yet implemented" << endl; + } + + delete dummy; + + return ind; +} + + +int Ng_IsElementCurved (int ei) +{ + if (mesh->GetDimension() == 2) + return mesh->GetCurvedElements().IsSurfaceElementCurved (ei-1); + else + return mesh->GetCurvedElements().IsElementCurved (ei-1); +} + + +int Ng_IsSurfaceElementCurved (int sei) +{ + if (mesh->GetDimension() == 2) + return mesh->GetCurvedElements().IsSegmentCurved (sei-1); + else + return mesh->GetCurvedElements().IsSurfaceElementCurved (sei-1); +} + + + + +void Ng_GetElementTransformation (int ei, const double * xi, + double * x, double * dxdxi) +{ + if (mesh->GetDimension() == 2) + { + Point<2> xl(xi[0], xi[1]); + Point<3> xg; + Mat<3,2> dx; + + mesh->GetCurvedElements().CalcSurfaceTransformation (xl, ei-1, xg, dx); + + if (x) + { + for (int i = 0; i < 2; i++) + x[i] = xg(i); + } + + if (dxdxi) + { + for (int i=0; i<2; i++) + { + dxdxi[2*i] = dx(i,0); + dxdxi[2*i+1] = dx(i,1); + } + } + } + else + { + Point<3> xl(xi[0], xi[1], xi[2]); + Point<3> xg; + Mat<3,3> dx; + + mesh->GetCurvedElements().CalcElementTransformation (xl, ei-1, xg, dx); + + // still 1-based arrays + if (x) + { + for (int i = 0; i < 3; i++) + x[i] = xg(i); + } + + if (dxdxi) + { + for (int i=0; i<3; i++) + { + dxdxi[3*i] = dx(i,0); + dxdxi[3*i+1] = dx(i,1); + dxdxi[3*i+2] = dx(i,2); + } + } + } +} + + + +void Ng_GetBufferedElementTransformation (int ei, const double * xi, + double * x, double * dxdxi, + void * buffer, int buffervalid) +{ + // buffer = 0; + // buffervalid = 0; + if (mesh->GetDimension() == 2) + { + return Ng_GetElementTransformation (ei, xi, x, dxdxi); + } + else + { + mesh->GetCurvedElements().CalcElementTransformation (reinterpret_cast<const Point<3> &> (*xi), + ei-1, + reinterpret_cast<Point<3> &> (*x), + reinterpret_cast<Mat<3,3> &> (*dxdxi), + buffer, (buffervalid != 0)); + + /* + Point<3> xl(xi[0], xi[1], xi[2]); + Point<3> xg; + Mat<3,3> dx; + // buffervalid = 0; + mesh->GetCurvedElements().CalcElementTransformation (xl, ei-1, xg, dx, buffer, buffervalid); + + // still 1-based arrays + if (x) + { + for (int i = 0; i < 3; i++) + x[i] = xg(i); + } + + if (dxdxi) + { + for (int i=0; i<3; i++) + { + dxdxi[3*i] = dx(i,0); + dxdxi[3*i+1] = dx(i,1); + dxdxi[3*i+2] = dx(i,2); + } + } + */ + } +} + + + + + + + + +void Ng_GetMultiElementTransformation (int ei, int n, + const double * xi, int sxi, + double * x, int sx, + double * dxdxi, int sdxdxi) +{ + if (mesh->GetDimension() == 2) + { + for (int i = 0; i < n; i++) + { + Point<2> xl(xi[i*sxi], xi[i*sxi+1]); + Point<3> xg; + Mat<3,2> dx; + + mesh->GetCurvedElements().CalcSurfaceTransformation (xl, ei-1, xg, dx); + + if (x) + { + x[i*sx ] = xg(0); + x[i*sx+1] = xg(1); + } + + if (dxdxi) + { + dxdxi[i*sdxdxi ] = dx(0,0); + dxdxi[i*sdxdxi+1] = dx(0,1); + dxdxi[i*sdxdxi+2] = dx(1,0); + dxdxi[i*sdxdxi+3] = dx(1,1); + } + } + } + else + { + mesh->GetCurvedElements().CalcMultiPointElementTransformation (ei-1, n, xi, sxi, x, sx, dxdxi, sdxdxi); + } +} + + + + + + + + +void Ng_GetSurfaceElementTransformation (int sei, const double * xi, + double * x, double * dxdxi) +{ + if (mesh->GetDimension() == 2) + { + Point<3> xg; + Vec<3> dx; + + mesh->GetCurvedElements().CalcSegmentTransformation (xi[0], sei-1, xg, dx); + + if (x) + for (int i = 0; i < 2; i++) + x[i] = xg(i); + + if (dxdxi) + for (int i=0; i<2; i++) + dxdxi[i] = dx(i); + + } + else + { + Point<2> xl(xi[0], xi[1]); + Point<3> xg; + Mat<3,2> dx; + + mesh->GetCurvedElements().CalcSurfaceTransformation (xl, sei-1, xg, dx); + + for (int i=0; i<3; i++) + { + if (x) + x[i] = xg(i); + if (dxdxi) + { + dxdxi[2*i] = dx(i,0); + dxdxi[2*i+1] = dx(i,1); + } + } + } +} + + + +void Ng_GetSurfaceElementNeighbouringDomains(const int selnr, int & in, int & out) +{ + if ( mesh->GetDimension() == 3 ) + { + in = mesh->GetFaceDescriptor(mesh->SurfaceElement(selnr).GetIndex()).DomainIn(); + out = mesh->GetFaceDescriptor(mesh->SurfaceElement(selnr).GetIndex()).DomainOut(); + } + else + { + in = mesh -> LineSegment(selnr) . domin; + out = mesh -> LineSegment(selnr) . domout; + } +} + + +#ifdef PARALLEL +// Is Element ei an element of this processor ?? +bool Ng_IsGhostEl (int ei) +{ + if ( mesh->GetDimension() == 3 ) + return mesh->VolumeElement(ei).IsGhost(); + else + return false; +} + +void Ng_SetGhostEl(const int ei, const bool aisghost ) +{ + if ( mesh -> GetDimension () == 3 ) + mesh -> VolumeElement(ei).SetGhost (aisghost); +} + +bool Ng_IsGhostSEl (int ei) +{ + if ( mesh -> GetDimension () == 3 ) + return mesh->SurfaceElement(ei).IsGhost(); + else + return false; +} + +void Ng_SetGhostSEl(const int ei, const bool aisghost ) +{ + if ( mesh -> GetDimension () == 3 ) + mesh -> SurfaceElement(ei).SetGhost (aisghost); +} + + +bool Ng_IsGhostVert ( int pnum ) +{ + return mesh -> Point ( pnum ).IsGhost() ; +} +bool Ng_IsGhostEdge ( int ednum ) +{ + return mesh -> GetParallelTopology() . IsGhostEdge ( ednum ); +} + +bool Ng_IsGhostFace ( int fanum ) +{ + return mesh -> GetParallelTopology() . IsGhostFace ( fanum ); +} + +// void Ng_SetGhostVert ( const int pnum, const bool aisghost ); +// void Ng_SetGhostEdge ( const int ednum, const bool aisghost ); +// void Ng_SetGhostFace ( const int fanum, const bool aisghost ); + + +bool Ng_IsExchangeEl ( int elnum ) +{ return mesh -> GetParallelTopology() . IsExchangeElement ( elnum ); } + +bool Ng_IsExchangeSEl ( int selnum ) +{ return mesh -> GetParallelTopology() . IsExchangeSEl ( selnum ); } + +void Ng_UpdateOverlap() +{ mesh->UpdateOverlap(); } + +int Ng_Overlap () +{ return mesh->GetParallelTopology() . Overlap(); } + +#endif + +void Ng_SetRefinementFlag (int ei, int flag) +{ + if (mesh->GetDimension() == 3) + { + mesh->VolumeElement(ei).SetRefinementFlag (flag != 0); + mesh->VolumeElement(ei).SetStrongRefinementFlag (flag >= 10); + } + else + { + mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0); + mesh->SurfaceElement(ei).SetStrongRefinementFlag (flag >= 10); + } +} + +void Ng_SetSurfaceRefinementFlag (int ei, int flag) +{ + if (mesh->GetDimension() == 3) + { + mesh->SurfaceElement(ei).SetRefinementFlag (flag != 0); + mesh->SurfaceElement(ei).SetStrongRefinementFlag (flag >= 10); + } +} + + +void Ng_Refine (NG_REFINEMENT_TYPE reftype) +{ + NgLock meshlock (mesh->MajorMutex(), 1); + + BisectionOptions biopt; + biopt.usemarkedelements = 1; + biopt.refine_p = 0; + biopt.refine_hp = 0; + if (reftype == NG_REFINE_P) + biopt.refine_p = 1; + if (reftype == NG_REFINE_HP) + biopt.refine_hp = 1; + Refinement * ref; + MeshOptimize2d * opt = NULL; + + if (geometry2d) + ref = new Refinement2d(*geometry2d); + else if (stlgeometry) + ref = new RefinementSTLGeometry(*stlgeometry); +#ifdef OCCGEOMETRY + else if (occgeometry) + ref = new OCCRefinementSurfaces (*occgeometry); +#endif +#ifdef ACIS + else if (acisgeometry) + { + ref = new ACISRefinementSurfaces (*acisgeometry); + opt = new ACISMeshOptimize2dSurfaces(*acisgeometry); + ref->Set2dOptimizer(opt); + } +#endif + else if (geometry && mesh->GetDimension() == 3) + { + ref = new RefinementSurfaces(*geometry); + opt = new MeshOptimize2dSurfaces(*geometry); + ref->Set2dOptimizer(opt); + } + else + { + ref = new Refinement(); + } + + + ref -> Bisect (*mesh, biopt); + + mesh -> UpdateTopology(); + + // mesh -> GetCurvedElements().BuildCurvedElements (ref, mparam.elementorder); + delete ref; + delete opt; +} + +void Ng_SecondOrder () +{ + if (stlgeometry) + { + RefinementSTLGeometry ref (*stlgeometry); + ref.MakeSecondOrder (*mesh); + } + + else if (geometry2d) + { + Refinement2d ref (*geometry2d); + ref.MakeSecondOrder (*mesh); + } + + else if (geometry && mesh->GetDimension() == 3) + + { + RefinementSurfaces ref (*geometry); + ref.MakeSecondOrder (*mesh); + } + else + { + if (printmessage_importance>0) + cout << "no geom" << endl; + Refinement ref; + ref.MakeSecondOrder (*mesh); + } + + mesh -> UpdateTopology(); +} + +/* +void Ng_HPRefinement (int levels) +{ + Refinement * ref; + + if (stlgeometry) + ref = new RefinementSTLGeometry (*stlgeometry); + else if (geometry2d) + ref = new Refinement2d (*geometry2d); + else + ref = new RefinementSurfaces (*geometry); + + + HPRefinement (*mesh, ref, levels); +} + +void Ng_HPRefinement (int levels, double parameter) +{ + Refinement * ref; + + if (stlgeometry) + ref = new RefinementSTLGeometry (*stlgeometry); + else if (geometry2d) + ref = new Refinement2d (*geometry2d); + else + ref = new RefinementSurfaces (*geometry); + + + HPRefinement (*mesh, ref, levels, parameter); +} +*/ + +void Ng_HPRefinement (int levels, double parameter, bool setorders, + bool ref_level) +{ + Refinement * ref; + + if (stlgeometry) + ref = new RefinementSTLGeometry (*stlgeometry); + else if (geometry2d) + ref = new Refinement2d (*geometry2d); + else + ref = new RefinementSurfaces (*geometry); + + + HPRefinement (*mesh, ref, levels, parameter, setorders, ref_level); +} + + +void Ng_HighOrder (int order, bool rational) +{ + NgLock meshlock (mesh->MajorMutex(), true); + + Refinement * ref; + + if (stlgeometry) + ref = new RefinementSTLGeometry (*stlgeometry); +#ifdef OCCGEOMETRY + else if (occgeometry) + ref = new OCCRefinementSurfaces (*occgeometry); +#endif +#ifdef ACIS + else if (acisgeometry) + { + ref = new ACISRefinementSurfaces (*acisgeometry); + } +#endif + else if (geometry2d) + ref = new Refinement2d (*geometry2d); + else + { + ref = new RefinementSurfaces (*geometry); + } + + // cout << "parameter 1: " << argv[1] << " (conversion to int = " << atoi(argv[1]) << ")" << endl; + + + mesh -> GetCurvedElements().BuildCurvedElements (ref, order, rational); + + + /* + if(mesh) + mesh -> GetCurvedElements().BuildCurvedElements (ref, order, rational); + */ + + delete ref; +} + + + + + + + + + + + + +int Ng_ME_GetNVertices (NG_ELEMENT_TYPE et) +{ + switch (et) + { + case NG_SEGM: + case NG_SEGM3: + return 2; + + case NG_TRIG: + case NG_TRIG6: + return 3; + + case NG_QUAD: + return 4; + + case NG_TET: + case NG_TET10: + return 4; + + case NG_PYRAMID: + return 5; + + case NG_PRISM: + case NG_PRISM12: + return 6; + + case NG_HEX: + return 8; + + default: + cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; + } + return 0; +} + +int Ng_ME_GetNEdges (NG_ELEMENT_TYPE et) +{ + switch (et) + { + case NG_SEGM: + case NG_SEGM3: + return 1; + + case NG_TRIG: + case NG_TRIG6: + return 3; + + case NG_QUAD: + return 4; + + case NG_TET: + case NG_TET10: + return 6; + + case NG_PYRAMID: + return 8; + + case NG_PRISM: + case NG_PRISM12: + return 9; + + case NG_HEX: + return 12; + + default: + cerr << "Ng_ME_GetNEdges, illegal element type " << et << endl; + } + return 0; +} + + +int Ng_ME_GetNFaces (NG_ELEMENT_TYPE et) +{ + switch (et) + { + case NG_SEGM: + case NG_SEGM3: + return 0; + + case NG_TRIG: + case NG_TRIG6: + return 1; + + case NG_QUAD: + case NG_QUAD6: + return 1; + + case NG_TET: + case NG_TET10: + return 4; + + case NG_PYRAMID: + return 5; + + case NG_PRISM: + case NG_PRISM12: + return 5; + + case NG_HEX: + return 6; + + default: + cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; + } + return 0; +} + + +const NG_POINT * Ng_ME_GetVertices (NG_ELEMENT_TYPE et) +{ + static double segm_points [][3] = + { { 1, 0, 0 }, + { 0, 0, 0 } }; + + static double trig_points [][3] = + { { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 0 } }; + + static double quad_points [][3] = + { { 0, 0, 0 }, + { 1, 0, 0 }, + { 1, 1, 0 }, + { 0, 1, 0 } }; + + static double tet_points [][3] = + { { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 0, 0, 0 } }; + + static double pyramid_points [][3] = + { + { 0, 0, 0 }, + { 1, 0, 0 }, + { 1, 1, 0 }, + { 0, 1, 0 }, + { 0, 0, 1-1e-7 }, + }; + + static double prism_points[][3] = + { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 0 }, + { 1, 0, 1 }, + { 0, 1, 1 }, + { 0, 0, 1 } + }; + + switch (et) + { + case NG_SEGM: + case NG_SEGM3: + return segm_points; + + case NG_TRIG: + case NG_TRIG6: + return trig_points; + + case NG_QUAD: + case NG_QUAD6: + return quad_points; + + case NG_TET: + case NG_TET10: + return tet_points; + + case NG_PYRAMID: + return pyramid_points; + + case NG_PRISM: + case NG_PRISM12: + return prism_points; + + case NG_HEX: + default: + cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; + } + return 0; +} + + + +const NG_EDGE * Ng_ME_GetEdges (NG_ELEMENT_TYPE et) +{ + static int segm_edges[1][2] = + { { 1, 2 }}; + + static int trig_edges[3][2] = + { { 3, 1 }, + { 3, 2 }, + { 1, 2 }}; + + static int quad_edges[4][2] = + { { 1, 2 }, + { 4, 3 }, + { 1, 4 }, + { 2, 3 }}; + + + static int tet_edges[6][2] = + { { 4, 1 }, + { 4, 2 }, + { 4, 3 }, + { 1, 2 }, + { 1, 3 }, + { 2, 3 }}; + + static int prism_edges[9][2] = + { { 3, 1 }, + { 1, 2 }, + { 3, 2 }, + { 6, 4 }, + { 4, 5 }, + { 6, 5 }, + { 3, 6 }, + { 1, 4 }, + { 2, 5 }}; + + static int pyramid_edges[8][2] = + { { 1, 2 }, + { 2, 3 }, + { 1, 4 }, + { 4, 3 }, + { 1, 5 }, + { 2, 5 }, + { 3, 5 }, + { 4, 5 }}; + + + + switch (et) + { + case NG_SEGM: + case NG_SEGM3: + return segm_edges; + + case NG_TRIG: + case NG_TRIG6: + return trig_edges; + + case NG_QUAD: + case NG_QUAD6: + return quad_edges; + + case NG_TET: + case NG_TET10: + return tet_edges; + + case NG_PYRAMID: + return pyramid_edges; + + case NG_PRISM: + case NG_PRISM12: + return prism_edges; + + case NG_HEX: + default: + cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; + } + return 0; +} + + +const NG_FACE * Ng_ME_GetFaces (NG_ELEMENT_TYPE et) +{ + static int tet_faces[4][4] = + { { 4, 2, 3, 0 }, + { 4, 1, 3, 0 }, + { 4, 1, 2, 0 }, + { 1, 2, 3, 0 } }; + + static int prism_faces[5][4] = + { + { 1, 2, 3, 0 }, + { 4, 5, 6, 0 }, + { 3, 1, 4, 6 }, + { 1, 2, 5, 4 }, + { 2, 3, 6, 5 } + }; + + static int pyramid_faces[5][4] = + { + { 1, 2, 5, 0 }, + { 2, 3, 5, 0 }, + { 3, 4, 5, 0 }, + { 4, 1, 5, 0 }, + { 1, 2, 3, 4 } + }; + + static int trig_faces[1][4] = + { + { 1, 2, 3, 0 }, + }; + + switch (et) + { + case NG_TET: + case NG_TET10: + return tet_faces; + + case NG_PRISM: + case NG_PRISM12: + return prism_faces; + + case NG_PYRAMID: + return pyramid_faces; + + + case NG_SEGM: + case NG_SEGM3: + + case NG_TRIG: + case NG_TRIG6: + return trig_faces; + case NG_QUAD: + + + case NG_HEX: + + default: + cerr << "Ng_ME_GetFaces, illegal element type " << et << endl; + } + return 0; +} + + +int Ng_GetNEdges() +{ + return mesh->GetTopology().GetNEdges(); +} +int Ng_GetNFaces() +{ + return mesh->GetTopology().GetNFaces(); +} + + + +int Ng_GetElement_Edges (int elnr, int * edges, int * orient) +{ + const MeshTopology & topology = mesh->GetTopology(); + if (mesh->GetDimension() == 3) + return topology.GetElementEdges (elnr, edges, orient); + else + return topology.GetSurfaceElementEdges (elnr, edges, orient); +} + +int Ng_GetElement_Faces (int elnr, int * faces, int * orient) +{ + const MeshTopology & topology = mesh->GetTopology(); + if (mesh->GetDimension() == 3) + return topology.GetElementFaces (elnr, faces, orient); + else + { + faces[0] = elnr; + if (orient) orient[0] = 0; + return 1; + } +} + +int Ng_GetSurfaceElement_Edges (int elnr, int * edges, int * orient) +{ + const MeshTopology & topology = mesh->GetTopology(); + if (mesh->GetDimension() == 3) + return topology.GetSurfaceElementEdges (elnr, edges, orient); + else + { + if (orient) + topology.GetSegmentEdge(elnr, edges[0], orient[0]); + else + edges[0] = topology.GetSegmentEdge(elnr); + } + return 1; + /* + int i, ned; + const MeshTopology & topology = mesh->GetTopology(); + ARRAY<int> ia; + topology.GetSurfaceElementEdges (elnr, ia); + ned = ia.Size(); + for (i = 1; i <= ned; i++) + edges[i-1] = ia.Get(i); + + if (orient) + { + topology.GetSurfaceElementEdgeOrientations (elnr, ia); + for (i = 1; i <= ned; i++) + orient[i-1] = ia.Get(i); + } + return ned; + */ +} + +int Ng_GetSurfaceElement_Face (int selnr, int * orient) +{ + if (mesh->GetDimension() == 3) + { + const MeshTopology & topology = mesh->GetTopology(); + if (orient) + *orient = topology.GetSurfaceElementFaceOrientation (selnr); + return topology.GetSurfaceElementFace (selnr); + } + return -1; +} + +int Ng_GetFace_Vertices (int fnr, int * vert) +{ + const MeshTopology & topology = mesh->GetTopology(); + ArrayMem<int,4> ia; + topology.GetFaceVertices (fnr, ia); + for (int i = 0; i < ia.Size(); i++) + vert[i] = ia[i]; + // cout << "face verts = " << ia << endl; + return ia.Size(); +} + + +int Ng_GetFace_Edges (int fnr, int * edge) +{ + const MeshTopology & topology = mesh->GetTopology(); + ArrayMem<int,4> ia; + topology.GetFaceEdges (fnr, ia); + for (int i = 0; i < ia.Size(); i++) + edge[i] = ia[i]; + return ia.Size(); +} + +void Ng_GetEdge_Vertices (int ednr, int * vert) +{ + const MeshTopology & topology = mesh->GetTopology(); + topology.GetEdgeVertices (ednr, vert[0], vert[1]); +} + + +int Ng_GetNVertexElements (int vnr) +{ + if (mesh->GetDimension() == 3) + return mesh->GetTopology().GetVertexElements(vnr).Size(); + else + return mesh->GetTopology().GetVertexSurfaceElements(vnr).Size(); +} + +void Ng_GetVertexElements (int vnr, int * els) +{ + FlatArray<int> ia(0,0); + if (mesh->GetDimension() == 3) + ia = mesh->GetTopology().GetVertexElements(vnr); + else + ia = mesh->GetTopology().GetVertexSurfaceElements(vnr); + for (int i = 0; i < ia.Size(); i++) + els[i] = ia[i]; +} + + +int Ng_GetElementOrder (int enr) +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(enr).GetOrder(); + else + return mesh->SurfaceElement(enr).GetOrder(); +} + +void Ng_GetElementOrders (int enr, int * ox, int * oy, int * oz) +{ + if (mesh->GetDimension() == 3) + mesh->VolumeElement(enr).GetOrder(*ox, *oy, *oz); + else + mesh->SurfaceElement(enr).GetOrder(*ox, *oy, *oz); +} + +void Ng_SetElementOrder (int enr, int order) +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(enr).SetOrder(order); + else + return mesh->SurfaceElement(enr).SetOrder(order); +} + +void Ng_SetElementOrders (int enr, int ox, int oy, int oz) +{ + if (mesh->GetDimension() == 3) + mesh->VolumeElement(enr).SetOrder(ox, oy, oz); + else + mesh->SurfaceElement(enr).SetOrder(ox, oy); +} + + +int Ng_GetSurfaceElementOrder (int enr) +{ + return mesh->SurfaceElement(enr).GetOrder(); +} + +//HERBERT: falsche Anzahl von Argumenten +//void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy, int * oz) +void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy) +{ + int d; + mesh->SurfaceElement(enr).GetOrder(*ox, *oy, d); +} + +void Ng_SetSurfaceElementOrder (int enr, int order) +{ + return mesh->SurfaceElement(enr).SetOrder(order); +} + +void Ng_SetSurfaceElementOrders (int enr, int ox, int oy) +{ + mesh->SurfaceElement(enr).SetOrder(ox, oy); +} + + +int Ng_GetNLevels () +{ + return (mesh) ? mesh->mglevels : 0; +} + + +void Ng_GetParentNodes (int ni, int * parents) +{ + if (ni <= mesh->mlbetweennodes.Size()) + { + parents[0] = mesh->mlbetweennodes.Get(ni).I1(); + parents[1] = mesh->mlbetweennodes.Get(ni).I2(); + } + else + parents[0] = parents[1] = 0; +} + + +int Ng_GetParentElement (int ei) +{ + if (mesh->GetDimension() == 3) + { + if (ei <= mesh->mlparentelement.Size()) + return mesh->mlparentelement.Get(ei); + } + else + { + if (ei <= mesh->mlparentsurfaceelement.Size()) + return mesh->mlparentsurfaceelement.Get(ei); + } + return 0; +} + + +int Ng_GetParentSElement (int ei) +{ + if (mesh->GetDimension() == 3) + { + if (ei <= mesh->mlparentsurfaceelement.Size()) + return mesh->mlparentsurfaceelement.Get(ei); + } + else + { + return 0; + } + return 0; +} + + + + + +int Ng_GetClusterRepVertex (int pi) +{ + return mesh->GetClusters().GetVertexRepresentant(pi); +} + +int Ng_GetClusterRepEdge (int pi) +{ + return mesh->GetClusters().GetEdgeRepresentant(pi); +} + +int Ng_GetClusterRepFace (int pi) +{ + return mesh->GetClusters().GetFaceRepresentant(pi); +} + +int Ng_GetClusterRepElement (int pi) +{ + return mesh->GetClusters().GetElementRepresentant(pi); +} + + + + + + +void Ng_InitSolutionData (Ng_SolutionData * soldata) +{ + soldata -> name = NULL; + soldata -> data = NULL; + soldata -> components = 1; + soldata -> dist = 1; + soldata -> order = 1; + soldata -> iscomplex = 0; + soldata -> draw_surface = 1; + soldata -> draw_volume = 1; + soldata -> soltype = NG_SOLUTION_NODAL; + soldata -> solclass = 0; +} + +void Ng_SetSolutionData (Ng_SolutionData * soldata) +{ +#ifdef OPENGL + // vssolution.ClearSolutionData (); + VisualSceneSolution::SolData * vss = new VisualSceneSolution::SolData; + + // cout << "Add solution " << soldata->name << ", type = " << soldata->soltype << endl; + + vss->name = new char[strlen (soldata->name)+1]; + strcpy (vss->name, soldata->name); + + vss->data = soldata->data; + vss->components = soldata->components; + vss->dist = soldata->dist; + vss->order = soldata->order; + vss->iscomplex = bool(soldata->iscomplex); + vss->draw_surface = soldata->draw_surface; + vss->draw_volume = soldata->draw_volume; + vss->soltype = VisualSceneSolution::SolType (soldata->soltype); + vss->solclass = soldata->solclass; + vssolution.AddSolutionData (vss); +#endif +} + +void Ng_ClearSolutionData () +{ +#ifdef OPENGL + vssolution.ClearSolutionData(); +#endif +} + + + +void Ng_Redraw () +{ +#ifdef OPENGL + extern bool nodisplay; // he: global in ngappinit.cpp + if (!nodisplay) + { + vssolution.UpdateSolutionTimeStamp(); + Render(); + } +#endif +} + + +void Ng_SetVisualizationParameter (const char * name, const char * value) +{ +#ifdef OPENGL +#ifndef NOTCL + char buf[100]; + sprintf (buf, "visoptions.%s", name); + if (printmessage_importance>0) + { + cout << "name = " << name << ", value = " << value << endl; + cout << "set tcl-variable " << buf << " to " << value << endl; + } + Tcl_SetVar (tcl_interp, buf, const_cast<char*> (value), 0); + Tcl_Eval (tcl_interp, "Ng_Vis_Set parameters;"); +#endif +#endif +} + + + + +int firsttime = 1; +int animcnt = 0; +void PlayAnimFile(const char* name, int speed, int maxcnt) +{ + //extern Mesh * mesh; + + /* + if (mesh.Ptr()) mesh->DeleteMesh(); + if (!mesh.Ptr()) mesh = new Mesh(); + */ + mesh.Reset (new Mesh()); + + int ne, np, i; + + char str[80]; + char str2[80]; + + //int tend = 5000; + // for (ti = 1; ti <= tend; ti++) + //{ + int rti = (animcnt%(maxcnt-1)) + 1; + animcnt+=speed; + + sprintf(str2,"%05i.sol",rti); + strcpy(str,"mbssol/"); + strcat(str,name); + strcat(str,str2); + + if (printmessage_importance>0) + cout << "read file '" << str << "'" << endl; + + ifstream infile(str); + infile >> ne; + for (i = 1; i <= ne; i++) + { + int j; + Element2d tri(TRIG); + tri.SetIndex(1); //faceind + + for (j = 1; j <= 3; j++) + infile >> tri.PNum(j); + + infile >> np; + for (i = 1; i <= np; i++) + { + Point3d p; + infile >> p.X() >> p.Y() >> p.Z(); + if (firsttime) + mesh->AddPoint (p); + else + mesh->Point(i) = Point<3> (p); + } + + //firsttime = 0; + Ng_Redraw(); + } +} + + +int Ng_GetNPeriodicVertices (int idnr) +{ + ARRAY<INDEX_2> apairs; + mesh->GetIdentifications().GetPairs (idnr, apairs); + return apairs.Size(); +} + + +// pairs should be an integer array of 2*npairs +void Ng_GetPeriodicVertices (int idnr, int * pairs) +{ + ARRAY<INDEX_2> apairs; + mesh->GetIdentifications().GetPairs (idnr, apairs); + for (int i = 0; i < apairs.Size(); i++) + { + pairs[2*i] = apairs[i].I1(); + pairs[2*i+1] = apairs[i].I2(); + } + +} + + + +int Ng_GetNPeriodicEdges (int idnr) +{ + ARRAY<INDEX,PointIndex::BASE> map; + //const MeshTopology & top = mesh->GetTopology(); + int nse = mesh->GetNSeg(); + + int cnt = 0; + // for (int id = 1; id <= mesh->GetIdentifications().GetMaxNr(); id++) + { + mesh->GetIdentifications().GetMap(idnr, map); + //(*testout) << "ident-map " << id << ":" << endl << map << endl; + + for (SegmentIndex si = 0; si < nse; si++) + { + PointIndex other1 = map[(*mesh)[si].p1]; + PointIndex other2 = map[(*mesh)[si].p2]; + // (*testout) << "seg = " << (*mesh)[si] << "; other = " + // << other1 << "-" << other2 << endl; + if (other1 && other2 && mesh->IsSegment (other1, other2)) + { + cnt++; + } + } + } + return cnt; +} + +void Ng_GetPeriodicEdges (int idnr, int * pairs) +{ + ARRAY<INDEX,PointIndex::BASE> map; + const MeshTopology & top = mesh->GetTopology(); + int nse = mesh->GetNSeg(); + + int cnt = 0; + // for (int id = 1; id <= mesh->GetIdentifications().GetMaxNr(); id++) + { + mesh->GetIdentifications().GetMap(idnr, map); + + //(*testout) << "map = " << map << endl; + + for (SegmentIndex si = 0; si < nse; si++) + { + PointIndex other1 = map[(*mesh)[si].p1]; + PointIndex other2 = map[(*mesh)[si].p2]; + if (other1 && other2 && mesh->IsSegment (other1, other2)) + { + SegmentIndex otherseg = mesh->SegmentNr (other1, other2); + pairs[cnt++] = top.GetSegmentEdge (si+1); + pairs[cnt++] = top.GetSegmentEdge (otherseg+1); + } + } + } +} + + + +void Ng_PushStatus (const char * str) +{ + PushStatus (MyStr (str)); +} + +void Ng_PopStatus () +{ + PopStatus (); +} + +void Ng_SetThreadPercentage (double percent) +{ + SetThreadPercent (percent); +} + +void Ng_GetStatus (char ** str, double & percent) +{ + MyStr s; + GetStatus(s,percent); + *str = new char[s.Length()+1]; + strcpy(*str,s.c_str()); +} + + +void Ng_SetTerminate(void) +{ + multithread.terminate = 1; +} +void Ng_UnSetTerminate(void) +{ + multithread.terminate = 0; +} + +int Ng_ShouldTerminate(void) +{ + return multithread.terminate; +} + +///// Added by Roman Stainko .... +int Ng_GetVertex_Elements( int vnr, int* elems ) +{ + const MeshTopology& topology = mesh->GetTopology(); + ArrayMem<int,4> indexArray; + topology.GetVertexElements( vnr, indexArray ); + + for( int i=0; i<indexArray.Size(); i++ ) + elems[i] = indexArray[i]; + + return indexArray.Size(); +} + +///// Added by Roman Stainko .... +int Ng_GetVertex_SurfaceElements( int vnr, int* elems ) +{ + const MeshTopology& topology = mesh->GetTopology(); + ArrayMem<int,4> indexArray; + topology.GetVertexSurfaceElements( vnr, indexArray ); + + for( int i=0; i<indexArray.Size(); i++ ) + elems[i] = indexArray[i]; + + return indexArray.Size(); +} + +///// Added by Roman Stainko .... +int Ng_GetVertex_NElements( int vnr ) +{ + const MeshTopology& topology = mesh->GetTopology(); + ArrayMem<int,4> indexArray; + topology.GetVertexElements( vnr, indexArray ); + + return indexArray.Size(); +} + +///// Added by Roman Stainko .... +int Ng_GetVertex_NSurfaceElements( int vnr ) +{ + const MeshTopology& topology = mesh->GetTopology(); + ArrayMem<int,4> indexArray; + topology.GetVertexSurfaceElements( vnr, indexArray ); + + return indexArray.Size(); +} + + + +#ifdef SOCKETS +int Ng_SocketClientOpen( const int port, const char * host ) +{ + try + { + if(host) + clientsocket.Reset(new ClientSocket(port,host)); + else + clientsocket.Reset(new ClientSocket(port)); + } + catch( SocketException e) + { + cerr << e.Description() << endl; + return 0; + } + return 1; +} + +void Ng_SocketClientWrite( const char * write, char** reply) +{ + string output = write; + (*clientsocket) << output; + string sreply; + (*clientsocket) >> sreply; + *reply = new char[sreply.size()+1]; + strcpy(*reply,sreply.c_str()); +} + + +void Ng_SocketClientClose ( void ) +{ + clientsocket.Reset(NULL); +} + + +void Ng_SocketClientGetServerHost ( const int number, char ** host ) +{ + *host = new char[servers[number]->host.size()+1]; + strcpy(*host,servers[number]->host.c_str()); +} + +void Ng_SocketClientGetServerPort ( const int number, int * port ) +{ + *port = servers[number]->port; +} + +void Ng_SocketClientGetServerClientID ( const int number, int * id ) +{ + *id = servers[number]->clientid; +} + +#endif // SOCKETS + + + + +#ifdef PARALLEL +void Ng_SetElementPartition ( const int elnr, const int part ) +{ + mesh->VolumeElement(elnr+1).SetPartition(part); + +} +int Ng_GetElementPartition ( const int elnr ) +{ + return mesh->VolumeElement(elnr+1).GetPartition(); +} +#endif + + +void Ng_InitPointCurve(double red, double green, double blue) +{ + mesh->InitPointCurve(red, green, blue); +} + +void Ng_AddPointCurvePoint(const double * point) +{ + Point3d pt; + pt.X() = point[0]; + pt.Y() = point[1]; + pt.Z() = point[2]; + mesh->AddPointCurvePoint(pt); +} + + +void Ng_SaveMesh ( const char * meshfile ) +{ + mesh -> Save(string(meshfile)); +} + + +int Ng_Bisect_WithInfo ( const char * refinementfile, double ** qualityloss, int * qualityloss_size ) +{ + BisectionOptions biopt; + biopt.outfilename = NULL; // "ngfepp.vol"; + biopt.femcode = "fepp"; + biopt.refinementfilename = refinementfile; + + Refinement * ref; + MeshOptimize2d * opt = NULL; + if (stlgeometry) + ref = new RefinementSTLGeometry(*stlgeometry); +#ifdef OCCGEOMETRY + else if (occgeometry) + ref = new OCCRefinementSurfaces (*occgeometry); +#endif +#ifdef ACIS + else if (acisgeometry) + { + ref = new ACISRefinementSurfaces(*acisgeometry); + opt = new ACISMeshOptimize2dSurfaces(*acisgeometry); + ref->Set2dOptimizer(opt); + } +#endif + else + { + ref = new RefinementSurfaces(*geometry); + opt = new MeshOptimize2dSurfaces(*geometry); + ref->Set2dOptimizer(opt); + } + + if(!mesh->LocalHFunctionGenerated()) + mesh->CalcLocalH(); + + mesh->LocalHFunction().SetGrading (mparam.grading); + + ARRAY<double> * qualityloss_arr = NULL; + if(qualityloss != NULL) + qualityloss_arr = new ARRAY<double>; + + ref -> Bisect (*mesh, biopt, qualityloss_arr); + + int retval = 0; + + if(qualityloss != NULL) + { + *qualityloss = new double[qualityloss_arr->Size()+1]; + + for(int i = 0; i<qualityloss_arr->Size(); i++) + (*qualityloss)[i+1] = (*qualityloss_arr)[i]; + + retval = qualityloss_arr->Size(); + + delete qualityloss_arr; + } + + mesh -> UpdateTopology(); + mesh -> GetCurvedElements().BuildCurvedElements (ref, mparam.elementorder); + + multithread.running = 0; + delete ref; + delete opt; + + return retval; +} + +void Ng_Bisect ( const char * refinementfile ) +{ + Ng_Bisect_WithInfo( refinementfile, NULL, NULL ); +} + + + + + +/* + number of nodes of type nt + nt = 0 is Vertex + nt = 1 is Edge + nt = 2 is Face + nt = 3 is Cell +*/ +int Ng_GetNNodes (int nt) +{ + switch (nt) + { + case 0: return mesh -> GetNV(); + case 1: return mesh->GetTopology().GetNEdges(); + case 2: return mesh->GetTopology().GetNFaces(); + case 3: return mesh -> GetNE(); + } + return -1; +} + + +int Ng_GetClosureNodes (int nt, int nodenr, int nodeset, int * nodes) +{ + switch (nt) + { + case 3: // The closure of a cell + { + int cnt = 0; + if (nodeset & 1) // Vertices + { + const Element & el = (*mesh)[ElementIndex(nodenr)]; + for (int i = 0; i < el.GetNP(); i++) + { + nodes[cnt++] = 0; + nodes[cnt++] = el[i] - PointIndex::BASE; + } + } + + if (nodeset & 2) // Edges + { + int edges[12]; + int ned; + ned = mesh->GetTopology().GetElementEdges (nodenr+1, edges, 0); + for (int i = 0; i < ned; i++) + { + nodes[cnt++] = 1; + nodes[cnt++] = edges[i]-1; + } + } + + if (nodeset & 4) // Faces + { + int faces[12]; + int nfa; + nfa = mesh->GetTopology().GetElementFaces (nodenr+1, faces, 0); + for (int i = 0; i < nfa; i++) + { + nodes[cnt++] = 2; + nodes[cnt++] = faces[i]-1; + } + } + + if (nodeset & 8) // Cell + { + nodes[cnt++] = 3; + nodes[cnt++] = nodenr; + } + + return cnt/2; + } + default: + { + cerr << "GetClosureNodes not implemented for Nodetype " << nt << endl; + } + } + return 0; +} + + + +int Ng_GetNElements (int dim) +{ + switch (dim) + { + case 0: return mesh -> GetNV(); + case 1: return mesh -> GetNSeg(); + case 2: return mesh -> GetNSE(); + case 3: return mesh -> GetNE(); + } + return -1; +} + + + + /* + closure nodes of element + nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc + E.g., nodeset = 6 includes edge and face nodes + nodes is pair of integers (nodetype, nodenr) + return value is number of nodes + */ +int Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes) +{ + switch (dim) + { + case 3: // The closure of a volume element = CELL + { + return Ng_GetClosureNodes (3, elementnr, nodeset, nodes); + } + case 2: + { + int cnt = 0; + if (nodeset & 1) // Vertices + { + const Element2d & el = (*mesh)[SurfaceElementIndex(elementnr)]; + for (int i = 0; i < el.GetNP(); i++) + { + nodes[cnt++] = 0; + nodes[cnt++] = el[i] - PointIndex::BASE; + } + } + + if (nodeset & 2) // Edges + { + int edges[12]; + int ned; + ned = mesh->GetTopology().GetSurfaceElementEdges (elementnr+1, edges, 0); + for (int i = 0; i < ned; i++) + { + nodes[cnt++] = 1; + nodes[cnt++] = edges[i]-1; + } + } + + if (nodeset & 4) // Faces + { + int face = mesh->GetTopology().GetSurfaceElementFace (elementnr+1); + nodes[cnt++] = 2; + nodes[cnt++] = face-1; + } + + return cnt/2; + } + default: + { + cerr << "GetClosureNodes not implemented for Element of dimension " << dim << endl; + } + } + return 0; +} diff --git a/contrib/Netgen/libsrc/interface/nginterface.h b/contrib/Netgen/libsrc/interface/nginterface.h new file mode 100644 index 0000000000000000000000000000000000000000..6301c23d822d6658f87892abb1218cec4e341fa4 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/nginterface.h @@ -0,0 +1,422 @@ +#ifndef NGINTERFACE +#define NGINTERFACE + + +/**************************************************************************/ +/* File: nginterface.h */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Nov. 99 */ +/**************************************************************************/ + +/* + Application program interface to Netgen + +*/ + + + +// max number of nodes per element +#define NG_ELEMENT_MAXPOINTS 12 + +// max number of nodes per surface element +#define NG_SURFACE_ELEMENT_MAXPOINTS 8 + + + +// implemented element types: +enum NG_ELEMENT_TYPE { + NG_SEGM = 1, NG_SEGM3 = 2, + NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, + NG_TET = 20, NG_TET10 = 21, + NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, + NG_HEX = 25 +}; + +typedef double NG_POINT[3]; // coordinates +typedef int NG_EDGE[2]; // initial point, end point +typedef int NG_FACE[4]; // points, last one is 0 for trig + + +#ifdef __cplusplus +extern "C" { +#endif + + // load geomtry from file + void Ng_LoadGeometry (const char * filename); + + // load netgen mesh + void Ng_LoadMesh (const char * filename); + + // load netgen mesh + void Ng_LoadMeshFromString (const char * mesh_as_string); + + // space dimension (2 or 3) + int Ng_GetDimension (); + + // number of mesh points + int Ng_GetNP (); + + // number of mesh vertices (differs from GetNP for 2nd order elements) + int Ng_GetNV (); + + // number of mesh elements + int Ng_GetNE (); + + // number of surface triangles + int Ng_GetNSE (); + + // Get Point coordintes, index from 1 .. np + void Ng_GetPoint (int pi, double * p); + + // Get Element Points + NG_ELEMENT_TYPE Ng_GetElement (int ei, int * epi, int * np = 0); + + // Get Element Type + NG_ELEMENT_TYPE Ng_GetElementType (int ei); + + // Get sub-domain of element ei + int Ng_GetElementIndex (int ei); + + void Ng_SetElementIndex(const int ei, const int index); + + // Get Material of element ei + char * Ng_GetElementMaterial (int ei); + + // Get Material of domain dom + char * Ng_GetDomainMaterial (int dom); + + // Get Surface Element Points + NG_ELEMENT_TYPE Ng_GetSurfaceElement (int ei, int * epi, int * np = 0); + + // Get Surface Element Type + NG_ELEMENT_TYPE Ng_GetSurfaceElementType (int ei); + + // Get Surface Element Index + int Ng_GetSurfaceElementIndex (int ei); + + // Get Surface Element Surface Number + int Ng_GetSurfaceElementSurfaceNumber (int ei); + + // Get Surface Element Number + int Ng_GetSurfaceElementFDNumber (int ei); + + // Get BCName for Surface Element + char * Ng_GetSurfaceElementBCName (int ei); + //void Ng_GetSurfaceElementBCName (int ei, char * name); + + // Get BCName for bc-number + char * Ng_GetBCNumBCName (int bcnr); + //void Ng_GetBCNumBCName (int bcnr, char * name); + + // Get normal vector of surface element node + void Ng_GetNormalVector (int sei, int locpi, double * nv); + + + void Ng_SetPointSearchStartElement(int el); + + // Find element of point, returns local coordinates + int Ng_FindElementOfPoint (double * p, double * lami, + int build_searchtrees = 0, + const int * const indices = NULL, const int numind = 0); + + // Find surface element of point, returns local coordinates + int Ng_FindSurfaceElementOfPoint (double * p, double * lami, + int build_searchtrees = 0, + const int * const indices = NULL, const int numind = 0); + + + // is elment ei curved ? + int Ng_IsElementCurved (int ei); + // is elment sei curved ? + int Ng_IsSurfaceElementCurved (int sei); + + /// Curved Elemens: + /// xi..local coordinates + /// x ..global coordinates + /// dxdxi...D x D Jacobian matrix (row major storage) + void Ng_GetElementTransformation (int ei, const double * xi, + double * x, double * dxdxi); + + + /// buffer must be at least 100 doubles, alignment of double + void Ng_GetBufferedElementTransformation (int ei, const double * xi, + double * x, double * dxdxi, + void * buffer, int buffervalid); + + + + /// Curved Elemens: + /// xi..local coordinates + /// x ..global coordinates + /// dxdxi...D x D-1 Jacobian matrix (row major storage) + /// curved ...is element curved ? + void Ng_GetSurfaceElementTransformation (int sei, const double * xi, + double * x, double * dxdxi); + + /// Curved Elemens: + /// xi..local coordinates + /// sxi..step xi + /// x ..global coordinates + /// dxdxi...D x D Jacobian matrix (row major storage) + void Ng_GetMultiElementTransformation (int ei, int n, + const double * xi, int sxi, + double * x, int sx, + double * dxdxi, int sdxdxi); + + + // Mark element for refinement + void Ng_SetRefinementFlag (int ei, int flag); + void Ng_SetSurfaceRefinementFlag (int sei, int flag); + + // Do local refinement + enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; + void Ng_Refine (NG_REFINEMENT_TYPE reftype); + + // Use second order elements + void Ng_SecondOrder (); + void Ng_HighOrder (int order, bool rational = false); + //void Ng_HPRefinement (int levels, double parameter = 0.125); + void Ng_HPRefinement (int levels, double parameter = 0.125, + bool setorders = true,bool ref_level = false); + // void Ng_HPRefinement (int levels); + // void Ng_HPRefinement (int levels, double parameter); + + + // Topology and coordinate information of master element: + + int Ng_ME_GetNVertices (NG_ELEMENT_TYPE et); + int Ng_ME_GetNEdges (NG_ELEMENT_TYPE et); + int Ng_ME_GetNFaces (NG_ELEMENT_TYPE et); + + const NG_POINT * Ng_ME_GetVertices (NG_ELEMENT_TYPE et); + const NG_EDGE * Ng_ME_GetEdges (NG_ELEMENT_TYPE et); + const NG_FACE * Ng_ME_GetFaces (NG_ELEMENT_TYPE et); + + int Ng_GetNEdges(); + int Ng_GetNFaces(); + + + int Ng_GetElement_Edges (int elnr, int * edges, int * orient = 0); + int Ng_GetElement_Faces (int elnr, int * faces, int * orient = 0); + + int Ng_GetSurfaceElement_Edges (int selnr, int * edges, int * orient = 0); + int Ng_GetSurfaceElement_Face (int selnr, int * orient = 0); + + void Ng_GetSurfaceElementNeighbouringDomains(const int selnr, int & in, int & out); + + int Ng_GetFace_Vertices (int fnr, int * vert); + void Ng_GetEdge_Vertices (int ednr, int * vert); + int Ng_GetFace_Edges (int fnr, int * edge); + + int Ng_GetNVertexElements (int vnr); + void Ng_GetVertexElements (int vnr, int * els); + + int Ng_GetElementOrder (int enr); + void Ng_GetElementOrders (int enr, int * ox, int * oy, int * oz); + + void Ng_SetElementOrder (int enr, int order); + void Ng_SetElementOrders (int enr, int ox, int oy, int oz); + + int Ng_GetSurfaceElementOrder (int enr); + void Ng_GetSurfaceElementOrders (int enr, int * ox, int * oy); + + void Ng_SetSurfaceElementOrder (int enr, int order); + void Ng_SetSurfaceElementOrders (int enr, int ox, int oy); + + // Multilevel functions: + + // number of levels: + int Ng_GetNLevels (); + // get two parent nodes (indeed vertices !) of node ni + void Ng_GetParentNodes (int ni, int * parents); + + // get parent element (first child has always same number) + int Ng_GetParentElement (int ei); + + // get parent surface element (first child has always same number) + int Ng_GetParentSElement (int ei); + + // representant of anisotropic cluster + int Ng_GetClusterRepVertex (int vi); + int Ng_GetClusterRepEdge (int edi); + int Ng_GetClusterRepFace (int fai); + int Ng_GetClusterRepElement (int eli); + + + void Ng_SurfaceElementTransformation (int eli, double x, double y, + double * p3d, double * jacobian); + +#ifdef PARALLEL + // Is Element ei an element of this processor ?? + bool Ng_IsGhostEl (int ei); + + void Ng_SetGhostEl(const int ei, const bool aisghost ); + + bool Ng_IsGhostSEl (int ei); + + void Ng_SetGhostSEl(const int ei, const bool aisghost ); + + bool Ng_IsGhostVert ( int pnum ); + bool Ng_IsGhostEdge ( int ednum ); + bool Ng_IsGhostFace ( int fanum ); + + bool Ng_IsExchangeEl ( int elnum ); + bool Ng_IsExchangeSEl ( int selnr ); + + void Ng_UpdateOverlap (); + int Ng_Overlap(); +/* void Ng_SetGhostVert ( const int pnum, const bool aisghost ); */ +/* void Ng_SetGhostEdge ( const int ednum, const bool aisghost ); */ +/* void Ng_SetGhostFace ( const int fanum, const bool aisghost ); */ + +#endif + +namespace netgen { +#include "../visualization/soldata.hpp" +} + + enum Ng_SolutionType + { NG_SOLUTION_NODAL = 1, + NG_SOLUTION_ELEMENT = 2, + NG_SOLUTION_SURFACE_ELEMENT = 3, + NG_SOLUTION_NONCONTINUOUS = 4, + NG_SOLUTION_SURFACE_NONCONTINUOUS = 5, + NG_SOLUTION_VIRTUAL_FUNCTION = 6, + NG_SOLUTION_MARKED_ELEMENTS = 10, + NG_SOLUTION_ELEMENT_ORDER = 11 + }; + + struct Ng_SolutionData + { + const char * name; // name of gridfunction + double * data; // solution values + int components; // relevant (double) components in solution vector + int dist; // # doubles per entry alignment! + int iscomplex; // complex vector ? + bool draw_surface; + bool draw_volume; + int order; // order of elements, only partially supported + Ng_SolutionType soltype; // type of solution function + netgen::SolutionData * solclass; + }; + + // initialize solution data with default arguments + void Ng_InitSolutionData (Ng_SolutionData * soldata); + // set solution data + void Ng_SetSolutionData (Ng_SolutionData * soldata); + /// delete gridfunctions + void Ng_ClearSolutionData(); + // redraw + void Ng_Redraw(); + // + void Ng_SetVisualizationParameter (const char * name, + const char * value); + + + // number of periodic vertices + int Ng_GetNPeriodicVertices (int idnr); + // pairs should be an integer array of 2*npairs + void Ng_GetPeriodicVertices (int idnr, int * pairs); + + // number of periodic edges + int Ng_GetNPeriodicEdges (int idnr); + // pairs should be an integer array of 2*npairs + void Ng_GetPeriodicEdges (int idnr, int * pairs); + + + void Ng_PushStatus (const char * str); + void Ng_PopStatus (); + void Ng_SetThreadPercentage (double percent); + void Ng_GetStatus (char ** str, double & percent); + + void Ng_SetTerminate(void); + void Ng_UnSetTerminate(void); + int Ng_ShouldTerminate(void); + + + //// added by Roman Stainko .... + int Ng_GetVertex_Elements( int vnr, int* elems); + int Ng_GetVertex_SurfaceElements( int vnr, int* elems ); + int Ng_GetVertex_NElements( int vnr ); + int Ng_GetVertex_NSurfaceElements( int vnr ); + + +#ifdef SOCKETS + int Ng_SocketClientOpen( const int port, const char * host ); + void Ng_SocketClientWrite( const char * write, char ** reply); + void Ng_SocketClientClose ( void ); + void Ng_SocketClientGetServerHost ( const int number, char ** host ); + void Ng_SocketClientGetServerPort ( const int number, int * port ); + void Ng_SocketClientGetServerClientID ( const int number, int * id ); +#endif + + void Ng_InitPointCurve(double red, double green, double blue); + void Ng_AddPointCurvePoint(const double * point); + + +#ifdef PARALLEL + void Ng_SetElementPartition ( int elnr, int part ); + int Ng_GetElementPartition ( int elnr ); +#endif + + void Ng_SaveMesh ( const char * meshfile ); + void Ng_Bisect ( const char * refinementfile ); + + // if qualityloss is not equal to NULL at input, a (1-based) list of qualitylosses (due to projection) + // is saved in *qualityloss, its size is the return value + int Ng_Bisect_WithInfo ( const char * refinementfile, double ** qualityloss); +#ifdef __cplusplus +} +#endif + +#endif + + + + + + +/* + The new node interface ... + it is 0-based ! + */ + +extern "C" { + + /* + number of nodes of type nt + nt = 0 is Vertex + nt = 1 is Edge + nt = 2 is Face + nt = 3 is Cell + */ + int Ng_GetNNodes (int nt); + + /* + closure nodes of node (nt, nodenr): + nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc + E.g., nodeset = 6 includes edge and face nodes + nodes consists of pairs of integers (nodetype, nodenr) + return value is number of nodes + */ + int Ng_GetClosureNodes (int nt, int nodenr, int nodeset, int * nodes); + + + /* + number of dim-dimensional elements + dim = 3 ... volume elements + dim = 2 ... surface elements + dim = 1 ... segments + dim = 0 ... not available + */ + int Ng_GetNElements (int dim); + + /* + closure nodes of dim-dimensional element elmentnr: + nodeset is bit-coded, bit 0 includes Vertices, bit 1 edges, etc + E.g., nodeset = 6 includes edge and face nodes + nodes consists of pairs of integers (nodetype, nodenr) + return value is number of nodes + */ + int Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes); +} diff --git a/contrib/Netgen/libsrc/interface/nglib.cpp b/contrib/Netgen/libsrc/interface/nglib.cpp new file mode 100644 index 0000000000000000000000000000000000000000..861c62cd97f692521c5e8ec202a081c6b7ff5396 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/nglib.cpp @@ -0,0 +1,602 @@ +/**************************************************************************/ +/* File: nglib.cc */ +/* Author: Joachim Schoeberl */ +/* Date: 7. May. 2000 */ +/**************************************************************************/ + +/* + + Interface to the netgen meshing kernel + +*/ + + +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> + +// MODIFIED FOR GMSH +//#include <csg.hpp> +//#include <stlgeom.hpp> +//#include <geometry2d.hpp> + +#include <meshing.hpp> + + + +// #include <FlexLexer.h> + +// MODIFIED FOR GMSH +//namespace netgen { +// extern void MeshFromSpline2D (SplineGeometry2d & geometry, +// Mesh *& mesh, +// MeshingParameters & mp); +//} + + + + + + + +namespace nglib { +#include "nglib.h" +} + +using namespace netgen; + +// constants and types: + +namespace nglib +{ +// initialize, deconstruct Netgen library: +void Ng_Init () +{ + mycout = &cout; + myerr = &cerr; + testout = new ofstream ("test.out"); +} + +void Ng_Exit () +{ + ; +} + + + +Ng_Mesh * Ng_NewMesh () +{ + Mesh * mesh = new Mesh; + mesh->AddFaceDescriptor (FaceDescriptor (1, 1, 0, 1)); + return (Ng_Mesh*)(void*)mesh; +} + +void Ng_DeleteMesh (Ng_Mesh * mesh) +{ + delete (Mesh*)mesh; +} + + +// feeds points, surface elements and volume elements to the mesh +void Ng_AddPoint (Ng_Mesh * mesh, double * x) +{ + Mesh * m = (Mesh*)mesh; + m->AddPoint (Point3d (x[0], x[1], x[2])); +} + +void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et, + int * pi) +{ + Mesh * m = (Mesh*)mesh; + Element2d el (3); + el.SetIndex (1); + el.PNum(1) = pi[0]; + el.PNum(2) = pi[1]; + el.PNum(3) = pi[2]; + m->AddSurfaceElement (el); +} + +void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et, + int * pi) +{ + Mesh * m = (Mesh*)mesh; + Element el (4); + el.SetIndex (1); + el.PNum(1) = pi[0]; + el.PNum(2) = pi[1]; + el.PNum(3) = pi[2]; + el.PNum(4) = pi[3]; + m->AddVolumeElement (el); +} + +// ask for number of points, surface and volume elements +int Ng_GetNP (Ng_Mesh * mesh) +{ + return ((Mesh*)mesh) -> GetNP(); +} + +int Ng_GetNSE (Ng_Mesh * mesh) +{ + return ((Mesh*)mesh) -> GetNSE(); +} + +int Ng_GetNE (Ng_Mesh * mesh) +{ + return ((Mesh*)mesh) -> GetNE(); +} + + +// return point coordinates +void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x) +{ + const Point3d & p = ((Mesh*)mesh)->Point(num); + x[0] = p.X(); + x[1] = p.Y(); + x[2] = p.Z(); +} + +// return surface and volume element in pi +Ng_Surface_Element_Type +Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi) +{ + const Element2d & el = ((Mesh*)mesh)->SurfaceElement(num); + for (int i = 1; i <= el.GetNP(); i++) + pi[i-1] = el.PNum(i); + Ng_Surface_Element_Type et; + switch (el.GetNP()) + { + case 3: et = NG_TRIG; break; + case 4: et = NG_QUAD; break; + case 6: et = NG_TRIG6; break; + } + return et; +} + +Ng_Volume_Element_Type +Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi) +{ + const Element & el = ((Mesh*)mesh)->VolumeElement(num); + for (int i = 1; i <= el.GetNP(); i++) + pi[i-1] = el.PNum(i); + Ng_Volume_Element_Type et; + switch (el.GetNP()) + { + case 4: et = NG_TET; break; + case 5: et = NG_PYRAMID; break; + case 6: et = NG_PRISM; break; + case 10: et = NG_TET10; break; + } + return et; +} + +void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h) +{ + ((Mesh*)mesh) -> SetGlobalH (h); +} + +void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h) +{ + ((Mesh*)mesh) -> RestrictLocalH (Point3d (p[0], p[1], p[2]), h); +} + +void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h) +{ + for (double x = pmin[0]; x < pmax[0]; x += h) + for (double y = pmin[1]; y < pmax[1]; y += h) + for (double z = pmin[2]; z < pmax[2]; z += h) + ((Mesh*)mesh) -> RestrictLocalH (Point3d (x, y, z), h); +} + + +// generates volume mesh from surface mesh +Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp) +{ + Mesh * m = (Mesh*)mesh; + + + MeshingParameters mparam; + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + + m->CalcLocalH(); + + MeshVolume (mparam, *m); + RemoveIllegalElements (*m); + OptimizeVolume (mparam, *m); + + return NG_OK; +} + + + +// 2D Meshing Functions: + +#if 0 // MODIFIED FOR GMSH + +void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x) +{ + Mesh * m = (Mesh*)mesh; + + m->AddPoint (Point3d (x[0], x[1], 0)); +} + +void Ng_AddBoundarySeg_2D (Ng_Mesh * mesh, int pi1, int pi2) +{ + Mesh * m = (Mesh*)mesh; + + Segment seg; + seg.p1 = pi1; + seg.p2 = pi2; + m->AddSegment (seg); +} + + +int Ng_GetNP_2D (Ng_Mesh * mesh) +{ + Mesh * m = (Mesh*)mesh; + return m->GetNP(); +} + +int Ng_GetNE_2D (Ng_Mesh * mesh) +{ + Mesh * m = (Mesh*)mesh; + return m->GetNSE(); +} + +int Ng_GetNSeg_2D (Ng_Mesh * mesh) +{ + Mesh * m = (Mesh*)mesh; + return m->GetNSeg(); +} + +void Ng_GetPoint_2D (Ng_Mesh * mesh, int num, double * x) +{ + Mesh * m = (Mesh*)mesh; + + Point<3> & p = m->Point(num); + x[0] = p(0); + x[1] = p(1); +} + +void Ng_GetElement_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum) +{ + const Element2d & el = ((Mesh*)mesh)->SurfaceElement(num); + for (int i = 1; i <= 3; i++) + pi[i-1] = el.PNum(i); + if (matnum) + *matnum = el.GetIndex(); +} + + +void Ng_GetSegment_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum) +{ + const Segment & seg = ((Mesh*)mesh)->LineSegment(num); + pi[0] = seg.p1; + pi[1] = seg.p2; + + if (matnum) + *matnum = seg.edgenr; +} + + + + +Ng_Geometry_2D * Ng_LoadGeometry_2D (const char * filename) +{ + SplineGeometry2d * geom = new SplineGeometry2d(); + geom -> Load (filename); + return (Ng_Geometry_2D *)geom; +} + +Ng_Result Ng_GenerateMesh_2D (Ng_Geometry_2D * geom, + Ng_Mesh ** mesh, + Ng_Meshing_Parameters * mp) +{ + // use global variable mparam + // MeshingParameters mparam; + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + mparam.quad = mp->quad_dominated; + + Mesh * m; + MeshFromSpline2D (*(SplineGeometry2d*)geom, m, mparam); + + cout << m->GetNSE() << " elements, " << m->GetNP() << " points" << endl; + + *mesh = (Ng_Mesh*)m; + return NG_OK; +} + +void Ng_HP_Refinement (Ng_Geometry_2D * geom, + Ng_Mesh * mesh, + int levels) +{ + Refinement2d ref(*(SplineGeometry2d*)geom); + HPRefinement (*(Mesh*)mesh, &ref, levels); +} + +void Ng_HP_Refinement (Ng_Geometry_2D * geom, + Ng_Mesh * mesh, + int levels, double parameter) +{ + Refinement2d ref(*(SplineGeometry2d*)geom); + HPRefinement (*(Mesh*)mesh, &ref, levels, parameter); +} + + + + + + + + + + + + + + + +ARRAY<STLReadTriangle> readtrias; //only before initstlgeometry +ARRAY<Point<3> > readedges; //only before init stlgeometry + +void Ng_SaveMesh(Ng_Mesh * mesh, const char* filename) +{ + ((Mesh*)mesh)->Save(filename); +} + +Ng_Mesh * Ng_LoadMesh(const char* filename) +{ + Mesh * mesh = new Mesh; + mesh->Load(filename); + return ( (Ng_Mesh*)mesh ); +} + +// loads geometry from STL file +Ng_STL_Geometry * Ng_STL_LoadGeometry (const char * filename, int binary) +{ + int i; + STLGeometry geom; + STLGeometry* geo; + ifstream ist(filename); + + if (binary) + { + geo = geom.LoadBinary(ist); + } + else + { + geo = geom.Load(ist); + } + + readtrias.SetSize(0); + readedges.SetSize(0); + + Point3d p; + Vec3d normal; + double p1[3]; + double p2[3]; + double p3[3]; + double n[3]; + + Ng_STL_Geometry * geo2 = Ng_STL_NewGeometry(); + + for (i = 1; i <= geo->GetNT(); i++) + { + const STLTriangle& t = geo->GetTriangle(i); + p = geo->GetPoint(t.PNum(1)); + p1[0] = p.X(); p1[1] = p.Y(); p1[2] = p.Z(); + p = geo->GetPoint(t.PNum(2)); + p2[0] = p.X(); p2[1] = p.Y(); p2[2] = p.Z(); + p = geo->GetPoint(t.PNum(3)); + p3[0] = p.X(); p3[1] = p.Y(); p3[2] = p.Z(); + normal = t.Normal(); + n[0] = normal.X(); n[1] = normal.Y(); n[2] = normal.Z(); + + Ng_STL_AddTriangle(geo2, p1, p2, p3, n); + } + + return geo2; +} + +// generate new STL Geometry +Ng_STL_Geometry * Ng_STL_NewGeometry () +{ + return (Ng_STL_Geometry*)(void*)new STLGeometry; +} + +// after adding triangles (and edges) initialize +Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom) +{ + STLGeometry* geo = (STLGeometry*)geom; + geo->InitSTLGeometry(readtrias); + readtrias.SetSize(0); + + if (readedges.Size() != 0) + { + int i; + /* + for (i = 1; i <= readedges.Size(); i+=2) + { + cout << "e(" << readedges.Get(i) << "," << readedges.Get(i+1) << ")" << endl; + } + */ + geo->AddEdges(readedges); + } + + if (geo->GetStatus() == STLTopology::STL_GOOD || geo->GetStatus() == STLTopology::STL_WARNING) return NG_OK; + return NG_SURFACE_INPUT_ERROR; +} + + // automatically generates edges: +Ng_Result Ng_STL_MakeEdges (Ng_STL_Geometry * geom, + Ng_Mesh* mesh, + Ng_Meshing_Parameters * mp) +{ + STLGeometry* stlgeometry = (STLGeometry*)geom; + Mesh* me = (Mesh*)mesh; + + MeshingParameters mparam; + + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + + me -> SetGlobalH (mparam.maxh); + me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), + stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), + 0.3); + + me -> LoadLocalMeshSize (mp->meshsize_filename); + /* + if (mp->meshsize_filename) + { + ifstream infile (mp->meshsize_filename); + if (!infile.good()) return NG_FILE_NOT_FOUND; + me -> LoadLocalMeshSize (infile); + } + */ + + STLMeshing (*stlgeometry, *me); + + stlgeometry->edgesfound = 1; + stlgeometry->surfacemeshed = 0; + stlgeometry->surfaceoptimized = 0; + stlgeometry->volumemeshed = 0; + + return NG_OK; +} + + +// generates mesh, empty mesh be already created. +Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom, + Ng_Mesh* mesh, + Ng_Meshing_Parameters * mp) +{ + STLGeometry* stlgeometry = (STLGeometry*)geom; + Mesh* me = (Mesh*)mesh; + + MeshingParameters mparam; + + mparam.maxh = mp->maxh; + mparam.meshsizefilename = mp->meshsize_filename; + + /* + me -> SetGlobalH (mparam.maxh); + me -> SetLocalH (stlgeometry->GetBoundingBox().PMin() - Vec3d(10, 10, 10), + stlgeometry->GetBoundingBox().PMax() + Vec3d(10, 10, 10), + 0.3); + */ + /* + STLMeshing (*stlgeometry, *me); + + stlgeometry->edgesfound = 1; + stlgeometry->surfacemeshed = 0; + stlgeometry->surfaceoptimized = 0; + stlgeometry->volumemeshed = 0; + */ + int retval = STLSurfaceMeshing (*stlgeometry, *me); + if (retval == MESHING3_OK) + { + (*mycout) << "Success !!!!" << endl; + stlgeometry->surfacemeshed = 1; + stlgeometry->surfaceoptimized = 0; + stlgeometry->volumemeshed = 0; + } + else if (retval == MESHING3_OUTERSTEPSEXCEEDED) + { + (*mycout) << "ERROR: Give up because of too many trials. Meshing aborted!" << endl; + } + else if (retval == MESHING3_TERMINATE) + { + (*mycout) << "Meshing Stopped!" << endl; + } + else + { + (*mycout) << "ERROR: Surface meshing not successful. Meshing aborted!" << endl; + } + + + STLSurfaceOptimization (*stlgeometry, *me, mparam); + + return NG_OK; +} + + + // fills STL Geometry + // positive orientation + // normal vector may be null-pointer +void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, + double * p1, double * p2, double * p3, double * nv) +{ + Point<3> apts[3]; + apts[0] = Point<3>(p1[0],p1[1],p1[2]); + apts[1] = Point<3>(p2[0],p2[1],p2[2]); + apts[2] = Point<3>(p3[0],p3[1],p3[2]); + + Vec<3> n; + if (!nv) + n = Cross (apts[0]-apts[1], apts[0]-apts[2]); + else + n = Vec<3>(nv[0],nv[1],nv[2]); + + readtrias.Append(STLReadTriangle(apts,n)); +} + + // add (optional) edges: +void Ng_STL_AddEdge (Ng_STL_Geometry * geom, + double * p1, double * p2) +{ + readedges.Append(Point3d(p1[0],p1[1],p1[2])); + readedges.Append(Point3d(p2[0],p2[1],p2[2])); +} + +#endif // MODIFIED FOR GMSH + +Ng_Meshing_Parameters :: Ng_Meshing_Parameters() +{ + maxh = 1000; + fineness = 0.5; + secondorder = 0; + meshsize_filename = 0; + quad_dominated = 0; +} + + +} + + +// compatibility functions: + +namespace netgen +{ + + char geomfilename[255]; + +void MyError (const char * ch) +{ + cerr << ch; +} + +//Destination for messages, errors, ... +void Ng_PrintDest(const char * s) +{ + (*mycout) << s << flush; +} + +double GetTime () +{ + return 0; +} + +void ResetTime () +{ + ; +} + +void MyBeep (int i) +{ + ; +} + +} diff --git a/contrib/Netgen/libsrc/interface/nglib.h b/contrib/Netgen/libsrc/interface/nglib.h new file mode 100644 index 0000000000000000000000000000000000000000..8c6285f619e841fab47ecea858391ce096d6a332 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/nglib.h @@ -0,0 +1,221 @@ +#ifndef NGLIB +#define NGLIB + +/**************************************************************************/ +/* File: nglib.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 7. May. 2000 */ +/**************************************************************************/ + +/* + +Interface to the netgen meshing kernel + +*/ + +/// Data type for NETGEN mesh +typedef void * Ng_Mesh; + +/// Data type for NETGEN CSG geomty +typedef void * Ng_CSG_Geometry; + +/// Data type for NETGEN 2D geomty +typedef void * Ng_Geometry_2D; + +/// Data type for NETGEN STL geomty +typedef void * Ng_STL_Geometry; + + + +// max number of nodes per element +#define NG_VOLUME_ELEMENT_MAXPOINTS 10 + +// implemented element types: +enum Ng_Volume_Element_Type { NG_TET = 1, NG_PYRAMID = 2, NG_PRISM = 3, + NG_TET10 = 4 }; + +// max number of nodes per surface element +#define NG_SURFACE_ELEMENT_MAXPOINTS 6 + +// implemented element types: +enum Ng_Surface_Element_Type { NG_TRIG = 1, NG_QUAD = 2, + NG_TRIG6 = 3 }; + + + +class Ng_Meshing_Parameters +{ + public: + + double maxh; + double fineness; // 0 .. coarse, 1 .. fine + int secondorder; + char * meshsize_filename; + int quad_dominated; + + Ng_Meshing_Parameters(); +}; + + +enum Ng_Result { NG_OK = 0, + NG_SURFACE_INPUT_ERROR = 1, + NG_VOLUME_FAILURE = 2, + NG_STL_INPUT_ERROR = 3, + NG_SURFACE_FAILURE = 4, + NG_FILE_NOT_FOUND = 5 }; + + + + + +// initialize, deconstruct Netgen library: +void Ng_Init (); +void Ng_Exit (); + + + +// Generates new mesh structure +Ng_Mesh * Ng_NewMesh (); +void Ng_DeleteMesh (Ng_Mesh * mesh); + +// feeds points, surface elements and volume elements to the mesh +void Ng_AddPoint (Ng_Mesh * mesh, double * x); +void Ng_AddSurfaceElement (Ng_Mesh * mesh, Ng_Surface_Element_Type et, + int * pi); +void Ng_AddVolumeElement (Ng_Mesh * mesh, Ng_Volume_Element_Type et, + int * pi); + +// ask for number of points, surface and volume elements +int Ng_GetNP (Ng_Mesh * mesh); +int Ng_GetNSE (Ng_Mesh * mesh); +int Ng_GetNE (Ng_Mesh * mesh); + + +// return point coordinates +void Ng_GetPoint (Ng_Mesh * mesh, int num, double * x); + +// return surface and volume element in pi +Ng_Surface_Element_Type +Ng_GetSurfaceElement (Ng_Mesh * mesh, int num, int * pi); + +Ng_Volume_Element_Type +Ng_GetVolumeElement (Ng_Mesh * mesh, int num, int * pi); + + +// Defines MeshSize Functions +void Ng_RestrictMeshSizeGlobal (Ng_Mesh * mesh, double h); +void Ng_RestrictMeshSizePoint (Ng_Mesh * mesh, double * p, double h); +void Ng_RestrictMeshSizeBox (Ng_Mesh * mesh, double * pmin, double * pmax, double h); + +// generates volume mesh from surface mesh +Ng_Result Ng_GenerateVolumeMesh (Ng_Mesh * mesh, Ng_Meshing_Parameters * mp); + +void Ng_SaveMesh(Ng_Mesh * mesh, const char* filename); +Ng_Mesh * Ng_LoadMesh(const char* filename); + + + + + +// ********************************************************** +// ** 2D Meshing ** +// ********************************************************** + + +// feeds points and boundary to mesh + +void Ng_AddPoint_2D (Ng_Mesh * mesh, double * x); +void Ng_AddBoundarySeg_2D (Ng_Mesh * mesh, int pi1, int pi2); + +// ask for number of points, elements and boundary segments +int Ng_GetNP_2D (Ng_Mesh * mesh); +int Ng_GetNE_2D (Ng_Mesh * mesh); +int Ng_GetNSeg_2D (Ng_Mesh * mesh); + +// return point coordinates +void Ng_GetPoint_2D (Ng_Mesh * mesh, int num, double * x); + +// return 2d triangles +void Ng_GetElement_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum = NULL); + +// return 2d boundary segment +void Ng_GetSegment_2D (Ng_Mesh * mesh, int num, int * pi, int * matnum = NULL); + + +// load 2d netgen spline geometry +Ng_Geometry_2D * Ng_LoadGeometry_2D (const char * filename); + +// generate 2d mesh, mesh is allocated by function +Ng_Result Ng_GenerateMesh_2D (Ng_Geometry_2D * geom, + Ng_Mesh ** mesh, + Ng_Meshing_Parameters * mp); + +void Ng_HP_Refinement (Ng_Geometry_2D * geom, + Ng_Mesh * mesh, + int levels); + + + + + +// ********************************************************** +// ** STL Meshing ** +// ********************************************************** + + +// loads geometry from STL file +Ng_STL_Geometry * Ng_STL_LoadGeometry (const char * filename, int binary = 0); + + +// generate new STL Geometry +Ng_STL_Geometry * Ng_STL_NewGeometry (); + + +// fills STL Geometry +// positive orientation +// normal vector may be null-pointer +void Ng_STL_AddTriangle (Ng_STL_Geometry * geom, + double * p1, double * p2, double * p3, + double * nv = NULL); + +// add (optional) edges : +void Ng_STL_AddEdge (Ng_STL_Geometry * geom, + double * p1, double * p2); + +// after adding triangles (and edges) initialize +Ng_Result Ng_STL_InitSTLGeometry (Ng_STL_Geometry * geom); + +// automatically generates edges: +Ng_Result Ng_STL_MakeEdges (Ng_STL_Geometry * geom, + Ng_Mesh* mesh, + Ng_Meshing_Parameters * mp); + + +// generates mesh, empty mesh must be already created. +Ng_Result Ng_STL_GenerateSurfaceMesh (Ng_STL_Geometry * geom, + Ng_Mesh * mesh, + Ng_Meshing_Parameters * mp); + + +#ifdef ACIS + +// ********************************************************** +// ** ACIS Meshing ** +// ********************************************************** + +/// Data type for NETGEN STL geomty +typedef void * Ng_ACIS_Geometry; + +// loads geometry from STL file +Ng_ACIS_Geometry * Ng_ACIS_LoadGeometry (const char * filename); + +// generates mesh, empty mesh must be already created. +Ng_Result Ng_ACIS_GenerateSurfaceMesh (Ng_ACIS_Geometry * geom, + Ng_Mesh * mesh, + Ng_Meshing_Parameters * mp); + + +#endif + + +#endif \ No newline at end of file diff --git a/contrib/Netgen/libsrc/interface/readtetmesh.cpp b/contrib/Netgen/libsrc/interface/readtetmesh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a81e5e7ab107f9294726f0b5a320d7033a94067 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/readtetmesh.cpp @@ -0,0 +1,797 @@ + +// +// Read CST file format +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + + +namespace netgen +{ +#include "writeuser.hpp" + + + + + void ReadTETFormat (Mesh & mesh, + const string & hfilename) + { + const char * filename = hfilename.c_str(); + + cout << "Reading .tet mesh" << endl; + + ifstream in (filename); + + int inputsection = 0; + bool done = false; + + char ch; + string str; + + string version; + + int unitcode; + double tolerance; + double dS1, dS2, alphaDeg, x3D, y3D, z3D; + int nelts,nfaces,nedges,nnodes; + int nperiodicmasternodes,ncornerperiodicmasternodes,ncubicperiodicmasternodes; + int nperiodicmasteredges,ncornerperiodicmasteredges; + int nperiodicmasterfaces; + int nodeid,type,pid; + int dummyint; + int modelverts,modeledges,modelfaces,modelcells; + Point3d p; + int numObj3D,numObj2D,numObj1D,numObj0D; + bool nullstarted; + ARRAY<int> eldom; + int minId3D,minId2D; + int maxId3D(-1), maxId2D(-1), maxId1D(-1), maxId0D(-1); + ARRAY<ARRAY<int> *> segmentdata; + ARRAY<Element2d* > tris; + + ARRAY<int> userdata_int; // just save data for 1:1 output + ARRAY<double> userdata_double; + ARRAY<int> point_pids; + ARRAY<int> tetfacedata; + ARRAY<int> uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D; + + while(!done) + { + // skip "//" comment + bool comment = true; + while(comment) + { + ch = in.get(); + while(ch == ' ' || ch == '\n' || ch == '\t' || ch =='\r') + ch = in.get(); + + if(ch != '/') + { + comment = false; + in.putback(ch); + } + else + { + ch = in.get(); + if(ch != '/') + { + comment = false; + in.putback(ch); + in.putback('/'); + } + else + { + in.ignore(10000,'\n'); + } + } + } + + + switch(inputsection) + { + case 0: + // version number + in >> version; + cout << "Version number " << version << endl; + if(version != "1.1" && version != "2" && version != "2.0") + { + cerr << "WARNING: import only tested for versions 1.1 and 2" << endl; + //done = true; + } + userdata_double.Append(atof(version.c_str())); + break; + + case 1: + // unit code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL) + in >> unitcode; + cout << "unit code " << unitcode << endl; + userdata_int.Append(unitcode); + break; + + case 2: + // Geometric coord "zero" tolerance threshold + in >> tolerance; + cout << "tolerance " << tolerance << endl; + userdata_double.Append(tolerance); + break; + + case 3: + // Periodic UnitCell dS1 , dS2 , alphaDeg + in >> dS1 >> dS2 >> alphaDeg; + userdata_double.Append(dS1); + userdata_double.Append(dS2); + userdata_double.Append(alphaDeg); + break; + + case 4: + // Periodic UnitCell origin in global coords (x3D,y3D,z3D) + in >> x3D >> y3D >> z3D; + userdata_double.Append(x3D); + userdata_double.Append(y3D); + userdata_double.Append(z3D); + break; + + case 5: + // Model entity count: Vertices, Edges, Faces, Cells (Version 2) + in >> modelverts >> modeledges >> modelfaces >> modelcells; + userdata_int.Append(modelverts); + userdata_int.Append(modeledges); + userdata_int.Append(modelfaces); + userdata_int.Append(modelcells); + break; + + case 6: + // Topological mesh-entity counts (#elements,#faces,#edges,#nodes) + in >> nelts >> nfaces >> nedges >> nnodes; + cout << nelts << " elements, " << nfaces << " faces, " << nedges << " edges, " << nnodes << " nodes" << endl; + mesh.SetAllocSize(nnodes,2*nedges,nfaces,nelts); + break; + + case 7: + // NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), PID: + { + cout << "read nodes" << endl; + for(int i=0; i<nnodes; i++) + { + in >> nodeid >> p.X() >> p.Y() >> p.Z() >> type >> pid; + mesh.AddPoint(p); + point_pids.Append(pid); + if(pid > maxId0D) + maxId0D = pid; + //(*testout) << "point " << p << " type " << type << " mastersexist " << mastersexist << endl; + } + } + break; + + case 8: + // Number of Periodic Master Nodes + in >> nperiodicmasternodes; + break; + + case 9: + // MasterNodeID, SlaveNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2) + for(int i=0; i<nperiodicmasternodes; i++) + { + for(int j=0; j<2; j++) + in >> dummyint; + + in >> dummyint; + } + break; + + case 10: + // Number of Corner Periodic Master Nodes + in >> ncornerperiodicmasternodes; + break; + + case 11: + // MasterNodeID, 3-SlaveNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2) + for(int i=0; i<ncornerperiodicmasternodes; i++) + { + for(int j=0; j<4; j++) + in >> dummyint; + + for(int j=0; j<3; j++) + in >> dummyint; + } + break; + + case 12: + // Number of Cubic Periodic Master Nodes + in >> ncubicperiodicmasternodes; + break; + + case 13: + //MasterNodeID, 7-SlaveNodeID's, TranslCodes + for(int i=0; i<ncubicperiodicmasternodes; i++) + { + for(int j=0; j<8; j++) + in >> dummyint; + + for(int j=0; j<7; j++) + in >> dummyint; + } + break; + + case 14: + // EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), PID + cout << "read edges" << endl; + nullstarted = false; + segmentdata.SetSize(nedges); + for(int i=0; i<nedges; i++) + { + segmentdata[i] = new ARRAY<int>(7); + *segmentdata[i] = -1; + in >> dummyint; + in >> (*segmentdata[i])[0] >> (*segmentdata[i])[1]; + in >> type; + in >> (*segmentdata[i])[2]; + if((*segmentdata[i])[2] > maxId1D) + maxId1D = (*segmentdata[i])[2]; + } + break; + + case 15: + // Number of Periodic Master Edges + in >> nperiodicmasteredges; + break; + + case 16: + // MasterEdgeID, SlaveEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2) + for(int i=0; i<nperiodicmasteredges; i++) + in >> dummyint >> dummyint >> dummyint; + break; + + case 17: + // Number of Corner Periodic Master Edges + in >> ncornerperiodicmasteredges; + break; + + case 18: + // MasterEdgeID, 3 SlaveEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2) + for(int i=0; i<ncornerperiodicmasteredges; i++) + { + in >> dummyint; + for(int j=0; j<3; j++) + in >> dummyint; + for(int j=0; j<3; j++) + in >> dummyint; + } + break; + + case 19: + // FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PSlave), PID + { + //Segment seg; + int segnum_ng[3]; + bool neg[3]; + cout << "read faces" << endl; + nullstarted = false; + for(int i=0; i<nfaces; i++) + { + int trinum; + int segnum; + + tris.Append(new Element2d(TRIG)); + + in >> trinum; + for(int j=0; j<3; j++) + { + in >> segnum; + neg[j] = (segnum<0); + if(!neg[j]) + segnum_ng[j] = segnum-1; + else + segnum_ng[j] = -segnum-1; + + if(neg[j]) + tris.Last()->PNum(j+1) = (*segmentdata[segnum_ng[j]])[1]; + else + tris.Last()->PNum(j+1) = (*segmentdata[segnum_ng[j]])[0]; + + tris.Last()->GeomInfoPi(j+1).trignum = trinum; + } + in >> type; + int faceid; + in >> faceid; + + if(faceid > maxId2D) + maxId2D = faceid; + + if(i==0 || faceid < minId2D) + minId2D = faceid; + + tris.Last()->SetIndex(faceid); + + if(faceid > 0) + { + //if(nullstarted) + // { + // cout << "Faces: Assumption about index 0 wrong (face"<<trinum <<")" << endl; + // } + //mesh.AddSurfaceElement(tri); + + for(int j=0; j<3; j++) + { + if(neg[j]) + { + (*segmentdata[segnum_ng[j]])[4] = faceid; + (*segmentdata[segnum_ng[j]])[6] = trinum; + } + else + { + (*segmentdata[segnum_ng[j]])[3] = faceid; + (*segmentdata[segnum_ng[j]])[5] = trinum; + } + } + } + else + nullstarted = true; + } + } + break; + + case 20: + // Number of Periodic Master Faces + in >> nperiodicmasterfaces; + break; + + case 21: + // MasterFaceID, SlaveFaceID, TranslCode (1=dS1 2=dS2) + { + Vec<3> randomvec(-1.32834,3.82399,0.5429151); + int maxtransl = -1; + for(int i=0; i<nperiodicmasterfaces; i++) + { + int tri1,tri2,transl; + ARRAY<PointIndex> nodes1(3),nodes2(3); + ARRAY<double> sortval1(3),sortval2(3); + in >> tri1 >> tri2 >> transl; + + if(transl > maxtransl) + maxtransl = transl; + + + for(int j=0; j<3; j++) + { + nodes1[j] = tris[tri1-1]->PNum(j+1); + sortval1[j] = Vec<3>(mesh[nodes1[j]])*randomvec; + nodes2[j] = tris[tri2-1]->PNum(j+1); + sortval2[j] = Vec<3>(mesh[nodes2[j]])*randomvec; + } + + BubbleSort(sortval1,nodes1); + BubbleSort(sortval2,nodes2); + + for(int j=0; j<3; j++) + mesh.GetIdentifications().Add(nodes1[j],nodes2[j],transl); + + } + for(int i=1; i<= maxtransl; i++) + mesh.GetIdentifications().SetType(i,Identifications::PERIODIC); + } + break; + + case 22: + // ElemID, FaceID0, FaceID1, FaceID2, FaceID3, PID + { + cout << "read elements (1)" << endl; + + //SurfaceElementIndex surf[4]; + bool neg[4]; + int elemid; + int domain; + + eldom.SetSize(nelts); + + for(int i=0; i<nelts; i++) + { + if(int(100.*i/nelts) % 5 == 0) + cout << int(100.*i/nelts) +#ifdef WIN32 + << "%%\r" +#else + << "\%\r" +#endif + << flush; + in >> elemid; + for(int j=0; j<4;j++) + { + in >> dummyint; + neg[j] = (dummyint < 0); + if(neg[j]) + tetfacedata.Append(-dummyint-1); + //surf[j] = -dummyint-1; + else + tetfacedata.Append(dummyint-1); + tetfacedata.Append(((neg[j]) ? 1 : 0)); + //surf[j] = dummyint-1; + } + + in >> domain; + eldom[i] = domain; + tetfacedata.Append(domain); + + if(i==0 || domain < minId3D) + minId3D = domain; + + if(domain > maxId3D) + maxId3D = domain; + + // for(int j=0; j<4; j++) + // { + // if(mesh.GetNSE() <= surf[j]) + // continue; + + // int faceind = 0; + // for(int k=1; k<=mesh.GetNFD(); k++) + // { + // if(mesh.GetFaceDescriptor(k).SurfNr() == mesh[surf[j]].GetIndex()) + // faceind = k; + // } + // if(faceind) + // { + // if(neg[j]) + // mesh.GetFaceDescriptor(faceind).SetDomainOut(domain); + // else + // mesh.GetFaceDescriptor(faceind).SetDomainIn(domain); + // } + // else + // { + // if(neg[j]) + // faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf[j]].GetIndex(),0,domain,0)); + // else + // faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf[j]].GetIndex(),domain,0,0)); + // mesh.GetFaceDescriptor(faceind).SetBCProperty(mesh[surf[j]].GetIndex()); + // } + // } + } + cout << endl; + + + // ARRAY<int> indextodescriptor(maxId2D+1); + + // for(int i=1; i<=mesh.GetNFD(); i++) + // indextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i; + + + // for(SurfaceElementIndex i=0; i<mesh.GetNSE(); i++) + // mesh[i].SetIndex(indextodescriptor[mesh[i].GetIndex()]); + } + break; + + case 23: + // ElemID, NodeID0, NodeID1, NodeID2, NodeID3 + { + cout << "read elements (2)" << endl; + Element el(TET); + for(ElementIndex i=0; i<nelts; i++) + { + in >> dummyint; + for(int j=1; j<=4; j++) + in >> el.PNum(j); + swap(el.PNum(1),el.PNum(2)); + + el.SetIndex(eldom[i]); + mesh.AddVolumeElement(el); + } + } + break; + + case 24: + // Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D) + { + in >> numObj3D; + userdata_int.Append(numObj3D); + in >> numObj2D; + userdata_int.Append(numObj2D); + in >> numObj1D; + userdata_int.Append(numObj1D); + in >> numObj0D; + userdata_int.Append(numObj0D); + } + break; + + case 25: + // Number of Ports (Ports are a subset of Object2D list) + { + in >> dummyint; + //userdata_int.Append(dummyint); + } + break; + + case 26: + // Object3D GroupID, #Elems <immediately followed by> ElemID List + { + uid_to_group_3D.SetSize(maxId3D+1); + uid_to_group_3D = -1; + for(int i=0; i<numObj3D; i++) + { + int groupid; + in >> groupid; + (*testout) << "3d groupid " << groupid << endl; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> dummyint; + + (*testout) << "read " << dummyint << endl; + //userdata_int.Append(dummyint); + + if(dummyint < 0) + dummyint *= -1; + uid_to_group_3D[eldom[dummyint-1]] = groupid; + } + } + } + break; + + case 27: + // Object2D GroupID, #Faces <immediately followed by> FaceID List + { + ARRAY<int> ports; + //int totnum = 0; + uid_to_group_2D.SetSize(maxId2D+1); + uid_to_group_2D = -1; + + for(int i=0; i<numObj2D; i++) + { + int groupid; + in >> groupid; + (*testout) << "2d groupid " << groupid << endl; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> dummyint; + char port; + while((port = in.get()) == ' ') + ; + + (*testout) << "read " << dummyint << endl; + if(dummyint < 0) + dummyint *= -1; + int uid = tris[dummyint-1]->GetIndex(); + + if(port == 'P' || port == 'p') + { + if(!ports.Contains(uid)) + ports.Append(uid); + } + else + in.putback(port); + + //userdata_int.Append(dummyint); + + uid_to_group_2D[uid] = groupid; + (*testout) << "setting " << uid << endl; + + //totnum++; + } + } + mesh.SetUserData("TETmesh:ports",ports); + } + break; + + case 28: + // Object1D GroupID, #Edges <immediately followed by> EdgeID List + { + uid_to_group_1D.SetSize(maxId1D+1); + uid_to_group_1D = -1; + + for(int i=0; i<numObj1D; i++) + { + int groupid; + in >> groupid; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> dummyint; + //userdata_int.Append(dummyint); + + if(dummyint < 0) + dummyint *= -1; + uid_to_group_1D[(*segmentdata[dummyint-1])[2]] = groupid; + } + } + } + break; + + case 29: + // Object0D GroupID, #Nodes <immediately followed by> NodeID List + { + uid_to_group_0D.SetSize(maxId0D+1); + uid_to_group_0D = -1; + for(int i=0; i<numObj0D; i++) + { + int groupid; + in >> groupid; + //userdata_int.Append(groupid); + int nelems; + in >> nelems; + //userdata_int.Append(nelems); + for(int j=0; j<nelems; j++) + { + in >> dummyint; + //userdata_int.Append(dummyint); + + if(dummyint < 0) + dummyint *= -1; + uid_to_group_0D[point_pids[dummyint-1]] = groupid; + } + } + } + break; + + + + default: + done = true; + + } + + if(inputsection == 4 && version == "1.1") + inputsection++; + + inputsection++; + } + in.close(); + + + mesh.SetUserData("TETmesh:double",userdata_double); + userdata_int.Append(minId2D); + userdata_int.Append(minId3D); + mesh.SetUserData("TETmesh:int",userdata_int); + //if(version == "1.1") + mesh.SetUserData("TETmesh:point_id",point_pids); + + mesh.SetUserData("TETmesh:uid_to_group_3D",uid_to_group_3D); + mesh.SetUserData("TETmesh:uid_to_group_2D",uid_to_group_2D); + mesh.SetUserData("TETmesh:uid_to_group_1D",uid_to_group_1D); + mesh.SetUserData("TETmesh:uid_to_group_0D",uid_to_group_0D); + + + ARRAY<SurfaceElementIndex> surfindices(tris.Size()); + surfindices = -1; + + for(int i=0; i<tris.Size(); i++) + { + if(atof(version.c_str()) <= 1.999999) + { + if(tris[i]->GetIndex() > 0) + surfindices[i] = mesh.AddSurfaceElement(*tris[i]); + } + else + { + if(tris[i]->GetIndex() > 0 && + tris[i]->GetIndex() < minId3D) + { + tris[i]->SetIndex(tris[i]->GetIndex()-minId2D+1); + surfindices[i] = mesh.AddSurfaceElement(*tris[i]); + } + } + delete tris[i]; + } + + + mesh.ClearFaceDescriptors(); + if(atof(version.c_str()) <= 1.999999) + for(int i = 1; i <= maxId2D; i++) + mesh.AddFaceDescriptor(FaceDescriptor(i,0,0,0)); + else + for(int i=minId2D; i<minId3D; i++) + mesh.AddFaceDescriptor(FaceDescriptor(i,0,0,0)); + + + for(int i=0; i<tetfacedata.Size(); i+=9) + { + for(int j=0; j<4; j++) + { + SurfaceElementIndex surf = surfindices[tetfacedata[i+2*j]]; + + //if(mesh.GetNSE() <= surf) + if(surf == -1) + continue; + + if(tetfacedata[i+2*j+1] == 1) + mesh.GetFaceDescriptor(mesh[surf].GetIndex()).SetDomainOut(tetfacedata[i+8]); + else + mesh.GetFaceDescriptor(mesh[surf].GetIndex()).SetDomainIn(tetfacedata[i+8]); + + + /* + int faceind = 0; + for(int k=1; k<=mesh.GetNFD(); k++) + { + if(mesh.GetFaceDescriptor(k).SurfNr() == mesh[surf].GetIndex()) + faceind = k; + } + if(faceind) + { + if(tetfacedata[i+4+j] == 1) + mesh.GetFaceDescriptor(faceind).SetDomainOut(tetfacedata[i+8]); + else + mesh.GetFaceDescriptor(faceind).SetDomainIn(tetfacedata[i+8]); + } + else + { + if(tetfacedata[i+4+j] == 1) + faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf].GetIndex(),0,tetfacedata[i+8],0)); + else + faceind = mesh.AddFaceDescriptor(FaceDescriptor(mesh[surf].GetIndex(),tetfacedata[i+8],0,0)); + mesh.GetFaceDescriptor(faceind).SetBCProperty(mesh[surf].GetIndex()); + } + */ + } + + } + + // ARRAY<int> indextodescriptor(maxId2D+1); + + // for(int i=1; i<=mesh.GetNFD(); i++) + // indextodescriptor[mesh.GetFaceDescriptor(i).SurfNr()] = i; + + + // for(SurfaceElementIndex i=0; i<mesh.GetNSE(); i++) + // mesh[i].SetIndex(indextodescriptor[mesh[i].GetIndex()]); + + + for(int i=0; i<segmentdata.Size(); i++) + { + Segment seg; + + + if((atof(version.c_str()) <= 1.999999 && (*segmentdata[i])[2] > 0) || + (atof(version.c_str()) > 1.999999 && (*segmentdata[i])[2] > 0 && (*segmentdata[i])[2] < minId2D)) + { + seg.p1 = (*segmentdata[i])[0]; + seg.p2 = (*segmentdata[i])[1]; + seg.edgenr = (*segmentdata[i])[2]; + seg.epgeominfo[0].edgenr = (*segmentdata[i])[2]; + seg.epgeominfo[1].edgenr = (*segmentdata[i])[2]; + seg.si = (*segmentdata[i])[3]-minId2D+1; + seg.surfnr1 = -1;//(*segmentdata[i])[3]; + seg.surfnr2 = -1;//(*segmentdata[i])[4]; + seg.geominfo[0].trignum = (*segmentdata[i])[5]; + seg.geominfo[1].trignum = (*segmentdata[i])[5]; + mesh.AddSegment(seg); + + seg.p1 = (*segmentdata[i])[1]; + seg.p2 = (*segmentdata[i])[0]; + seg.si = (*segmentdata[i])[4]-minId2D+1; + seg.surfnr1 = -1;//(*segmentdata[i])[3]; + seg.surfnr2 = -1;//(*segmentdata[i])[4]; + seg.geominfo[0].trignum = (*segmentdata[i])[6]; + seg.geominfo[1].trignum = (*segmentdata[i])[6]; + mesh.AddSegment(seg); + } + delete segmentdata[i]; + } + + /* + for(int i=mesh.GetNSeg(); i>=1; i--) + if(mesh.LineSegment(i).epgeominfo[0].edgenr == 0 || + mesh.LineSegment(i).epgeominfo[1].edgenr == 0) + mesh.FullDeleteSegment(i); + */ + + mesh.CalcSurfacesOfNode(); + + } +} + + diff --git a/contrib/Netgen/libsrc/interface/readuser.cpp b/contrib/Netgen/libsrc/interface/readuser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb677d8d72421cf35bce5f96dd8fb64a72478688 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/readuser.cpp @@ -0,0 +1,407 @@ +// +// Read user dependent output file +// + + +#include <mystdlib.h> + + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + void ReadFile (Mesh & mesh, + const string & hfilename) + { + cout << "Read User File" << endl; + + const char * filename = hfilename.c_str(); + + int i, j; + + char reco[100]; + int np, nbe; + + + + // ".surf" - mesh + + if ( (strlen (filename) > 5) && + strcmp (&filename[strlen (filename)-5], ".surf") == 0 ) + + { + cout << "Surface file" << endl; + + ifstream in (filename); + + in >> reco; + in >> np; + for (i = 1; i <= np; i++) + { + Point3d p; + in >> p.X() >> p.Y() >> p.Z(); + mesh.AddPoint (p); + } + + mesh.ClearFaceDescriptors(); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + + in >> nbe; + // int invert = globflags.GetDefineFlag ("invertsurfacemesh"); + for (i = 1; i <= nbe; i++) + { + Element2d el; + int hi; + + el.SetIndex(1); + + // in >> hi; + for (j = 1; j <= 3; j++) + { + in >> el.PNum(j); + // el.PNum(j)++; + if (el.PNum(j) < PointIndex(1) || + el.PNum(j) > PointIndex(np)) + { + cerr << "Point Number " << el.PNum(j) << " out of range 1..." + << np << endl; + return; + } + } + + /* + if (invert) + swap (el.PNum(2), el.PNum(3)); + */ + + mesh.AddSurfaceElement (el); + } + + + cout << "points: " << np << " faces: " << nbe << endl; + } + + + + + + // Universal mesh (AVL) + if ( (strlen (filename) > 4) && + strcmp (&filename[strlen (filename)-4], ".unv") == 0 ) + { + int i, j, k; + + double h; + char reco[100]; + int np, nbe; + int invert; + + + ifstream in(filename); + + invert = 0; // globflags.GetDefineFlag ("invertsurfacemesh"); + double scale = 1; // globflags.GetNumFlag ("scale", 1); + + mesh.ClearFaceDescriptors(); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + + + while (in.good()) + { + in >> reco; + if (strcmp (reco, "NODES") == 0) + { + cout << "nodes found" << endl; + for (j = 1; j <= 4; j++) + in >> reco; // read dummy + + while (1) + { + int pi, hi; + double x, y, z; + Point3d p; + + in >> pi; + if (pi == -1) + break; + + in >> hi >> hi >> hi; + in >> p.X() >> p.Y() >> p.Z(); + + p.X() *= scale; + p.Y() *= scale; + p.Z() *= scale; + + + mesh.AddPoint (p); + } + } + + if (strcmp (reco, "ELEMENTS") == 0) + { + cout << "elements found" << endl; + for (j = 1; j <= 4; j++) + in >> reco; // read dummy + + while (1) + { + int hi; + in >> hi; + if (hi == -1) break; + for (j = 1; j <= 7; j++) + in >> hi; + + Element2d el; + el.SetIndex(1); + in >> el.PNum(1) >> el.PNum(2) >> el.PNum(3); + + if (invert) + swap (el.PNum(2), el.PNum(3)); + mesh.AddSurfaceElement (el); + + for (j = 1; j <= 5; j++) + in >> hi; + } + } + } + + + Point3d pmin, pmax; + mesh.GetBox (pmin, pmax); + cout << "bounding-box = " << pmin << "-" << pmax << endl; + } + + + + // fepp format2d: + + if ( (strlen (filename) > 7) && + strcmp (&filename[strlen (filename)-7], ".mesh2d") == 0 ) + { + cout << "Reading FEPP2D Mesh" << endl; + + char buf[100]; + int np, ne, nseg, i, j; + + ifstream in (filename); + + in >> buf; + + in >> nseg; + for (i = 1; i <= nseg; i++) + { + int bound, p1, p2; + in >> bound >> p1 >> p2; + // forget them + } + + in >> ne; + for (i = 1; i <= ne; i++) + { + int mat, nelp; + in >> mat >> nelp; + Element2d el (nelp == 3 ? TRIG : QUAD); + el.SetIndex (mat); + for (j = 1; j <= nelp; j++) + in >> el.PNum(j); + mesh.AddSurfaceElement (el); + } + + in >> np; + for (i = 1; i <= np; i++) + { + Point3d p(0,0,0); + in >> p.X() >> p.Y(); + mesh.AddPoint (p); + } + } + + + else if ( (strlen (filename) > 5) && + strcmp (&filename[strlen (filename)-5], ".mesh") == 0 ) + { + cout << "Reading Neutral Format" << endl; + + int np, ne, nse, i, j; + + ifstream in (filename); + + in >> np; + + if (in.good()) + { + // file starts with an integer + + for (i = 1; i <= np; i++) + { + Point3d p(0,0,0); + in >> p.X() >> p.Y() >> p.Z(); + mesh.AddPoint (p); + } + + in >> ne; + for (i = 1; i <= ne; i++) + { + int mat; + in >> mat; + Element el (4); + el.SetIndex (mat); + for (j = 1; j <= 4; j++) + in >> el.PNum(j); + mesh.AddVolumeElement (el); + } + + mesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0)); + + in >> nse; + for (i = 1; i <= nse; i++) + { + int mat, nelp; + in >> mat; + Element2d el (TRIG); + el.SetIndex (mat); + for (j = 1; j <= 3; j++) + in >> el.PNum(j); + mesh.AddSurfaceElement (el); + } + } + else + { + char buf[100]; + in.clear(); + do + { + in >> buf; + cout << "buf = " << buf << endl; + if (strcmp (buf, "points") == 0) + { + in >> np; + cout << "np = " << np << endl; + } + } + while (in.good()); + } + } + + + if ( (strlen (filename) > 4) && + strcmp (&filename[strlen (filename)-4], ".emt") == 0 ) + { + ifstream inemt (filename); + + string pktfile = filename; + int len = strlen (filename); + pktfile[len-3] = 'p'; + pktfile[len-2] = 'k'; + pktfile[len-1] = 't'; + cout << "pktfile = " << pktfile << endl; + + int np, nse, i; + int num, bcprop; + ifstream inpkt (pktfile.c_str()); + inpkt >> np; + ARRAY<double> values(np); + for (i = 1; i <= np; i++) + { + Point3d p(0,0,0); + inpkt >> p.X() >> p.Y() >> p.Z() + >> bcprop >> values.Elem(i); + mesh.AddPoint (p); + } + + mesh.ClearFaceDescriptors(); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + mesh.GetFaceDescriptor(1).SetBCProperty (1); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + mesh.GetFaceDescriptor(2).SetBCProperty (2); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + mesh.GetFaceDescriptor(3).SetBCProperty (3); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + mesh.GetFaceDescriptor(4).SetBCProperty (4); + mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + mesh.GetFaceDescriptor(5).SetBCProperty (5); + + int p1, p2, p3; + double value; + inemt >> nse; + for (i = 1; i <= nse; i++) + { + inemt >> p1 >> p2 >> p3 >> bcprop >> value; + + if (bcprop < 1 || bcprop > 4) + cerr << "bcprop out of range, bcprop = " << bcprop << endl; + p1++; + p2++; + p3++; + if (p1 < 1 || p1 > np || p2 < 1 || p2 > np || p3 < 1 || p3 > np) + { + cout << "p1 = " << p1 << " p2 = " << p2 << " p3 = " << p3 << endl; + } + + if (i > 110354) Swap (p2, p3); + if (mesh.Point(p1)(0) < 0.25) + Swap (p2,p3); + + Element2d el(TRIG); + + if (bcprop == 1) + { + if (values.Get(p1) < -69999) + el.SetIndex(1); + else + el.SetIndex(2); + } + else + el.SetIndex(3); + + + el.PNum(1) = p1; + el.PNum(2) = p2; + el.PNum(3) = p3; + mesh.AddSurfaceElement (el); + } + + + ifstream incyl ("ngusers/guenter/cylinder.surf"); + int npcyl, nsecyl; + incyl >> npcyl; + cout << "npcyl = " << npcyl << endl; + for (i = 1; i <= npcyl; i++) + { + Point3d p(0,0,0); + incyl >> p.X() >> p.Y() >> p.Z(); + mesh.AddPoint (p); + } + incyl >> nsecyl; + cout << "nsecyl = " << nsecyl << endl; + for (i = 1; i <= nsecyl; i++) + { + incyl >> p1 >> p2 >> p3; + p1 += np; + p2 += np; + p3 += np; + Element2d el(TRIG); + el.SetIndex(5); + el.PNum(1) = p1; + el.PNum(2) = p2; + el.PNum(3) = p3; + mesh.AddSurfaceElement (el); + } + } + + + // .tet mesh + if ( (strlen (filename) > 4) && + strcmp (&filename[strlen (filename)-4], ".tet") == 0 ) + { + ReadTETFormat (mesh, filename); + } + } + +} + diff --git a/contrib/Netgen/libsrc/interface/writeabaqus.cpp b/contrib/Netgen/libsrc/interface/writeabaqus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2564da0be6af9523482a487cdda872a81f32f0e5 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeabaqus.cpp @@ -0,0 +1,237 @@ +// +// Write Abaqus file +// +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + + + +void WriteAbaqusFormat (const Mesh & mesh, + const string & filename) + +{ + + cout << "\nWrite Abaqus Volume Mesh" << endl; + + ofstream outfile (filename.c_str()); + + outfile << "*Heading" << endl; + outfile << " " << filename << endl; + + outfile.precision(8); + + outfile << "*Node" << endl; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int i, j, k; + + for (i = 1; i <= np; i++) + { + outfile << i << ", "; + outfile << mesh.Point(i)(0) << ", "; + outfile << mesh.Point(i)(1) << ", "; + outfile << mesh.Point(i)(2) << "\n"; + } + + int elemcnt = 0; //element counter + int finished = 0; + int indcnt = 1; //index counter + + while (!finished) + { + int actcnt = 0; + const Element & el1 = mesh.VolumeElement(1); + int non = el1.GetNP(); + if (non == 4) + { + outfile << "*Element, type=C3D4, ELSET=PART" << indcnt << endl; + } + else if (non == 10) + { + outfile << "*Element, type=C3D10, ELSET=PART" << indcnt << endl; + } + else + { + cout << "unsupported Element type!!!" << endl; + } + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + + if (el.GetIndex() == indcnt) + { + actcnt++; + if (el.GetNP() != non) + { + cout << "different element-types in a subdomain are not possible!!!" << endl; + continue; + } + + elemcnt++; + outfile << elemcnt << ", "; + if (non == 4) + { + outfile << el.PNum(1) << ", "; + outfile << el.PNum(2) << ", "; + outfile << el.PNum(4) << ", "; + outfile << el.PNum(3) << "\n"; + } + else if (non == 10) + { + outfile << el.PNum(1) << ", "; + outfile << el.PNum(2) << ", "; + outfile << el.PNum(4) << ", "; + outfile << el.PNum(3) << ", "; + outfile << el.PNum(5) << ", "; + outfile << el.PNum(9) << ", "; + outfile << el.PNum(7) << ", " << "\n"; + outfile << el.PNum(6) << ", "; + outfile << el.PNum(8) << ", "; + outfile << el.PNum(10) << "\n"; + } + else + { + cout << "unsupported Element type!!!" << endl; + for (j = 1; j <= el.GetNP(); j++) + { + outfile << el.PNum(j); + if (j != el.GetNP()) outfile << ", "; + } + outfile << "\n"; + } + } + } + indcnt++; + if (elemcnt == ne) {finished = 1; cout << "all elements found by Index!" << endl;} + if (actcnt == 0) {finished = 1;} + } + + if (mesh.GetIdentifications().GetMaxNr()) + { + // periodic identification, implementation for + // Helmut J. Boehm, TU Vienna + + char cfilename[255]; + strcpy (cfilename, filename.c_str()); + + char mpcfilename[255]; + strcpy (mpcfilename, cfilename); + size_t len = strlen (cfilename); + if (len >= 4 && (strcmp (mpcfilename+len-4, ".inp") == 0)) + strcpy (mpcfilename+len-4, ".mpc"); + else + strcat (mpcfilename, ".mpc"); + + ofstream mpc (mpcfilename); + + int masternode(0); + + ARRAY<INDEX_2> pairs; + BitArray master(np), help(np); + master.Set(); + for (i = 1; i <= 3; i++) + { + mesh.GetIdentifications().GetPairs (i, pairs); + help.Clear(); + for (j = 1; j <= pairs.Size(); j++) + { + help.Set (pairs.Get(j).I1()); + } + master.And (help); + } + for (i = 1; i <= np; i++) + if (master.Test(i)) + masternode = i; + + cout << "masternode = " << masternode << " = " + << mesh.Point(masternode) << endl; + ARRAY<int> slaves(3); + for (i = 1; i <= 3; i++) + { + mesh.GetIdentifications().GetPairs (i, pairs); + for (j = 1; j <= pairs.Size(); j++) + { + if (pairs.Get(j).I1() == masternode) + slaves.Elem(i) = pairs.Get(j).I2(); + } + cout << "slave(" << i << ") = " << slaves.Get(i) + << " = " << mesh.Point(slaves.Get(i)) << endl; + } + + + outfile << "**\n" + << "*NSET,NSET=CTENODS\n" + << slaves.Get(1) << ", " + << slaves.Get(2) << ", " + << slaves.Get(3) << endl; + + + outfile << "**\n" + << "**POINT_fixed\n" + << "**\n" + << "*BOUNDARY, OP=NEW\n"; + for (j = 1; j <= 3; j++) + outfile << masternode << ", " << j << ",, 0.\n"; + + outfile << "**\n" + << "*BOUNDARY, OP=NEW\n"; + for (j = 1; j <= 3; j++) + { + Vec3d v(mesh.Point(masternode), mesh.Point(slaves.Get(j))); + double vlen = v.Length(); + int dir = 0; + if (fabs (v.X()) > 0.9 * vlen) dir = 2; + if (fabs (v.Y()) > 0.9 * vlen) dir = 3; + if (fabs (v.Z()) > 0.9 * vlen) dir = 1; + if (!dir) + cout << "ERROR: Problem with rigid body constraints" << endl; + outfile << slaves.Get(j) << ", " << dir << ",, 0.\n"; + } + + outfile << "**\n" + << "*EQUATION, INPUT=" << mpcfilename << endl; + + + BitArray eliminated(np); + eliminated.Clear(); + for (i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) + { + mesh.GetIdentifications().GetPairs (i, pairs); + if (!pairs.Size()) + continue; + + for (j = 1; j <= pairs.Size(); j++) + if (pairs.Get(j).I1() != masternode && + !eliminated.Test(pairs.Get(j).I2())) + { + eliminated.Set (pairs.Get(j).I2()); + for (k = 1; k <= 3; k++) + { + mpc << "4" << "\n"; + mpc << pairs.Get(j).I2() << "," << k << ", -1.0, "; + mpc << pairs.Get(j).I1() << "," << k << ", 1.0, "; + mpc << slaves.Get(i) << "," << k << ", 1.0, "; + mpc << masternode << "," << k << ", -1.0 \n"; + } + } + } + } + + + cout << "done" << endl; +} + +} diff --git a/contrib/Netgen/libsrc/interface/writediffpack.cpp b/contrib/Netgen/libsrc/interface/writediffpack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..649702521ff5568baf2e2531c7132cc8da4e707c --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writediffpack.cpp @@ -0,0 +1,296 @@ +// +// Write diffpack file +// +// by +// Bartosz Sawicki <sawickib@ee.pw.edu.pl> +// extended by +// Jacques Lechelle <jacques.lechelle@wanadoo.fr> +// +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + +namespace netgen +{ +#include "writeuser.hpp" + + +void WriteDiffPackFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + // double scale = globflags.GetNumFlag ("scale", 1); + double scale = 1; + + ofstream outfile(filename.c_str()); + + if (mesh.GetDimension() == 3) + + { + // Output compatible to Diffpack grid format + // Bartosz Sawicki <sawickib@ee.pw.edu.pl> + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + ARRAY <int> BIname; + ARRAY <int> BCsinpoint; + int i, j, k, l; + + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + const Element & eldummy = mesh.VolumeElement((int)1); + outfile << "\n\n" + "Finite element mesh (GridFE):\n\n" + " Number of space dim. = 3\n" + " Number of elements = " << ne << "\n" + " Number of nodes = " << np << "\n\n" + " All elements are of the same type : dpTRUE\n" + " Max number of nodes in an element: "<< eldummy.GetNP() << "\n" + " Only one subdomain : dpFALSE\n" + " Lattice data ? 0\n\n\n\n"; + + for (i = 1; i <= nse; i++) + { + int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty(); + int nbi=BIname.Size(); + int found=0; + for (j = 1; j <= nbi; j++) + if(BI == BIname.Get(j)) found = 1; + if( ! found ) BIname.Append(BI); + } + + outfile << " " << BIname.Size() << " Boundary indicators: "; + for (i =1 ; i <= BIname.Size(); i++) + outfile << BIname.Get(i) << " "; + outfile << "\n\n\n"; + + outfile << " Nodal coordinates and nodal boundary indicators,\n" + " the columns contain:\n" + " - node number\n" + " - coordinates\n" + " - no of boundary indicators that are set (ON)\n" + " - the boundary indicators that are set (ON) if any.\n" + "#\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + outfile.width(4); + outfile << i << " ("; + outfile.width(10); + outfile << p.X()/scale << ", "; + outfile.width(9); + outfile << p.Y()/scale << ", "; + outfile.width(9); + outfile << p.Z()/scale << ") "; + + if(mesh[PointIndex(i)].Type() != INNERPOINT) + { + BCsinpoint.DeleteAll(); + for (j = 1; j <= nse; j++) + { + for (k = 1; k <= mesh.SurfaceElement(j).GetNP(); k++) + { + if(mesh.SurfaceElement(j).PNum(k)==i) + { + int BC=mesh.GetFaceDescriptor(mesh.SurfaceElement(j).GetIndex()).BCProperty(); + int nbcsp=BCsinpoint.Size(); + int found = 0; + for (l = 1; l <= nbcsp; l++) + if(BC == BCsinpoint.Get(l)) found = 1; + if( ! found ) BCsinpoint.Append(BC); + } + } + } + int nbcsp = BCsinpoint.Size(); + outfile << "[" << nbcsp << "] "; + for (j = 1; j <= nbcsp; j++) + outfile << BCsinpoint.Get(j) << " "; + outfile << "\n"; + } + else outfile << "[0]\n"; + + } + + outfile << "\n" + " Element types and connectivity\n" + " the columns contain:\n" + " - element number\n" + " - element type\n" + " - subdomain number\n" + " - the global node numbers of the nodes in the element.\n" + "#\n"; + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + outfile.width(5); + if(el.GetNP()==4) + outfile << i << " ElmT4n3D "; + else + outfile << i << " ElmT10n3D "; + outfile.width(4); + outfile << el.GetIndex() << " "; + if(el.GetNP()==10) + { + outfile.width(8); + outfile << el.PNum(1); + outfile.width(8); + outfile << el.PNum(3); + outfile.width(8); + outfile << el.PNum(2); + outfile.width(8); + outfile << el.PNum(4); + outfile.width(8); + outfile << el.PNum(6); + outfile.width(8); + outfile << el.PNum(8); + outfile.width(8); + outfile << el.PNum(5); + outfile.width(8); + outfile << el.PNum(7); + outfile.width(8); + outfile << el.PNum(10); + outfile.width(8); + outfile << el.PNum(9); + } + else + { + outfile.width(8); + outfile << el.PNum(1); + outfile.width(8); + outfile << el.PNum(3); + outfile.width(8); + outfile << el.PNum(2); + outfile.width(8); + outfile << el.PNum(4); + } + outfile << "\n"; + } + } /* Diffpack */ + + else + + { + // Output compatible to Diffpack grid format 2D + + int np = mesh.GetNP(); + //int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + ARRAY <int> BIname; + ARRAY <int> BCsinpoint; + int i, j, k, l; + + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + outfile << "\n\n" + "Finite element mesh (GridFE):\n\n" + " Number of space dim. = 2\n" + " Number of elements = " << nse << "\n" + " Number of nodes = " << np << "\n\n" + " All elements are of the same type : dpTRUE\n" + " Max number of nodes in an element: 3\n" + " Only one subdomain : dpFALSE\n" + " Lattice data ? 0\n\n\n\n"; + + for (i = 1; i <= nse; i++) + { + int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty(); + int nbi=BIname.Size(); + int found=0; + for (j = 1; j <= nbi; j++) + if(BI == BIname.Get(j)) found = 1; + if( ! found ) BIname.Append(BI); + } + + outfile << " " << BIname.Size() << " Boundary indicators: "; + for (i =1 ; i <= BIname.Size(); i++) + outfile << BIname.Get(i) << " "; + outfile << "\n\n\n"; + + outfile << " Nodal coordinates and nodal boundary indicators,\n" + " the columns contain:\n" + " - node number\n" + " - coordinates\n" + " - no of boundary indicators that are set (ON)\n" + " - the boundary indicators that are set (ON) if any.\n" + "#\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + outfile.width(4); + outfile << i << " ("; + outfile.width(10); + outfile << p.X()/scale << ", "; + outfile.width(9); + outfile << p.Y()/scale << ", "; + + if(mesh[PointIndex(i)].Type() != INNERPOINT) + { + BCsinpoint.DeleteAll(); + for (j = 1; j <= nse; j++) + { + for (k = 1; k <= 2; k++) + { + if(mesh.SurfaceElement(j).PNum(k)==i) + { + int BC=mesh.GetFaceDescriptor(mesh.SurfaceElement(j).GetIndex()).BCProperty(); + int nbcsp=BCsinpoint.Size(); + int found = 0; + for (l = 1; l <= nbcsp; l++) + if(BC == BCsinpoint.Get(l)) found = 1; + if( ! found ) BCsinpoint.Append(BC); + } + } + } + int nbcsp = BCsinpoint.Size(); + outfile << "[" << nbcsp << "] "; + for (j = 1; j <= nbcsp; j++) + outfile << BCsinpoint.Get(j) << " "; + outfile << "\n"; + } + else outfile << "[0]\n"; + + } + + outfile << "\n" + " Element types and connectivity\n" + " the columns contain:\n" + " - element number\n" + " - element type\n" + " - subdomain number\n" + " - the global node numbers of the nodes in the element.\n" + "#\n"; + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + outfile.width(5); + outfile << i << " ElmT3n2D "; + outfile.width(4); + outfile << el.GetIndex() << " "; + outfile.width(8); + outfile << el.PNum(1); + outfile.width(8); + outfile << el.PNum(3); + outfile.width(8); + outfile << el.PNum(2); + outfile << "\n"; + } + } +} +} diff --git a/contrib/Netgen/libsrc/interface/writedolfin.cpp b/contrib/Netgen/libsrc/interface/writedolfin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0fe36e94af8b45a9a49058967c262283968cf92b --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writedolfin.cpp @@ -0,0 +1,69 @@ +// +// Write dolfin file +// +// by +// Kent-Andre Mardal <kent-and@simula.no> + + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +#include "writeuser.hpp" + + + + void WriteDolfinFormat (const Mesh & mesh, const string & filename) + { + cout << "start writing dolfin export" << endl; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int nsd = mesh.GetDimension(); + int invertsurf = mparam.inverttrigs; + int i, j; + + ofstream outfile (filename.c_str()); + + char str[100]; + outfile.precision(8); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + if ( nsd == 3) { + + outfile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" <<endl; + outfile << ""<<endl; + + outfile << "<dolfin xmlns:dolfin=\"http://www.phi.chalmers.se/dolfin/\">"<<endl; + outfile << " <mesh celltype=\"tetrahedron\" dim=\"3\">" <<endl; + outfile << " <vertices size=\""<<np<<"\">"<<endl; + for (i = 1; i <= np; i++) { + const Point3d & p = mesh.Point(i); + outfile << " <vertex index=\""<<i-1<<"\" x=\""<<p.X()<<"\" y=\""<<p.Y()<<"\" z=\""<<p.Z()<<"\"/>"<<endl; + } + outfile << " </vertices>"<<endl; + + + + outfile << " <cells size=\""<<ne<<"\">"<<endl; + for (i = 1; i <= ne; i++) { + const Element & el = mesh.VolumeElement(i); + + outfile << " <tetrahedron index=\""<<i-1<<"\" v0=\""<<el.PNum(1)-1<<"\" v1=\""<<el.PNum(2)-1<<"\" v2=\""<<el.PNum(3)-1<<"\" v3=\""<<el.PNum(4)-1<<"\"/>"<<endl; + } + outfile << " </cells>"<<endl; + } + outfile << " </mesh>"<<endl; + outfile << "</dolfin>"<<endl; + + cout << "done writing dolfin export" << endl; + } +} diff --git a/contrib/Netgen/libsrc/interface/writeelmer.cpp b/contrib/Netgen/libsrc/interface/writeelmer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f902cdeb23c1ee06e0f74ed92c4344d381eb1822 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeelmer.cpp @@ -0,0 +1,131 @@ + +// +// Write Elmer file +// +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + + +namespace netgen +{ +#include "writeuser.hpp" + + + +void WriteElmerFormat (const Mesh &mesh, + const string &filename) +{ + cout << "write elmer mesh files" << endl; + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int i, j; + char str[200]; + + int inverttets = mparam.inverttets; + int invertsurf = mparam.inverttrigs; + +#ifdef WIN32 + char a[256]; + sprintf( a, "mkdir %s", filename.c_str() ); + system( a ); +#else + int rc = mkdir(filename.c_str(), S_IRWXU|S_IRWXG); +#endif + + sprintf( str, "%s/mesh.header", filename.c_str() ); + ofstream outfile_h(str); + sprintf( str, "%s/mesh.nodes", filename.c_str() ); + ofstream outfile_n(str); + sprintf( str, "%s/mesh.elements", filename.c_str() ); + ofstream outfile_e(str); + sprintf( str, "%s/mesh.boundary", filename.c_str() ); + ofstream outfile_b(str); + + // fill hashtable + + INDEX_3_HASHTABLE<int> face2volelement(ne); + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + INDEX_3 i3; + int k, l; + for (j = 1; j <= 4; j++) // loop over faces of tet + { + l = 0; + for (k = 1; k <= 4; k++) + if (k != j) + { + l++; + i3.I(l) = el.PNum(k); + } + i3.Sort(); + face2volelement.Set (i3, i); + } + } + +// outfile.precision(6); +// outfile.setf (ios::fixed, ios::floatfield); +// outfile.setf (ios::showpoint); + + outfile_h << np << " " << ne << " " << nse << "\n"; + outfile_h << "2" << "\n"; + outfile_h << "303 " << nse << "\n"; + outfile_h << "504 " << ne << "\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + outfile_n << i << " -1 "; + outfile_n << p.X() << " "; + outfile_n << p.Y() << " "; + outfile_n << p.Z() << "\n"; + } + + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (inverttets) el.Invert(); + sprintf( str, "5%02d", (int)el.GetNP() ); + outfile_e << i << " " << el.GetIndex() << " " << str << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile_e << " "; + outfile_e << el.PNum(j); + } + outfile_e << "\n"; + } + + for (i = 1; i <= nse; i++) + { + Element2d el = mesh.SurfaceElement(i); + if (invertsurf) el.Invert(); + sprintf( str, "3%02d", (int)el.GetNP() ); + { + INDEX_3 i3; + for (j = 1; j <= 3; j++) i3.I(j) = el.PNum(j); + i3.Sort(); + + int elind = face2volelement.Get(i3); + outfile_b << i << " " << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << + " " << elind << " 0 " << str << " "; + } + for (j = 1; j <= el.GetNP(); j++) + { + outfile_b << " "; + outfile_b << el.PNum(j); + } + outfile_b << "\n"; + } +} + +} diff --git a/contrib/Netgen/libsrc/interface/writefeap.cpp b/contrib/Netgen/libsrc/interface/writefeap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85681aa0cf63d1ad1186864a8aefaf4f01aa5bb8 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writefeap.cpp @@ -0,0 +1,220 @@ +// +// Write FEAP file +// FEAP by Bob Taylor, Berkely +// +// contact Peter Wriggers or Albrecht Rieger, Hannover +// rieger@ibnm.uni-hannover.de +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +#include "writeuser.hpp" + + +void WriteFEAPFormat (const Mesh & mesh, + const string & filename) + +{ + // Feap format by A. Rieger + // rieger@ibnm.uni-hannover.de + + int inverttets = mparam.inverttets; + //int invertsurf = mparam.inverttrigs; + + int i, j; + + double scale = 1; // globflags.GetNumFlag ("scale", 1); + + ofstream outfile(filename.c_str()); + + outfile << "feap" << "\n"; + outfile << mesh.GetNP(); + outfile << ","; + outfile << mesh.GetNE(); + outfile << ","; + outfile << "1,3,3,4" << "\n" << "\n"; + outfile << "!numnp,numel,nummat,ndm,ndf,nen"; + outfile << "\n"; + + outfile << "\n" << "\n"; + outfile << "!node,, X Y Z" << "\n"; + outfile << "COOR" << "\n"; + outfile.precision(4); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + for (i = 1; i <= mesh.GetNP(); i++) + { + outfile.width(5); + outfile << i; + outfile << ",,"; + outfile.width(10); + outfile << mesh.Point(i)(0)/scale << " "; + outfile.width(10); + outfile << mesh.Point(i)(1)/scale << " "; + outfile.width(10); + outfile << mesh.Point(i)(2)/scale << "\n"; + } + + outfile << "\n" << "\n"; + outfile << "!elm,,mat, n1 n2 n3 n4" << "\n"; + outfile << "ELEM" << "\n"; + + for (i = 1; i <= mesh.GetNE(); i++) + { + Element el = mesh.VolumeElement(i); + if (inverttets) + el.Invert(); + + + outfile.width(5); + outfile << i; + outfile << ",,"; + outfile << el.GetIndex(); + outfile << ","; + + + for (j = 1; j <= el.NP(); j++) + { + outfile.width(8); + outfile << el.PNum(j); + } + outfile << "\n"; + } + + outfile << "\n" << "\n"; + + + /* + + //outfile << "SLOA" << "\n"; + //outfile << "2,3,3" << "\n"; + //outfile << GetNSE() << "\n"; + outfile << "selm" << "\n" << GetNSE() << "\n"; + for (i = 1; i <= GetNSE(); i++) + { + if (SurfaceElement(i).GetIndex()) + { + outfile.width(8); + outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).surfnr; + //outfile.width(8); + //outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).domin; + //outfile.width(8); + //outfile << facedecoding.Get(SurfaceElement(i).GetIndex ()).domout; + } + else + outfile << " 0 0 0"; + + + Element2d sel = SurfaceElement(i); + if (invertsurf) + sel.Invert(); + //outfile.width(8); + //outfile << sel.GetNP(); + //if (facedecoding.Get(SurfaceElement(i).GetIndex ()).surfnr == 4) + //{ + for (j = 1; j <= sel.GetNP(); j++) + { + outfile.width(8); + outfile << sel.PNum(j); + } + //outfile.width(8); + //outfile << "0.0"; + //outfile.width(8); + //outfile << "0.0"; + //outfile.width(8); + //outfile << "1.0" << "\n"; + //} + outfile << "\n"; + //outfile << endl; + } + */ + + + + // BEGIN CONTACT OUTPUT + /* + int masterindex, slaveindex; + cout << "Master Surface index = "; + cin >> masterindex; + cout << "Slave Surface index = "; + cin >> slaveindex; + + + // CONTACT SURFACE 1 + outfile << "\n"; + outfile << "\n"; + outfile << "surface,1" << "\n";; + outfile.width(6); + outfile << "tria" << "\n";; + outfile.width(13); + outfile << "facet" << "\n";; + zz = 0; + for (i = 1; i <= mesh.GetNSE(); i++) + { + Element2d sel = mesh.SurfaceElement(i); + if (invertsurf) + sel.Invert(); + if (mesh.GetFaceDescriptor(sel.GetIndex ()).BCProperty() == masterindex) + { + zz++; + outfile.width(14); + outfile << zz; + outfile << ",,"; + for (j = 1; j <= sel.GetNP(); j++) + { + outfile << sel.PNum(j); + outfile << ","; + } + outfile << "\n"; + } + } + + + // CONTACT SURFACE 2 + outfile << "\n"; + outfile << "\n"; + outfile << "surface,2" << "\n";; + outfile.width(6); + outfile << "tria" << "\n";; + outfile.width(13); + outfile << "facet" << "\n";; + zz = 0; + for (i = 1; i <= mesh.GetNSE(); i++) + { + + Element2d sel = mesh.SurfaceElement(i); + if (invertsurf) + sel.Invert(); + if (mesh.GetFaceDescriptor(sel.GetIndex ()).BCProperty() == slaveindex) + { + zz++; + outfile.width(14); + outfile << zz; + outfile << ",,"; + for (j = 1; j <= sel.GetNP(); j++) + { + outfile << sel.PNum(j); + outfile << ","; + } + outfile << "\n"; + } + } + + outfile << "\n"; + outfile << "\n"; + */ + + // END CONTACT OUTPUT + + cout << "done" << endl; +} +} diff --git a/contrib/Netgen/libsrc/interface/writefluent.cpp b/contrib/Netgen/libsrc/interface/writefluent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c08d59857596c0f38d2b2217db91b15b69600f2 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writefluent.cpp @@ -0,0 +1,193 @@ +// +// Write Fluent file +// Johannes Gerstmayr, University Linz +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +#include "writeuser.hpp" + + + +void WriteFluentFormat (const Mesh & mesh, + const string & filename) + +{ + cout << "start writing fluent export" << endl; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int i, j; + + ofstream outfile (filename.c_str()); + char str[100]; + + outfile.precision(6); + //outfile.setf (ios::fixed, ios::floatfield); + //outfile.setf (ios::showpoint); + + outfile << "(0 \"Exported file from NETGEN \")" << endl; + outfile << "(0 \"Dimension:\")" << endl; + outfile << "(2 3)" << endl << endl; + + outfile << "(0 \"Nodes:\")" << endl; + + //number of nodes: + sprintf(str,"(10 (0 1 %x 1))",np); //hexadecimal!!! + outfile << str << endl; + + //nodes of zone 1: + sprintf(str,"(10 (7 1 %x 1)(",np); //hexadecimal!!! + outfile << str << endl; + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + //outfile.width(10); + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z() << "\n"; + } + outfile << "))" << endl << endl; + + //write faces with elements + + outfile << "(0 \"Faces:\")" << endl; + + Element2d face, face2; + int i2, j2; + ARRAY<INDEX_3> surfaceelp; + ARRAY<int> surfaceeli; + ARRAY<int> locels; + + //no cells=no tets + //no faces=2*tets + + int noverbface = 2*ne-nse/2; + + sprintf(str,"(13 (0 1 %x 0))",(noverbface+nse)); //hexadecimal!!! + outfile << str << endl; + + sprintf(str,"(13 (4 1 %x 2 3)(",noverbface); //hexadecimal!!! + outfile << str << endl; + + const_cast<Mesh&> (mesh).BuildElementSearchTree(); + + for (i = 1; i <= ne; i++) + { + if (ne > 2000) + { + if (i%2000 == 0) + { + cout << (double)i/(double)ne*100. << "%" << endl; + } + } + + Element el = mesh.VolumeElement(i); + //if (inverttets) + // el.Invert(); + + //outfile << el.GetIndex() << " "; + if (el.GetNP() != 4) {cout << "only tet-meshes supported in write fluent!" << endl;} + + //faces: + + Box3d box; + el.GetBox(mesh.Points(), box); + box.IncreaseRel(1e-6); + + mesh.GetIntersectingVolEls(box.PMin(),box.PMax(),locels); + int nel = locels.Size(); + int locind; + + //cout << "nel=" << nel << endl; + + for (j = 1; j <= el.GetNFaces(); j++) + { + el.GetFace(j, face); + face.Invert(); + int eli2 = 0; + int stopsig = 0; + + for (i2 = 1; i2 <= nel; i2++) + { + locind = locels.Get(i2); + //cout << " locind=" << locind << endl; + + Element el2 = mesh.VolumeElement(locind); + //if (inverttets) + // el2.Invert(); + + for (j2 = 1; j2 <= el2.GetNFaces(); j2++) + { + el2.GetFace(j2, face2); + + if (face2.HasFace(face)) {eli2 = locind; stopsig = 1; break;} + } + if (stopsig) break; + } + + if (eli2==i) cout << "error in WRITE_FLUENT!!!" << endl; + + if (eli2 > i) //dont write faces two times! + { + //i: left cell, eli: right cell + outfile << hex << face.PNum(2) << " " + << hex << face.PNum(1) << " " + << hex << face.PNum(3) << " " + << hex << i << " " + << hex << eli2 << "\n"; + } + if (eli2 == 0) + { + surfaceelp.Append(INDEX_3(face.PNum(2),face.PNum(1),face.PNum(3))); + surfaceeli.Append(i); + } + } + } + outfile << "))" << endl; + + sprintf(str,"(13 (2 %x %x 3 3)(",(noverbface+1),noverbface+nse); //hexadecimal!!! + outfile << str << endl; + + for (i = 1; i <= surfaceelp.Size(); i++) + { + outfile << hex << surfaceelp.Get(i).I1() << " " + << hex << surfaceelp.Get(i).I2() << " " + << hex << surfaceelp.Get(i).I3() << " " + << hex << surfaceeli.Get(i) << " " << 0 << "\n"; + } + + outfile << "))" << endl << endl; + + outfile << "(0 \"Cells:\")" << endl; + + sprintf(str,"(12 (0 1 %x 0))",ne); //hexadecimal!!! + outfile << str << endl; + + sprintf(str,"(12 (1 1 %x 1 2))",ne); //hexadecimal!!! + outfile << str << endl << endl; + + + + + outfile << "(0 \"Zones:\")\n" + << "(45 (1 fluid fluid)())\n" + // << "(45 (2 velocity-inlet velocity_inlet.1)())\n" + // << "(45 (3 pressure-outlet pressure_outlet.2)())\n" + << "(45 (2 wall wall)())\n" + << "(45 (4 interior default-interior)())\n" << endl; + + cout << "done" << endl; +} + +} diff --git a/contrib/Netgen/libsrc/interface/writegmsh.cpp b/contrib/Netgen/libsrc/interface/writegmsh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93def677835846f85917ccf3243f841e8d9480e6 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writegmsh.cpp @@ -0,0 +1,200 @@ +/************************************* + * Write Gmsh file + * First issue the 04/26/2004 by Paul CARRICO (paul.carrico@free.fr) + * At the moment, the GMSH format is available for + * linear tetrahedron elements i.e. in 3D + * (based on Neutral Format) + * + * Second issue the 05/05/2004 by Paul CARRICO + * Thanks to Joachim Schoeberl for the correction of a minor bug + * the 2 initial Gmsh Format (i.e. volume format and surface format) are group together) + * in only one file + **************************************/ + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + + +/* + * GMSH mesh format + * points, elements, surface elements and physical entities + */ + +void WriteGmshFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + ofstream outfile (filename.c_str()); + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + int np = mesh.GetNP(); /// number of point + int ne = mesh.GetNE(); /// number of element + int nse = mesh.GetNSE(); /// number of surface element (BC) + int i, j, k, l; + + + /* + * 3D section : Linear volume elements (only tetrahedra) + */ + + if (ne > 0 && mesh.VolumeElement(1).GetNP() == 4) + { + cout << "Write GMSH Format \n"; + cout << "The GMSH format is available for linear tetrahedron elements only in 3D\n" << endl; + + int inverttets = mparam.inverttets; + int invertsurf = mparam.inverttrigs; + + + /// Write nodes + outfile << "$NOD\n"; + outfile << np << "\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + outfile << i << " "; /// node number + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z() << "\n"; + } + outfile << "$ENDNOD\n"; + + /// write elements + outfile << "$ELM\n"; + outfile << ne + nse << "\n"; //// number of elements + number of surfaces BC + + for (i = 1; i <= nse; i++) + { + Element2d el = mesh.SurfaceElement(i); + if (invertsurf) el.Invert(); + outfile << i; + outfile << " "; + outfile << "2"; + outfile << " "; + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + /// that means that physical entity = elementary entity (arbitrary approach) + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + outfile << "3"; + outfile << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile << el.PNum(j); + } + outfile << "\n"; + } + + + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (inverttets) el.Invert(); + outfile << nse + i; /// element number + outfile << " "; + outfile << "4"; /// element type i.e. Tetraedron == 4 + outfile << " "; + outfile << 100000 + el.GetIndex(); + /// that means that physical entity = elementary entity (arbitrary approach) + outfile << " "; + outfile << 100000 + el.GetIndex(); /// volume number + outfile << " "; + outfile << "4"; /// number of nodes i.e. 4 for a tetrahedron + + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile << el.PNum(j); + } + outfile << "\n"; + } + + + outfile << "$ENDELM\n"; + } + + /* + * End of 3D section + */ + + + + + + /* + * 2D section : available for triangles and quadrangles + */ + else if (ne == 0) /// means that there's no 3D element + { + cout << "\n Write Gmsh Surface Mesh (triangle and/or quadrangles)" << endl; + + /// Write nodes + outfile << "$NOD\n"; + outfile << np << "\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + outfile << i << " "; /// node number + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z() << "\n"; + } + outfile << "$ENDNOD\n"; + + + /// write triangles & quadrangles + outfile << "$ELM\n"; + outfile << nse << "\n"; + + for (k = 1; k <= nse; k++) + { + const Element2d & el = mesh.SurfaceElement(k); + + + outfile << k; + outfile << " "; + outfile << (el.GetNP()-1); // 2 for a triangle and 3 for a quadrangle + outfile << " "; + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + /// that means that physical entity = elementary entity (arbitrary approach) + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + outfile << (el.GetNP()); // number of node per surfacic element + outfile << " "; + + for (l = 1; l <= el.GetNP(); l++) + { + outfile << " "; + outfile << el.PNum(l); + } + outfile << "\n"; + + } + outfile << "$ENDELM$ \n"; + } + + /* + * End of 2D section + */ + + else + { + cout << " Invalide element type for Gmsh volume Format !\n"; + } + + +} +} + + diff --git a/contrib/Netgen/libsrc/interface/writejcm.cpp b/contrib/Netgen/libsrc/interface/writejcm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00ef4f9f49a3dc36d74b38ee51250defb4804672 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writejcm.cpp @@ -0,0 +1,430 @@ +// +// Write JCMwave file +// 07.07.2005, Sven Burger, ZIB Berlin +// + + +#include <mystdlib.h> +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> +#include <sys/stat.h> + +namespace netgen +{ +#include "writeuser.hpp" + +void WriteJCMFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + if (mesh.GetDimension() != 3) + { + cout <<"\n Error: Dimension 3 only supported by this output format!"<<endl; + return; + } + + int bc_at_infinity = 0; + int i, j, jj, ct(0), counter; + double dx1, dx2, dx3, dy1, dy2, dy3, dz1, dz2, dz3, vol; + + // number of points + int np = mesh.GetNP(); + + // Identic points + ARRAY<int,1> identmap1, identmap2, identmap3; + mesh.GetIdentifications().GetMap(1, identmap1); + mesh.GetIdentifications().GetMap(2, identmap2); + mesh.GetIdentifications().GetMap(3, identmap3); + + // number of volume elements + int ne = mesh.GetNE(); + int ntets = 0; + int nprisms = 0; + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (el.GetNP() == 4) + { + ntets++; + // Check that no two points on a tetrahedron are identified with each other + for (j = 1; j <= 4; j++) + for (jj = 1; jj <=4; jj++) + { + if (identmap1.Elem(el.PNum(j)) == el.PNum(jj)) + { + cout << "\n Error: two points on a tetrahedron identified (1) with each other" + << "\n REFINE MESH !" << endl; + return; + } + if (identmap2.Elem(el.PNum(j)) == el.PNum(jj)) + { + cout << "\n Error: two points on a tetrahedron identified (2) with each other" + << "\n REFINE MESH !" << endl; + return; + } + if (identmap3.Elem(el.PNum(j)) == el.PNum(jj)) + { + cout << "\n Error: two points on a tetrahedron identified (3) with each other" + << "\n REFINE MESH !" << endl; + return; + } + } + + } + else if (el.GetNP() == 6) + nprisms++; + } + if ( ne != (ntets+nprisms)) + { + cout<< "\n Error in determining number of volume elements!\n" + << "\n Prisms and tetrahedra only implemented in the JCMwave format!\n"<<endl; + return; + } + + if (nprisms > 0) + cout << " Please note: Boundaries at infinity have to carry the bc-attribute '-bc=" + << bc_at_infinity <<"'."<<endl; + + // number of surface elements + int nse = mesh.GetNSE(); + // number of boundary triangles + int nbtri = 0; + // number of boundary quadrilaterals + int nbquad = 0; + // array with 1 if point on any tetra, 0 else + // this is needed in order to arrange the prism points in the right order + ARRAY<int,1> pointsOnTetras; + pointsOnTetras.SetSize (mesh.GetNP()); + pointsOnTetras = 0; + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (el.GetNP() == 4) + { + for (j = 1; j <= 4; j++) + pointsOnTetras.Set(el.PNum(j).GetInt(),1); + } + } + + // number of boundary triangles and boundary quadrilaterals + for (i = 1; i <= nse; i++) + { + Element2d el = mesh.SurfaceElement(i); + if (el.GetNP() == 3 && + ( mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 || + mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0 ) ) + nbtri++; + else if (el.GetNP() == 4 && + ( mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 || + mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0 ) ) + nbquad++; + } + + ofstream outfile (filename.c_str()); + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + outfile << "/* <BLOBHead>\n"; + outfile << "__BLOBTYPE__=Grid\n"; + outfile << "__OWNER__=JCMwave\n"; + outfile << "<I>SpaceDim=3\n"; + outfile << "<I>ManifoldDim=3\n"; + outfile << "<I>NRefinementSteps=0\n"; + outfile << "<I>NPoints="<<np<<"\n"; + outfile << "<I>NTetrahedra="<<ntets<<"\n"; + outfile << "<I>NPrisms="<<nprisms<<"\n"; + outfile << "<I>NBoundaryTriangles="<<nbtri<<"\n"; + outfile << "<I>NBoundaryQuadrilaterals="<<nbquad<<"\n"; + outfile << "*/\n"; + outfile << "\n"; + outfile << "# output from Netgen\n\n"; + int nDomains=mesh.GetNDomains(); + for (i=1; i<=nDomains; i++) + { + if (mesh.GetMaterial(i)) + outfile << "#" << mesh.GetMaterial(i) + << ": Material ID = " + << i << "\n"; + } + + outfile << "# Points\n"; + cout << " Please note: The unit of length in the .geo file is assumed to be 'microns'."<<endl; + for (i = 1; i <= np; i++) + { + const Point<3> & p = mesh.Point(i); + outfile << i << "\n"; + outfile << p(0) << "e-6\n"; + outfile << p(1) << "e-6\n"; + outfile << p(2) << "e-6\n\n"; + } + + outfile << "\n"; + outfile << "# Tetrahedra\n"; + counter = 0; + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (el.GetNP() == 4) + { + counter++; + dx1 = mesh.Point(el.PNum(2))(0) - mesh.Point(el.PNum(1))(0); + dx2 = mesh.Point(el.PNum(3))(0) - mesh.Point(el.PNum(1))(0); + dx3 = mesh.Point(el.PNum(4))(0) - mesh.Point(el.PNum(1))(0); + dy1 = mesh.Point(el.PNum(2))(1) - mesh.Point(el.PNum(1))(1); + dy2 = mesh.Point(el.PNum(3))(1) - mesh.Point(el.PNum(1))(1); + dy3 = mesh.Point(el.PNum(4))(1) - mesh.Point(el.PNum(1))(1); + dz1 = mesh.Point(el.PNum(2))(2) - mesh.Point(el.PNum(1))(2); + dz2 = mesh.Point(el.PNum(3))(2) - mesh.Point(el.PNum(1))(2); + dz3 = mesh.Point(el.PNum(4))(2) - mesh.Point(el.PNum(1))(2); + vol = (dy1*dz2-dz1*dy2)*dx3 + (dz1*dx2-dx1*dz2)*dy3 + (dx1*dy2-dy1*dx2)*dz3; + + if ( vol > 0 ) + for (j = 1; j <= 4; j++) + outfile << el.PNum(j)<<"\n"; + else + { + for (j = 2; j >= 1; j--) + outfile << el.PNum(j)<<"\n"; + for (j = 3; j <= 4; j++) + outfile << el.PNum(j)<<"\n"; + } + outfile << el.GetIndex() << "\n\n"; + } + } + if ( counter != ntets) + { + cout<< "\n Error in determining number of tetras!\n"<<endl; + return; + } + + outfile << "\n"; + outfile << "# Prisms\n"; + counter = 0; + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (el.GetNP() == 6) + { + counter++; + dx1 = mesh.Point(el.PNum(2))(0) - mesh.Point(el.PNum(1))(0); + dx2 = mesh.Point(el.PNum(3))(0) - mesh.Point(el.PNum(1))(0); + dx3 = mesh.Point(el.PNum(4))(0) - mesh.Point(el.PNum(1))(0); + dy1 = mesh.Point(el.PNum(2))(1) - mesh.Point(el.PNum(1))(1); + dy2 = mesh.Point(el.PNum(3))(1) - mesh.Point(el.PNum(1))(1); + dy3 = mesh.Point(el.PNum(4))(1) - mesh.Point(el.PNum(1))(1); + dz1 = mesh.Point(el.PNum(2))(2) - mesh.Point(el.PNum(1))(2); + dz2 = mesh.Point(el.PNum(3))(2) - mesh.Point(el.PNum(1))(2); + dz3 = mesh.Point(el.PNum(4))(2) - mesh.Point(el.PNum(1))(2); + vol = (dy1*dz2-dz1*dy2)*dx3 + (dz1*dx2-dx1*dz2)*dy3 + (dx1*dy2-dy1*dx2)*dz3; + + if (pointsOnTetras.Get(el.PNum(1)) && + pointsOnTetras.Get(el.PNum(2)) && + pointsOnTetras.Get(el.PNum(3))) + { + if (vol > 0) + for (j = 1; j <= 6; j++) + outfile << el.PNum(j)<<"\n"; + else + { + for (j = 3; j >= 1; j--) + outfile << el.PNum(j)<<"\n"; + for (j = 6; j >= 4; j--) + outfile << el.PNum(j)<<"\n"; + } + } + else if ( pointsOnTetras.Get(el.PNum(4)) && + pointsOnTetras.Get(el.PNum(5)) && + pointsOnTetras.Get(el.PNum(6)) ) + { + if ( vol < 0 ) + { + for (j = 4; j <= 6; j++) + outfile << el.PNum(j)<<"\n"; + for (j = 1; j <= 3; j++) + outfile << el.PNum(j)<<"\n"; + } + else + { + for (j = 6; j >= 4; j--) + outfile << el.PNum(j)<<"\n"; + for (j = 3; j >= 1; j--) + outfile << el.PNum(j)<<"\n"; + } + } + else + { + cout << "\n Error in determining prism point numbering!\n"<<endl; + return; + } + outfile << el.GetIndex() << "\n\n"; + } + } + if ( counter != nprisms) + { + cout<< "\n Error in determining number of prisms!\n"<<endl; + return; + } + + int npid1 = 0; + int npid2 = 0; + int npid3 = 0; + for (i=1; i<=np; i++) + { + if (identmap1.Elem(i)) + npid1++; + if (identmap2.Elem(i)) + npid2++; + if (identmap3.Elem(i)) + npid3++; + } + + outfile << "\n"; + outfile << "# Boundary triangles\n"; + outfile << "# Number of identified points in 1-direction: " << npid1 << "\n"; + outfile << "# Number of identified points in 2-direction: " << npid2 << "\n"; + outfile << "# Number of identified points in 3-direction: " << npid3 << "\n"; + for (i = 1; i <= nse; i++) + { + Element2d el = mesh.SurfaceElement(i); + if (el.GetNP() == 3 + && (mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 + || mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0)) + { + outfile <<"# T\n"; + for (j = 1; j <= 3; j++) + outfile << el.PNum(j)<<"\n"; + if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty()==bc_at_infinity) + outfile << 1000 << "\n"; + else + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << "\n"; + if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() == bc_at_infinity) + outfile << "-2\n\n"; + else if (identmap1.Elem(el.PNum(1)) + &&identmap1.Elem(el.PNum(2)) + &&identmap1.Elem(el.PNum(3))) + { + outfile << "-1\n"; + for (j = 1; j <= 3; j++) + outfile << identmap1.Elem(el.PNum(j))<<"\n"; + outfile << "\n"; + } + else if (identmap2.Elem(el.PNum(1)) + &&identmap2.Elem(el.PNum(2)) + &&identmap2.Elem(el.PNum(3))) + { + outfile << "-1\n"; + for (j = 1; j <= 3; j++) + outfile << identmap2.Elem(el.PNum(j))<<"\n"; + outfile << "\n"; + } + else if (identmap3.Elem(el.PNum(1)) + &&identmap3.Elem(el.PNum(2)) + &&identmap3.Elem(el.PNum(3))) + { + outfile << "-1\n"; + for (j = 1; j <= 3; j++) + outfile << identmap3.Elem(el.PNum(j))<<"\n"; + outfile << "\n"; + } + else + outfile << "1\n\n"; + + } + } + + outfile << "\n"; + outfile << "# Boundary quadrilaterals\n"; + for (i = 1; i <= nse; i++) + { + Element2d el = mesh.SurfaceElement(i); + + if (el.GetNP() == 4 + && (mesh.GetFaceDescriptor (el.GetIndex()).DomainIn()==0 + || mesh.GetFaceDescriptor (el.GetIndex()).DomainOut()==0)) + { + if (pointsOnTetras.Get(el.PNum(1)) && + pointsOnTetras.Get(el.PNum(2))) + ct = 0; + else if (pointsOnTetras.Get(el.PNum(2)) && + pointsOnTetras.Get(el.PNum(3))) + ct = 1; + else if (pointsOnTetras.Get(el.PNum(3)) && + pointsOnTetras.Get(el.PNum(4))) + ct = 2; + else if (pointsOnTetras.Get(el.PNum(4)) && + pointsOnTetras.Get(el.PNum(1))) + ct = 3; + else + cout << "\nWarning: Quadrilateral with inconsistent points found!"<<endl; + + for (j = 1; j <= 4; j++) + { + jj = j + ct; + if ( jj >= 5 ) + jj = jj - 4; + outfile << el.PNum(jj)<<"\n"; + } + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << "\n"; + if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() == bc_at_infinity) + { + outfile << "-2\n\n"; + cout << "\nWarning: Quadrilateral at infinity found (this should not occur)!"<<endl; + } + else if ( identmap1.Elem(el.PNum(1)) && + identmap1.Elem(el.PNum(2)) && + identmap1.Elem(el.PNum(3)) && + identmap1.Elem(el.PNum(4)) ) + { + outfile << "-1\n"; + for (j = 1; j <= 4; j++) + { + jj = j + ct; + if ( jj >= 5 ) + jj = jj - 4; + outfile << identmap1.Elem(el.PNum(jj))<<"\n"; + } + outfile << "\n"; + } + else if ( identmap2.Elem(el.PNum(1)) && + identmap2.Elem(el.PNum(2)) && + identmap2.Elem(el.PNum(3)) && + identmap2.Elem(el.PNum(4)) ) + { + outfile << "-1\n"; + for (j = 1; j <= 4; j++) + { + jj = j + ct; + if ( jj >= 5 ) + jj = jj - 4; + outfile << identmap2.Elem(el.PNum(jj))<<"\n"; + } + outfile << "\n"; + } + else if ( identmap3.Elem(el.PNum(1)) && + identmap3.Elem(el.PNum(2)) && + identmap3.Elem(el.PNum(3)) && + identmap3.Elem(el.PNum(4)) ) + { + outfile << "-1\n"; + for (j = 1; j <= 4; j++) + { + jj = j + ct; + if ( jj >= 5 ) + jj = jj - 4; + outfile << identmap3.Elem(el.PNum(jj))<<"\n"; + } + outfile << "\n"; + } + else + outfile << "1\n\n"; + } + } + + cout << " JCMwave grid file written." << endl; +} + +} + diff --git a/contrib/Netgen/libsrc/interface/writepermas.cpp b/contrib/Netgen/libsrc/interface/writepermas.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc46e87cd9c9e225d4cb2a961d4e27e570ac9ccb --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writepermas.cpp @@ -0,0 +1,208 @@ +// +// Write Permas file +// for Intes GmbH, Stuttgart +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +#include <string> + +using namespace std; + +namespace netgen +{ +#include "writeuser.hpp" + // Forward declarations (don't know, where to define them, sorry) + int addComponent(string &strComp, string &strSitu, ofstream &out); + + + // This should be the new function to export a PERMAS file + void WritePermasFormat (const Mesh &mesh, const string &filename, + string &strComp, string &strSitu) + { + ofstream outfile (filename.c_str()); + addComponent(strComp, strSitu, outfile); + WritePermasFormat ( mesh, filename); + } + + void WritePermasFormat (const Mesh &mesh, const string &filename) + { + string strComp, strSitu; + ofstream outfile (filename.c_str()); + + outfile.precision(8); + + strSitu = strComp = ""; + if (addComponent(strComp, strSitu, outfile) == 1) { + printf("Error while exporting PERMAS dat!\n"); + return; + } + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int i, j, k; + + if (ne == 0) + { + // pure surface mesh + cout << "\nWrite Permas Surface Mesh" << endl; + + int elnr = 0; + for (j = 1; j <= 2; j++) + { + int nelp(0); + switch (j) + { + case 1: + nelp = 3; + outfile << "$ELEMENT TYPE = TRIA3 ESET = ALLQUAD" << endl; + break; + case 2: + nelp = 4; + outfile << "$ELEMENT TYPE = QUAD4 ESET = ALLQUAD" << endl; + break; + } + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (el.GetNP() != nelp) + continue; + + elnr++; + outfile << elnr << " "; + for (k = 1; k <= nelp; k++) + outfile << " " << el.PNum(k); + outfile << endl; + + } + } + } + else + { + cout << "\nWrite Permas Volume Mesh" << endl; + + int secondorder = (mesh.VolumeElement(1).GetNP() == 10); + + if (!secondorder) + { + outfile << "$ELEMENT TYPE = TET4 ESET = ALLTET" << endl; + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + outfile << i + << " " << el.PNum(1) + << " " << el.PNum(2) + << " " << el.PNum(3) + << " " << el.PNum(4) << endl; + } + } + else + { + outfile << "$ELEMENT TYPE = TET10 ESET = ALLTET" << endl; + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + outfile << i + << " " << el.PNum(1) + << " " << el.PNum(5) + << " " << el.PNum(2) + << " " << el.PNum(8) + << " " << el.PNum(3) + << " " << el.PNum(6) << endl << "& " + << " " << el.PNum(7) + << " " << el.PNum(9) + << " " << el.PNum(10) + << " " << el.PNum(4) << endl; + } + } + + outfile << endl << endl; + + + outfile << "$SURFACE GEO SURFID = 1 SFSET = ALLSUR" << endl; + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (el.GetNP() == 3) + outfile << "STRIA3" + << " " << el.PNum(1) + << " " << el.PNum(2) + << " " << el.PNum(3) << endl; + } + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (el.GetNP() == 4) + outfile << "SQUAD4" + << " " << el.PNum(1) + << " " << el.PNum(2) + << " " << el.PNum(3) + << " " << el.PNum(4) << endl; + } + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (el.GetNP() == 6) + outfile << "STRIA6" + << " " << el.PNum(1) + << " " << el.PNum(4) + << " " << el.PNum(2) + << " " << el.PNum(5) + << " " << el.PNum(3) + << " " << el.PNum(6) << endl; + } + } + + + outfile << endl << endl; + + outfile << "$COOR NSET = ALLNODES" << endl; + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + for (i = 1; i <= np; i++) + { + outfile << i << " "; + outfile << mesh.Point(i)(0) << " "; + outfile << mesh.Point(i)(1) << " "; + outfile << mesh.Point(i)(2) << "\n"; + } + } + ////////////////////////////////////////////////////////////////////////////////// + // \brief Writes PERMAS configuration header into export file + // Returns >0 in case of errors + // \par string &strComp : Reference to component description + // \par string &strComp : Reference to situation description + ////////////////////////////////////////////////////////////////////////////////// + int addComponent(string &strComp, string &strSitu, ofstream &out) + { + if (strComp.size() > 12 || strSitu > 12) + return 1; + + if (0 == strComp.size()) + strComp = "KOMPO1"; + + if (0 == strSitu.size()) + strSitu = "SIT1"; + + // Writing description header of configuration + out << "$ENTER COMPONENT NAME = " << strComp << " DOFTYPE = DISP MATH" << endl << endl; + out << " $SITUATION NAME = " << strSitu << endl; + out << " $END SITUATION" << endl << endl; + out << " $STRUCTURE" << endl; + + return 0; + } + +} diff --git a/contrib/Netgen/libsrc/interface/writetecplot.cpp b/contrib/Netgen/libsrc/interface/writetecplot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f6063747a28c416034ab21a92596108670789fa --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writetecplot.cpp @@ -0,0 +1,127 @@ +// +// +// TECPLOT file by Jawor Georgiew +// +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + + +namespace netgen +{ +#include "writeuser.hpp" + +void WriteTecPlotFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + INDEX i; + int j, k, e, z; + Vec<3> n; + + INDEX np = mesh.GetNP(); + INDEX ne = mesh.GetNE(); + INDEX nse = mesh.GetNSE(); + + ARRAY<int> sn(np); + ofstream outfile(filename.c_str()); + + outfile << "TITLE=\" " << filename << "\"" << endl; + + // fill hashtable + + INDEX_3_HASHTABLE<int> face2volelement(ne); + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + INDEX_3 i3; + int l; + for (j = 1; j <= 4; j++) // loop over faces of tet + { + l = 0; + for (k = 1; k <= 4; k++) + if (k != j) + { + l++; + i3.I(l) = el.PNum(k); + } + i3.Sort(); + face2volelement.Set (i3, i); + } + } + + + for (j = 1; j <= geom.GetNSurf(); j++) /* Flaeche Nummer j */ + { + for (i = 1; i <= np; i++) + sn.Elem(i) = 0; + + e = 0; + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (j == mesh.GetFaceDescriptor (el.GetIndex ()).SurfNr()) + { + for (k = 1; k <= 3; k++) + sn.Elem(el.PNum(k)) = 1; + e++; /* e= Anzahl der neuen Elemente */ + } + } + + z = 0; + for (i = 1; i <= np; i++) + if (sn.Elem(i) == 1) + sn.Elem(i) = ++z; + + outfile << "ZONE T=\" Surface " << j << " \", N=" << z + << ", E=" << e << ", ET=TRIANGLE, F=FEPOINT" << endl; + + for (i = 1; i <= np; i++) + if (sn.Elem(i) != 0) + { + n = geom.GetSurface(j) -> GetNormalVector ( mesh.Point(i) ); + + outfile << mesh.Point(i)(0) << " " /* Knoten Koordinaten */ + << mesh.Point(i)(1) << " " + << mesh.Point(i)(2) << " " + << n(0) << " " + << n(1) << " " + << n(2) << " " + << i << endl; + } + + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (j == mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr()) + /* FlaechenKnoten (3) */ + outfile << sn.Get(el.PNum(1)) << " " + << sn.Get(el.PNum(2)) << " " + << sn.Get(el.PNum(3)) << endl; + + /// Hier soll noch die Ausgabe der Nummer des angrenzenden + /// Vol.elements erfolgen ! + + for (k = 1; k <= nse; k++) + { + const Element2d & sel = mesh.SurfaceElement(k); + INDEX_3 i3; + for (j = 1; j <= 3; j++) + i3.I(j) = sel.PNum(j); + i3.Sort(); + + //int elind = face2volelement.Get(i3); + } + } + } +} + + +} diff --git a/contrib/Netgen/libsrc/interface/writetet.cpp b/contrib/Netgen/libsrc/interface/writetet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..581cc0a3feb5220e3356ca12a932fe5212a3b815 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writetet.cpp @@ -0,0 +1,1096 @@ + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <acisgeom.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +#include "writeuser.hpp" + + + void WriteTETFormat (const Mesh & mesh, + const string & filename)//, const string& problemType ) + { + string problemType = ""; + if(!mesh.PureTetMesh()) + throw NgException("Can only export pure tet mesh in this format"); + + cout << "starting .tet export to file " << filename << endl; + + + ARRAY<int> point_ids,edge_ids,face_ids; + ARRAY<int> elnum(mesh.GetNE()); + elnum = -1; + + + ARRAY<int> userdata_int; + ARRAY<double> userdata_double; + ARRAY<int> ports; + + ARRAY<int> uid_to_group_3D, uid_to_group_2D, uid_to_group_1D, uid_to_group_0D; + + int pos_int = 0; + int pos_double = 0; + + bool haveuserdata = + (mesh.GetUserData("TETmesh:double",userdata_double) && + mesh.GetUserData("TETmesh:int",userdata_int) && + mesh.GetUserData("TETmesh:ports",ports) && + mesh.GetUserData("TETmesh:point_id",point_ids,PointIndex::BASE) && + mesh.GetUserData("TETmesh:uid_to_group_3D",uid_to_group_3D) && + mesh.GetUserData("TETmesh:uid_to_group_2D",uid_to_group_2D) && + mesh.GetUserData("TETmesh:uid_to_group_1D",uid_to_group_1D) && + mesh.GetUserData("TETmesh:uid_to_group_0D",uid_to_group_0D)); + + + int version,subversion; + + if(haveuserdata) + { + version = int(userdata_double[0]); + subversion = int(10*(userdata_double[0] - version)); + pos_double++; + } + else + { + version = 2; + subversion = 0; + } + + + if(version >= 2) + { + // test if ids are disjunct, if not version 2.0 not possible + int maxbc(-1),mindomain(-1); + + for(ElementIndex i=0; i<mesh.GetNE(); i++) + if(i==0 || mesh[i].GetIndex() < mindomain) + mindomain = mesh[i].GetIndex(); + for(int i=1; i<=mesh.GetNFD(); i++) + if(i==1 || mesh.GetFaceDescriptor(i).BCProperty() > maxbc) + maxbc = mesh.GetFaceDescriptor(i).BCProperty(); + + if(maxbc >= mindomain) + { + cout << "WARNING: writing version " << version << "." << subversion << " tetfile not possible, "; + version = 1; subversion = 1; + cout << "using version " << version << "." << subversion << endl; + } + } + + + + int startsize = point_ids.Size(); + point_ids.SetSize(mesh.GetNP()+1); + for(int i=startsize; i<point_ids.Size(); i++) + point_ids[i] = -1; + + + for(int i=0; i<PointIndex::BASE; i++) + point_ids[i] = -1; + + + INDEX_2_CLOSED_HASHTABLE<int> edgenumbers(6*mesh.GetNE()+3*mesh.GetNSE());; + INDEX_3_CLOSED_HASHTABLE<int> facenumbers(4*mesh.GetNE()+mesh.GetNSE()); + + ARRAY<INDEX_2> edge2node; + ARRAY<INDEX_3> face2edge; + ARRAY<INDEX_4> element2face; + + int numelems(0),numfaces(0),numedges(0),numnodes(0); + + for(SegmentIndex si = 0; si < mesh.GetNSeg(); si++) + { + const Segment & seg = mesh[si]; + INDEX_2 i2(seg.p1,seg.p2); + i2.Sort(); + if(edgenumbers.Used(i2)) + continue; + + numedges++; + edgenumbers.Set(i2,numedges); + edge2node.Append(i2); + + edge_ids.Append(seg.edgenr); + + if(point_ids[seg.p1] == -1) + point_ids[seg.p1] = (version >= 2) ? seg.edgenr : 0; + if(point_ids[seg.p2] == -1) + point_ids[seg.p2] = (version >= 2) ? seg.edgenr : 0; + } + + for(SurfaceElementIndex si = 0; si < mesh.GetNSE(); si++) + { + if(mesh[si].IsDeleted()) + continue; + + const Element2d & elem = mesh[si]; + + numfaces++; + INDEX_3 i3(elem[0], elem[1], elem[2]); + + int min = i3[0]; + int minpos = 0; + for(int j=1; j<3; j++) + if(i3[j] < min) + { + min = i3[j]; minpos = j; + } + if(minpos == 1) + { + int aux = i3[0]; i3[0] = i3[1]; i3[1] = i3[2]; i3[2] = aux; + } + else if(minpos == 2) + { + int aux = i3[0]; i3[0] = i3[2]; i3[2] = i3[1]; i3[1] = aux; + } + facenumbers.Set(i3,numfaces); + + int bc = mesh.GetFaceDescriptor(elem.GetIndex()).BCProperty(); + face_ids.Append(bc); + + for(int j=0; j<3; j++) + if(point_ids[elem[j]] == -1) + point_ids[elem[j]] = (version >= 2) ? bc : 0; + + INDEX_2 i2a,i2b; + INDEX_3 f_to_n; + for(int j=0; j<3; j++) + { + i2a = INDEX_2(i3[j],i3[(j+1)%3]); + i2b[0] = i2a[1]; i2b[1] = i2a[0]; + if(edgenumbers.Used(i2a)) + f_to_n[j] = edgenumbers.Get(i2a); + else if(edgenumbers.Used(i2b)) + f_to_n[j] = -edgenumbers.Get(i2b); + else + { + numedges++; + edgenumbers.Set(i2a,numedges); + edge2node.Append(i2a); + f_to_n[j] = numedges; + if(version >= 2) + edge_ids.Append(bc); + else + edge_ids.Append(0); + } + } + face2edge.Append(f_to_n); + } + + for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + { + const Element & el = mesh[ei]; + + if(el.IsDeleted()) + continue; + + numelems++; + elnum[ei] = numelems; + + static int tetfaces[4][3] = + { { 0, 2, 1 }, + { 0, 1, 3 }, + { 1, 2, 3 }, + { 2, 0, 3 } }; + + for(int j=0; j<4; j++) + if(point_ids[el[j]] == -1) + point_ids[el[j]] = (version >= 2) ? el.GetIndex() : 0; + + INDEX_4 e_to_f; + + for(int i = 0; i < 4; i++) + { + INDEX_3 i3a(el[tetfaces[i][0]],el[tetfaces[i][1]],el[tetfaces[i][2]]); + + int min = i3a[0]; + int minpos = 0; + for(int j=1; j<3; j++) + if(i3a[j] < min) + { + min = i3a[j]; minpos = j; + } + if(minpos == 1) + { + int aux = i3a[0]; i3a[0] = i3a[1]; i3a[1] = i3a[2]; i3a[2] = aux; + } + else if(minpos == 2) + { + int aux = i3a[0]; i3a[0] = i3a[2]; i3a[2] = i3a[1]; i3a[1] = aux; + } + INDEX_3 i3b(i3a[0],i3a[2],i3a[1]); + + + if(facenumbers.Used(i3a)) + e_to_f[i] = facenumbers.Get(i3a); + else if(facenumbers.Used(i3b)) + e_to_f[i] = -facenumbers.Get(i3b); + else + { + numfaces++; + facenumbers.Set(i3a,numfaces); + e_to_f[i] = numfaces; + if(version >= 2) + face_ids.Append(el.GetIndex()); + else + face_ids.Append(0); + + INDEX_2 i2a,i2b; + INDEX_3 f_to_n; + for(int j=0; j<3; j++) + { + i2a = INDEX_2(i3a[j],i3a[(j+1)%3]); + i2b[0] = i2a[1]; i2b[1] = i2a[0]; + if(edgenumbers.Used(i2a)) + f_to_n[j] = edgenumbers.Get(i2a); + else if(edgenumbers.Used(i2b)) + f_to_n[j] = -edgenumbers.Get(i2b); + else + { + numedges++; + edgenumbers.Set(i2a,numedges); + edge2node.Append(i2a); + f_to_n[j] = numedges; + if(version >= 2) + edge_ids.Append(el.GetIndex()); + else + edge_ids.Append(0); + } + } + face2edge.Append(f_to_n); + } + } + element2face.Append(e_to_f); + } + + + + + ofstream outfile(filename.c_str()); + + outfile.precision(16); + + int unitcode; + double tolerance; + double dS1,dS2, alphaDeg; + double x3D,y3D,z3D; + int modelverts(0), modeledges(0), modelfaces(0), modelcells(0); + + int numObj0D,numObj1D,numObj2D,numObj3D; + int numports = ports.Size(); + + ARRAY<int> nodenum(point_ids.Size()+1); + + nodenum = -1; + + + + numnodes = 0; + for(int i=0; i<point_ids.Size(); i++) + { + if(point_ids[i] != -1) + { + numnodes++; + nodenum[i] = numnodes; + } + } + + + if(haveuserdata) + { + unitcode = userdata_int[pos_int]; + pos_int++; + + tolerance = userdata_double[pos_double]; + pos_double++; + + dS1 = userdata_double[pos_double]; + pos_double++; + dS2 = userdata_double[pos_double]; + pos_double++; + alphaDeg = userdata_double[pos_double]; + pos_double++; + + x3D = userdata_double[pos_double]; + pos_double++; + y3D = userdata_double[pos_double]; + pos_double++; + z3D = userdata_double[pos_double]; + pos_double++; + + if(version == 2) + { + modelverts = userdata_int[pos_int]; + pos_int++; + modeledges = userdata_int[pos_int]; + pos_int++; + modelfaces = userdata_int[pos_int]; + pos_int++; + modelcells = userdata_int[pos_int]; + pos_int++; + } + + numObj3D = userdata_int[pos_int]; + pos_int++; + numObj2D = userdata_int[pos_int]; + pos_int++; + numObj1D = userdata_int[pos_int]; + pos_int++; + numObj0D = userdata_int[pos_int]; + pos_int++; + } + else + { + unitcode = 3; + + tolerance = 1e-5; + + dS1 = dS2 = alphaDeg = 0; + + x3D = y3D = z3D = 0; + + modelverts = modeledges = modelfaces = modelcells = 0; + + numObj3D = numObj2D = numObj1D = numObj0D = 0; + } + + string uidpid; + if(version == 1) + uidpid = "PID"; + else if (version == 2) + uidpid = "UID"; + + + ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps; + for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) + { + idmaps.Append(new ARRAY<int,PointIndex::BASE>); + mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true); + } + } + + ARRAY<int> id_num,id_type; + ARRAY< ARRAY<int> *> id_groups; + + + // sst 2008-03-12: Write problem class... + { + std::string block; + block = "// CST Tetrahedral "; + block += !problemType.empty() ? problemType : "High Frequency"; + block += " Mesh, Version no.:\n"; + + size_t size = block.size()-3; + block += "// "; + block.append( size, '^' ); + block += "\n"; + + outfile + << block + << version << "." << subversion << "\n\n"; + } + + outfile + << "// User Units Code (1=CM 2=MM 3=M 4=MIC 5=NM 6=FT 7=IN 8=MIL):\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << unitcode << "\n\n" \ + << "// Geometric coord \"zero\" tolerance threshold:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << tolerance << "\n\n" \ + << "// Periodic UnitCell dS1 , dS2 , alphaDeg:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << dS1 << " " << dS2 << " " << alphaDeg <<"\n\n" \ + << "// Periodic UnitCell origin in global coords (x3D,y3D,z3D):\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << x3D << " " << y3D << " " << z3D << "\n" << endl; + + if(version == 2) + { + outfile << "// Model entity count: Vertices, Edges, Faces, Cells:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << modelverts << " " << modeledges << " " << modelfaces << " " << modelcells << endl << endl; + } + + + outfile << "// Topological mesh-entity counts (#elements,#faces,#edges,#nodes):\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + outfile << numelems << " " + << numfaces << " " + << numedges << " " + << numnodes << endl << endl; + + outfile << "// NodeID, X, Y, Z, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<< uidpid <<":\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + + + id_num.SetSize(mesh.GetNP()+1); + id_type.SetSize(mesh.GetNP()+1); + id_num = 0; + id_type = 0; + + int n2,n4,n8; + n2 = n4 = n8 = 0; + + + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + { + if(id_num[i] != 0) + continue; + + if(nodenum[i] == -1) + continue; + + ARRAY<int> group; + group.Append(i); + for(int j=0; j<idmaps.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps[j])[group[k]]; + if(id != 0 && !group.Contains(id) && nodenum[id] != -1) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_groups.Append(new ARRAY<int>(group)); + if(group.Size() == 2) + { + id_type[i] = 1; + id_type[group[1]] = 2; + n2++; + } + else if(group.Size() == 4) + { + id_type[i] = 3; + for(int j=1; j<group.Size(); j++) + id_type[group[j]] = 4; + n4++; + } + else if(group.Size() == 8) + { + id_type[i] = 5; + for(int j=1; j<group.Size(); j++) + id_type[group[j]] = 6; + n8++; + } + else + cerr << "ERROR: Identification group size = " << group.Size() << endl; + } + + } + + + for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + { + if(nodenum[i] == -1) + continue; + outfile << nodenum[i] << " " + << mesh[i](0) << " " + << mesh[i](1) << " " + << mesh[i](2) << " " << id_type[i] << " "; + if(i-PointIndex::BASE < point_ids.Size()) + outfile << point_ids[i]; + else + outfile << "0"; + outfile << "\n"; + } + outfile << endl; + + outfile << "\n// Number of Periodic Master Nodes:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << n2 << "\n" \ + << "\n" \ + << "// MasterNodeID, SlaveNodeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(id_groups[i]->Size() != 2) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << nodenum[(*id_groups[i])[j]] << " "; + for(int j=1; j<id_groups[i]->Size(); j++) + outfile << id_num[(*id_groups[i])[j]] << " "; + outfile << "\n"; + + delete id_groups[i]; + id_groups[i] = NULL; + } + outfile << endl; + + + outfile << "// Number of Corner Periodic Master Nodes:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << n4 << "\n" \ + << "\n" \ + << "// MasterNodeID, 3-SlaveNodeID's, 3-TranslCodes (1=dS1 2=dS2 3=dS1+dS2):\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + + for(int i=0; i<id_groups.Size(); i++) + { + if(!id_groups[i] || id_groups[i]->Size() != 4) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << nodenum[(*id_groups[i])[j]] << " "; + for(int j=1; j<id_groups[i]->Size(); j++) + { + outfile << id_num[(*id_groups[i])[j]] << " "; + } + outfile << "\n"; + + delete id_groups[i]; + id_groups[i] = NULL; + } + outfile << endl; + + + outfile << "// Number of Cubic Periodic Master Nodes:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << n8 << "\n" \ + << "\n" \ + << "// MasterNodeID, 7-SlaveNodeID's, TranslCodes:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(!id_groups[i] || id_groups[i]->Size() != 8) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << nodenum[(*id_groups[i])[j]] << " "; + for(int j=1; j<id_groups[i]->Size(); j++) + outfile << id_num[(*id_groups[i])[j]] << " "; + outfile << "\n"; + + delete id_groups[i]; + id_groups[i] = NULL; + } + outfile << endl; + + + + + outfile << "// EdgeID, NodeID0, NodeID1, Type (0=Reg 1=PMaster 2=PSlave 3=CPMaster 4=CPSlave), "<<uidpid<<":\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + + + ARRAY< ARRAY<int>* > vertex_to_edge(mesh.GetNP()+1); + for(int i=0; i<=mesh.GetNP(); i++) + vertex_to_edge[i] = new ARRAY<int>; + + ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps_edge(idmaps.Size()); + for(int i=0; i<idmaps_edge.Size(); i++) + { + idmaps_edge[i] = new ARRAY<int,PointIndex::BASE>(numedges); + (*idmaps_edge[i]) = 0; + } + + ARRAY<int> possible; + for(int i=0; i<edge2node.Size(); i++) + { + const INDEX_2 & v = edge2node[i]; + for(int j=0; j<idmaps.Size(); j++) + { + INDEX_2 vid((*idmaps[j])[v[0]], (*idmaps[j])[v[1]]); + if(vid[0] != 0 && vid[0] != v[0] && vid[1] != 0 && vid[1] != v[1]) + { + Intersection(*vertex_to_edge[vid[0]],*vertex_to_edge[vid[1]],possible); + if(possible.Size() == 1) + { + (*idmaps_edge[j])[possible[0]] = i+1; + (*idmaps_edge[j])[i+1] = possible[0]; + } + else if(possible.Size() > 0) + { + cerr << "ERROR: too many possible edge identifications" << endl; + (*testout) << "ERROR: too many possible edge identifications" << endl + << "*vertex_to_edge["<<vid[0]<<"] " << *vertex_to_edge[vid[0]] << endl + << "*vertex_to_edge["<<vid[1]<<"] " << *vertex_to_edge[vid[1]] << endl + << "possible " << possible << endl; + } + } + } + vertex_to_edge[v[0]]->Append(i+1); + vertex_to_edge[v[1]]->Append(i+1); + } + + + for(int i=0; i<vertex_to_edge.Size(); i++) + delete vertex_to_edge[i]; + + + id_groups.SetSize(0); + id_num.SetSize(numedges+1); + id_num = 0; + id_type.SetSize(numedges+1); + id_type = 0; + + n2 = n4 = n8 = 0; + + for(int i=1; i<=edge2node.Size(); i++) + { + if(id_num[i] != 0) + continue; + + + ARRAY<int> group; + group.Append(i); + for(int j=0; j<idmaps_edge.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps_edge[j])[group[k]]; + if(id != 0 && !group.Contains(id)) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_num[i] = 1; + id_groups.Append(new ARRAY<int>(group)); + if(group.Size() == 2) + { + id_type[i] = 1; + id_type[group[1]] = 2; + n2++; + } + else if(group.Size() == 4) + { + id_type[i] = 3; + for(int j=1; j<group.Size(); j++) + id_type[group[j]] = 4; + n4++; + } + else + { + cerr << "ERROR: edge identification group size = " << group.Size() << endl; + (*testout) << "edge group " << group << endl; + for(int j=0; j<idmaps_edge.Size(); j++) + { + (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl; + } + } + } + } + + + + for(int i=1; i<=edge2node.Size(); i++) + { + if(id_num[i] != 0) + continue; + + + ARRAY<int> group; + group.Append(i); + for(int j=0; j<idmaps_edge.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps_edge[j])[group[k]]; + if(id != 0 && !group.Contains(id)) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_num[i] = 1; + id_groups.Append(new ARRAY<int>(group)); + if(group.Size() == 2) + { + id_type[i] = 1; + id_type[group[1]] = 2; + n2++; + } + else if(group.Size() == 4) + { + id_type[i] = 3; + for(int j=1; j<group.Size(); j++) + id_type[group[j]] = 4; + n4++; + } + else + { + cerr << "ERROR: edge identification group size = " << group.Size() << endl; + (*testout) << "edge group " << group << endl; + for(int j=0; j<idmaps_edge.Size(); j++) + { + (*testout) << "edge id map " << j << endl << *idmaps_edge[j] << endl; + } + } + } + + } + + + for(int i=0; i<edge2node.Size(); i++) + outfile << i+1 << " " << nodenum[edge2node[i][0]] << " " << nodenum[edge2node[i][1]] + << " " << id_type[i+1] << " " << edge_ids[i] << "\n"; + + outfile << endl; + + + + outfile << "// Number of Periodic Master Edges:\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ + << n2 << "\n" \ + << "\n"\ + << "// MasterEdgeID, SlaveEdgeID, TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(id_groups[i]->Size() != 2) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << (*id_groups[i])[j] << " "; + for(int j=1; j<id_groups[i]->Size(); j++) + outfile << id_num[(*id_groups[i])[j]] << " "; + outfile << "\n"; + + delete id_groups[i]; + id_groups[i] = NULL; + } + outfile << endl; + + outfile << "// Number of Corner Periodic Master Edges:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ + << n4 << "\n" \ + << "\n"\ + << "// MasterEdgeID, 3 SlaveEdgeID's, 3 TranslCode (1=dS1 2=dS2 3=dS1+dS2):\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(!id_groups[i] || id_groups[i]->Size() != 4) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << (*id_groups[i])[j] << " "; + for(int j=1; j<id_groups[i]->Size(); j++) + outfile << id_num[(*id_groups[i])[j]] << " "; + outfile << "\n"; + + delete id_groups[i]; + id_groups[i] = NULL; + } + outfile << endl; + + + outfile << "// FaceID, EdgeID0, EdgeID1, EdgeID2, FaceType (0=Reg 1=PMaster 2=PSlave), "<<uidpid<<":\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + + + ARRAY< ARRAY<int>* > edge_to_face(numedges+1); + for(int i=0; i<edge_to_face.Size(); i++) + edge_to_face[i] = new ARRAY<int>; + + + for(int i=0; i<idmaps.Size(); i++) + { + idmaps[i]->SetSize(numfaces); + (*idmaps[i]) = 0; + } + + + for(int i=0; i<face2edge.Size(); i++) + { + for(int j=0; j<idmaps_edge.Size(); j++) + { + int e1id,e2id,e3id; + e1id = (*idmaps_edge[j])[abs(face2edge[i][0])]; + e2id = (*idmaps_edge[j])[abs(face2edge[i][1])]; + e3id = (*idmaps_edge[j])[abs(face2edge[i][2])]; + if(e1id != 0 && e1id != abs(face2edge[i][0]) && + e2id != 0 && e2id != abs(face2edge[i][1]) && + e3id != 0 && e3id != abs(face2edge[i][2])) + { + Intersection(*edge_to_face[e1id],*edge_to_face[e2id],*edge_to_face[e3id],possible); + if(possible.Size() == 1) + { + (*idmaps[j])[possible[0]] = i+1; + (*idmaps[j])[i+1] = possible[0]; + } + else if(possible.Size() > 0) + cerr << "ERROR: too many possible face identifications" << endl; + } + } + + edge_to_face[abs(face2edge[i][0])]->Append(i+1); + edge_to_face[abs(face2edge[i][1])]->Append(i+1); + edge_to_face[abs(face2edge[i][2])]->Append(i+1); + } + + for(int i=0; i<edge_to_face.Size(); i++) + delete edge_to_face[i]; + + + for(int i=0; i<idmaps_edge.Size(); i++) + delete idmaps_edge[i]; + + + id_groups.SetSize(0); + id_num.SetSize(numfaces+1); + id_num = 0; + + n2 = n4 = n8 = 0; + + for(int i=1; i<=numfaces; i++) + { + if(id_num[i] != 0) + continue; + + ARRAY<int> group; + group.Append(i); + for(int j=0; j<idmaps.Size(); j++) + { + startsize = group.Size(); + for(int k=0; k<startsize; k++) + { + int id = (*idmaps[j])[group[k]]; + if(id != 0 && !group.Contains(id)) + { + group.Append(id); + id_num[id] = j+1+id_num[group[k]]; + } + } + } + if(group.Size() > 1) + { + id_num[i] = -1; + id_groups.Append(new ARRAY<int>(group)); + if(group.Size() == 2) + n2++; + else + cerr << "ERROR: face identification group size = " << group.Size() << endl; + } + + } + + + for(int i=0; i<idmaps.Size(); i++) + delete idmaps[i]; + + + + + for(int i=0; i<face2edge.Size(); i++) + { + outfile << i+1 << " "; + for(int j=0; j<3; j++) + outfile << face2edge[i][j] << " "; + + if(id_num[i+1] == 0) + outfile << 0; + else if(id_num[i+1] == -1) + outfile << 1; + else + outfile << 2; + + outfile << " " << face_ids[i] <<"\n"; + } + outfile << endl; + + + outfile << "// Number of Periodic Master Faces:\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"\ + << n2 << "\n" \ + << "\n"\ + << "// MasterFaceID, SlaveFaceID, TranslCode (1=dS1 2=dS2):\n"\ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<id_groups.Size(); i++) + { + if(id_groups[i]->Size() != 2) + continue; + + for(int j=0; j<id_groups[i]->Size(); j++) + outfile << (*id_groups[i])[j] << " "; + for(int j=1; j<id_groups[i]->Size(); j++) + outfile << id_num[(*id_groups[i])[j]] << " "; + outfile << "\n"; + + delete id_groups[i]; + } + outfile << endl; + + + + + outfile << "// ElemID, FaceID0, FaceID1, FaceID2, FaceID3, "<<uidpid<<":\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + for(ElementIndex i=0; i<mesh.GetNE(); i++) + { + if(elnum[i] >= 0) + { + outfile << elnum[i] << " "; + for(int j=0; j<4; j++) + outfile << element2face[elnum[i]-1][j] << " "; + + outfile << mesh[i].GetIndex() << "\n"; + } + } + outfile << endl; + + outfile << "// ElemID, NodeID0, NodeID1, NodeID2, NodeID3:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + + + for(ElementIndex i=0; i<mesh.GetNE(); i++) + { + if(elnum[i] >= 0) + outfile << elnum[i] << " " + << nodenum[mesh[i][1]] << " " << nodenum[mesh[i][0]] << " " << nodenum[mesh[i][2]] << " " << nodenum[mesh[i][3]] << "\n"; + } + outfile << endl; + + + + + outfile << "// Physical Object counts (#Obj3D,#Obj2D,#Obj1D,#Obj0D):\n" + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + << " "<< numObj3D << " " << numObj2D << " " << numObj1D << " " << numObj0D << "\n" \ + << "\n" \ + << "// Number of Ports (Ports are a subset of Object2D list):\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" \ + << numports << "\n" \ + << endl; + + + ARRAY< ARRAY<int> * > groups; + + int maxg = -1; + for(int i = 0; i<uid_to_group_3D.Size(); i++) + if(uid_to_group_3D[i] > maxg) + maxg = uid_to_group_3D[i]; + for(int i = 0; i<uid_to_group_2D.Size(); i++) + if(uid_to_group_2D[i] > maxg) + maxg = uid_to_group_2D[i]; + for(int i = 0; i<uid_to_group_1D.Size(); i++) + if(uid_to_group_1D[i] > maxg) + maxg = uid_to_group_1D[i]; + for(int i = 0; i<uid_to_group_0D.Size(); i++) + if(uid_to_group_0D[i] > maxg) + maxg = uid_to_group_0D[i]; + + groups.SetSize(maxg+1); + for(int i=0; i<groups.Size(); i++) + groups[i] = new ARRAY<int>; + + for(ElementIndex i=0; i<mesh.GetNE(); i++) + if(uid_to_group_3D[mesh[i].GetIndex()] >= 0) + groups[uid_to_group_3D[mesh[i].GetIndex()]]->Append(i+1); + + + + + outfile << "// Object3D GroupID, #Elems <immediately followed by> ElemID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj3D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + outfile << (*groups[i])[j] << "\n"; + } + + for(int i=0; i<groups.Size(); i++) + groups[i]->SetSize(0); + + for(int i=0; i<face_ids.Size(); i++) + if(uid_to_group_2D[face_ids[i]] >= 0) + groups[uid_to_group_2D[face_ids[i]]]->Append(i+1); + + + outfile << "// Object2D GroupID, #Faces <immediately followed by> FaceID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj2D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + { + outfile << (*groups[i])[j]; + if(ports.Contains(face_ids[(*groups[i])[j]-1])) + outfile << " P"; + outfile << "\n"; + } + } + outfile << endl; + + + for(int i=0; i<groups.Size(); i++) + groups[i]->SetSize(0); + + for(int i=0; i<edge_ids.Size(); i++) + if(uid_to_group_1D[edge_ids[i]] >= 0) + groups[uid_to_group_1D[edge_ids[i]]]->Append(i+1); + + + + outfile << "// Object1D GroupID, #Edges <immediately followed by> EdgeID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj1D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + outfile << (*groups[i])[j] << "\n"; + } + outfile << endl; + + + for(int i=0; i<groups.Size(); i++) + groups[i]->SetSize(0); + for(PointIndex i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + { + if(i-PointIndex::BASE < point_ids.Size()) + { + if(uid_to_group_0D[point_ids[i]] >= 0) + groups[uid_to_group_0D[point_ids[i]]]->Append(i+1-PointIndex::BASE); + } + else + groups[uid_to_group_0D[0]]->Append(i+1-PointIndex::BASE); + } + + + outfile << "// Object0D GroupID, #Nodes <immediately followed by> NodeID List:\n" \ + << "// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; + for(int i=0; i<numObj0D; i++) + { + outfile << i << " " << groups[i]->Size() << "\n"; + for(int j=0; j<groups[i]->Size(); j++) + outfile << (*groups[i])[j] << "\n"; + } + outfile << endl; + + for(int i=0; i<groups.Size(); i++) + delete groups[i]; + + + outfile.close(); + + cout << ".tet export done" << endl; + } +} diff --git a/contrib/Netgen/libsrc/interface/writetochnog.cpp b/contrib/Netgen/libsrc/interface/writetochnog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9ec6e3ce9c6b2c6faae0b771f484a928eb0ce17 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writetochnog.cpp @@ -0,0 +1,108 @@ +// +// Write Tochnog file +// +// by +// +// Andreas Seltmann +// email: A.Seltmann@lsw.uni-heidelberg.de +// +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + + +namespace netgen +{ +#include "writeuser.hpp" + + +void WriteTochnogFormat (const Mesh & mesh, + const string & filename) +{ + cout << "\nWrite Tochnog Volume Mesh" << endl; + + ofstream outfile (filename.c_str()); + + outfile << "(Nodes and Elements generated with NETGEN" << endl; + outfile << " " << filename << ")" << endl; + + outfile.precision(8); + + outfile << "(Nodes)" << endl; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int i, j; + + for (i = 1; i <= np; i++) + { + outfile << "node " << " " << i << " "; + outfile << mesh.Point(i)(0) << " "; + outfile << mesh.Point(i)(1) << " "; + outfile << mesh.Point(i)(2) << "\n"; + } + + int elemcnt = 0; //element counter + int finished = 0; + int indcnt = 1; //index counter + + while (!finished) + { + int actcnt = 0; + const Element & el1 = mesh.VolumeElement(1); + int non = el1.GetNP(); + if (non == 4) + { + outfile << "(Elements, type=-tet4)" << endl; + } + else + { + cout << "unsupported Element type!!!" << endl; + } + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + + if (el.GetIndex() == indcnt) + { + actcnt++; + if (el.GetNP() != non) + { + cout << "different element-types in a subdomain are not possible!!!" << endl; + continue; + } + + elemcnt++; + outfile << "element " << elemcnt << " -tet4 "; + if (non == 4) + { + outfile << el.PNum(1) << " "; + outfile << el.PNum(2) << " "; + outfile << el.PNum(4) << " "; + outfile << el.PNum(3) << "\n"; + } + else + { + cout << "unsupported Element type!!!" << endl; + for (j = 1; j <= el.GetNP(); j++) + { + outfile << el.PNum(j); + if (j != el.GetNP()) outfile << ", "; + } + outfile << "\n"; + } + } + } + indcnt++; + if (elemcnt == ne) {finished = 1; cout << "all elements found by Index!" << endl;} + if (actcnt == 0) {finished = 1;} + } + + cout << "done" << endl; +} + +} diff --git a/contrib/Netgen/libsrc/interface/writeuser.cpp b/contrib/Netgen/libsrc/interface/writeuser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..92b76520dcbe9d0a8819f2ef7f5ecb754bff6ae4 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeuser.cpp @@ -0,0 +1,910 @@ +// +// Write user dependent output file +// + +#include <mystdlib.h> + +#include <myadt.hpp> +#include <linalg.hpp> +#include <csg.hpp> +#include <geometry2d.hpp> +#include <meshing.hpp> + +namespace netgen +{ +#include "writeuser.hpp" + + +void RegisterUserFormats (ARRAY<const char*> & names) +{ + const char *types[] = + { + "Neutral Format", + "Surface Mesh Format" , + "DIFFPACK Format", + "TecPlot Format", + "Tochnog Format", + "Abaqus Format", + "Fluent Format", + "Permas Format", + "FEAP Format", + "Elmer Format", + "STL Format", + "VRML Format", + "Gmsh Format", + "JCMwave Format", + "TET Format", + // { "Chemnitz Format" }, + 0 + }; + + for (int i = 0; types[i]; i++) + names.Append (types[i]); +} + + + +bool WriteUserFormat (const string & format, + const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + PrintMessage (1, "Export mesh to file ", filename, + ", format is ", format); + + if (format == "Neutral Format") + WriteNeutralFormat (mesh, geom, filename); + + else if (format == "Surface Mesh Format") + WriteSurfaceFormat (mesh, filename); + + else if (format == "DIFFPACK Format") + WriteDiffPackFormat (mesh, geom, filename); + + else if (format == "Tochnog Format") + WriteTochnogFormat (mesh, filename); + + else if (format == "TecPlot Format") + cerr << "ERROR: TecPlot format currently out of order" << endl; + // WriteTecPlotFormat (mesh, geom, filename); + + else if (format == "Abaqus Format") + WriteAbaqusFormat (mesh, filename); + + else if (format == "Fluent Format") + WriteFluentFormat (mesh, filename); + + else if (format == "Permas Format") + WritePermasFormat (mesh, filename); + + else if (format == "FEAP Format") + WriteFEAPFormat (mesh, filename); + + else if (format == "Elmer Format") + WriteElmerFormat (mesh, filename); + + else if (format == "STL Format") + WriteSTLFormat (mesh, filename); + + else if (format == "VRML Format") + WriteVRMLFormat (mesh, 1, filename); + + else if (format == "Fepp Format") + WriteFEPPFormat (mesh, geom, filename); + + else if (format == "EdgeElement Format") + WriteEdgeElementFormat (mesh, geom, filename); + + else if (format == "Chemnitz Format") + WriteUserChemnitz (mesh, filename); + + else if (format == "Gmsh Format") + WriteGmshFormat (mesh, geom, filename); + + else if (format == "JCMwave Format") + WriteJCMFormat (mesh, geom, filename); + +#ifdef OLIVER + else if (format == "TET Format") + WriteTETFormat( mesh, filename);//, "High Frequency" ); +#endif + + else + { + return 1; + } + + return 0; +} + + + + +/* + * Neutral mesh format + * points, elements, surface elements + */ + +void WriteNeutralFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + cout << "write neutral, new" << endl; + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int nseg = mesh.GetNSeg(); + int i, j; + + int inverttets = mparam.inverttets; + int invertsurf = mparam.inverttrigs; + + ofstream outfile (filename.c_str()); + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + outfile << np << "\n"; + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + outfile.width(10); + outfile << p.X() << " "; + outfile.width(9); + outfile << p.Y() << " "; + if (mesh.GetDimension() == 3) + { + outfile.width(9); + outfile << p.Z(); + } + outfile << "\n"; + } + + if (mesh.GetDimension() == 3) + { + outfile << ne << "\n"; + for (i = 1; i <= ne; i++) + { + Element el = mesh.VolumeElement(i); + if (inverttets) + el.Invert(); + outfile.width(4); + outfile << el.GetIndex() << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile.width(8); + outfile << el.PNum(j); + } + outfile << "\n"; + } + } + + outfile << nse << "\n"; + for (i = 1; i <= nse; i++) + { + Element2d el = mesh.SurfaceElement(i); + if (invertsurf) + el.Invert(); + outfile.width(4); + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile.width(8); + outfile << el.PNum(j); + } + outfile << "\n"; + } + + + if (mesh.GetDimension() == 2) + { + outfile << nseg << "\n"; + for (i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + outfile.width(4); + outfile << seg.si << " "; + + outfile << " "; + outfile.width(8); + outfile << seg.p1; + outfile << " "; + outfile.width(8); + outfile << seg.p2; + + outfile << "\n"; + } + } +} + + + + + + + + + +void WriteSurfaceFormat (const Mesh & mesh, + const string & filename) +{ + // surface mesh + int i, j; + + cout << "Write Surface Mesh" << endl; + + ofstream outfile (filename.c_str()); + + outfile << "surfacemesh" << endl; + + outfile << mesh.GetNP() << endl; + for (i = 1; i <= mesh.GetNP(); i++) + { + for (j = 0; j < 3; j++) + { + outfile.width(10); + outfile << mesh.Point(i)(j) << " "; + } + outfile << endl; + } + outfile << mesh.GetNSE() << endl; + for (i = 1; i <= mesh.GetNSE(); i++) + { + for (j = 1; j <= 3; j++) + { + outfile.width(8); + outfile << mesh.SurfaceElement(i).PNum(j); + } + outfile << endl; + } +} + + + + + +/* + * save surface mesh as STL file + */ + +void WriteSTLFormat (const Mesh & mesh, + const string & filename) +{ + cout << "\nWrite STL Surface Mesh" << endl; + + ofstream outfile (filename.c_str()); + + int i; + + outfile.precision(10); + + outfile << "solid" << endl; + + for (i = 1; i <= mesh.GetNSE(); i++) + { + outfile << "facet normal "; + const Point3d& p1 = mesh.Point(mesh.SurfaceElement(i).PNum(1)); + const Point3d& p2 = mesh.Point(mesh.SurfaceElement(i).PNum(2)); + const Point3d& p3 = mesh.Point(mesh.SurfaceElement(i).PNum(3)); + + Vec3d normal = Cross(p2-p1,p3-p1); + if (normal.Length() != 0) + { + normal /= (normal.Length()); + } + + outfile << normal.X() << " " << normal.Y() << " " << normal.Z() << "\n"; + outfile << "outer loop\n"; + + outfile << "vertex " << p1.X() << " " << p1.Y() << " " << p1.Z() << "\n"; + outfile << "vertex " << p2.X() << " " << p2.Y() << " " << p2.Z() << "\n"; + outfile << "vertex " << p3.X() << " " << p3.Y() << " " << p3.Z() << "\n"; + + outfile << "endloop\n"; + outfile << "endfacet\n"; + } + outfile << "endsolid" << endl; +} + + + + + +/* + * + * write surface mesh as VRML file + * + */ + +void WriteVRMLFormat (const Mesh & mesh, + bool faces, + const string & filename) +{ + + if (faces) + + { + // Output in VRML, IndexedFaceSet is used + // Bartosz Sawicki <sawickib@ee.pw.edu.pl> + + int np = mesh.GetNP(); + int nse = mesh.GetNSE(); + int i, j; + + ofstream outfile (filename.c_str()); + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + outfile << "#VRML V2.0 utf8 \n" + "Background {\n" + " skyColor [1 1 1]\n" + " groundColor [1 1 1]\n" + "}\n" + "Group{ children [\n" + "Shape{ \n" + "appearance Appearance { material Material { }} \n" + "geometry IndexedFaceSet { \n" + "coord Coordinate { point [ \n"; + + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + outfile.width(10); + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z() << " \n"; + } + + outfile << " ] } \n" + "coordIndex [ \n"; + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + + for (j = 1; j <= 3; j++) + { + outfile.width(8); + outfile << el.PNum(j)-1; + } + outfile << " -1 \n"; + } + + outfile << " ] \n"; + + //define number and RGB definitions of colors + outfile << "color Color { color [1 0 0, 0 1 0, 0 0 1, 1 1 0]} \n" + "colorIndex [\n"; + + for (i = 1; i <= nse; i++) + { + outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).BCProperty(); + outfile << endl; + } + + outfile << " ] \n" + "colorPerVertex FALSE \n" + "creaseAngle 0 \n" + "solid FALSE \n" + "ccw FALSE \n" + "convex TRUE \n" + "} } # end of Shape\n" + "] }\n"; + + } /* end of VRMLFACES */ + + + else + + { + // Output in VRML, IndexedLineSet is used + // Bartosz Sawicki <sawickib@ee.pw.edu.pl> + + int np = mesh.GetNP(); + int nse = mesh.GetNSE(); + int i, j; + + ofstream outfile (filename.c_str()); + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + outfile << "#VRML V2.0 utf8 \n" + "Background {\n" + " skyColor [1 1 1]\n" + " groundColor [1 1 1]\n" + "}\n" + "Group{ children [\n" + "Shape{ \n" + "appearance Appearance { material Material { }} \n" + "geometry IndexedLineSet { \n" + "coord Coordinate { point [ \n"; + + + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + outfile.width(10); + outfile << p.X() << " "; + outfile << p.Y() << " "; + outfile << p.Z() << " \n"; + } + + outfile << " ] } \n" + "coordIndex [ \n"; + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + + for (j = 1; j <= 3; j++) + { + outfile.width(8); + outfile << el.PNum(j)-1; + } + outfile.width(8); + outfile << el.PNum(1)-1; + outfile << " -1 \n"; + } + + outfile << " ] \n"; + +/* Uncomment if you want color mesh + outfile << "color Color { color [1 1 1, 0 1 0, 0 0 1, 1 1 0]} \n" + "colorIndex [\n"; + + for (i = 1; i <= nse; i++) + { + outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).BCProperty(); + outfile << endl; + } + + outfile << " ] \n" +*/ + outfile << "colorPerVertex FALSE \n" + "} } #end of Shape\n" + "] } \n"; + + } + +} + + + + + + +/* + * FEPP .. a finite element package developed at University Linz, Austria + */ +void WriteFEPPFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + + ofstream outfile (filename.c_str()); + + if (mesh.GetDimension() == 3) + + { + + // output for FEPP + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int ns = mesh.GetNFD(); + int i, j; + + outfile.precision(5); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + outfile << "volumemesh4" << endl; + outfile << nse << endl; + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + + // int facenr = mesh.facedecoding.Get(el.GetIndex()).surfnr; + outfile.width(4); + outfile << el.GetIndex() << " "; + outfile.width(4); + // outfile << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << " "; + outfile << mesh.GetFaceDescriptor(el.GetIndex()).BCProperty() << " "; + outfile.width(4); + outfile << el.GetNP() << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile.width(8); + outfile << el.PNum(j); + } + outfile << "\n"; + } + + + outfile << ne << "\n"; + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + outfile.width(4); + outfile << el.GetIndex() << " "; + outfile.width(4); + outfile << el.GetNP() << " "; + for (j = 1; j <= el.GetNP(); j++) + { + outfile.width(8); + outfile << el.PNum(j); + } + outfile << "\n"; + } + + outfile << np << "\n"; + for (i = 1; i <= np; i++) + { + const Point3d & p = mesh.Point(i); + + outfile.width(10); + outfile << p.X() << " "; + outfile.width(9); + outfile << p.Y() << " "; + outfile.width(9); + outfile << p.Z() << "\n"; + } + + /* + if (typ == WRITE_FEPPML) + { + int nbn = mesh.mlbetweennodes.Size(); + outfile << nbn << "\n"; + for (i = 1; i <= nbn; i++) + outfile << mesh.mlbetweennodes.Get(i).I1() << " " + << mesh.mlbetweennodes.Get(i).I2() << "\n"; + + + // int ncon = mesh.connectedtonode.Size(); + // outfile << ncon << "\n"; + // for (i = 1; i <= ncon; i++) + // outfile << i << " " << mesh.connectedtonode.Get(i) << endl; + } + */ + + + // write CSG surfaces + if (&geom && geom.GetNSurf() >= ns) + { + outfile << ns << endl; + for (i = 1; i <= ns; i++) + geom.GetSurface(mesh.GetFaceDescriptor(i).SurfNr())->Print(outfile); + } + else + outfile << "0" << endl; + } + + + else + + { // 2D fepp format + + ; + /* + extern SplineGeometry2d * geometry2d; + if (geometry2d) + Save2DMesh (mesh, &geometry2d->GetSplines(), outfile); + else + Save2DMesh (mesh, 0, outfile); + */ + } +} + + + + + + +/* + * Edge element mesh format + * points, elements, edges + */ + +void WriteEdgeElementFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename) +{ + cout << "write edge element format" << endl; + + const MeshTopology * top = &mesh.GetTopology(); + int npoints = mesh.GetNP(); + int nelements = mesh.GetNE(); + int nsurfelem = mesh.GetNSE(); + int nedges = top->GetNEdges(); + int i, j; + + int inverttets = mparam.inverttets; + int invertsurf = mparam.inverttrigs; + ARRAY<int> edges; + + ofstream outfile (filename.c_str()); + + outfile.precision(6); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + + // vertices with coordinates + outfile << npoints << "\n"; + for (i = 1; i <= npoints; i++) + { + const Point3d & p = mesh.Point(i); + + outfile.width(10); + outfile << p.X() << " "; + outfile.width(9); + outfile << p.Y() << " "; + outfile.width(9); + outfile << p.Z() << "\n"; + } + + // element - edge - list + outfile << nelements << " " << nedges << "\n"; + for (i = 1; i <= nelements; i++) + { + Element el = mesh.VolumeElement(i); + if (inverttets) + el.Invert(); + outfile.width(4); + outfile << el.GetIndex() << " "; + outfile.width(8); + outfile << el.GetNP(); + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile.width(8); + outfile << el.PNum(j); + } + + top->GetElementEdges(i,edges); + outfile << endl << " "; + outfile.width(8); + outfile << edges.Size(); + for (j=1; j <= edges.Size(); j++) + { + outfile << " "; + outfile.width(8); + outfile << edges[j-1]; + } + outfile << "\n"; + + // orientation: + top->GetElementEdgeOrientations(i,edges); + outfile << " "; + for (j=1; j <= edges.Size(); j++) + { + outfile << " "; + outfile.width(8); + outfile << edges[j-1]; + } + outfile << "\n"; + } + + // surface element - edge - list (with boundary conditions) + outfile << nsurfelem << "\n"; + for (i = 1; i <= nsurfelem; i++) + { + Element2d el = mesh.SurfaceElement(i); + if (invertsurf) + el.Invert(); + outfile.width(4); + outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " "; + outfile.width(8); + outfile << el.GetNP(); + for (j = 1; j <= el.GetNP(); j++) + { + outfile << " "; + outfile.width(8); + outfile << el.PNum(j); + } + + top->GetSurfaceElementEdges(i,edges); + outfile << endl << " "; + outfile.width(8); + outfile << edges.Size(); + for (j=1; j <= edges.Size(); j++) + { + outfile << " "; + outfile.width(8); + outfile << edges[j-1]; + } + outfile << "\n"; + } + + + int v1, v2; + // edge - vertex - list + outfile << nedges << "\n"; + for (i=1; i <= nedges; i++) + { + top->GetEdgeVertices(i,v1,v2); + outfile.width(4); + outfile << v1; + outfile << " "; + outfile.width(8); + outfile << v2 << endl; + } +} + + + + + + + + + +#ifdef OLDSTYLE_WRITE + + +void WriteFile (int typ, + const Mesh & mesh, + const CSGeometry & geom, + const char * filename, + const char * geomfile, + double h) +{ + + + int inverttets = mparam.inverttets; + int invertsurf = mparam.inverttrigs; + + + + + + + + + if (typ == WRITE_EDGEELEMENT) + { + // write edge element file + // Peter Harscher, ETHZ + + cout << "Write Edge-Element Format" << endl; + + ofstream outfile (filename); + + int i, j; + int ned; + + // hash table representing edges; + INDEX_2_HASHTABLE<int> edgeht(mesh.GetNP()); + + // list of edges + ARRAY<INDEX_2> edgelist; + + // edge (point) on boundary ? + BitArray bedge, bpoint(mesh.GetNP()); + + static int eledges[6][2] = { { 1, 2 } , { 1, 3 } , { 1, 4 }, + { 2, 3 } , { 2, 4 } , { 3, 4 } }; + + // fill hashtable (point1, point2) ----> edgenr + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement (i); + INDEX_2 edge; + for (j = 1; j <= 6; j++) + { + edge.I1() = el.PNum (eledges[j-1][0]); + edge.I2() = el.PNum (eledges[j-1][1]); + edge.Sort(); + + if (!edgeht.Used (edge)) + { + edgelist.Append (edge); + edgeht.Set (edge, edgelist.Size()); + } + } + } + + + // set bedges, bpoints + bedge.SetSize (edgelist.Size()); + bedge.Clear(); + bpoint.Clear(); + + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + for (j = 1; j <= 3; j++) + { + bpoint.Set (sel.PNum(j)); + + INDEX_2 edge; + edge.I1() = sel.PNum(j); + edge.I2() = sel.PNum(j%3+1); + edge.Sort(); + + bedge.Set (edgeht.Get (edge)); + } + } + + + + outfile << mesh.GetNE() << endl; + // write element ---> point + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + + outfile.width(8); + outfile << i; + for (j = 1; j <= 4; j++) + { + outfile.width(8); + outfile << el.PNum(j); + } + outfile << endl; + } + + // write element ---> edge + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement (i); + INDEX_2 edge; + for (j = 1; j <= 6; j++) + { + edge.I1() = el.PNum (eledges[j-1][0]); + edge.I2() = el.PNum (eledges[j-1][1]); + edge.Sort(); + + outfile.width(8); + outfile << edgeht.Get (edge); + } + outfile << endl; + } + + // write points + outfile << mesh.GetNP() << endl; + outfile.precision (6); + for (i = 1; i <= mesh.GetNP(); i++) + { + const Point3d & p = mesh.Point(i); + + for (j = 1; j <= 3; j++) + { + outfile.width(8); + outfile << p.X(j); + } + outfile << " " + << (bpoint.Test(i) ? "1" : 0) << endl; + } + + // write edges + outfile << edgelist.Size() << endl; + for (i = 1; i <= edgelist.Size(); i++) + { + outfile.width(8); + outfile << edgelist.Get(i).I1(); + outfile.width(8); + outfile << edgelist.Get(i).I2(); + outfile << " " + << (bedge.Test(i) ? "1" : "0") << endl; + } + } + + + + +} +#endif +} + diff --git a/contrib/Netgen/libsrc/interface/writeuser.hpp b/contrib/Netgen/libsrc/interface/writeuser.hpp new file mode 100644 index 0000000000000000000000000000000000000000..61dd5aa27f1ff0e89488ce503850adc81b5cc358 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/writeuser.hpp @@ -0,0 +1,140 @@ +#ifndef WRITEUSER +#define WRITEUSER + +/**************************************************************************/ +/* File: writeuser.hh */ +/* Authors: many */ +/* Date: 10. Dec. 97 */ +/**************************************************************************/ + + +extern +void WriteFile (int typ, + const Mesh & mesh, + const CSGeometry & geom, + const char * filename, + const char * geomfile = NULL, + double h = 0); + + + +extern +void ReadFile (Mesh & mesh, + const string & filename); + +extern +void ImportSolution (const char * filename); + + + + + + + +extern +void WriteNeutralFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + +extern +void WriteSurfaceFormat (const Mesh & mesh, + const string & filename); + +extern +void WriteSTLFormat (const Mesh & mesh, + const string & filename); + +extern +void WriteVRMLFormat (const Mesh & mesh, + bool faces, + const string & filename); + +extern +void WriteFEPPFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + +extern +void WriteGmshFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + +extern +void WriteUserChemnitz (const Mesh & mesh, + const string & filename); + +extern +void WriteJCMFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + + +extern +void WriteDiffPackFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + +extern +void WriteTochnogFormat (const Mesh & mesh, + const string & filename); + +extern +void WriteTecPlotFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + +extern +void WriteAbaqusFormat (const Mesh & mesh, + const string & filename); + +extern +void WriteFluentFormat (const Mesh & mesh, + const string & filename); + +extern +void WritePermasFormat (const Mesh & mesh, + const string & filename); + +extern +void WriteFEAPFormat (const Mesh & mesh, + const string & filename); + +extern +void WriteElmerFormat (const Mesh & mesh, + const string & filename); + + +extern +void WriteEdgeElementFormat (const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + + + +#ifdef OLIVER +extern +void WriteTETFormat (const Mesh & mesh, + const string & filename); + +#endif + +extern void ReadTETFormat (Mesh & mesh, + const string & filename); + + +void WriteDolfinFormat (const Mesh & mesh, + const string & filename); + + +extern void RegisterUserFormats (ARRAY<const char*> & names); + +extern bool WriteUserFormat (const string & format, + const Mesh & mesh, + const CSGeometry & geom, + const string & filename); + + + + +#endif + diff --git a/contrib/Netgen/libsrc/interface/wuchemnitz.cpp b/contrib/Netgen/libsrc/interface/wuchemnitz.cpp new file mode 100644 index 0000000000000000000000000000000000000000..147d0d4d06b2e9badab48195942a4b9e904eb832 --- /dev/null +++ b/contrib/Netgen/libsrc/interface/wuchemnitz.cpp @@ -0,0 +1,313 @@ +// Write Chemnitz file format + + +#include <mystdlib.h> + +#include <myadt.hpp> + +#include <linalg.hpp> +#include <csg.hpp> +#include <meshing.hpp> + +namespace netgen +{ + +class POINT3D + { + public: + POINT3D () { }; + double x, y, z; + }; + +class VOLELEMENT + { + public: + VOLELEMENT () {}; + int domnr, p1, p2, p3, p4; + int faces[4]; + }; + +class SURFELEMENT + { + public: + SURFELEMENT () { }; + int snr, p1, p2, p3; + }; + + +class FACE + { + public: + FACE () { }; + int p1, p2, p3; + int edges[3]; + }; + +class EDGE + { + public: + EDGE () { }; + int p1, p2; + }; + +static ARRAY<POINT3D> points; +static ARRAY<VOLELEMENT> volelements; +static ARRAY<SURFELEMENT> surfelements; + +static ARRAY<FACE> faces; +static ARRAY<EDGE> edges; + + +void ReadFile (char * filename) + { + int i, n; + ifstream infile(filename); + char reco[100]; + + + infile >> reco; // file format recognition + + infile >> n; // number of surface elements + cout << n << " Surface elements" << endl; + + for (i = 1; i <= n; i++) + { + SURFELEMENT sel; + infile >> sel.snr >> sel.p1 >> sel.p2 >> sel.p3; + surfelements.Append (sel); + } + + infile >> n; // number of volume elements + cout << n << " Volume elements" << endl; + + for (i = 1; i <= n; i++) + { + VOLELEMENT el; + infile >> el.p1 >> el.p2 >> el.p3 >> el.p4; + volelements.Append (el); + } + + infile >> n; // number of points + cout << n << " Points" << endl; + + for (i = 1; i <= n; i++) + { + POINT3D p; + infile >> p.x >> p.y >> p.z; + points.Append (p); + } + } + + + +void ReadFileMesh (const Mesh & mesh) +{ + int i, n; + + n = mesh.GetNSE(); // number of surface elements + cout << n << " Surface elements" << endl; + + for (i = 1; i <= n; i++) + { + SURFELEMENT sel; + const Element2d & el = mesh.SurfaceElement(i); + sel.snr = el.GetIndex(); + sel.p1 = el.PNum(1); + sel.p2 = el.PNum(2); + sel.p3 = el.PNum(3); + surfelements.Append (sel); + } + + n = mesh.GetNE(); // number of volume elements + cout << n << " Volume elements" << endl; + + for (i = 1; i <= n; i++) + { + VOLELEMENT el; + const Element & nel = mesh.VolumeElement(i); + el.p1 = nel.PNum(1); + el.p2 = nel.PNum(2); + el.p3 = nel.PNum(3); + el.p4 = nel.PNum(4); + // infile >> el.p1 >> el.p2 >> el.p3 >> el.p4; + volelements.Append (el); + } + + n = mesh.GetNP(); // number of points + cout << n << " Points" << endl; + + for (i = 1; i <= n; i++) + { + POINT3D p; + Point3d mp = mesh.Point(i); + p.x = mp.X(); + p.y = mp.Y(); + p.z = mp.Z(); + // infile >> p.x >> p.y >> p.z; + points.Append (p); + } + } + + + + +void Convert () + { + int i, j, facei, edgei; + INDEX_3 i3; + INDEX_2 i2; + + INDEX_3_HASHTABLE<int> faceindex(volelements.Size()/5 + 1); + INDEX_2_HASHTABLE<int> edgeindex(volelements.Size()/5 + 1); + + for (i = 1; i <= volelements.Size(); i++) + { + for (j = 1; j <= 4; j++) + { + switch (j) + { + case 1: + i3.I1() = volelements.Get(i).p2; + i3.I2() = volelements.Get(i).p3; + i3.I3() = volelements.Get(i).p4; + break; + case 2: + i3.I1() = volelements.Get(i).p1; + i3.I2() = volelements.Get(i).p3; + i3.I3() = volelements.Get(i).p4; + break; + case 3: + i3.I1() = volelements.Get(i).p1; + i3.I2() = volelements.Get(i).p2; + i3.I3() = volelements.Get(i).p4; + break; + case 4: + i3.I1() = volelements.Get(i).p1; + i3.I2() = volelements.Get(i).p2; + i3.I3() = volelements.Get(i).p3; + break; + default: + i3.I1()=i3.I2()=i3.I3()=0; + } + i3.Sort(); + if (faceindex.Used (i3)) + facei = faceindex.Get(i3); + else + { + FACE fa; + fa.p1 = i3.I1(); + fa.p2 = i3.I2(); + fa.p3 = i3.I3(); + facei = faces.Append (fa); + faceindex.Set (i3, facei); + } + + volelements.Elem(i).faces[j-1] = facei; + } + + } + + + for (i = 1; i <= faces.Size(); i++) + { + for (j = 1; j <= 3; j++) + { + switch (j) + { + case 1: + i2.I1() = faces.Get(i).p2; + i2.I2() = faces.Get(i).p3; + break; + case 2: + i2.I1() = faces.Get(i).p1; + i2.I2() = faces.Get(i).p3; + break; + case 3: + i2.I1() = faces.Get(i).p1; + i2.I2() = faces.Get(i).p2; + break; + default: + i2.I1()=i2.I2()=0; + } + if (i2.I1() > i2.I2()) swap (i2.I1(), i2.I2()); + if (edgeindex.Used (i2)) + edgei = edgeindex.Get(i2); + else + { + EDGE ed; + ed.p1 = i2.I1(); + ed.p2 = i2.I2(); + edgei = edges.Append (ed); + edgeindex.Set (i2, edgei); + } + + faces.Elem(i).edges[j-1] = edgei; + } + + } + + } + + +void WriteFile (ostream & outfile) + { + int i; + + outfile + << "#VERSION: 1.0" << endl + << "#PROGRAM: NETGEN" << endl + << "#EQN_TYPE: POISSON" << endl + << "#DIMENSION: 3D" << endl + << "#DEG_OF_FREE: 1" << endl + << "#DESCRIPTION: I don't know" << endl + << "##RENUM: not done" << endl + << "#USER: Kleinzen" << endl + << "DATE: 10.06.1996" << endl; + + outfile << "#HEADER: 8" << endl + << points.Size() << " " << edges.Size() << " " + << faces.Size() << " " << volelements.Size() << " 0 0 0 0" << endl; + + outfile << "#VERTEX: " << points.Size() << endl; + for (i = 1; i <= points.Size(); i++) + outfile << " " << i << " " << points.Get(i).x << " " << points.Get(i).y + << " " << points.Get(i).z << endl; + + outfile << "#EDGE: " << edges.Size() << endl; + for (i = 1; i <= edges.Size(); i++) + outfile << " " << i << " 1 " + << edges.Get(i).p1 << " " + << edges.Get(i).p2 + << " 0" << endl; + + outfile << "#FACE: " << faces.Size() << endl; + for (i = 1; i <= faces.Size(); i++) + outfile << " " << i << " 1 3 " + << faces.Get(i).edges[0] << " " + << faces.Get(i).edges[1] << " " + << faces.Get(i).edges[2] << endl; + + outfile << "#SOLID: " << volelements.Size() << endl; + for (i = 1; i <= volelements.Size(); i++) + outfile << " " << i << " 1 4 " + << volelements.Get(i).faces[0] << " " + << volelements.Get(i).faces[1] << " " + << volelements.Get(i).faces[2] << " " + << volelements.Get(i).faces[3] << endl; + + outfile << "#END_OF_DATA" << endl; + } + + +void WriteUserChemnitz (const Mesh & mesh, + const string & filename) +{ + ofstream outfile (filename.c_str()); + + ReadFileMesh (mesh); + Convert (); + + WriteFile (outfile); + cout << "Wrote Chemnitz standard file" << endl; +} +} diff --git a/contrib/Netgen/libsrc/linalg/Makefile b/contrib/Netgen/libsrc/linalg/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1fac5fdd0607be1783487e61166151265494fa69 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/Makefile @@ -0,0 +1,13 @@ +# +# Makefile for linear algebra library +# +src = densemat.cpp polynomial.cpp +# +lib = la +libpath = libsrc/linalg +# +# +include ../makefile.inc +# + + diff --git a/contrib/Netgen/libsrc/linalg/densemat.cpp b/contrib/Netgen/libsrc/linalg/densemat.cpp new file mode 100644 index 0000000000000000000000000000000000000000..762792f5c523031c9efd250b5ae545cc598280e3 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/densemat.cpp @@ -0,0 +1,1444 @@ +#include <mystdlib.h> + +#include <linalg.hpp> + + +namespace netgen +{ + DenseMatrix :: DenseMatrix () + { + data = NULL; + height = 0; + width = 0; + } + + DenseMatrix :: DenseMatrix (int h, int w) + { + if (!w) w = h; + width = w; + height = h; + if (h*w) + data = new double[h*w]; + else + data = 0; + + for (int i = 0 ; i < (h * w); i++) + data[i] = 0; + } + + /* + DenseMatrix :: DenseMatrix (int h, int w, const double * d) + : BaseMatrix (h, w) + { + int size = h * w; + int i; + + if (size) + { + data = new double[size]; + for (i = 0; i < size; i++) + data[i] = d[i]; + } + else + data = NULL; + } + */ + + DenseMatrix :: DenseMatrix (const DenseMatrix & m2) + { + data = NULL; height = width = 0; + SetSize (m2.Height(), m2.Width()); + memcpy (data, m2.data, sizeof(double) * Height() * Width()); + } + + DenseMatrix :: ~DenseMatrix () + { + delete [] data; + } + + + void DenseMatrix :: SetSize (int h, int w) + { + if (!w) w = h; + if (height == h && width == w) + return; + + height = h; + width = w; + + delete[] data; + + if (h*w) + data = new double[h*w]; + else + data = NULL; + } + + + /* +DenseMatrix & DenseMatrix :: operator= (const BaseMatrix & m2) + { + int i, j; + + SetSize (m2.Height(), m2.Width()); + + if (data) + for (i = 1; i <= Height(); i++) + for (j = 1; j <= Width(); j++) + Set (i, j, m2(i, j)); + else + (*myerr) << "DenseMatrix::Operator=: Matrix not allocated" << endl; + + return *this; + } + */ + + + DenseMatrix & DenseMatrix :: operator= (const DenseMatrix & m2) + { + SetSize (m2.Height(), m2.Width()); + + if (data) memcpy (data, m2.data, sizeof(double) * m2.Height() * m2.Width()); + return *this; + } + + + DenseMatrix & DenseMatrix :: operator+= (const DenseMatrix & m2) + { + int i; + double * p, * q; + + if (Height() != m2.Height() || Width() != m2.Width()) + { + (*myerr) << "DenseMatrix::Operator+=: Sizes don't fit" << endl; + return *this; + } + + if (data) + { + p = data; + q = m2.data; + for (i = Width() * Height(); i > 0; i--) + { + *p += *q; + p++; + q++; + } + } + else + (*myerr) << "DenseMatrix::Operator+=: Matrix not allocated" << endl; + + return *this; + } + + +DenseMatrix & DenseMatrix :: operator-= (const DenseMatrix & m2) + { + int i; + double * p, * q; + + if (Height() != m2.Height() || Width() != m2.Width()) + { + (*myerr) << "DenseMatrix::Operator-=: Sizes don't fit" << endl; + return *this; + } + + if (data) + { + p = data; + q = m2.data; + for (i = Width() * Height(); i > 0; i--) + { + *p -= *q; + p++; + q++; + } + } + else + (*myerr) << "DenseMatrix::Operator-=: Matrix not allocated" << endl; + + return *this; + } + + + + + /* +double & DenseMatrix :: operator() (int i, int j) +{ + if (i >= 1 && j >= 1 && i <= height && j <= width) + return Elem(i,j); + else (*myerr) << "DenseMatrix: index (" << i << "," << j << ") out of range (1.." + << height << ",1.." << width << ")\n"; + static double dummy = 0; + return dummy; +} + + double DenseMatrix :: operator() (int i, int j) const + { + if (i >= 1 && j >= 1 && i <= height && j <= width) + return Get(i,j); + else (*myerr) << "DenseMatrix: index (" << i << "," << j << ") out of range (1.." + << height << ",1.." << width << ")\n"; + + static double dummy = 0; + return dummy; + } + */ + +DenseMatrix & DenseMatrix :: operator= (double v) + { + int i; + double * p = data; + + if (data) + for (i = width*height; i > 0; i--, p++) + *p = v; + + return *this; + } + + + +DenseMatrix & DenseMatrix :: operator*= (double v) + { + int i; + double * p = data; + + if (data) + for (i = width*height; i > 0; i--, p++) + *p *= v; + + return *this; + } + + +double DenseMatrix :: Det () const + { + if (width != height) + { + (*myerr) << "DenseMatrix :: Det: width != height" << endl; + return 0; + } + + switch (width) + { + case 1: return Get(1, 1); + case 2: return Get(1) * Get(4) - Get(2) * Get(3); + + case 3: return Get(1) * Get(5) * Get(9) + + Get(2) * Get(6) * Get(7) + + Get(3) * Get(4) * Get(8) + - Get(1) * Get(6) * Get(8) + - Get(2) * Get(4) * Get(9) + - Get(3) * Get(5) * Get(7); + default: + { + (*myerr) << "Matrix :: Det: general size not implemented (size=" << width << ")" << endl; + return 0; + } + } + } + + +void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2) + { + // int i, j, k, n; + double det; + // DenseMatrix m1 = hm1; + + if (m1.width != m1.height) + { + (*myerr) << "CalcInverse: matrix not symmetric" << endl; + return; + } + if (m1.width != m2.width || m1.height != m2.height) + { + (*myerr) << "CalcInverse: dim(m2) != dim(m1)" << endl; + return; + } + + + if (m1.Width() <= 3) + { + det = m1.Det(); + if (det == 0) + { + (*myerr) << "CalcInverse: Matrix singular" << endl; + return; + } + + det = 1e0 / det; + switch (m1.width) + { + case 1: + { + m2.Set(1, 1, det); + return; + } + case 2: + { + m2.Set(1, 1, det * m1.Get(4)); + m2.Set(2, 2, det * m1.Get(1)); + m2.Set(1, 2, - det * m1.Get(2)); + m2.Set(2, 1, - det * m1.Get(3)); + return; + } + case 3: + { + m2.Set(1, 1, det * (m1.Get(5) * m1.Get(9) - m1.Get(6) * m1.Get(8))); + m2.Set(2, 1, -det * (m1.Get(4) * m1.Get(9) - m1.Get(6) * m1.Get(7))); + m2.Set(3, 1, det * (m1.Get(4) * m1.Get(8) - m1.Get(5) * m1.Get(7))); + + m2.Set(1, 2, -det * (m1.Get(2) * m1.Get(9) - m1.Get(3) * m1.Get(8))); + m2.Set(2, 2, det * (m1.Get(1) * m1.Get(9) - m1.Get(3) * m1.Get(7))); + m2.Set(3, 2, -det * (m1.Get(1) * m1.Get(8) - m1.Get(2) * m1.Get(7))); + + m2.Set(1, 3, det * (m1.Get(2) * m1.Get(6) - m1.Get(3) * m1.Get(5))); + m2.Set(2, 3, -det * (m1.Get(1) * m1.Get(6) - m1.Get(3) * m1.Get(4))); + m2.Set(3, 3, det * (m1.Get(1) * m1.Get(5) - m1.Get(2) * m1.Get(4))); + return; + } + } + } + + else + { + int i, j, k, n; + n = m1.Height(); + + +#ifdef CHOL + int dots = (n > 200); + + // Cholesky + + double x; + Vector p(n); + + m2 = m1; + /* + m2.SetSymmetric(); + if (!m2.Symmetric()) + cerr << "m should be symmetric for Cholesky" << endl; + */ + + for (i = 1; i <= n; i++) + for (j = 1; j < i; j++) + m2.Elem(j, i) = m2.Get(i, j); + + for (i = 1; i <= n; i++) + { + if (dots && i % 10 == 0) + (*mycout) << "." << flush; + + for (j = i; j <= n; j++) + { + x = m2.Get(i, j); + + const double * pik = &m2.Get(i, 1); + const double * pjk = &m2.Get(j, 1); + + for (k = i-2; k >= 0; --k, ++pik, ++pjk) + x -= (*pik) * (*pjk); + + // for (k = i-1; k >= 1; --k) + // x -= m2.Get(j, k) * m2.Get(i, k); + + if (i == j) + { + if (x <= 0) + { + cerr << "Matrix indefinite 1" << endl; + return; + } + + p.Elem(i) = 1 / sqrt(x); + } + else + { + m2.Elem(j, i) = x * p.Get(i); + } + } + } + + for (i = 1; i <= n; i++) + m2.Elem(i, i) = 1 / p.Get(i); + + // check: A = L L^t + +// for (i = 1; i <= n; i++) +// for (j = 1; j <= n; j++) +// { +// x = 0; +// for (k = 1; k <= i && k <= j; k++) +// x += m2.Get(i, k) * m2.Get(j, k); +// (*testout) << "err " << i << "," << j << " = " << (m1.Get(i, j) - x) << endl; +// } + + + + // calc L^{-1}, store upper triangle + + // DenseMatrix hm(n); + // hm = m2; + + for (i = 1; i <= n; i++) + { + if (dots && i % 10 == 0) + (*mycout) << "+" << flush; + + for (j = i; j <= n; j++) + { + x = 0; + if (j == i) x = 1; + + const double * pjk = &m2.Get(j, i); + const double * pik = &m2.Get(i, i); + for (k = i; k < j; k++, ++pjk, ++pik) + x -= *pik * *pjk; + + // for (k = i; k < j; k++) + // x -= m2.Get(j, k) * m2.Get(i, k); + + m2.Elem(i, j) = x / m2.Get(j, j); + } + } + +// (*testout) << "check L^-1" << endl; +// for (i = 1; i <= n; i++) +// for (j = 1; j <= n; j++) +// { +// x = 0; +// for (k = j; k <= i; k++) +// x += hm.Get(i, k) * m2.Get(j, k); +// (*testout) << "i, j = " << i << "," << j << " x = " << x << endl; +// } + + + // calc A^-1 = L^-T * L^-1 + + for (i = 1; i <= n; i++) + { + if (dots && i % 10 == 0) + (*mycout) << "-" << flush; + + for (j = 1; j <= i; j++) + { + x = 0; + k = i; + if (j > i) k = j; + + const double * pik = &m2.Get(i, k); + const double * pjk = &m2.Get(j, k); + + for ( ; k <= n; ++k, ++pik, ++pjk) + x += *pik * *pjk; + // for ( ; k <= n; k++) + // x += m2.Get(i, k) * m2.Get(j, k); + + m2.Elem(i, j) = x; + } + } + + for (i = 1; i <= n; i++) + for (j = 1; j < i; j++) + m2.Elem(j, i) = m2.Get(i, j); + + if (dots) (*mycout) << endl; +#endif + + + + // Gauss - Jordan - algorithm + + int r, hi; + double max, hr; + + + ARRAY<int> p(n); // pivot-permutation + Vector hv(n); + + + m2 = m1; + + /* + if (m2.Symmetric()) + for (i = 1; i <= n; i++) + for (j = 1; j < i; j++) + m2.Elem(j, i) = m2.Get(i, j); + */ + + // Algorithm of Stoer, Einf. i. d. Num. Math, S 145 + + for (j = 1; j <= n; j++) + p.Set(j, j); + + for (j = 1; j <= n; j++) + { + // pivot search + + max = fabs(m2.Get(j, j)); + r = j; + + for (i = j+1; i <= n ;i++) + if (fabs (m2.Get(i, j)) > max) + { + r = i; + max = fabs (m2.Get(i, j)); + } + + if (max < 1e-20) + { + cerr << "Inverse matrix: matrix singular" << endl; + return; + } + + r = j; + + // exchange rows + if (r > j) + { + for (k = 1; k <= n; k++) + { + hr = m2.Get(j, k); + m2.Elem(j, k) = m2.Get(r, k); + m2.Elem(r, k) = hr; + } + hi = p.Get(j); + p.Elem(j) = p.Get(r); + p.Elem(r) = hi; + } + + + // transformation + + hr = 1 / m2.Get(j, j); + for (i = 1; i <= n; i++) + m2.Elem(i, j) *= hr; + m2.Elem(j, j) = hr; + + for (k = 1; k <= n; k++) + if (k != j) + { + for (i = 1; i <= n; i++) + if (i != j) + m2.Elem(i, k) -= m2.Elem(i, j) * m2.Elem(j, k); + m2.Elem(j, k) *= -hr; + } + } + + // col exchange + + for (i = 1; i <= n; i++) + { + for (k = 1; k <= n; k++) + hv.Elem(p.Get(k)) = m2.Get(i, k); + for (k = 1; k <= n; k++) + m2.Elem(i, k) = hv.Get(k); + } + + + + /* + if (m1.Symmetric()) + for (i = 1; i <= n; i++) + for (j = 1; j < i; j++) + m1.Elem(j, i) = m1.Get(i, j); + + m2 = 0; + + for (i = 1; i <= n; i++) + m2.Elem(i, i) = 1; + + for (i = 1; i <= n; i++) + { + // (*mycout) << '.' << flush; + q = m1.Get(i, i); + for (k = 1; k <= n; k++) + { + m1.Elem(i, k) /= q; + m2.Elem(i, k) /= q; + } + + for (j = i+1; j <= n; j++) + { + q = m1.Elem(j, i); + + double * m1pi = &m1.Elem(i, i); + double * m1pj = &m1.Elem(j, i); + + for (k = n; k >= i; --k, ++m1pi, ++m1pj) + *m1pj -= q * (*m1pi); + + double * m2pi = &m2.Elem(i, 1); + double * m2pj = &m2.Elem(j, 1); + + for (k = i; k > 0; --k, ++m2pi, ++m2pj) + *m2pj -= q * (*m2pi); + + // for (k = 1; k <= n; k++) + // { + // m1.Elem(j, k) -= q * m1.Elem(i, k); + // m2.Elem(j, k) -= q * m2.Elem(i, k); + // } + + } + } + + for (i = n; i >= 1; i--) + { + // (*mycout) << "+" << flush; + for (j = 1; j < i; j++) + { + q = m1.Elem(j, i); + + double * m2pi = &m2.Elem(i, 1); + double * m2pj = &m2.Elem(j, 1); + + for (k = n; k > 0; --k, ++m2pi, ++m2pj) + *m2pj -= q * (*m2pi); + + + // for (k = 1; k <= n; k++) + // { + // m1.Elem(j, k) -= q * m1.Elem(i, k); + // m2.Elem(j, k) -= q * m2.Elem(i, k); + // } + } + } + + if (m2.Symmetric()) + { + for (i = 1; i <= n; i++) + for (j = 1; j < i; j++) + m2.Elem(i, j) = m2.Elem(j, i); + } +*/ + } + } + + +void CalcAAt (const DenseMatrix & a, DenseMatrix & m2) + { + int n1 = a.Height(); + int n2 = a.Width(); + int i, j, k; + double sum; + const double *p, *q, *p0; + + if (m2.Height() != n1 || m2.Width() != n1) + { + (*myerr) << "CalcAAt: sizes don't fit" << endl; + return; + } + + for (i = 1; i <= n1; i++) + { + sum = 0; + p = &a.ConstElem(i, 1); + for (k = 1; k <= n2; k++) + { + sum += *p * *p; + p++; + } + m2.Set(i, i, sum); + + p0 = &a.ConstElem(i, 1); + q = a.data; + for (j = 1; j < i; j++) + { + sum = 0; + p = p0; + + for (k = 1; k <= n2; k++) + { + sum += *p * *q; + p++; + q++; + } + m2.Set(i, j, sum); + m2.Set(j, i, sum); + } + } + } + + + +#ifdef ABC +BaseMatrix * DenseMatrix :: InverseMatrix (const BitArray * /* inner */) const +{ + if (Height() != Width()) + { + (*myerr) << "BaseMatrix::InverseMatrix(): Matrix not symmetric" << endl; + return new DenseMatrix(1); + } + else + { + if (Symmetric()) + { + (*mycout) << "Invmat not available" << endl; + BaseMatrix * invmat = NULL; + return invmat; + } + + DenseMatrix * invmat = new DenseMatrix (Height()); + + CalcInverse (*this, *invmat); + return invmat; + } +} +#endif + + + +void CalcAtA (const DenseMatrix & a, DenseMatrix & m2) + { + int n1 = a.Height(); + int n2 = a.Width(); + int i, j, k; + double sum; + + if (m2.Height() != n2 || m2.Width() != n2) + { + (*myerr) << "CalcAtA: sizes don't fit" << endl; + return; + } + + for (i = 1; i <= n2; i++) + for (j = 1; j <= n2; j++) + { + sum = 0; + for (k = 1; k <= n1; k++) + sum += a.Get(k, i) * a.Get(k, j); + m2.Elem(i, j) = sum; + } + } + + + + + + +void CalcABt (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2) + { + int n1 = a.Height(); + int n2 = a.Width(); + int n3 = b.Height(); + int i, j, k; + double sum; + + if (m2.Height() != n1 || m2.Width() != n3 || b.Width() != n2) + { + (*myerr) << "CalcABt: sizes don't fit" << endl; + return; + } + + double * pm2 = &m2.Elem(1, 1); + const double * pa1 = &a.Get(1, 1); + + for (i = 1; i <= n1; i++) + { + const double * pb = &b.Get(1, 1); + for (j = 1; j <= n3; j++) + { + sum = 0; + const double * pa = pa1; + + for (k = 1; k <= n2; k++) + { + sum += *pa * *pb; + pa++; pb++; + } + + *pm2 = sum; + pm2++; + } + pa1 += n2; + } + } + + +void CalcAtB (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2) + { + int n1 = a.Height(); + int n2 = a.Width(); + int n3 = b.Width(); + int i, j, k; + + if (m2.Height() != n2 || m2.Width() != n3 || b.Height() != n1) + { + (*myerr) << "CalcAtB: sizes don't fit" << endl; + return; + } + + for (i = 1; i <= n2 * n3; i++) + m2.data[i-1] = 0; + + for (i = 1; i <= n1; i++) + for (j = 1; j <= n2; j++) + { + const double va = a.Get(i, j); + double * pm2 = &m2.Elem(j, 1); + const double * pb = &b.Get(i, 1); + + for (k = 1; k <= n3; ++k, ++pm2, ++pb) + *pm2 += va * *pb; + // for (k = 1; k <= n3; k++) + // m2.Elem(j, k) += va * b.Get(i, k); + } + /* + for (i = 1; i <= n2; i++) + for (j = 1; j <= n3; j++) + { + sum = 0; + for (k = 1; k <= n1; k++) + sum += a.Get(k, i) * b.Get(k, j); + m2.Elem(i, j) = sum; + } + */ + } + + + + + + + +DenseMatrix operator* (const DenseMatrix & m1, const DenseMatrix & m2) + { + DenseMatrix temp (m1.Height(), m2.Width()); + + if (m1.Width() != m2.Height()) + { + (*myerr) << "DenseMatrix :: operator*: Matrix Size does not fit" << endl; + } + else if (temp.Height() != m1.Height()) + { + (*myerr) << "DenseMatrix :: operator*: temp not allocated" << endl; + } + else + { + Mult (m1, m2, temp); + } + return temp; + } + + +void Mult (const DenseMatrix & m1, const DenseMatrix & m2, DenseMatrix & m3) + { + double sum; + double *p1, *p1s, *p1sn, *p1snn, *p2, *p2s, *p2sn, *p3; + + if (m1.Width() != m2.Height() || m1.Height() != m3.Height() || + m2.Width() != m3.Width() ) + { + (*myerr) << "DenseMatrix :: Mult: Matrix Size does not fit" << endl; + (*myerr) << "m1: " << m1.Height() << " x " << m1.Width() << endl; + (*myerr) << "m2: " << m2.Height() << " x " << m2.Width() << endl; + (*myerr) << "m3: " << m3.Height() << " x " << m3.Width() << endl; + return; + } + /* + else if (m1.Symmetric() || m2.Symmetric() || m3.Symmetric()) + { + (*myerr) << "DenseMatrix :: Mult: not implemented for symmetric matrices" << endl; + return; + } + */ + else + { + // int i, j, k; + int n1 = m1.Height(); + int n2 = m2.Width(); + int n3 = m1.Width(); + + /* + for (i = n1 * n2-1; i >= 0; --i) + m3.data[i] = 0; + + const double * pm1 = &m1.Get(1, 1); + for (i = 1; i <= n1; i++) + { + const double * pm2 = &m2.Get(1, 1); + double * pm3i = &m3.Elem(i, 1); + + for (j = 1; j <= n3; j++) + { + const double vm1 = *pm1; + ++pm1; + // const double vm1 = m1.Get(i, j); + double * pm3 = pm3i; + // const double * pm2 = &m2.Get(j, 1); + + for (k = 0; k < n2; k++) + { + *pm3 += vm1 * *pm2; + ++pm2; + ++pm3; + } + + // for (k = 1; k <= n2; k++) + // m3.Elem(i, k) += m1.Get(i, j) * m2.Get(j, k); + } + } + */ + + /* + for (i = 1; i <= n1; i++) + for (j = 1; j <= n2; j++) + { + sum = 0; + for (k = 1; k <= n3; k++) + sum += m1.Get(i, k) * m2.Get(k, j); + m3.Set(i, j, sum); + } + */ + + + /* + for (i = 1; i <= n1; i++) + { + const double pm1i = &m1.Get(i, 1); + const double pm2j = &m2.Get(1, 1); + + for (j = 1; j <= n2; j++) + { + double sum = 0; + const double * pm1 = pm1i; + const double * pm2 = pm2j; + pm2j++; + + for (k = 1; k <= n3; k++) + { + sum += *pm1 * *pm2; + ++pm1; + pm2 += n2; + } + + m3.Set (i, j, sum); + } + } + */ + + + p3 = m3.data; + p1s = m1.data; + p2sn = m2.data + n2; + p1snn = p1s + n1 * n3; + + while (p1s != p1snn) + { + p1sn = p1s + n3; + p2s = m2.data; + + while (p2s != p2sn) + { + sum = 0; + p1 = p1s; + p2 = p2s; + p2s++; + + while (p1 != p1sn) + { + sum += *p1 * *p2; + p1++; + p2 += n2; + } + *p3++ = sum; + } + p1s = p1sn; + } + } + } + + + +DenseMatrix operator+ (const DenseMatrix & m1, const DenseMatrix & m2) + { + DenseMatrix temp (m1.Height(), m1.Width()); + int i, j; + + if (m1.Width() != m2.Width() || m1.Height() != m2.Height()) + { + (*myerr) << "BaseMatrix :: operator+: Matrix Size does not fit" << endl; + } + else if (temp.Height() != m1.Height()) + { + (*myerr) << "BaseMatrix :: operator+: temp not allocated" << endl; + } + else + { + for (i = 1; i <= m1.Height(); i++) + for (j = 1; j <= m1.Width(); j++) + { + temp.Set(i, j, m1.Get(i, j) + m2.Get(i, j)); + } + } + return temp; + } + + + + +void Transpose (const DenseMatrix & m1, DenseMatrix & m2) +{ + int w = m1.Width(); + int h = m1.Height(); + int i, j; + + m2.SetSize (w, h); + + double * pm2 = &m2.Elem(1, 1); + for (j = 1; j <= w; j++) + { + const double * pm1 = &m1.Get(1, j); + for (i = 1; i <= h; i++) + { + *pm2 = *pm1; + pm2 ++; + pm1 += w; + } + } +} + + +/* +void DenseMatrix :: Mult (const Vector & v, Vector & prod) const + { + double sum, val; + const double * mp, * sp; + double * dp; + // const Vector & v = bv.CastToVector(); + // Vector & prod = bprod.CastToVector(); + + + int n = Height(); + int m = Width(); + + if (prod.Size() != n) + prod.SetSize (n); + +#ifdef DEVELOP + if (!n) + { + cout << "DenseMatrix::Mult mheight = 0" << endl; + } + if (!m) + { + cout << "DenseMatrix::Mult mwidth = 0" << endl; + } + + if (m != v.Size()) + { + (*myerr) << "\nMatrix and Vector don't fit" << endl; + } + else if (Height() != prod.Size()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else +#endif + { + if (Symmetric()) + { + int i, j; + + + for (i = 1; i <= n; i++) + { + sp = &v.Get(1); + dp = &prod.Elem(1); + mp = &Get(i, 1); + + val = v.Get(i); + sum = Get(i, i) * val; + + for (j = 1; j < i; ++j, ++mp, ++sp, ++dp) + { + sum += *mp * *sp; + *dp += val * *mp; + } + + prod.Elem(i) = sum; + } + } + else + { + mp = data; + dp = &prod.Elem(1); + for (int i = 1; i <= n; i++) + { + sum = 0; + sp = &v.Get(1); + + for (int j = 1; j <= m; j++) + { + // sum += Get(i,j) * v.Get(j); + sum += *mp * *sp; + mp++; + sp++; + } + + // prod.Set (i, sum); + *dp = sum; + dp++; + } + } + } + } +*/ + +void DenseMatrix :: MultTrans (const Vector & v, Vector & prod) const +{ + // const Vector & v = (const Vector&)bv; // .CastToVector(); + // Vector & prod = (Vector & )bprod; // .CastToVector(); + + /* + if (Height() != v.Size()) + { + (*myerr) << "\nMatrix and Vector don't fit" << endl; + } + else if (Width() != prod.Size()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else + */ + { + int i, j; + int w = Width(), h = Height(); + if (prod.Size() != w) + prod.SetSize (w); + + const double * pmat = &Get(1, 1); + const double * pv = &v.Get(1); + + prod = 0; + + for (i = 1; i <= h; i++) + { + double val = *pv; + ++pv; + + double * pprod = &prod.Elem(1); + + for (j = w-1; j >= 0; --j, ++pmat, ++pprod) + { + *pprod += val * *pmat; + } + } + + /* + double sum; + + for (i = 1; i <= Width(); i++) + { + sum = 0; + + for (int j = 1; j <= Height(); j++) + sum += Get(j, i) * v.Get(j); + + prod.Set (i, sum); + } + */ + } + } + + +void DenseMatrix :: Residuum (const Vector & x, const Vector & b, + Vector & res) const + { + double sum; + // const Vector & x = bx.CastToVector(); + // const Vector & b = bb.CastToVector(); + // Vector & res = bres.CastToVector(); + + res.SetSize (Height()); + + if (Width() != x.Size() || Height() != b.Size()) + { + (*myerr) << "\nMatrix and Vector don't fit" << endl; + } + else if (Height() != res.Size()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else + { + int i, j; + int h = Height(); + int w = Width(); + const double * mp = &Get(1, 1); + + for (i = 1; i <= h; i++) + { + sum = b.Get(i); + const double * xp = &x.Get(1); + + for (j = 1; j <= w; ++j, ++mp, ++xp) + sum -= *mp * *xp; + + res.Elem(i) = sum; + } + } + } + +#ifdef ABC +double DenseMatrix :: EvaluateBilinearform (const Vector & hx) const + { + double sum = 0, hsum; + // const Vector & hx = x.CastToVector(); + int i, j; + + if (Width() != hx.Size() || Height() != hx.Size()) + { + (*myerr) << "Matrix::EvaluateBilinearForm: sizes don't fit" << endl; + } + else + { + for (i = 1; i <= Height(); i++) + { + hsum = 0; + for (j = 1; j <= Height(); j++) + { + hsum += Get(i, j) * hx.Get(j); + } + sum += hsum * hx.Get(i); + } + } + +// testout << "sum = " << sum << endl; + return sum; + } + + +void DenseMatrix :: MultElementMatrix (const ARRAY<int> & pnum, + const Vector & hx, Vector & hy) + { + int i, j; + // const Vector & hx = x.CastToVector(); + // Vector & hy = y.CastToVector(); + + if (Symmetric()) + { + for (i = 1; i <= Height(); i++) + { + for (j = 1; j < i; j++) + { + hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j)); + hy.Elem(pnum.Get(j)) += Get(i, j) * hx.Get(pnum.Get(i)); + } + hy.Elem(pnum.Get(j)) += Get(i, i) * hx.Get(pnum.Get(i)); + } + } + else + for (i = 1; i <= Height(); i++) + for (j = 1; j <= Width(); j++) + hy.Elem(pnum.Get(i)) += Get(i, j) * hx.Get(pnum.Get(j)); + + } + +void DenseMatrix :: MultTransElementMatrix (const ARRAY<int> & pnum, + const Vector & hx, Vector & hy) + { + int i, j; + // const Vector & hx = x.CastToVector(); + // Vector & hy = y.CastToVector(); + + if (Symmetric()) + MultElementMatrix (pnum, hx, hy); + else + for (i = 1; i <= Height(); i++) + for (j = 1; j <= Width(); j++) + hy.Elem(pnum.Get(i)) += Get(j, i) * hx.Get(pnum.Get(j)); + } +#endif + + +void DenseMatrix :: Solve (const Vector & v, Vector & sol) const +{ + DenseMatrix temp (*this); + temp.SolveDestroy (v, sol); +} + + +void DenseMatrix :: SolveDestroy (const Vector & v, Vector & sol) + { + double q; + + if (Width() != Height()) + { + (*myerr) << "SolveDestroy: Matrix not square"; + return; + } + if (Width() != v.Size()) + { + (*myerr) << "SolveDestroy: Matrix and Vector don't fit"; + return; + } + + sol = v; + if (Height() != sol.Size()) + { + (*myerr) << "SolveDestroy: Solution Vector not ok"; + return; + } + + + if (0 /* Symmetric() */) + { + + // Cholesky factorization + + int i, j, k, n; + n = Height(); + + // Cholesky + + double x; + Vector p(n); + + for (i = 1; i <= n; i++) + for (j = 1; j < i; j++) + Elem(j, i) = Get(i, j); + + for (i = 1; i <= n; i++) + { + // (*mycout) << "." << flush; + for (j = i; j <= n; j++) + { + x = Get(i, j); + + const double * pik = &Get(i, 1); + const double * pjk = &Get(j, 1); + + for (k = i-2; k >= 0; --k, ++pik, ++pjk) + x -= (*pik) * (*pjk); + + // for (k = i-1; k >= 1; --k) + // x -= Get(j, k) * Get(i, k); + + if (i == j) + { + if (x <= 0) + { + cerr << "Matrix indefinite" << endl; + return; + } + + p.Elem(i) = 1 / sqrt(x); + } + else + { + Elem(j, i) = x * p.Get(i); + } + } + } + + for (i = 1; i <= n; i++) + Elem(i, i) = 1 / p.Get(i); + + // A = L L^t + // L stored in left-lower triangle + + + sol = v; + + // Solve L sol = sol + + for (i = 1; i <= n; i++) + { + double val = sol.Get(i); + + const double * pij = &Get(i, 1); + const double * solj = &sol.Get(1); + + for (j = 1; j < i; j++, ++pij, ++solj) + val -= *pij * *solj; + // for (j = 1; j < i; j++) + // val -= Get(i, j) * sol.Get(j); + + sol.Elem(i) = val / Get(i, i); + } + + // Solve L^t sol = sol + + for (i = n; i >= 1; i--) + { + double val = sol.Get(i) / Get(i, i); + sol.Elem(i) = val; + + double * solj = &sol.Elem(1); + const double * pij = &Get(i, 1); + + for (j = 1; j < i; ++j, ++pij, ++solj) + *solj -= val * *pij; + // for (j = 1; j < i; j++) + // sol.Elem(j) -= Get(i, j) * val; + } + + + } + else + { + // (*mycout) << "gauss" << endl; + int i, j, k, n = Height(); + for (i = 1; i <= n; i++) + { + for (j = i+1; j <= n; j++) + { + q = Get(j,i) / Get(i,i); + if (q) + { + const double * pik = &Get(i, i+1); + double * pjk = &Elem(j, i+1); + + for (k = i+1; k <= n; ++k, ++pik, ++pjk) + *pjk -= q * *pik; + + // for (k = i+1; k <= Height(); k++) + // Elem(j, k) -= q * Get(i,k); + + + sol.Elem(j) -= q * sol.Get(i); + } + } + } + + for (i = n; i >= 1; i--) + { + q = sol.Get(i); + for (j = i+1; j <= n; j++) + q -= Get(i,j) * sol.Get(j); + + sol.Elem(i) = q / Get(i,i); + } + } + } + + +/* +BaseMatrix * DenseMatrix :: Copy () const + { + return new DenseMatrix (*this); + } +*/ + + + + +ostream & operator<< (ostream & ost, const DenseMatrix & m) +{ + for (int i = 0; i < m.Height(); i++) + { + for (int j = 0; j < m.Width(); j++) + ost << m.Get(i+1,j+1) << " "; + ost << endl; + } + return ost; +} + + + +} diff --git a/contrib/Netgen/libsrc/linalg/densemat.hpp b/contrib/Netgen/libsrc/linalg/densemat.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a63d5a875751b55fb97b008ef4e78230aec2b418 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/densemat.hpp @@ -0,0 +1,284 @@ +#ifndef FILE_DENSEMAT +#define FILE_DENSEMAT + +/**************************************************************************/ +/* File: densemat.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/**************************************************************************/ + +/** + Data type dense matrix +*/ + + +#include <assert.h> + + +class DenseMatrix +{ +protected: + int height; + int width; + double * data; + +public: + /// + DenseMatrix (); + /// + DenseMatrix (int h, int w = 0); + /// + DenseMatrix (const DenseMatrix & m2); + /// + ~DenseMatrix (); + + /// + void SetSize (int h, int w = 0); + + int Height() const { return height; } + int Width() const {return width; } + + double & operator() (int i, int j) { return data[i*width+j]; } + double operator() (int i, int j) const { return data[i*width+j]; } + double & operator() (int i) { return data[i]; } + double operator() (int i) const { return data[i]; } + + /// + DenseMatrix & operator= (const DenseMatrix & m2); + /// + DenseMatrix & operator+= (const DenseMatrix & m2); + /// + DenseMatrix & operator-= (const DenseMatrix & m2); + + /// + DenseMatrix & operator= (double v); + /// + DenseMatrix & operator*= (double v); + + /// + void Mult (const FlatVector & v, FlatVector & prod) const + { + double sum; + const double * mp, * sp; + double * dp; + +#ifdef DEBUG + if (prod.Size() != height) + { + cerr << "Mult: wrong vector size " << endl; + assert (1); + // prod.SetSize (height); + } + + + if (!height) + { + cout << "DenseMatrix::Mult height = 0" << endl; + } + if (!width) + { + cout << "DenseMatrix::Mult width = 0" << endl; + } + + if (width != v.Size()) + { + (*myerr) << "\nMatrix and Vector don't fit" << endl; + } + else if (Height() != prod.Size()) + { + (*myerr) << "Base_Matrix::operator*(Vector): prod vector not ok" << endl; + } + else +#endif + { + mp = data; + dp = &prod.Elem(1); + for (int i = 1; i <= height; i++) + { + sum = 0; + sp = &v.Get(1); + + for (int j = 1; j <= width; j++) + { + // sum += Get(i,j) * v.Get(j); + sum += *mp * *sp; + mp++; + sp++; + } + + *dp = sum; + dp++; + } + } + } + + /// + void MultTrans (const Vector & v, Vector & prod) const; + /// + void Residuum (const Vector & x, const Vector & b, Vector & res) const; + /// + double Det () const; + + /// + friend DenseMatrix operator* (const DenseMatrix & m1, const DenseMatrix & m2); + /// + friend DenseMatrix operator+ (const DenseMatrix & m1, const DenseMatrix & m2); + + /// + friend void Transpose (const DenseMatrix & m1, DenseMatrix & m2); + /// + friend void Mult (const DenseMatrix & m1, const DenseMatrix & m2, DenseMatrix & m3); + /// + friend void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2); + /// + friend void CalcAAt (const DenseMatrix & a, DenseMatrix & m2); + /// + friend void CalcAtA (const DenseMatrix & a, DenseMatrix & m2); + /// + friend void CalcABt (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2); + /// + friend void CalcAtB (const DenseMatrix & a, const DenseMatrix & b, DenseMatrix & m2); + /// + void Solve (const Vector & b, Vector & x) const; + /// + void SolveDestroy (const Vector & b, Vector & x); + /// + const double & Get(int i, int j) const { return data[(i-1)*width+j-1]; } + /// + const double & Get(int i) const { return data[i-1]; } + /// + void Set(int i, int j, double v) { data[(i-1)*width+j-1] = v; } + /// + double & Elem(int i, int j) { return data[(i-1)*width+j-1]; } + /// + const double & ConstElem(int i, int j) const { return data[(i-1)*width+j-1]; } +}; + + +extern ostream & operator<< (ostream & ost, const DenseMatrix & m); + + + +template <int WIDTH> +class MatrixFixWidth +{ +protected: + int height; + double * data; + +public: + /// + MatrixFixWidth () + { height = 0; data = 0; } + /// + MatrixFixWidth (int h) + { height = h; data = new double[WIDTH*height]; } + /// + ~MatrixFixWidth () + { delete [] data; } + + void SetSize (int h) + { + if (h != height) + { + delete data; + height = h; + data = new double[WIDTH*height]; + } + } + + /// + int Height() const { return height; } + + /// + int Width() const { return WIDTH; } + + /// + MatrixFixWidth & operator= (double v) + { + for (int i = 0; i < height*WIDTH; i++) + data[i] = v; + return *this; + } + + /// + void Mult (const FlatVector & v, FlatVector & prod) const + { + double sum; + const double * mp, * sp; + double * dp; + + /* + if (prod.Size() != height) + { + cerr << "MatrixFixWidth::Mult: wrong vector size " << endl; + assert (1); + } + */ + + mp = data; + dp = &prod[0]; + for (int i = 0; i < height; i++) + { + sum = 0; + sp = &v[0]; + + for (int j = 0; j < WIDTH; j++) + { + sum += *mp * *sp; + mp++; + sp++; + } + + *dp = sum; + dp++; + } + } + + double & operator() (int i, int j) + { return data[i*WIDTH+j]; } + + const double & operator() (int i, int j) const + { return data[i*WIDTH+j]; } + + + MatrixFixWidth & operator*= (double v) + { + if (data) + for (int i = 0; i < height*WIDTH; i++) + data[i] *= v; + return *this; + } + + + + const double & Get(int i, int j) const { return data[(i-1)*WIDTH+j-1]; } + /// + const double & Get(int i) const { return data[i-1]; } + /// + void Set(int i, int j, double v) { data[(i-1)*WIDTH+j-1] = v; } + /// + double & Elem(int i, int j) { return data[(i-1)*WIDTH+j-1]; } + /// + const double & ConstElem(int i, int j) const { return data[(i-1)*WIDTH+j-1]; } +}; + + +template <int WIDTH> +extern ostream & operator<< (ostream & ost, const MatrixFixWidth<WIDTH> & m) +{ + for (int i = 0; i < m.Height(); i++) + { + for (int j = 0; j < m.Width(); j++) + ost << m.Get(i+1,j+1) << " "; + ost << endl; + } + return ost; +}; + + + +extern void CalcInverse (const DenseMatrix & m1, DenseMatrix & m2); + + +#endif diff --git a/contrib/Netgen/libsrc/linalg/linalg.hpp b/contrib/Netgen/libsrc/linalg/linalg.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7be9b4adedc36945fd3ce917ae87352b0e8734cf --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/linalg.hpp @@ -0,0 +1,33 @@ +#ifndef FILE_LINALG +#define FILE_LINALG + +/* *************************************************************************/ +/* File: linalg.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/* *************************************************************************/ + +/* + + Data types for basic linear algebra + more data types are found in linalgl.hpp + + The basic concepts include the data types + + Vector + SparseMatrix + DenseMatrix + +*/ + + +#include "../include/myadt.hpp" +namespace netgen +{ +#include "vector.hpp" +#include "densemat.hpp" +#include "polynomial.hpp" +} +#endif + + diff --git a/contrib/Netgen/libsrc/linalg/polynomial.cpp b/contrib/Netgen/libsrc/linalg/polynomial.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f947e0a19124088c132db8acd5dc995174a22e62 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/polynomial.cpp @@ -0,0 +1,216 @@ +#include <mystdlib.h> +#include <linalg.hpp> + +namespace netgen +{ + +QuadraticPolynomial1V :: +QuadraticPolynomial1V (double ac, double acx, double acxx) +{ + c = ac; + cx = acx; + cxx = acxx; +} + +double QuadraticPolynomial1V :: +Value (double x) +{ + return c + cx * x + cxx * x * x; +} + +double QuadraticPolynomial1V :: MaxUnitInterval () +{ + // inner max + if (cxx < 0 && cx > 0 && cx < -2 * cxx) + { + return c - 0.25 * cx * cx / cxx; + } + + + if (cx + cxx > 0) // right edge + return c + cx + cxx; + + // left end + return c; +} + + + + +LinearPolynomial2V :: +LinearPolynomial2V (double ac, double acx, double acy) +{ + c = ac; + cx = acx; + cy = acy; +}; + + +QuadraticPolynomial2V :: +QuadraticPolynomial2V () +{ + ; +} + + +QuadraticPolynomial2V :: +QuadraticPolynomial2V (double ac, double acx, double acy, + double acxx, double acxy, double acyy) +{ + c = ac; + cx = acx; + cy = acy; + cxx = acxx; + cxy = acxy; + cyy = acyy; +} + +void QuadraticPolynomial2V :: +Square (const LinearPolynomial2V & lp) +{ + c = lp.c * lp.c; + cx = 2 * lp.c * lp.cx; + cy = 2 * lp.c * lp.cy; + + cxx = lp.cx * lp.cx; + cxy = 2 * lp.cx * lp.cy; + cyy = lp.cy * lp.cy; +} + +void QuadraticPolynomial2V :: +Add (double lam, const QuadraticPolynomial2V & qp2) +{ + c += lam * qp2.c; + cx += lam * qp2.cx; + cy += lam * qp2.cy; + cxx += lam * qp2.cxx; + cxy += lam * qp2.cxy; + cyy += lam * qp2.cyy; +} + +double QuadraticPolynomial2V :: +Value (double x, double y) +{ + return c + cx * x + cy * y + cxx * x * x + cxy * x * y + cyy * y * y; +} + +/* +double QuadraticPolynomial2V :: +MinUnitSquare () +{ + double x, y; + double minv = 1e8; + double val; + for (x = 0; x <= 1; x += 0.1) + for (y = 0; y <= 1; y += 0.1) + { + val = Value (x, y); + if (val < minv) + minv = val; + } + return minv; +}; +*/ + +double QuadraticPolynomial2V :: +MaxUnitSquare () +{ + // find critical point + + double maxv = c; + double hv; + + double det, x0, y0; + det = 4 * cxx * cyy - cxy * cxy; + + if (det > 0) + { + // definite surface + + x0 = (-2 * cyy * cx + cxy * cy) / det; + y0 = (cxy * cx -2 * cxx * cy) / det; + + if (x0 >= 0 && x0 <= 1 && y0 >= 0 && y0 <= 1) + { + hv = Value (x0, y0); + if (hv > maxv) maxv = hv; + } + } + + QuadraticPolynomial1V e1(c, cx, cxx); + QuadraticPolynomial1V e2(c, cy, cyy); + QuadraticPolynomial1V e3(c+cy+cyy, cx+cxy, cxx); + QuadraticPolynomial1V e4(c+cx+cxx, cy+cxy, cyy); + + hv = e1.MaxUnitInterval(); + if (hv > maxv) maxv = hv; + hv = e2.MaxUnitInterval(); + if (hv > maxv) maxv = hv; + hv = e3.MaxUnitInterval(); + if (hv > maxv) maxv = hv; + hv = e4.MaxUnitInterval(); + if (hv > maxv) maxv = hv; + + return maxv; + + // (*testout) << "maxv = " << maxv << " =~= "; + + /* + double x, y; + maxv = -1e8; + double val; + for (x = 0; x <= 1.01; x += 0.1) + for (y = 0; y <= 1.01; y += 0.1) + { + val = Value (x, y); + if (val > maxv) + maxv = val; + } + + // (*testout) << maxv << endl; + return maxv; + */ +}; + + + + +double QuadraticPolynomial2V :: +MaxUnitTriangle () +{ + // find critical point + + double maxv = c; + double hv; + + double det, x0, y0; + det = 4 * cxx * cyy - cxy * cxy; + + if (cxx < 0 && det > 0) + { + // definite surface + + x0 = (-2 * cyy * cx + cxy * cy) / det; + y0 = (cxy * cx -2 * cxx * cy) / det; + + if (x0 >= 0 && y0 >= 0 && x0+y0 <= 1) + { + return Value (x0, y0); + } + } + + + QuadraticPolynomial1V e1(c, cx, cxx); + QuadraticPolynomial1V e2(c, cy, cyy); + QuadraticPolynomial1V e3(c+cy+cyy, cx-cy+cxy-2*cyy, cxx-cxy+cyy); + + hv = e1.MaxUnitInterval(); + if (hv > maxv) maxv = hv; + hv = e2.MaxUnitInterval(); + if (hv > maxv) maxv = hv; + hv = e3.MaxUnitInterval(); + if (hv > maxv) maxv = hv; + + return maxv; +} +} diff --git a/contrib/Netgen/libsrc/linalg/polynomial.hpp b/contrib/Netgen/libsrc/linalg/polynomial.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3108d4dd729172bd644052524aab62f3d150576f --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/polynomial.hpp @@ -0,0 +1,45 @@ +#ifndef FILE_POLYNOMIAL +#define FILE_POLYNOMIAL + +/* *************************************************************************/ +/* File: polynomial.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 25. Nov. 99 */ +/* *************************************************************************/ + + +class QuadraticPolynomial1V +{ + double c, cx, cxx; +public: + QuadraticPolynomial1V (double ac, double acx, double acxx); + double Value (double x); + double MaxUnitInterval (); +}; + +class LinearPolynomial2V +{ + double c, cx, cy; +public: + LinearPolynomial2V (double ac, double acx, double acy); + friend class QuadraticPolynomial2V; +}; + + +class QuadraticPolynomial2V +{ + double c, cx, cy, cxx, cxy, cyy; +public: + QuadraticPolynomial2V (); + QuadraticPolynomial2V (double ac, double acx, double acy, + double acxx, double acxy, double acyy); + void Square (const LinearPolynomial2V & lp); + void Add (double lam, const QuadraticPolynomial2V & qp); + + double Value (double x, double y); + // double MinUnitSquare (); + double MaxUnitSquare (); + double MaxUnitTriangle (); +}; + +#endif diff --git a/contrib/Netgen/libsrc/linalg/vector.cpp b/contrib/Netgen/libsrc/linalg/vector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9dabda3669d6f4879de4999f3ef7d1317bcb45a --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/vector.cpp @@ -0,0 +1,786 @@ +#ifdef abc +#include <mystdlib.h> +#include <linalg.hpp> +#include <algorithm> + +namespace netgen +{ + +double BaseVector :: shit = 0; + +// %FD Constructs a vector of length zero +BaseVector :: BaseVector () + { + length = 0; + } + +// %FD Constructs a vector of given length +BaseVector :: BaseVector ( + INDEX alength // length of the vector + ) + { + length = alength; + } + +// %FD Sets length of the vector, old vector will be destroyed +void +BaseVector :: SetLength ( + INDEX alength // new length of the vector + ) + { + length = alength; + } + +// %FD Changes length of the vector, old values stay valid +void +BaseVector :: ChangeLength ( + INDEX alength // new length of the vector + ) + { + length = alength; + } + + + +// %FD { Write a vector with the help of the '<<' operator onto a stream } +ostream & // stream for further use +operator<< ( + ostream & s, // stream to write vector onto + const BaseVector & v // vector to write + ) + { + return v.Print (s); + } + + +// %FD{ Divides every component of the vector by the scalar c. +// The function checks for division by zero } +BaseVector & // result vector +BaseVector :: operator/= ( + double c // scalar to divide by + ) + { + if (c) + return (*this) *= (1/c); + else + { + (*myerr) << "operator/=: division by zero" << endl; + return *this; + } + } + + +// %FD Creates a copy of the object +BaseVector * // pointer to the new vector +BaseVector :: Copy () const + { + cerr << "Base_vector::Copy called" << endl << flush; + return NULL; + } + + + + +void BaseVector :: GetElementVector (const ARRAY<INDEX> & pnum, + BaseVector & elvec) const +{ + int i; + for (i = 1; i <= pnum.Size(); i++) + elvec(i) = (*this)(pnum.Get(i)); +} + +void BaseVector :: SetElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + for (i = 1; i <= pnum.Size(); i++) + (*this)(pnum.Get(i)) = elvec(i); +} + + +void BaseVector :: AddElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + for (i = 1; i <= pnum.Size(); i++) + (*this)(pnum.Get(i)) += elvec(i); +} + + + + + + + + + + + +TempVector :: ~TempVector () + { + delete vec; + } + +TempVector BaseVector :: operator+ (const BaseVector & v2) const + { + return (*Copy()) += v2; + } + +TempVector BaseVector :: operator- (const BaseVector & v2) const + { + return (*Copy()) -= v2; + } + +TempVector BaseVector :: operator- () const + { + return (*Copy()) *= -1; + } + + +TempVector operator* (const BaseVector & v1, double scal) + { + return (*v1.Copy()) *= scal; + } + +TempVector operator/ (const BaseVector & v1, double scal) + { + return (*v1.Copy()) /= scal; + } + + +TempVector operator* (double scal, const BaseVector & v1) + { + return v1 * scal; + } + + + + + +BaseVector * TempVector :: Copy () const + { + return vec->Copy(); + } + + + + + + + + + + +double Vector :: shit = 0; + +class clVecpool +{ +public: + ARRAY<double *> vecs; + ARRAY<INDEX> veclens; + + ~clVecpool(); +}; + +clVecpool :: ~clVecpool() +{ + int i; + for (i = 1; i <= vecs.Size(); i++) + delete vecs.Elem(i); +} + +static clVecpool vecpool; + + + +static double * NewDouble (INDEX len) +{ + if (len < 10) + return new double[len]; + else + { + int i; + for (i = 1; i <= vecpool.veclens.Size(); i++) + if (vecpool.veclens.Get(i) == len) + { + double * hvec = vecpool.vecs.Get(i); + vecpool.vecs.DeleteElement(i); + vecpool.veclens.DeleteElement(i); + return hvec; + } + + return new double[len]; + } +} + +static void DeleteDouble (INDEX len, double * dp) +{ + if (len < 10) + delete [] dp; + else + { + vecpool.vecs.Append (dp); + vecpool.veclens.Append (len); + } +} + + + +Vector :: Vector () : BaseVector() + { + data = NULL; + } + +Vector :: Vector (INDEX alength) : BaseVector (alength) + { + if (length) + { + // data = new double[length]; + data = NewDouble (length); + + if (!data) + { + length = 0; + (*myerr) << "Vector not allocated" << endl; + } + } + else + data = NULL; + } + + +Vector :: Vector (const Vector & v2) + { + length = v2.length; + + if (length) + { + // data = new double[length]; + data = NewDouble (length); + + if (data) + { + memcpy (data, v2.data, length * sizeof (double)); + } + else + { + length = 0; + (*myerr) << "Vector::Vector : Vector not allocated" << endl; + } + } + else + data = NULL; + } + + +Vector :: ~Vector () +{ + // veclenfile << "~Vector delete: " << length << endl; + if (data) + { + DeleteDouble (length, data); + // delete [] data; + } + +} + +void Vector :: SetLength (INDEX alength) + { + if (length == alength) return; + + if (data) + { + DeleteDouble (length, data); + // delete [] data; + } + data = NULL; + length = alength; + + if (length == 0) return; + // data = new double[length]; + data = NewDouble (length); + + if (!data) + { + length = 0; + (*myerr) << "Vector::SetLength: Vector not allocated" << endl; + } + } + +void Vector :: ChangeLength (INDEX alength) +{ + (*mycout) << "Vector::ChangeLength called" << endl; + if (length == alength) return; + + if (alength == 0) + { + // delete [] data; + DeleteDouble (length, data); + length = 0; + return; + } + + double * olddata = data; + + data = NewDouble (alength); + // data = new double[alength]; + if (!data) + { + length = 0; + (*myerr) << "Vector::SetLength: Vector not allocated" << endl; + delete [] olddata; + } + + memcpy (data, olddata, min2(alength, length)); + + delete [] olddata; + length = alength; + } + +/// NEW RM +void Vector::SetBlockLength (INDEX /* blength */) +{ + MyError("BaseVector::SetBlockLength was called for a Vector"); +} + + +double & Vector :: operator() (INDEX i) + { + if (i >= 1 && i <= length) return Elem(i); + else (*myerr) << "\nindex " << i << " out of range (" + << 1 << "," << Length() << ")\n"; + return shit; + } + +double Vector :: operator() (INDEX i) const + { + if (i >= 1 && i <= length) return Get(i); + else (*myerr) << "\nindex " << i << " out of range (" + << 1 << "," << Length() << ")\n" << flush; + return shit; + } + + + +double Vector :: SupNorm () const + { + double sup = 0; + + for (INDEX i = 1; i <= Length(); i++) + if (fabs (Get(i)) > sup) + sup = fabs(Get(i)); + + return sup; + } + +double Vector :: L2Norm () const + { + double sum = 0; + + for (INDEX i = 1; i <= Length(); i++) + sum += Get(i) * Get(i); + + return sqrt (sum); + } + +double Vector :: L1Norm () const + { + double sum = 0; + + for (INDEX i = 1; i <= Length(); i++) + sum += fabs (Get(i)); + + return sum; + } + +double Vector :: Max () const + { + if (!Length()) return 0; + double m = Get(1); + for (INDEX i = 2; i <= Length(); i++) + if (Get(i) > m) m = Get(i); + return m; + } + +double Vector :: Min () const + { + if (!Length()) return 0; + double m = Get(1); + for (INDEX i = 2; i <= Length(); i++) + if (Get(i) < m) m = Get(i); + return m; + } + + +/* +ostream & operator<<(ostream & s, const Vector & v) + { + int w = s.width(); + if (v.Length()) + { + s.width(0); + s << '('; + for (INDEX i = 1; i < v.Length(); i++) + { + s.width(w); + s << v.Get(i) << ","; + if (i % 8 == 0) s << endl << ' '; + } + s.width(w); + s << v.Get(v.Length()) << ')'; + } + else + s << "(Vector not allocated)"; + + return s; + } +*/ + +ostream & Vector :: Print (ostream & s) const + { + int w = s.width(); + if (Length()) + { + s.width(0); + s << '('; + for (INDEX i = 1; i < Length(); i++) + { + s.width(w); + s << Get(i) << ","; + if (i % 8 == 0) s << endl << ' '; + } + s.width(w); + s << Get(Length()) << ')'; + } + else + s << "(Vector not allocated)"; + + return s; + } + + + +BaseVector & Vector :: operator+= (const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + for (INDEX i = 1; i <= Length(); i++) + Elem (i) += hv2.Get(i); + else + (*myerr) << "operator+= illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: operator-= (const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + for (INDEX i = 1; i <= Length(); i++) + Elem (i) -= hv2.Get(i); + else + (*myerr) << "operator-= illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: operator*= (double c) + { + for (INDEX i = 1; i <= Length(); i++) + Elem(i) *= c; + return *this; + } + + + +BaseVector & Vector :: Add (double scal, const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) += scal * (*p2); + p1++; p2++; + } + } + else + (*myerr) << "Vector::Add: illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: Add2 (double scal, const BaseVector & v2, + double scal3, const BaseVector & v3) + { + const Vector & hv2 = v2.CastToVector(); + const Vector & hv3 = v3.CastToVector(); + + if (Length() == hv2.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + double * p3 = hv3.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) += (scal * (*p2) + scal3 * (*p3)); + p1++; p2++; p3++; + } + } + else + (*myerr) << "Vector::Add: illegal dimension" << endl; + return *this; + } + +BaseVector & Vector :: Set (double scal, const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + if (Length() == hv2.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) = scal * (*p2); + p1++; p2++; + } + } + else + (*myerr) << "Vector::Set: illegal dimension" << endl; + return *this; + } + + +BaseVector & Vector :: Set2 (double scal , const BaseVector & v2, + double scal3, const BaseVector & v3) +{ + const Vector & hv2 = v2.CastToVector(); + const Vector & hv3 = v3.CastToVector(); + + if (Length() == hv2.Length() && Length() == hv3.Length()) + { + double * p1 = data; + double * p2 = hv2.data; + double * p3 = hv3.data; + + for (INDEX i = Length(); i > 0; i--) + { + (*p1) = scal * (*p2) + scal3 * (*p3); + p1++; p2++; p3++; + } + } + else + (*myerr) << "Vector::Set: illegal dimension" << endl; + return *this; +} + + +void Vector :: GetPart (int startpos, BaseVector & v2) const +{ + Vector & hv2 = v2.CastToVector(); + + if (Length() >= startpos + v2.Length() - 1) + { + const double * p1 = &Get(startpos); + double * p2 = &hv2.Elem(1); + + memcpy (p2, p1, hv2.Length() * sizeof(double)); + } + else + MyError ("Vector::GetPart: Vector to short"); +} + + +// NEW RM +void Vector :: SetPart (int startpos, const BaseVector & v2) +{ + const Vector & hv2 = v2.CastToVector(); + INDEX i; + INDEX n = v2.Length(); + + if (Length() >= startpos + n - 1) + { + double * p1 = &Elem(startpos); + const double * p2 = &hv2.Get(1); + + for (i = 1; i <= n; i++) + { + (*p1) = (*p2); + p1++; + p2++; + } + } + else + MyError ("Vector::SetPart: Vector to short"); +} + +void Vector :: AddPart (int startpos, double val, const BaseVector & v2) +{ + const Vector & hv2 = v2.CastToVector(); + INDEX i; + INDEX n = v2.Length(); + + if (Length() >= startpos + n - 1) + { + double * p1 = &Elem(startpos); + const double * p2 = &hv2.Get(1); + + for (i = 1; i <= n; i++) + { + (*p1) += val * (*p2); + p1++; + p2++; + } + } + else + MyError ("Vector::AddPart: Vector to short"); +} + + + + +double Vector :: operator* (const BaseVector & v2) const + { + const Vector & hv2 = v2.CastToVector(); + + double sum = 0; + double * p1 = data; + double * p2 = hv2.data; + + if (Length() == hv2.Length()) + { + for (INDEX i = Length(); i > 0; i--) + { + sum += (*p1) * (*p2); + p1++; p2++; + } + } + else + (*myerr) << "Scalarproduct illegal dimension" << endl; + return sum; + } + +void Vector :: SetRandom () + { + INDEX i; + for (i = 1; i <= Length(); i++) + Elem(i) = rand (); + + double l2 = L2Norm(); + if (l2 > 0) + (*this) /= l2; + // Elem(i) = 1.0 / double(i); + // Elem(i) = drand48(); + } + + +/* +TempVector Vector :: operator- () const + { + Vector & sum = *(Vector*)Copy(); + + if (sum.Length () == Length()) + { + for (INDEX i = 1; i <= Length(); i++) + sum.Set (i, Get(i)); + } + else + (*myerr) << "operator+ (Vector, Vector): sum.Length() not ok" << endl; + return sum; + } +*/ + +BaseVector & Vector::operator= (const Vector & v2) + { + SetLength (v2.Length()); + + if (data == v2.data) return *this; + + if (v2.Length() == Length()) + memcpy (data, v2.data, sizeof (double) * Length()); + else + (*myerr) << "Vector::operator=: not allocated" << endl; + + return *this; + } + +BaseVector & Vector::operator= (const BaseVector & v2) + { + const Vector & hv2 = v2.CastToVector(); + + SetLength (hv2.Length()); + + if (data == hv2.data) return *this; + + if (hv2.Length() == Length()) + memcpy (data, hv2.data, sizeof (double) * Length()); + else + (*myerr) << "Vector::operator=: not allocated" << endl; + + return *this; + } + + +BaseVector & Vector::operator= (double scal) + { + if (!Length()) (*myerr) << "Vector::operator= (double) : data not allocated" + << endl; + + for (INDEX i = 1; i <= Length(); i++) + Set (i, scal); + + return *this; + } + + +BaseVector * Vector :: Copy () const + { + return new Vector (*this); + } + + +void Vector :: Swap (BaseVector & v2) + { + Vector & hv2 = v2.CastToVector(); + swap (length, hv2.length); + swap (data, hv2.data); + } + + + + +void Vector :: GetElementVector (const ARRAY<INDEX> & pnum, + BaseVector & elvec) const +{ + int i; + Vector & helvec = elvec.CastToVector(); + for (i = 1; i <= pnum.Size(); i++) + helvec.Elem(i) = Get(pnum.Get(i)); +} + +void Vector :: SetElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + const Vector & helvec = elvec.CastToVector(); + for (i = 1; i <= pnum.Size(); i++) + Elem(pnum.Get(i)) = helvec.Get(i); +} + + +void Vector :: AddElementVector (const ARRAY<INDEX> & pnum, + const BaseVector & elvec) +{ + int i; + const Vector & helvec = elvec.CastToVector(); + for (i = 1; i <= pnum.Size(); i++) + Elem(pnum.Get(i)) += helvec.Get(i); +} +} +#endif diff --git a/contrib/Netgen/libsrc/linalg/vector.hpp b/contrib/Netgen/libsrc/linalg/vector.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c6c2dcce30ad62a36abd84c5f81f8a2c65415891 --- /dev/null +++ b/contrib/Netgen/libsrc/linalg/vector.hpp @@ -0,0 +1,138 @@ +#ifndef FILE_VECTOR +#define FILE_VECTOR + +/* *************************************************************************/ +/* File: vector.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Oct. 94 */ +/* *************************************************************************/ + + +class FlatVector +{ +protected: + int s; + double *data; +public: + FlatVector () { ; } + FlatVector (int as, double * adata) + { s = as; data = adata; } + + int Size () const + { return s; } + + FlatVector & operator= (const FlatVector & v) + { memcpy (data, v.data, s*sizeof(double)); return *this; } + + FlatVector & operator= (double scal) + { + for (int i = 0; i < s; i++) data[i] = scal; + return *this; + } + + double & operator[] (int i) { return data[i]; } + const double & operator[] (int i) const { return data[i]; } + double & operator() (int i) { return data[i]; } + const double & operator() (int i) const { return data[i]; } + + double & Elem (int i) { return data[i-1]; } + const double & Get (int i) const { return data[i-1]; } + void Set (int i, double val) { data[i-1] = val; } + + FlatVector & operator*= (double scal) + { + for (int i = 0; i < s; i++) data[i] *= scal; + return *this; + } + + FlatVector & Add (double scal, const FlatVector & v2) + { + for (int i = 0; i < s; i++) + data[i] += scal * v2[i]; + return *this; + } + + FlatVector & Set (double scal, const FlatVector & v2) + { + for (int i = 0; i < s; i++) + data[i] = scal * v2[i]; + return *this; + } + + FlatVector & Set2 (double scal1, const FlatVector & v1, + double scal2, const FlatVector & v2) + { + for (int i = 0; i < s; i++) + data[i] = scal1 * v1[i] + scal2 * v2[i]; + return *this; + } + + double L2Norm() const + { + double sum = 0; + for (int i = 0; i < s; i++) + sum += data[i] * data[i]; + return sqrt (sum); + } + + friend double operator* (const FlatVector & v1, const FlatVector & v2); +}; + + + +class Vector : public FlatVector +{ + +public: + Vector () + { s = 0; data = 0; } + Vector (int as) + { s = as; data = new double[s]; } + ~Vector () + { delete [] data; } + + Vector & operator= (const FlatVector & v) + { memcpy (data, &v.Get(1), s*sizeof(double)); return *this; } + + Vector & operator= (double scal) + { + for (int i = 0; i < s; i++) data[i] = scal; + return *this; + } + + void SetSize (int as) + { + if (s != as) + { + s = as; + delete [] data; + data = new double [s]; + } + } + +}; + + +inline double operator* (const FlatVector & v1, const FlatVector & v2) +{ + double sum = 0; + for (int i = 0; i < v1.s; i++) + sum += v1.data[i] * v2.data[i]; + return sum; +} + + + + +inline ostream & operator<< (ostream & ost, const FlatVector & v) +{ + for (int i = 0; i < v.Size(); i++) + ost << " " << setw(7) << v[i]; + return ost; +} + + + +#endif + + diff --git a/contrib/Netgen/libsrc/makefile.inc b/contrib/Netgen/libsrc/makefile.inc new file mode 100644 index 0000000000000000000000000000000000000000..091210bc91fc8e56954fbeacda977965a39f3516 --- /dev/null +++ b/contrib/Netgen/libsrc/makefile.inc @@ -0,0 +1,19 @@ +# MODIFIED FOR GMSH - This replaces the original makefile.inc provided by Netgen + +include ../../../../variables + +INC = ${DASH}I../../../../Common ${DASH}I../include ${DASH}I../interface + +CFLAGS = ${OPTIM} ${FLAGS} ${INC} ${SYSINCLUDE} ${DASH}DNO_PARALLEL_THREADS + +OBJ = ${src:.cpp=${OBJEXT}} + +.SUFFIXES: ${OBJEXT} .cpp + +default: ${OBJ} + +.cpp${OBJEXT}: + ${CXX} ${CFLAGS} ${DASH}c $< + +clean: + ${RM} *.o *.obj diff --git a/contrib/Netgen/libsrc/meshing/Makefile b/contrib/Netgen/libsrc/meshing/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..22c86ee98629764a6a5c347cbcfe0ea29f57d9f6 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/Makefile @@ -0,0 +1,19 @@ +# MODIFIED FOR GMSH +src = meshclass.cpp adfront2.cpp adfront3.cpp geomsearch.cpp global.cpp \ + meshtool.cpp \ + netrule2.cpp netrule3.cpp parser2.cpp parser3.cpp ruler2.cpp ruler3.cpp \ + meshtype.cpp improve2.cpp smoothing2.5.cpp smoothing2.cpp improve3.cpp smoothing3.cpp \ + improve2gen.cpp meshing2.cpp meshing3.cpp \ + localh.cpp delaunay.cpp topology.cpp clusters.cpp \ + tetrarls.cpp triarls.cpp quadrls.cpp meshfunc.cpp meshfunc2d.cpp \ + refine.cpp bisect.cpp \ + boundarylayer.cpp specials.cpp msghandler.cpp \ + pyramidrls.cpp pyramid2rls.cpp prism2rls.cpp \ + curvedelems.cpp curvedelems2.cpp curvedelems_new.cpp \ + validate.cpp +# +lib = mesh +libpath = libsrc/meshing +# +include ../makefile.inc +# diff --git a/contrib/Netgen/libsrc/meshing/adfront2.cpp b/contrib/Netgen/libsrc/meshing/adfront2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37a7c385f6be371098865058c3cd0c3aa3db6ac0 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront2.cpp @@ -0,0 +1,466 @@ +/* + Advancing front class for surfaces +*/ + +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + AdFront2::FrontPoint2 :: FrontPoint2 (const Point<3> & ap, PointIndex agi, + MultiPointGeomInfo * amgi, bool aonsurface) + { + p = ap; + globalindex = agi; + nlinetopoint = 0; + frontnr = INT_MAX-10; + onsurface = aonsurface; + + if (amgi) + { + mgi = new MultiPointGeomInfo (*amgi); + for (int i = 1; i <= mgi->GetNPGI(); i++) + if (mgi->GetPGI(i).trignum <= 0) + cout << "Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl; + } + else + mgi = NULL; + } + + + AdFront2 :: AdFront2 (const Box3d & aboundingbox) + : boundingbox(aboundingbox), + linesearchtree(boundingbox.PMin(), boundingbox.PMax()), + pointsearchtree(boundingbox.PMin(), boundingbox.PMax()), + cpointsearchtree(boundingbox.PMin(), boundingbox.PMax()) + { + nfl = 0; + allflines = 0; + + minval = 0; + starti = lines.Begin(); + } + + AdFront2 :: ~AdFront2 () + { + delete allflines; + } + + + void AdFront2 :: PrintOpenSegments (ostream & ost) const + { + if (nfl > 0) + { + ost << nfl << " open front segments left:" << endl; + for (int i = lines.Begin(); i < lines.End(); i++) + if (lines[i].Valid()) + ost << i << ": " + << GetGlobalIndex (lines[i].L().I1()) << "-" + << GetGlobalIndex (lines[i].L().I2()) << endl; + } + } + + /* + void AdFront2 :: GetPoints (ARRAY<Point<3> > & apoints) const + { + apoints.Append (points); + // for (int i = 0; i < points.Size(); i++) + // apoints.Append (points[i].P()); + } + */ + + + + int AdFront2 :: AddPoint (const Point<3> & p, PointIndex globind, + MultiPointGeomInfo * mgi, + bool pointonsurface) + { + // inserts at empty position or resizes array + int pi; + + if (delpointl.Size() != 0) + { + pi = delpointl.Last(); + delpointl.DeleteLast (); + + points[pi] = FrontPoint2 (p, globind, mgi, pointonsurface); + } + else + { + pi = points.Append (FrontPoint2 (p, globind, mgi, pointonsurface)) - 1; + } + + if (mgi) + cpointsearchtree.Insert (p, pi); + + pointsearchtree.Insert (p, pi); + + return pi; + } + + + int AdFront2 :: AddLine (int pi1, int pi2, + const PointGeomInfo & gi1, const PointGeomInfo & gi2) + { + int minfn; + int li; + + FrontPoint2 & p1 = points[pi1]; + FrontPoint2 & p2 = points[pi2]; + + + nfl++; + + p1.AddLine(); + p2.AddLine(); + + minfn = min2 (p1.FrontNr(), p2.FrontNr()); + p1.DecFrontNr (minfn+1); + p2.DecFrontNr (minfn+1); + + if (dellinel.Size() != 0) + { + li = dellinel.Last(); + dellinel.DeleteLast (); + lines[li] = FrontLine (INDEX_2(pi1, pi2)); + } + else + { + li = lines.Append(FrontLine (INDEX_2(pi1, pi2))) - 1; + } + + + if (!gi1.trignum || !gi2.trignum) + { + cout << "ERROR: in AdFront::AddLine, illegal geominfo" << endl; + } + + lines[li].SetGeomInfo (gi1, gi2); + + Box3d lbox; + lbox.SetPoint(p1.P()); + lbox.AddPoint(p2.P()); + + linesearchtree.Insert (lbox.PMin(), lbox.PMax(), li); + + if (allflines) + { + if (allflines->Used (INDEX_2 (GetGlobalIndex (pi1), + GetGlobalIndex (pi2)))) + { + cerr << "ERROR Adfront2::AddLine: line exists" << endl; + (*testout) << "ERROR Adfront2::AddLine: line exists" << endl; + } + + allflines->Set (INDEX_2 (GetGlobalIndex (pi1), + GetGlobalIndex (pi2)), 1); + } + + return li; + } + + + void AdFront2 :: DeleteLine (int li) + { + int pi; + + nfl--; + + for (int i = 1; i <= 2; i++) + { + pi = lines[li].L().I(i); + points[pi].RemoveLine(); + + if (!points[pi].Valid()) + { + delpointl.Append (pi); + if (points[pi].mgi) + { + cpointsearchtree.DeleteElement (pi); + delete points[pi].mgi; + points[pi].mgi = NULL; + } + + pointsearchtree.DeleteElement (pi); + } + } + + if (allflines) + { + allflines->Set (INDEX_2 (GetGlobalIndex (lines[li].L().I1()), + GetGlobalIndex (lines[li].L().I2())), 2); + } + + lines[li].Invalidate(); + linesearchtree.DeleteElement (li); + + dellinel.Append (li); + } + + + int AdFront2 :: ExistsLine (int pi1, int pi2) + { + if (!allflines) + return 0; + if (allflines->Used (INDEX_2(pi1, pi2))) + return allflines->Get (INDEX_2 (pi1, pi2)); + else + return 0; + } + + + /* + void AdFront2 :: IncrementClass (int li) + { + lines[li].IncrementClass(); + } + + + void AdFront2 :: ResetClass (int li) + { + lines[li].ResetClass(); + } + */ + + int AdFront2 :: SelectBaseLine (Point<3> & p1, Point<3> & p2, + const PointGeomInfo *& geominfo1, + const PointGeomInfo *& geominfo2, + int & qualclass) + { + int baselineindex = -1; + + for (int i = starti; i < lines.End(); i++) + { + if (lines[i].Valid()) + { + int hi = lines[i].LineClass() + + points[lines[i].L().I1()].FrontNr() + + points[lines[i].L().I2()].FrontNr(); + + if (hi <= minval) + { + minval = hi; + baselineindex = i; + break; + } + } + } + + if (baselineindex == -1) + { + minval = INT_MAX; + for (int i = lines.Begin(); i < lines.End(); i++) + if (lines[i].Valid()) + { + int hi = lines[i].LineClass() + + points[lines[i].L().I1()].FrontNr() + + points[lines[i].L().I2()].FrontNr(); + + if (hi < minval) + { + minval = hi; + baselineindex = i; + } + } + } + starti = baselineindex+1; + + p1 = points[lines[baselineindex].L().I1()].P(); + p2 = points[lines[baselineindex].L().I2()].P(); + geominfo1 = &lines[baselineindex].GetGeomInfo(1); + geominfo2 = &lines[baselineindex].GetGeomInfo(2); + + qualclass = lines[baselineindex].LineClass(); + + return baselineindex; + } + + + + + int AdFront2 :: GetLocals (int baselineindex, + ARRAY<Point3d> & locpoints, + ARRAY<MultiPointGeomInfo> & pgeominfo, + ARRAY<INDEX_2> & loclines, // local index + ARRAY<INDEX> & pindex, + ARRAY<INDEX> & lindex, + double xh) + { + // baselineindex += 1-lines.Begin(); + + int pstind; + Point<3> midp, p0; + + pstind = lines[baselineindex].L().I1(); + p0 = points[pstind].P(); + + loclines.Append(lines[baselineindex].L()); + lindex.Append(baselineindex); // +1-lines.Begin()); + + static ARRAY<int> nearlines; + nearlines.SetSize(0); + static ARRAY<int> nearpoints; + nearpoints.SetSize(0); + + linesearchtree.GetIntersecting (p0 - Vec3d(xh, xh, xh), + p0 + Vec3d(xh, xh, xh), + nearlines); + + pointsearchtree.GetIntersecting (p0 - Vec3d(xh, xh, xh), + p0 + Vec3d(xh, xh, xh), + nearpoints); + + + for (int ii = 1; ii <= nearlines.Size(); ii++) + { + int i = nearlines.Get(ii); + if (lines[i].Valid() && i != baselineindex) // + 1-lines.Begin()) + { + loclines.Append(lines[i].L()); + lindex.Append(i); + } + } + + static ARRAY<int> invpindex; + invpindex.SetSize (points.Size()); + // invpindex = -1; + for (int i = 0; i < nearpoints.Size(); i++) + invpindex[nearpoints[i]] = -1; + + for (int i = 0; i < loclines.Size(); i++) + { + invpindex[loclines[i].I1()] = 0; + invpindex[loclines[i].I2()] = 0; + } + + + for (int i = 0; i < loclines.Size(); i++) + { + for (int j = 0; j < 2; j++) + { + int pi = loclines[i][j]; + if (invpindex[pi] == 0) + { + pindex.Append (pi); + invpindex[pi] = pindex.Size(); + loclines[i][j] = locpoints.Append (points[pi].P()); + } + else + loclines[i][j] = invpindex[pi]; + } + } + + + // double xh2 = xh*xh; + for (int ii = 0; ii < nearpoints.Size(); ii++) + { + int i = nearpoints[ii]; + if (points[i].Valid() && + points[i].OnSurface() && + // Dist2 (points.Get(i).P(), p0) <= xh2 && + invpindex[i] <= 0) + { + invpindex[i] = locpoints.Append (points[i].P()); + pindex.Append(i); + } + } + /* + double xh2 = xh*xh; + for (i = 1; i <= points.Size(); i++) + { + if (points.Get(i).Valid() && + points.Get(i).OnSurface() && + Dist2 (points.Get(i).P(), p0) <= xh2 && + invpindex.Get(i) <= 0) + { + invpindex.Elem(i) = + locpoints.Append (points.Get(i).P()); + pindex.Append(i); + } + } + */ + + pgeominfo.SetSize (locpoints.Size()); + for (int i = 0; i < pgeominfo.Size(); i++) + pgeominfo[i].Init(); + + + for (int i = 0; i < loclines.Size(); i++) + for (int j = 0; j < 2; j++) + { + int lpi = loclines[i][j]; + + const PointGeomInfo & gi = + lines[lindex[i]].GetGeomInfo (j+1); + pgeominfo.Elem(lpi).AddPointGeomInfo (gi); + + /* + if (pgeominfo.Elem(lpi).cnt == MULTIPOINTGEOMINFO_MAX) + break; + + const PointGeomInfo & gi = + lines.Get(lindex.Get(i)).GetGeomInfo (j); + + PointGeomInfo * pgi = pgeominfo.Elem(lpi).mgi; + + int found = 0; + for (k = 0; k < pgeominfo.Elem(lpi).cnt; k++) + if (pgi[k].trignum == gi.trignum) + found = 1; + + if (!found) + { + pgi[pgeominfo.Elem(lpi).cnt] = gi; + pgeominfo.Elem(lpi).cnt++; + } + */ + } + + for (int i = 0; i < locpoints.Size(); i++) + { + int pi = pindex[i]; + + if (points[pi].mgi) + for (int j = 1; j <= points[pi].mgi->GetNPGI(); j++) + pgeominfo[i].AddPointGeomInfo (points[pi].mgi->GetPGI(j)); + } + + if (loclines.Size() == 1) + { + cout << "loclines.Size = 1" << endl; + (*testout) << "loclines.size = 1" << endl + << " h = " << xh << endl + << " nearline.size = " << nearlines.Size() << endl + << " p0 = " << p0 << endl; + } + + return lines[baselineindex].LineClass(); + } + + + + void AdFront2 :: SetStartFront () + { + for (int i = lines.Begin(); i < lines.End(); i++) + if (lines[i].Valid()) + for (int j = 1; j <= 2; j++) + points[lines[i].L().I(j)].DecFrontNr(0); + } + + + void AdFront2 :: Print (ostream & ost) const + { + ost << points.Size() << " Points: " << endl; + for (int i = points.Begin(); i < points.End(); i++) + if (points[i].Valid()) + ost << i << " " << points[i].P() << endl; + + ost << nfl << " Lines: " << endl; + for (int i = lines.Begin(); i < lines.End(); i++) + if (lines[i].Valid()) + ost << lines[i].L().I1() << " - " << lines[i].L().I2() << endl; + + ost << flush; + } +} diff --git a/contrib/Netgen/libsrc/meshing/adfront2.hpp b/contrib/Netgen/libsrc/meshing/adfront2.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4266d3332ecba37c2fc0d4d192f6826a1bd807ae --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront2.hpp @@ -0,0 +1,264 @@ +#ifndef FILE_ADFRONT2 +#define FILE_ADFRONT2 + +/**************************************************************************/ +/* File: adfront2.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + + +/** + + Advancing front class for surfaces + +*/ +class AdFront2 +{ + + /// + class FrontPoint2 + { + /// coordinates + Point<3> p; + /// global node index + PointIndex globalindex; + /// number of front lines connected to point + int nlinetopoint; + /// distance to original boundary + int frontnr; + + bool onsurface; + + public: + /// + MultiPointGeomInfo * mgi; + + /// + FrontPoint2 () + { + globalindex = -1; + nlinetopoint = 0; + frontnr = INT_MAX-10; // attention: overflow on calculating INT_MAX + 1 + mgi = NULL; + onsurface = true; + } + + /// + FrontPoint2 (const Point<3> & ap, PointIndex agi, + MultiPointGeomInfo * amgi, bool aonsurface = true); + /// + ~FrontPoint2 () { ; } + + /// + const Point<3> & P () const { return p; } + /// + operator const Point<3> & () const { return p; } + /// + PointIndex GlobalIndex () const { return globalindex; } + + /// + void AddLine () { nlinetopoint++; } + /// + void RemoveLine () + { + nlinetopoint--; + if (nlinetopoint == 0) + nlinetopoint = -1; + } + + /// + bool Valid () const + { return nlinetopoint >= 0; } + + /// + bool OnSurface() const + { return onsurface; } + + /// + void DecFrontNr (int afrontnr) + { + if (frontnr > afrontnr) frontnr = afrontnr; + } + + /// + int FrontNr () const { return frontnr; } + }; + + + /// + class FrontLine + { + private: + /// Point Indizes + INDEX_2 l; + /// quality class + int lineclass; + /// geometry specific data + PointGeomInfo geominfo[2]; + public: + + FrontLine () + { + lineclass = 1; + } + + /// + FrontLine (const INDEX_2 & al) + { + l = al; + lineclass = 1; + } + + + /// + const INDEX_2 & L () const + { + return l; + } + + /// + int LineClass() const + { + return lineclass; + } + + /// + void IncrementClass () + { + lineclass++; + } + /// + void ResetClass () + { + lineclass = 1; + } + + /// + bool Valid () const + { + return l.I1() != -1; + } + /// + void Invalidate () + { + l.I1() = -1; + l.I2() = -1; + lineclass = 1000; + } + + void SetGeomInfo (const PointGeomInfo & gi1, const PointGeomInfo & gi2) + { + geominfo[0] = gi1; + geominfo[1] = gi2; + } + + const PointGeomInfo * GetGeomInfo () const + { return geominfo; } + + const PointGeomInfo & GetGeomInfo (int endp) const + { return geominfo[endp-1]; } + + friend class AdFront2; + }; + + + + /// + ARRAY<FrontPoint2> points; /// front points + ARRAY<FrontLine> lines; /// front lines + + Box3d boundingbox; + Box3dTree linesearchtree; /// search tree for lines + Point3dTree pointsearchtree; /// search tree for points + Point3dTree cpointsearchtree; /// search tree for cone points (not used ???) + + ARRAY<int> delpointl; /// list of deleted front points + ARRAY<int> dellinel; /// list of deleted front lines + + int nfl; /// number of front lines; + INDEX_2_HASHTABLE<int> * allflines; /// all front lines ever have been + + + int minval; + int starti; + +public: + /// + // AdFront2 (); + AdFront2 (const Box3d & aboundingbox); + /// + ~AdFront2 (); + + /// + // void GetPoints (ARRAY<Point<3> > & apoints) const; + /// + void Print (ostream & ost) const; + + /// + bool Empty () const + { + return nfl == 0; + } + /// + int GetNFL () const { return nfl; } + /// + int SelectBaseLine (Point<3> & p1, Point<3> & p2, + const PointGeomInfo *& geominfo1, + const PointGeomInfo *& geominfo2, + int & qualclass); + + /// + int GetLocals (int baseline, + ARRAY<Point3d> & locpoints, + ARRAY<MultiPointGeomInfo> & pgeominfo, + ARRAY<INDEX_2> & loclines, // local index + ARRAY<int> & pindex, + ARRAY<int> & lindex, + double xh); + + /// + void DeleteLine (int li); + /// + int AddPoint (const Point<3> & p, PointIndex globind, + MultiPointGeomInfo * mgi = NULL, + bool pointonsurface = true); + /// + int AddLine (int pi1, int pi2, + const PointGeomInfo & gi1, const PointGeomInfo & gi2); + /// + int ExistsLine (int gpi1, int gpi2); + + /// + void IncrementClass (int li) + { + lines[li].IncrementClass(); + } + + /// + void ResetClass (int li) + { + lines[li].ResetClass(); + } + + /// + const PointGeomInfo & GetLineGeomInfo (int li, int lend) const + { return lines[li].GetGeomInfo (lend); } + /// + + PointIndex GetGlobalIndex (int pi) const + { + return points[pi].GlobalIndex(); + } + /// + void SetStartFront (); + /// + void PrintOpenSegments (ostream & ost) const; +}; + + + +#endif + + + diff --git a/contrib/Netgen/libsrc/meshing/adfront3.cpp b/contrib/Netgen/libsrc/meshing/adfront3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dfe2edc839881517939f5eddf73f0f985c831492 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront3.cpp @@ -0,0 +1,876 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +/* ********************** FrontPoint ********************** */ + +namespace netgen +{ + +FrontPoint3 :: FrontPoint3 () +{ + globalindex = -1; + nfacetopoint = 0; + frontnr = 1000; + cluster = 0; +} + + +FrontPoint3 :: FrontPoint3 (const Point<3> & ap, PointIndex agi) +{ + p = ap; + globalindex = agi; + nfacetopoint = 0; + frontnr = 1000; + cluster = 0; +} + + + +/* ********************** FrontFace ********************** */ + +FrontFace :: FrontFace () +{ + qualclass = 1; + oldfront = 0; + hashvalue = 0; + cluster = 0; +} + +FrontFace :: FrontFace (const MiniElement2d & af) +{ + f = af; + oldfront = 0; + qualclass = 1; + hashvalue = 0; +} + +void FrontFace :: Invalidate () +{ + f.Delete(); + oldfront = 0; + qualclass = 1000; +} + + + + +/* ********************** AddFront ********************** */ + + +AdFront3 :: AdFront3 () +{ + nff = 0; + nff4 = 0; + vol = 0; + + hashon = 1; + hashcreated = 0; + if (hashon) + hashtable.Init(&points, &faces); + + facetree = NULL; + connectedpairs = NULL; + + rebuildcounter = -1; + lasti = 0; + minval = -1; +} + + +AdFront3 :: ~AdFront3 () +{ + delete facetree; + delete connectedpairs; +} + +void AdFront3 :: GetPoints (ARRAY<Point<3> > & apoints) const +{ + for (PointIndex pi = PointIndex::BASE; + pi < points.Size()+PointIndex::BASE; pi++) + + apoints.Append (points[pi].P()); +} + + +PointIndex AdFront3 :: AddPoint (const Point<3> & p, PointIndex globind) +{ + if (delpointl.Size()) + { + PointIndex pi = delpointl.Last(); + delpointl.DeleteLast (); + + points[pi] = FrontPoint3 (p, globind); + return pi; + } + else + { + points.Append (FrontPoint3 (p, globind)); + return points.Size()-1+PointIndex::BASE; + } +} + + +INDEX AdFront3 :: AddFace (const MiniElement2d & aface) +{ + int i, minfn; + + nff++; + + for (i = 0; i < aface.GetNP(); i++) + points[aface[i]].AddFace(); + + const Point3d & p1 = points[aface[0]].P(); + const Point3d & p2 = points[aface[1]].P(); + const Point3d & p3 = points[aface[2]].P(); + + vol += 1.0/6.0 * (p1.X() + p2.X() + p3.X()) * + ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) - + (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) ); + + if (aface.GetNP() == 4) + { + nff4++; + const Point3d & p4 = points[aface[3]].P(); + vol += 1.0/6.0 * (p1.X() + p3.X() + p4.X()) * + ( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) - + (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) ); + } + + + minfn = 1000; + for (i = 0; i < aface.GetNP(); i++) + { + int fpn = points[aface[i]].FrontNr(); + if (i == 0 || fpn < minfn) + minfn = fpn; + } + + + int cluster = 0; + for (i = 1; i <= aface.GetNP(); i++) + { + if (points[aface.PNum(i)].cluster) + cluster = points[aface.PNum(i)].cluster; + } + for (i = 1; i <= aface.GetNP(); i++) + points[aface.PNum(i)].cluster = cluster; + + + for (i = 1; i <= aface.GetNP(); i++) + points[aface.PNum(i)].DecFrontNr (minfn+1); + + int nfn = faces.Append(FrontFace (aface)); + faces.Elem(nfn).cluster = cluster; + + if (hashon && hashcreated) + hashtable.AddElem(aface, nfn); + + return nfn; +} + + + +void AdFront3 :: DeleteFace (INDEX fi) +{ + nff--; + + for (int i = 1; i <= faces.Get(fi).Face().GetNP(); i++) + { + PointIndex pi = faces.Get(fi).Face().PNum(i); + points[pi].RemoveFace(); + if (!points[pi].Valid()) + delpointl.Append (pi); + } + + const MiniElement2d & face = faces.Get(fi).Face(); + const Point3d & p1 = points[face.PNum(1)].P(); + const Point3d & p2 = points[face.PNum(2)].P(); + const Point3d & p3 = points[face.PNum(3)].P(); + + vol -= 1.0/6.0 * (p1.X() + p2.X() + p3.X()) * + ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) - + (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) ); + + if (face.GetNP() == 4) + { + const Point3d & p4 = points[face.PNum(4)].P(); + vol -= 1.0/6.0 * (p1.X() + p3.X() + p4.X()) * + ( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) - + (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) ); + + nff4--; + } + + faces.Elem(fi).Invalidate(); +} + + +INDEX AdFront3 :: AddConnectedPair (const INDEX_2 & apair) +{ + if (!connectedpairs) + connectedpairs = new TABLE<int, PointIndex::BASE> (GetNP()); + + connectedpairs->Add (apair.I1(), apair.I2()); + connectedpairs->Add (apair.I2(), apair.I1()); + + return 0; +} + + +void AdFront3 :: CreateTrees () +{ + int i, j; + PointIndex pi; + Point3d pmin, pmax; + + for (pi = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; pi++) + { + const Point<3> & p = GetPoint(pi); + if (pi == PointIndex::BASE) + { + pmin = p; + pmax = p; + } + else + { + pmin.SetToMin (p); + pmax.SetToMax (p); + } + } + + pmax = pmax + 0.5 * (pmax - pmin); + pmin = pmin + 0.5 * (pmin - pmax); + + delete facetree; + facetree = new Box3dTree (pmin, pmax); + + for (i = 1; i <= GetNF(); i++) + { + const MiniElement2d & el = GetFace(i); + pmin = GetPoint (el[0]); + pmax = pmin; + for (j = 1; j < 3; j++) + { + const Point<3> & p = GetPoint (el[j]); + pmin.SetToMin (p); + pmax.SetToMax (p); + } + pmax = pmax + 0.01 * (pmax - pmin); + pmin = pmin + 0.01 * (pmin - pmax); + // (*testout) << "insert " << i << ": " << pmin << " - " << pmax << "\n"; + facetree -> Insert (pmin, pmax, i); + } +} + + +void AdFront3 :: GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax, + ARRAY<int> & ifaces) const +{ + facetree -> GetIntersecting (pmin, pmax, ifaces); +} + +void AdFront3 :: GetFaceBoundingBox (int i, Box3d & box) const +{ + const FrontFace & face = faces.Get(i); + box.SetPoint (points[face.f[0]].p); + box.AddPoint (points[face.f[1]].p); + box.AddPoint (points[face.f[2]].p); +} + +void AdFront3 :: RebuildInternalTables () +{ + static int timer_a = NgProfiler::CreateTimer ("Adfront3::RebuildInternal A"); + static int timer_b = NgProfiler::CreateTimer ("Adfront3::RebuildInternal B"); + static int timer_c = NgProfiler::CreateTimer ("Adfront3::RebuildInternal C"); + static int timer_d = NgProfiler::CreateTimer ("Adfront3::RebuildInternal D"); + + + NgProfiler::StartTimer (timer_a); + int hi = 0; + for (int i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + hi++; + if (hi < i) + faces.Elem(hi) = faces.Get(i); + } + + faces.SetSize (nff); + + int np = points.Size(); + + for (int i = PointIndex::BASE; + i < np+PointIndex::BASE; i++) + points[i].cluster = i; + + NgProfiler::StopTimer (timer_a); + NgProfiler::StartTimer (timer_b); + + int change; + do + { + change = 0; + for (int i = 1; i <= faces.Size(); i++) + { + const MiniElement2d & el = faces.Get(i).Face(); + + int mini = points[el.PNum(1)].cluster; + int maxi = mini; + + for (int j = 2; j <= 3; j++) + { + int ci = points[el.PNum(j)].cluster; + if (ci < mini) mini = ci; + if (ci > maxi) maxi = ci; + } + + if (mini < maxi) + { + change = 1; + for (int j = 1; j <= 3; j++) + points[el.PNum(j)].cluster = mini; + } + } + } + while (change); + + + NgProfiler::StopTimer (timer_b); + NgProfiler::StartTimer (timer_c); + + + + + BitArrayChar<PointIndex::BASE> usecl(np); + usecl.Clear(); + for (int i = 1; i <= faces.Size(); i++) + { + usecl.Set (points[faces.Get(i).Face().PNum(1)].cluster); + faces.Elem(i).cluster = + points[faces.Get(i).Face().PNum(1)].cluster; + } + int cntcl = 0; + for (int i = PointIndex::BASE; + i < np+PointIndex::BASE; i++) + if (usecl.Test(i)) + cntcl++; + + ARRAY<double, PointIndex::BASE> clvol (np); + clvol = 0.0; + + for (int i = 1; i <= faces.Size(); i++) + { + const MiniElement2d & face = faces.Get(i).Face(); + + const Point3d p1 = points[face.PNum(1)].P(); + const Point3d p2 = points[face.PNum(2)].P(); + const Point3d p3 = points[face.PNum(3)].P(); + + double vi = 1.0/6.0 * (p1.X() + p2.X() + p3.X()) * + ( (p2.Y() - p1.Y()) * (p3.Z() - p1.Z()) - + (p2.Z() - p1.Z()) * (p3.Y() - p1.Y()) ); + + if (face.GetNP() == 4) + { + const Point3d p4 = points[face.PNum(4)].P(); + vi += 1.0/6.0 * (p1.X() + p3.X() + p4.X()) * + ( (p3.Y() - p1.Y()) * (p4.Z() - p1.Z()) - + (p3.Z() - p1.Z()) * (p4.Y() - p1.Y()) ); + } + + clvol[faces.Get(i).cluster] += vi; + } + + NgProfiler::StopTimer (timer_c); + NgProfiler::StartTimer (timer_d); + + + + int negvol = 0; + for (int i = PointIndex::BASE; + i < clvol.Size()+PointIndex::BASE; i++) + { + if (clvol[i] < 0) + negvol = 1; + } + + if (negvol) + { + for (int i = 1; i <= faces.Size(); i++) + faces.Elem(i).cluster = 1; + for (int i = PointIndex::BASE; + i < points.Size()+PointIndex::BASE; i++) + points[i].cluster = 1; + } + + if (hashon) + hashtable.Create(); + + NgProfiler::StopTimer (timer_d); +} + + + +int AdFront3 :: SelectBaseElement () +{ + int i, hi, fstind; + + /* + static int minval = -1; + static int lasti = 0; + static int counter = 0; + */ + if (rebuildcounter <= 0) + { + RebuildInternalTables(); + rebuildcounter = nff / 10 + 1; + + lasti = 0; + } + rebuildcounter--; + + /* + if (faces.Size() > 2 * nff) + { + // compress facelist + + RebuildInternalTables (); + lasti = 0; + } + */ + + fstind = 0; + + for (i = lasti+1; i <= faces.Size() && !fstind; i++) + if (faces.Elem(i).Valid()) + { + hi = faces.Get(i).QualClass() + + points[faces.Get(i).Face().PNum(1)].FrontNr() + + points[faces.Get(i).Face().PNum(2)].FrontNr() + + points[faces.Get(i).Face().PNum(3)].FrontNr(); + + if (hi <= minval) + { + minval = hi; + fstind = i; + lasti = fstind; + } + } + + if (!fstind) + { + minval = INT_MAX; + for (i = 1; i <= faces.Size(); i++) + if (faces.Elem(i).Valid()) + { + hi = faces.Get(i).QualClass() + + points[faces.Get(i).Face().PNum(1)].FrontNr() + + points[faces.Get(i).Face().PNum(2)].FrontNr() + + points[faces.Get(i).Face().PNum(3)].FrontNr(); + + if (hi <= minval) + { + minval = hi; + fstind = i; + lasti = 0; + } + } + } + + + return fstind; +} + + + +int AdFront3 :: GetLocals (int fstind, + ARRAY<Point3d > & locpoints, + ARRAY<MiniElement2d> & locfaces, // local index + ARRAY<PointIndex> & pindex, + ARRAY<INDEX> & findex, + INDEX_2_HASHTABLE<int> & getconnectedpairs, + float xh, + float relh, + INDEX& facesplit) +{ + static int timer = NgProfiler::CreateTimer ("AdFront3::GetLocals"); + NgProfiler::RegionTimer reg (timer); + + + if (hashon && faces.Size() < 500) { hashon=0; } + if (hashon && !hashcreated) + { + hashtable.Create(); + hashcreated=1; + } + + INDEX i, j; + PointIndex pstind; + INDEX pi; + Point3d midp, p0; + + static ARRAY<int, PointIndex::BASE> invpindex; + + static ARRAY<MiniElement2d> locfaces2; //all local faces in radius xh + static ARRAY<int> locfaces3; // all faces in outer radius relh + static ARRAY<INDEX> findex2; + + locfaces2.SetSize(0); + locfaces3.SetSize(0); + findex2.SetSize(0); + + int cluster = faces.Get(fstind).cluster; + + pstind = faces.Get(fstind).Face().PNum(1); + p0 = points[pstind].P(); + + locfaces2.Append(faces.Get(fstind).Face()); + findex2.Append(fstind); + + + Box3d b1 (p0 - Vec3d(xh, xh, xh), p0 + Vec3d (xh, xh, xh)); + + if (hashon) + { + hashtable.GetLocals(locfaces2, findex2, fstind, p0, xh); + } + else + { + for (i = 1; i <= faces.Size(); i++) + { + const MiniElement2d & face = faces.Get(i).Face(); + if (faces.Get(i).cluster == cluster && faces.Get(i).Valid() && i != fstind) + { + Box3d b2; + b2.SetPoint (points[face[0]].P()); + b2.AddPoint (points[face[1]].P()); + b2.AddPoint (points[face[2]].P()); + + if (b1.Intersect (b2)) + { + locfaces2.Append(faces.Get(i).Face()); + findex2.Append(i); + } + } + } + } + + //local faces for inner radius: + for (i = 1; i <= locfaces2.Size(); i++) + { + const MiniElement2d & face = locfaces2.Get(i); + const Point3d & p1 = points[face[0]].P(); + const Point3d & p2 = points[face[1]].P(); + const Point3d & p3 = points[face[2]].P(); + + midp = Center (p1, p2, p3); + + if (Dist2 (midp, p0) <= relh * relh || i == 1) + { + locfaces.Append(locfaces2.Get(i)); + findex.Append(findex2.Get(i)); + } + else + locfaces3.Append (i); + } + + facesplit=locfaces.Size(); + + + //local faces for outer radius: + for (i = 1; i <= locfaces3.Size(); i++) + { + locfaces.Append (locfaces2.Get(locfaces3.Get(i))); + findex.Append (findex2.Get(locfaces3.Get(i))); + } + + + invpindex.SetSize (points.Size()); + for (i = 1; i <= locfaces.Size(); i++) + for (j = 1; j <= locfaces.Get(i).GetNP(); j++) + { + pi = locfaces.Get(i).PNum(j); + invpindex[pi] = -1; + } + + for (i = 1; i <= locfaces.Size(); i++) + { + for (j = 1; j <= locfaces.Get(i).GetNP(); j++) + { + pi = locfaces.Get(i).PNum(j); + if (invpindex[pi] == -1) + { + pindex.Append (pi); + invpindex[pi] = pindex.Size(); // -1+PointIndex::BASE; + locfaces.Elem(i).PNum(j) = locpoints.Append (points[pi].P()); + } + else + locfaces.Elem(i).PNum(j) = invpindex[pi]; + + } + } + + + + if (connectedpairs) + { + for (i = 1; i <= locpoints.Size(); i++) + { + int pind = pindex.Get(i); + if (pind >= 1 && pind <= connectedpairs->Size ()) + { + for (j = 1; j <= connectedpairs->EntrySize(pind); j++) + { + int oi = connectedpairs->Get(pind, j); + int other = invpindex.Get(oi); + if (other >= 1 && other <= pindex.Size() && + pindex.Get(other) == oi) + { + // INDEX_2 coned(i, other); + // coned.Sort(); + // (*testout) << "connected: " << locpoints.Get(i) << "-" << locpoints.Get(other) << endl; + getconnectedpairs.Set (INDEX_2::Sort (i, other), 1); + } + } + } + } + } + + + /* + // add isolated points + for (i = 1; i <= points.Size(); i++) + if (points.Elem(i).Valid() && Dist (points.Elem(i).P(), p0) <= xh) + { + if (!invpindex.Get(i)) + { + locpoints.Append (points.Get(i).P()); + pindex.Append (i); + invpindex.Elem(i) = pindex.Size(); + } + } + */ + return faces.Get(fstind).QualClass(); +} + + +// returns all points connected with fi +void AdFront3 :: GetGroup (int fi, + ARRAY<MeshPoint> & grouppoints, + ARRAY<MiniElement2d> & groupelements, + ARRAY<PointIndex> & pindex, + ARRAY<INDEX> & findex) const +{ + static ARRAY<char> pingroup; + int i, j, changed; + + pingroup.SetSize(points.Size()); + + pingroup = 0; + for (j = 1; j <= 3; j++) + pingroup.Elem (faces.Get(fi).Face().PNum(j)) = 1; + + do + { + changed = 0; + + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + const MiniElement2d & face = faces.Get(i).Face(); + + int fused = 0; + for (j = 1; j <= 3; j++) + if (pingroup.Elem(face.PNum(j))) + fused++; + + if (fused >= 2) + for (j = 1; j <= 3; j++) + if (!pingroup.Elem(face.PNum(j))) + { + pingroup.Elem(face.PNum(j)) = 1; + changed = 1; + } + } + + } + while (changed); + + + static ARRAY<int> invpindex; + invpindex.SetSize (points.Size()); + + + for (i = 1; i <= points.Size(); i++) + if (points.Get(i).Valid()) + { + grouppoints.Append (points.Get(i).P()); + pindex.Append (i); + invpindex.Elem(i) = pindex.Size(); + } + + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + int fused = 0; + for (j = 1; j <= 3; j++) + if (pingroup.Get(faces.Get(i).Face().PNum(j))) + fused++; + + if (fused >= 2) + { + groupelements.Append (faces.Get(i).Face()); + findex.Append (i); + } + } + + for (i = 1; i <= groupelements.Size(); i++) + for (j = 1; j <= 3; j++) + { + groupelements.Elem(i).PNum(j) = + invpindex.Get(groupelements.Elem(i).PNum(j)); + } + + /* + for (i = 1; i <= groupelements.Size(); i++) + for (j = 1; j <= 3; j++) + for (k = 1; k <= grouppoints.Size(); k++) + if (pindex.Get(k) == groupelements.Get(i).PNum(j)) + { + groupelements.Elem(i).PNum(j) = k; + break; + } + */ +} + + +void AdFront3 :: SetStartFront (int /* baseelnp */) +{ + INDEX i; + int j; + + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + const MiniElement2d & face = faces.Get(i).Face(); + for (j = 1; j <= 3; j++) + points[face.PNum(j)].DecFrontNr(0); + } + + /* + if (baseelnp) + { + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid() && faces.Get(i).Face().GetNP() != baseelnp) + faces.Elem(i).qualclass = 1000; + } + */ +} + + +bool AdFront3 :: Inside (const Point<3> & p) const +{ + int i, cnt; + Vec3d n, v1, v2; + DenseMatrix a(3), ainv(3); + Vector b(3), u(3); + + // random numbers: + n.X() = 0.123871; + n.Y() = 0.15432; + n.Z() = -0.43989; + + cnt = 0; + for (i = 1; i <= faces.Size(); i++) + if (faces.Get(i).Valid()) + { + const Point<3> & p1 = points[faces.Get(i).Face().PNum(1)].P(); + const Point<3> & p2 = points[faces.Get(i).Face().PNum(2)].P(); + const Point<3> & p3 = points[faces.Get(i).Face().PNum(3)].P(); + + v1 = p2 - p1; + v2 = p3 - p1; + + a.Elem(1, 1) = v1.X(); + a.Elem(2, 1) = v1.Y(); + a.Elem(3, 1) = v1.Z(); + a.Elem(1, 2) = v2.X(); + a.Elem(2, 2) = v2.Y(); + a.Elem(3, 2) = v2.Z(); + a.Elem(1, 3) = -n.X(); + a.Elem(2, 3) = -n.Y(); + a.Elem(3, 3) = -n.Z(); + + b.Elem(1) = p(0) - p1(0); + b.Elem(2) = p(1) - p1(1); + b.Elem(3) = p(2) - p1(2); + + CalcInverse (a, ainv); + ainv.Mult (b, u); + + if (u.Elem(1) >= 0 && u.Elem(2) >= 0 && u.Elem(1)+u.Elem(2) <= 1 && + u.Elem(3) > 0) + { + cnt++; + } + } + + return ((cnt % 2) != 0); +} + + + + + +int AdFront3 :: SameSide (const Point<3> & lp1, const Point<3> & lp2, + const ARRAY<int> * testfaces) const +{ + int i, ii, cnt; + + const Point<3> *line[2]; + line[0] = &lp1; + line[1] = &lp2; + + + cnt = 0; + + Point3d pmin(lp1); + Point3d pmax(lp1); + pmin.SetToMin (lp2); + pmax.SetToMax (lp2); + + static ARRAY<int> aprif; + aprif.SetSize(0); + + if (!testfaces) + facetree->GetIntersecting (pmin, pmax, aprif); + else + { + for (i = 1; i <= testfaces->Size(); i++) + aprif.Append (testfaces->Get(i)); + } + + // (*testout) << "test ss, p1,p2 = " << lp1 << lp2 << ", inters = " << aprif.Size() << endl; + // for (i = 1; i <= faces.Size(); i++) + for (ii = 1; ii <= aprif.Size(); ii++) + { + i = aprif.Get(ii); + + if (faces.Get(i).Valid()) + { + const Point<3> *tri[3]; + tri[0] = &points[faces.Get(i).Face().PNum(1)].P(); + tri[1] = &points[faces.Get(i).Face().PNum(2)].P(); + tri[2] = &points[faces.Get(i).Face().PNum(3)].P(); + + if (IntersectTriangleLine (&tri[0], &line[0])) + cnt++; + + } + } + + return ((cnt+1) % 2); +} +} diff --git a/contrib/Netgen/libsrc/meshing/adfront3.hpp b/contrib/Netgen/libsrc/meshing/adfront3.hpp new file mode 100644 index 0000000000000000000000000000000000000000..40d6eabb99c391d046cde49f3e9a2f8623f3432d --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/adfront3.hpp @@ -0,0 +1,319 @@ +#ifndef FILE_ADFRONT3 +#define FILE_ADFRONT3 + +/**************************************************************************/ +/* File: adfront3.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +/* + Advancing front class for volume meshing +*/ + + + +/// Point in advancing front +class FrontPoint3 +{ + /// coordinates +Point<3> p; + /// global node index +PointIndex globalindex; + /// number of faces connected to point +int nfacetopoint; + /// distance to original boundary +int frontnr; + /// +int cluster; +public: + /// + FrontPoint3 (); + /// + FrontPoint3 (const Point<3> & ap, PointIndex agi); + + /// + const Point<3> & P () const + { return p; } + /// + PointIndex GlobalIndex () const + { return globalindex; } + + /// + void AddFace () + { nfacetopoint++; } + + /// + void RemoveFace() + { + nfacetopoint--; + if (nfacetopoint == 0) nfacetopoint = -1; + } + + /// + int Valid () const + { return nfacetopoint >= 0; } + + /// + void DecFrontNr (int afrontnr) + { + if (frontnr > afrontnr) frontnr = afrontnr; + } + + /// + int FrontNr () const + { return frontnr; } + + /// + friend class AdFront3; +}; + + + +class MiniElement2d +{ +protected: + int np; + PointIndex pnum[4]; + bool deleted; +public: + MiniElement2d () + { np = 3; deleted = 0; } + MiniElement2d (int anp) + { np = anp; deleted = 0; } + + int GetNP() const { return np; } + PointIndex & operator[] (int i) { return pnum[i]; } + const PointIndex operator[] (int i) const { return pnum[i]; } + + const PointIndex PNum (int i) const { return pnum[i-1]; } + PointIndex & PNum (int i) { return pnum[i-1]; } + const PointIndex PNumMod (int i) const { return pnum[(i-1)%np]; } + + void Delete () { deleted = 1; pnum[0] = pnum[1] = pnum[2] = pnum[3] = PointIndex::BASE-1; } + bool IsDeleted () const { return deleted; } +}; + + +inline ostream & operator<<(ostream & s, const MiniElement2d & el) +{ + s << "np = " << el.GetNP(); + for (int j = 0; j < el.GetNP(); j++) + s << " " << el[j]; + return s; +} + + + + +/// Face in advancing front +class FrontFace +{ +private: + /// + MiniElement2d f; + /// + int qualclass; + /// + char oldfront; + /// + int hashvalue; + /// + int cluster; + +public: + /// + FrontFace (); + /// + FrontFace (const MiniElement2d & af); + /// + const MiniElement2d & Face () const + { return f; } + + /// + int QualClass () const + { return qualclass; } + + /// + void IncrementQualClass () + { qualclass++; } + + /// + void ResetQualClass () + { + if (qualclass > 1) + { + qualclass = 1; + oldfront = 0; + } + } + + /// + bool Valid () const + { return !f.IsDeleted(); } + + /// + void Invalidate (); + + /// + int HashValue() const + { return hashvalue; } + + /// + void SetHashValue(int hv) + { hashvalue = hv; } + + /// + friend class AdFront3; + + int Cluster () const { return cluster; } +}; + + + + +/// Advancing front, 3D. +class AdFront3 +{ + /// +ARRAY<FrontPoint3, PointIndex::BASE> points; + /// +ARRAY<FrontFace> faces; + /// +ARRAY<PointIndex> delpointl; + + /// which points are connected to pi ? +TABLE<int, PointIndex::BASE> * connectedpairs; + + /// number of total front faces; +int nff; + /// number of quads in front +int nff4; + + /// +double vol; + + /// +GeomSearch3d hashtable; + + /// +int hashon; + + /// +int hashcreated; + + /// counter for rebuilding internal tables +int rebuildcounter; + /// last base element +int lasti; + /// minimal selection-value of baseelements +int minval; + + /// +class Box3dTree * facetree; +public: + + /// + AdFront3 (); + /// + ~AdFront3 (); + /// + void GetPoints (ARRAY<Point<3> > & apoints) const; + /// + int GetNP() const + { return points.Size(); } + /// + const Point<3> & GetPoint (PointIndex pi) const + { return points[pi].P(); } + /// + int GetNF() const + { return nff; } + /// + const MiniElement2d & GetFace (int i) const + { return faces.Get(i).Face(); } + /// + void Print () const; + /// + bool Empty () const + { return nff == 0; } + /// + bool Empty (int elnp) const + { + if (elnp == 4) + return (nff4 == 0); + return (nff - nff4 == 0); + } + /// + int SelectBaseElement (); + + /// + void CreateTrees (); + + /// + void GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax, + ARRAY<int> & ifaces) const; + + /// + void GetFaceBoundingBox (int i, Box3d & box) const; + + /// + int GetLocals (int baseelement, + ARRAY<Point3d > & locpoints, + ARRAY<MiniElement2d> & locfaces, // local index + ARRAY<PointIndex> & pindex, + ARRAY<INDEX> & findex, + INDEX_2_HASHTABLE<int> & connectedpairs, + float xh, + float relh, + INDEX& facesplit); + + /// + void GetGroup (int fi, + ARRAY<MeshPoint> & grouppoints, + ARRAY<MiniElement2d> & groupelements, + ARRAY<PointIndex> & pindex, + ARRAY<INDEX> & findex + ) const; + + /// + void DeleteFace (INDEX fi); + /// + PointIndex AddPoint (const Point<3> & p, PointIndex globind); + /// + INDEX AddFace (const MiniElement2d & e); + /// + INDEX AddConnectedPair (const INDEX_2 & pair); + /// + void IncrementClass (INDEX fi) + { faces.Elem(fi).IncrementQualClass(); } + + /// + void ResetClass (INDEX fi) + { faces.Elem(fi).ResetQualClass(); } + + /// + void SetStartFront (int baseelnp = 0); + + /// is Point p inside Surface ? + bool Inside (const Point<3> & p) const; + /// both points on same side ? + int SameSide (const Point<3> & lp1, const Point<3> & lp2, + const ARRAY<int> * testfaces = NULL) const; + + + /// + PointIndex GetGlobalIndex (PointIndex pi) const + { return points[pi].GlobalIndex(); } + /// + double Volume () const + { return vol; } + + +private: + void RebuildInternalTables(); +}; + + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/bisect.cpp b/contrib/Netgen/libsrc/meshing/bisect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c56671b547ecdc076dea8840465c935cc0a18fcb --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/bisect.cpp @@ -0,0 +1,3994 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + //#include "../interface/writeuser.hpp" + class MarkedTet; + class MarkedPrism; + class MarkedIdentification; + class MarkedTri; + class MarkedQuad; + + typedef MoveableArray<MarkedTet> T_MTETS; + typedef MoveableArray<MarkedPrism> T_MPRISMS; + typedef MoveableArray<MarkedIdentification> T_MIDS; + typedef MoveableArray<MarkedTri> T_MTRIS; + typedef MoveableArray<MarkedQuad> T_MQUADS; + + class MarkedTet + { + public: + /// pnums of tet + PointIndex pnums[4]; + /// material number + int matindex; + /// element marked for refinement + /// marked = 1: marked by element marker, marked = 2 due to closure + unsigned int marked:2; + /// flag of Arnold-Mukherjee algorithm + unsigned int flagged:1; + /// tetedge (local coordinates 0..3) + unsigned int tetedge1:3; + unsigned int tetedge2:3; + /// marked edge of faces + /// face_j : face without node j, + /// mark_k : edge without node k + unsigned char faceedges[4]; + + bool incorder; + unsigned int order:6; + + }; + + ostream & operator<< (ostream & ost, const MarkedTet & mt) + { + for(int i=0; i<4; i++) + ost << mt.pnums[i] << " "; + + ost << mt.matindex << " " << int(mt.marked) << " " << int(mt.flagged) << " " << int(mt.tetedge1) << " " << int(mt.tetedge2) << " "; + + for(int i=0; i<4; i++) + ost << char(mt.faceedges[i]) << " "; + + ost << mt.incorder << " " << int(mt.order) << "\n"; + return ost; + } + istream & operator>> (istream & ost, MarkedTet & mt) + { + for(int i=0; i<4; i++) + ost >> mt.pnums[i]; + + ost >> mt.matindex; + + int auxint; + ost >> auxint; + mt.marked = auxint; + ost >> auxint; + mt.flagged = auxint; + ost >> auxint; + mt.tetedge1 = auxint; + ost >> auxint; + mt.tetedge2 = auxint; + + char auxchar; + + for(int i=0; i<4; i++) + { + ost >> auxchar; + mt.faceedges[i] = auxchar; + } + + ost >> mt.incorder; + ost >> auxint; + mt.order = auxint; + return ost; + } + + class MarkedPrism + { + public: + /// 6 point numbers + PointIndex pnums[6]; + /// material number + int matindex; + /// marked for refinement + int marked; + /// edge without node k (0,1,2) + int markededge; + + bool incorder; + unsigned int order:6; + }; + + + ostream & operator<< (ostream & ost, const MarkedPrism & mp) + { + for(int i=0; i<6; i++) + ost << mp.pnums[i] << " "; + + ost << mp.matindex << " " << mp.marked << " " << mp.markededge << " " << mp.incorder << " " << int(mp.order) << "\n"; + return ost; + } + istream & operator>> (istream & ist, MarkedPrism & mp) + { + for(int i=0; i<6; i++) + ist >> mp.pnums[i]; + + ist >> mp.matindex >> mp.marked >> mp.markededge >> mp.incorder; + int auxint; + ist >> auxint; + mp.order = auxint; + return ist; + } + + + class MarkedIdentification + { + public: + // number of points of one face (3 or 4) + int np; + /// 6 or 8 point numbers + PointIndex pnums[8]; + /// marked for refinement + int marked; + /// edge starting with node k (0,1,2, or 3) + int markededge; + + bool incorder; + unsigned int order:6; + }; + + + ostream & operator<< (ostream & ost, const MarkedIdentification & mi) + { + ost << mi.np << " "; + for(int i=0; i<2*mi.np; i++) + ost << mi.pnums[i] << " "; + ost << mi.marked << " " << mi.markededge << " " << mi.incorder << " " << int(mi.order) << "\n"; + return ost; + } + istream & operator>> (istream & ist, MarkedIdentification & mi) + { + ist >> mi.np; + for(int i=0; i<2*mi.np; i++) + ist >> mi.pnums[i]; + ist >> mi.marked >> mi.markededge >> mi.incorder; + int auxint; + ist >> auxint; + mi.order = auxint; + return ist; + } + + + + + + class MarkedTri + { + public: + /// three point numbers + PointIndex pnums[3]; + /// three geominfos + PointGeomInfo pgeominfo[3]; + /// marked for refinement + int marked; + /// edge without node k + int markededge; + /// surface id + int surfid; + + bool incorder; + unsigned int order:6; + }; + + ostream & operator<< (ostream & ost, const MarkedTri & mt) + { + for(int i=0; i<3; i++) + ost << mt.pnums[i] << " "; + for(int i=0; i<3; i++) + ost << mt.pgeominfo[i] << " "; + ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n"; + return ost; + } + istream & operator>> (istream & ist, MarkedTri & mt) + { + for(int i=0; i<3; i++) + ist >> mt.pnums[i]; + for(int i=0; i<3; i++) + ist >> mt.pgeominfo[i]; + ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder; + int auxint; + ist >> auxint; + mt.order = auxint; + return ist; + } + + + + class MarkedQuad + { + public: + /// point numbers + PointIndex pnums[4]; + /// + PointGeomInfo pgeominfo[4]; + /// marked for refinement + int marked; + /// marked edge: 0/2 = vertical, 1/3 = horizontal + int markededge; + /// surface id + int surfid; + + bool incorder; + unsigned int order:6; + }; + + ostream & operator<< (ostream & ost, const MarkedQuad & mt) + { + for(int i=0; i<4; i++) + ost << mt.pnums[i] << " "; + for(int i=0; i<4; i++) + ost << mt.pgeominfo[i] << " "; + ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n"; + return ost; + } + istream & operator>> (istream & ist, MarkedQuad & mt) + { + for(int i=0; i<4; i++) + ist >> mt.pnums[i]; + for(int i=0; i<4; i++) + ist >> mt.pgeominfo[i]; + ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder; + int auxint; + ist >> auxint; + mt.order = auxint; + return ist; + } + + + + + void PrettyPrint(ostream & ost, const MarkedTet & mt) + { + int te1 = mt.tetedge1; + int te2 = mt.tetedge2; + int order = mt.order; + + ost << "MT: " << mt.pnums[0] << " - " << mt.pnums[1] << " - " + << mt.pnums[2] << " - " << mt.pnums[3] << endl + << "marked edge: " << te1 << " - " << te2 + << ", order = " << order << endl; + //for (int k = 0; k < 4; k++) + // ost << int(mt.faceedges[k]) << " "; + for (int k = 0; k < 4; k++) + { + ost << "face"; + for (int j=0; j<4; j++) + if(j != k) + ost << " " << mt.pnums[j]; + for(int i=0; i<3; i++) + for(int j=i+1; j<4; j++) + if(i != k && j != k && mt.faceedges[k] == 6-k-i-j) + ost << " marked edge " << mt.pnums[i] << " " << mt.pnums[j] << endl; + } + ost << endl; + } + + + + + int BTSortEdges (const Mesh & mesh, + const ARRAY< ARRAY<int,PointIndex::BASE>* > & idmaps, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber) + { + PrintMessage(4,"sorting ... "); + + // if (mesh.PureTetMesh()) + if (1) + { + // new, fast version + + ARRAY<INDEX_2> edges; + ARRAY<int> eclasses; + + int i, j, k; + int cntedges = 0; + int go_on; + int ned(0); + + // enumerate edges: + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement (i); + static int tetedges[6][2] = + { { 1, 2 }, + { 1, 3 }, + { 1, 4 }, + { 2, 3 }, + { 2, 4 }, + { 3, 4 } } ; + static int prismedges[9][2] = + { { 1, 2 }, + { 1, 3 }, + { 2, 3 }, + { 4, 5 }, + { 4, 6 }, + { 5, 6 }, + { 1, 4 }, + { 2, 5 }, + { 3, 6 } }; + int pyramidedges[6][2] = + { { 1, 2 }, + { 3, 4 }, + { 1, 5 }, + { 2, 5 }, + { 3, 5 }, + { 4, 5 } }; + + int (*tip)[2] = NULL; + + switch (el.GetType()) + { + case TET: + case TET10: + { + tip = tetedges; + ned = 6; + break; + } + case PRISM: + case PRISM12: + { + tip = prismedges; + ned = 6; + break; + } + case PYRAMID: + { + tip = pyramidedges; + ned = 6; + break; + } + } + + for (j = 0; j < ned; j++) + { + INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1])); + i2.Sort(); + //(*testout) << "edge " << i2 << endl; + if (!edgenumber.Used(i2)) + { + cntedges++; + edges.Append (i2); + edgenumber.Set(i2, cntedges); + } + } + } + + // additional surface edges: + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & el = mesh.SurfaceElement (i); + static int trigedges[3][2] = + { { 1, 2 }, + { 2, 3 }, + { 3, 1 } }; + + static int quadedges[4][2] = + { { 1, 2 }, + { 2, 3 }, + { 3, 4 }, + { 4, 1 } }; + + + int (*tip)[2] = NULL; + + switch (el.GetType()) + { + case TRIG: + case TRIG6: + { + tip = trigedges; + ned = 3; + break; + } + case QUAD: + case QUAD6: + { + tip = quadedges; + ned = 4; + break; + } + default: + { + cerr << "Error: Sort for Bisect, SE has " << el.GetNP() << " points" << endl; + ned = 0; + } + } + + for (j = 0; j < ned; j++) + { + INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1])); + i2.Sort(); + if (!edgenumber.Used(i2)) + { + cntedges++; + edges.Append (i2); + edgenumber.Set(i2, cntedges); + } + } + } + + + + + + eclasses.SetSize (cntedges); + for (i = 1; i <= cntedges; i++) + eclasses.Elem(i) = i; + + // identify edges in element stack + do + { + go_on = 0; + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement (i); + + if (el.GetType() != PRISM && + el.GetType() != PRISM12 && + el.GetType() != PYRAMID) + continue; + + int prismpairs[3][4] = + { { 1, 2, 4, 5 }, + { 2, 3, 5, 6 }, + { 1, 3, 4, 6 } }; + + int pyramidpairs[3][4] = + { { 1, 2, 4, 3 }, + { 1, 5, 4, 5 }, + { 2, 5, 3, 5 } }; + + int (*pairs)[4] = NULL; + switch (el.GetType()) + { + case PRISM: + case PRISM12: + { + pairs = prismpairs; + break; + } + case PYRAMID: + { + pairs = pyramidpairs; + break; + } + } + + for (j = 0; j < 3; j++) + { + INDEX_2 e1 (el.PNum(pairs[j][0]), + el.PNum(pairs[j][1])); + INDEX_2 e2 (el.PNum(pairs[j][2]), + el.PNum(pairs[j][3])); + e1.Sort(); + e2.Sort(); + + int eclass1 = edgenumber.Get (e1); + int eclass2 = edgenumber.Get (e2); + + // (*testout) << "identify edges " << eclass1 << "-" << eclass2 << endl; + + if (eclasses.Get(eclass1) > + eclasses.Get(eclass2)) + { + eclasses.Elem(eclass1) = + eclasses.Get(eclass2); + go_on = 1; + } + else if (eclasses.Get(eclass2) > + eclasses.Get(eclass1)) + { + eclasses.Elem(eclass2) = + eclasses.Get(eclass1); + go_on = 1; + } + } + } + + for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) + { + const Element2d & el2d = mesh[sei]; + + for(i = 0; i < el2d.GetNP(); i++) + { + INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]); + e1.Sort(); + INDEX_2 e2; + + for(k = 0; k < idmaps.Size(); k++) + { + e2.I1() = (*idmaps[k])[e1.I1()]; + e2.I2() = (*idmaps[k])[e1.I2()]; + + if(e2.I1() == 0 || e2.I2() == 0 || + e1.I1() == e2.I1() || e1.I2() == e2.I2()) + continue; + + e2.Sort(); + if(!edgenumber.Used(e2)) + continue; + + + int eclass1 = edgenumber.Get (e1); + int eclass2 = edgenumber.Get (e2); + + if (eclasses.Get(eclass1) > + eclasses.Get(eclass2)) + { + eclasses.Elem(eclass1) = + eclasses.Get(eclass2); + + + go_on = 1; + } + else if (eclasses.Get(eclass2) > + eclasses.Get(eclass1)) + { + eclasses.Elem(eclass2) = + eclasses.Get(eclass1); + go_on = 1; + } + } + } + + } + + } + while (go_on); + +// for (i = 1; i <= cntedges; i++) +// { +// (*testout) << "edge " << i << ": " +// << edges.Get(i).I1() << "-" << edges.Get(i).I2() +// << ", class = " << eclasses.Get(i) << endl; +// } + + // compute classlength: + ARRAY<double> edgelength(cntedges); + + /* + for (i = 1; i <= cntedges; i++) + edgelength.Elem(i) = 1e20; + */ + + for (i = 1; i <= cntedges; i++) + { + INDEX_2 edge = edges.Get(i); + double elen = Dist (mesh.Point(edge.I1()), + mesh.Point(edge.I2())); + edgelength.Elem (i) = elen; + } + + /* + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement (i); + + if (el.GetType() == TET) + { + for (j = 1; j <= 3; j++) + for (k = j+1; k <= 4; k++) + { + INDEX_2 i2(el.PNum(j), el.PNum(k)); + i2.Sort(); + + int enr = edgenumber.Get(i2); + double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); + if (elen < edgelength.Get(enr)) + edgelength.Set (enr, elen); + } + } + else if (el.GetType() == PRISM) + { + for (j = 1; j <= 3; j++) + { + k = (j % 3) + 1; + + INDEX_2 i2(el.PNum(j), el.PNum(k)); + i2.Sort(); + + int enr = edgenumber.Get(i2); + double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); + if (elen < edgelength.Get(enr)) + edgelength.Set (enr, elen); + + i2 = INDEX_2(el.PNum(j+3), el.PNum(k+3)); + i2.Sort(); + + enr = edgenumber.Get(i2); + elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); + if (elen < edgelength.Get(enr)) + edgelength.Set (enr, elen); + + if (!edgenumber.Used(i2)) + { + cntedges++; + edgenumber.Set(i2, cntedges); + } + i2 = INDEX_2(el.PNum(j), el.PNum(j+3)); + i2.Sort(); + + enr = edgenumber.Get(i2); + elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2())); + if (elen < edgelength.Get(enr)) + edgelength.Set (enr, elen); + } + } + } + */ + + + for (i = 1; i <= cntedges; i++) + { + if (eclasses.Get(i) != i) + { + if (edgelength.Get(i) < edgelength.Get(eclasses.Get(i))) + edgelength.Elem(eclasses.Get(i)) = edgelength.Get(i); + edgelength.Elem(i) = 1e20; + } + } + + + TABLE<int> eclasstab(cntedges); + for (i = 1; i <= cntedges; i++) + eclasstab.Add1 (eclasses.Get(i), i); + + + // sort edges: + ARRAY<int> sorted(cntedges); + + QickSort (edgelength, sorted); + + int cnt = 0; + for (i = 1; i <= cntedges; i++) + { + int ii = sorted.Get(i); + for (j = 1; j <= eclasstab.EntrySize(ii); j++) + { + cnt++; + edgenumber.Set (edges.Get(eclasstab.Get(ii, j)), cnt); + } + } + return cnt; + } + + else + + { + // old version + + int i, j; + int cnt = 0; + int found; + double len2, maxlen2; + INDEX_2 ep; + + // sort edges by length, parallel edges (on prisms) + // are added in blocks + + do + { + found = 0; + maxlen2 = 1e30; + + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement (i); + int ned; + int tetedges[6][2] = + { { 1, 2 }, + { 1, 3 }, + { 1, 4 }, + { 2, 3 }, + { 2, 4 }, + { 3, 4 } }; + int prismedges[6][2] = + { { 1, 2 }, + { 1, 3 }, + { 2, 4 }, + { 4, 5 }, + { 4, 6 }, + { 5, 6 } }; + int pyramidedges[6][2] = + { { 1, 2 }, + { 3, 4 }, + { 1, 5 }, + { 2, 5 }, + { 3, 5 }, + { 4, 5 } }; + + int (*tip)[2]; + + switch (el.GetType()) + { + case TET: + { + tip = tetedges; + ned = 6; + break; + } + case PRISM: + { + tip = prismedges; + ned = 6; + break; + } + case PYRAMID: + { + tip = pyramidedges; + ned = 6; + break; + } + } + + for (j = 0; j < ned; j++) + { + INDEX_2 i2(el.PNum(tip[j][0]), el.PNum(tip[j][1])); + i2.Sort(); + if (!edgenumber.Used(i2)) + { + len2 = Dist (mesh.Point (i2.I1()), + mesh.Point (i2.I2())); + if (len2 < maxlen2) + { + maxlen2 = len2; + ep = i2; + found = 1; + } + } + } + } + if (found) + { + cnt++; + edgenumber.Set (ep, cnt); + + + // find connected edges: + int go_on = 0; + do + { + go_on = 0; + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement (i); + if (el.GetNP() != 6) continue; + + int prismpairs[3][4] = + { { 1, 2, 4, 5 }, + { 2, 3, 5, 6 }, + { 1, 3, 4, 6 } }; + + int pyramidpairs[3][4] = + { { 1, 2, 4, 3 }, + { 1, 5, 4, 5 }, + { 2, 5, 3, 5 } }; + + int (*pairs)[4]; + switch (el.GetType()) + { + case PRISM: + { + pairs = prismpairs; + break; + } + case PYRAMID: + { + pairs = pyramidpairs; + break; + } + } + + for (j = 0; j < 3; j++) + { + INDEX_2 e1 (el.PNum(pairs[j][0]), + el.PNum(pairs[j][1])); + INDEX_2 e2 (el.PNum(pairs[j][2]), + el.PNum(pairs[j][3])); + e1.Sort(); + e2.Sort(); + + int used1 = edgenumber.Used (e1); + int used2 = edgenumber.Used (e2); + + if (used1 && !used2) + { + cnt++; + edgenumber.Set (e2, cnt); + go_on = 1; + } + if (used2 && !used1) + { + cnt++; + edgenumber.Set (e1, cnt); + go_on = 1; + } + } + } + } + while (go_on); + } + } + while (found); + + return cnt; + } + } + + + + + void BTDefineMarkedTet (const Element & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + MarkedTet & mt) + { + int i, j, k; + for (i = 0; i < 4; i++) + mt.pnums[i] = el[i]; + + mt.marked = 0; + mt.flagged = 0; + + mt.incorder = 0; + mt.order = 1; + + int val = 0; + // find marked edge of tet: + for (i = 0; i < 3; i++) + for (j = i+1; j < 4; j++) + { + INDEX_2 i2(mt.pnums[i], mt.pnums[j]); + i2.Sort(); + int hval = edgenumber.Get(i2); + if (hval > val) + { + val = hval; + mt.tetedge1 = i; + mt.tetedge2 = j; + } + } + + + // find marked edges of faces: + for (k = 0; k < 4; k++) + { + val = 0; + for (i = 0; i < 3; i++) + for (j = i+1; j < 4; j++) + if (i != k && j != k) + { + INDEX_2 i2(mt.pnums[i], mt.pnums[j]); + i2.Sort(); + int hval = edgenumber.Get(i2); + if (hval > val) + { + val = hval; + mt.faceedges[k] = 6 - k - i - j; + } + } + } + } + + + + + void BTDefineMarkedPrism (const Element & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + MarkedPrism & mp) + { + int i, j; + + if (el.GetType() == PRISM || + el.GetType() == PRISM12) + { + for (i = 0; i < 6; i++) + mp.pnums[i] = el[i]; + } + else if (el.GetType() == PYRAMID) + { + static int map[6] = + { 1, 2, 5, 4, 3, 5 }; + for (i = 0; i < 6; i++) + mp.pnums[i] = el.PNum(map[i]); + } + else if (el.GetType() == TET || + el.GetType() == TET10) + { + static int map[6] = + { 1, 4, 3, 2, 4, 3 }; + for (i = 0; i < 6; i++) + mp.pnums[i] = el.PNum(map[i]); + + } + else + { + PrintSysError ("Define marked prism called for non-prism and non-pyramid"); + } + + + + mp.marked = 0; + + mp.incorder = 0; + mp.order = 1; + + int val = 0; + for (i = 0; i < 2; i++) + for (j = i+1; j < 3; j++) + { + INDEX_2 i2(mp.pnums[i], mp.pnums[j]); + i2.Sort(); + int hval = edgenumber.Get(i2); + if (hval > val) + { + val = hval; + mp.markededge = 3 - i - j; + } + } + } + + + + bool BTDefineMarkedId(const Element2d & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + const ARRAY<int,PointIndex::BASE> & idmap, + MarkedIdentification & mi) + { + + bool identified = true; + mi.np = el.GetNP(); + int min1(0),min2(0); + for(int j = 0; identified && j < mi.np; j++) + { + mi.pnums[j] = el[j]; + mi.pnums[j+mi.np] = idmap[el[j]]; + + if(j == 0 || el[j] < min1) + min1 = el[j]; + if(j == 0 || mi.pnums[j+mi.np] < min2) + min2 = mi.pnums[j+mi.np]; + + identified = (mi.pnums[j+mi.np] != 0 && mi.pnums[j+mi.np] != mi.pnums[j]); + } + + identified = identified && (min1 < min2); + + if(identified) + { + mi.marked = 0; + + mi.incorder = 0; + mi.order = 1; + + int val = 0; + for (int i = 0; i < mi.np; i++) + { + INDEX_2 i2(mi.pnums[i], mi.pnums[(i+1)%mi.np]); + i2.Sort(); + int hval = edgenumber.Get(i2); + if (hval > val) + { + val = hval; + mi.markededge = i; + } + } + } + + return identified; + } + + + void BTDefineMarkedTri (const Element2d & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + MarkedTri & mt) + { + int i, j; + for (i = 0; i < 3; i++) + { + mt.pnums[i] = el[i]; + mt.pgeominfo[i] = el.GeomInfoPi (i+1); + } + + mt.marked = 0; + mt.surfid = el.GetIndex(); + + mt.incorder = 0; + mt.order = 1; + + int val = 0; + for (i = 0; i < 2; i++) + for (j = i+1; j < 3; j++) + { + INDEX_2 i2(mt.pnums[i], mt.pnums[j]); + i2.Sort(); + int hval = edgenumber.Get(i2); + if (hval > val) + { + val = hval; + mt.markededge = 3 - i - j; + } + } + } + + + + void PrettyPrint(ostream & ost, const MarkedTri & mt) + { + ost << "MarkedTrig: " << endl; + ost << " pnums = "; for (int i=0; i<3; i++) ost << mt.pnums[i] << " "; ost << endl; + ost << " marked = " << mt.marked << ", markededge=" << mt.markededge << endl; + for(int i=0; i<2; i++) + for(int j=i+1; j<3; j++) + if(mt.markededge == 3-i-j) + ost << " marked edge pnums = " << mt.pnums[i] << " " << mt.pnums[j] << endl; + } + + + void PrettyPrint(ostream & ost, const MarkedQuad & mq) + { + ost << "MarkedQuad: " << endl; + ost << " pnums = "; for (int i=0; i<4; i++) ost << mq.pnums[i] << " "; ost << endl; + ost << " marked = " << mq.marked << ", markededge=" << mq.markededge << endl; + } + + + + + + void BTDefineMarkedQuad (const Element2d & el, + INDEX_2_CLOSED_HASHTABLE<int> & edgenumber, + MarkedQuad & mq) + { + int i; + for (i = 0; i < 4; i++) + mq.pnums[i] = el[i]; + Swap (mq.pnums[2], mq.pnums[3]); + + mq.marked = 0; + mq.markededge = 0; + mq.surfid = el.GetIndex(); + } + + + + + // mark elements due to local h + int BTMarkTets (T_MTETS & mtets, + T_MPRISMS & mprisms, + const Mesh & mesh) + { + int i, j, k; + int step; + + int marked = 0; + + int np = mesh.GetNP(); + Vector hv(np); + for (i = 1; i <= np; i++) + hv.Elem(i) = mesh.GetH (mesh.Point(i)); + + double hfac = 1; + + for (step = 1; step <= 2; step++) + { + for (i = 1; i <= mtets.Size(); i++) + { + double h = 0; + + for (j = 0; j < 3; j++) + for (k = j+1; k < 4; k++) + { + const Point<3> & p1 = mesh.Point (mtets.Get(i).pnums[j]); + const Point<3> & p2 = mesh.Point (mtets.Get(i).pnums[k]); + double hh = Dist2 (p1, p2); + if (hh > h) h = hh; + } + h = sqrt (h); + + double hshould = 1e10; + for (j = 0; j < 4; j++) + { + double hi = hv.Get (mtets.Get(i).pnums[j]); + if (hi < hshould) + hshould = hi; + } + + + if (step == 1) + { + if (h / hshould > hfac) + hfac = h / hshould; + } + else + { + if (h > hshould * hfac) + { + mtets.Elem(i).marked = 1; + marked = 1; + } + else + mtets.Elem(i).marked = 0; + } + + } + for (i = 1; i <= mprisms.Size(); i++) + { + double h = 0; + + for (j = 0; j < 2; j++) + for (k = j+1; k < 3; k++) + { + const Point<3> & p1 = mesh.Point (mprisms.Get(i).pnums[j]); + const Point<3> & p2 = mesh.Point (mprisms.Get(i).pnums[k]); + double hh = Dist2 (p1, p2); + if (hh > h) h = hh; + } + h = sqrt (h); + + double hshould = 1e10; + for (j = 0; j < 6; j++) + { + double hi = hv.Get (mprisms.Get(i).pnums[j]); + if (hi < hshould) + hshould = hi; + } + + + if (step == 1) + { + if (h / hshould > hfac) + hfac = h / hshould; + } + else + { + if (h > hshould * hfac) + { + mprisms.Elem(i).marked = 1; + marked = 1; + } + else + mprisms.Elem(i).marked = 0; + } + + } + + + + if (step == 1) + { + if (hfac > 2) + hfac /= 2; + else + hfac = 1; + } + + } + return marked; + } + + + + + + + + + + + + + + + void BTBisectTet (const MarkedTet & oldtet, int newp, + MarkedTet & newtet1, MarkedTet & newtet2) + { + int i, j, k; + + + // points vis a vis from tet-edge + int vis1, vis2; + vis1 = 0; + while (vis1 == oldtet.tetedge1 || vis1 == oldtet.tetedge2) + vis1++; + vis2 = 6 - vis1 - oldtet.tetedge1 - oldtet.tetedge2; + + + // is tet of type P ? + int istypep = 0; + for (i = 0; i < 4; i++) + { + int cnt = 0; + for (j = 0; j < 4; j++) + if (oldtet.faceedges[j] == i) + cnt++; + if (cnt == 3) + istypep = 1; + } + + + + for (i = 0; i < 4; i++) + { + newtet1.pnums[i] = oldtet.pnums[i]; + newtet2.pnums[i] = oldtet.pnums[i]; + } + newtet1.flagged = istypep && !oldtet.flagged; + newtet2.flagged = istypep && !oldtet.flagged; + + int nm = oldtet.marked - 1; + if (nm < 0) nm = 0; + newtet1.marked = nm; + newtet2.marked = nm; + + + for (i = 0; i < 4; i++) + { + if (i == oldtet.tetedge1) + { + newtet2.pnums[i] = newp; + newtet2.faceedges[i] = oldtet.faceedges[i]; // inherited face + newtet2.faceedges[vis1] = i; // cut faces + newtet2.faceedges[vis2] = i; + + j = 0; + while (j == i || j == oldtet.faceedges[i]) + j++; + k = 6 - i - oldtet.faceedges[i] - j; + newtet2.tetedge1 = j; // tet-edge + newtet2.tetedge2 = k; + + // new face: + if (istypep && oldtet.flagged) + newtet2.faceedges[oldtet.tetedge2] = + 6 - oldtet.tetedge1 - j - k; + else + newtet2.faceedges[oldtet.tetedge2] = oldtet.tetedge1; + } + + if (i == oldtet.tetedge2) + { + newtet1.pnums[i] = newp; + newtet1.faceedges[i] = oldtet.faceedges[i]; // inherited face + newtet1.faceedges[vis1] = i; + newtet1.faceedges[vis2] = i; + j = 0; + while (j == i || j == oldtet.faceedges[i]) + j++; + k = 6 - i - oldtet.faceedges[i] - j; + newtet1.tetedge1 = j; + newtet1.tetedge2 = k; + + // new face: + if (istypep && oldtet.flagged) + newtet1.faceedges[oldtet.tetedge1] = + 6 - oldtet.tetedge2 - j - k; + else + newtet1.faceedges[oldtet.tetedge1] = oldtet.tetedge2; + } + } + + newtet1.matindex = oldtet.matindex; + newtet2.matindex = oldtet.matindex; + newtet1.incorder = 0; + newtet1.order = oldtet.order; + newtet2.incorder = 0; + newtet2.order = oldtet.order; + } + + + + + void BTBisectPrism (const MarkedPrism & oldprism, int newp1, int newp2, + MarkedPrism & newprism1, MarkedPrism & newprism2) + { + int i; + + for (i = 0; i < 6; i++) + { + newprism1.pnums[i] = oldprism.pnums[i]; + newprism2.pnums[i] = oldprism.pnums[i]; + } + + int pe1, pe2; + pe1 = 0; + if (pe1 == oldprism.markededge) + pe1++; + pe2 = 3 - oldprism.markededge - pe1; + + newprism1.pnums[pe2] = newp1; + newprism1.pnums[pe2+3] = newp2; + newprism1.markededge = pe2; + newprism2.pnums[pe1] = newp1; + newprism2.pnums[pe1+3] = newp2; + newprism2.markededge = pe1; + + newprism1.matindex = oldprism.matindex; + newprism2.matindex = oldprism.matindex; + + int nm = oldprism.marked - 1; + if (nm < 0) nm = 0; + newprism1.marked = nm; + newprism2.marked = nm; + + newprism1.incorder = 0; + newprism1.order = oldprism.order; + newprism2.incorder = 0; + newprism2.order = oldprism.order; + } + + + void BTBisectIdentification (const MarkedIdentification & oldid, + ARRAY<int> & newp, + MarkedIdentification & newid1, + MarkedIdentification & newid2) + { + for(int i=0; i<2*oldid.np; i++) + { + newid1.pnums[i] = oldid.pnums[i]; + newid2.pnums[i] = oldid.pnums[i]; + } + newid1.np = newid2.np = oldid.np; + + if(oldid.np == 3) + { + newid1.pnums[(oldid.markededge+1)%3] = newp[0]; + newid1.pnums[(oldid.markededge+1)%3+3] = newp[1]; + newid1.markededge = (oldid.markededge+2)%3; + + newid2.pnums[oldid.markededge] = newp[0]; + newid2.pnums[oldid.markededge+3] = newp[1]; + newid2.markededge = (oldid.markededge+1)%3; + } + else if(oldid.np == 4) + { + newid1.pnums[(oldid.markededge+1)%4] = newp[0]; + newid1.pnums[(oldid.markededge+2)%4] = newp[2]; + newid1.pnums[(oldid.markededge+1)%4+4] = newp[1]; + newid1.pnums[(oldid.markededge+2)%4+4] = newp[3]; + newid1.markededge = (oldid.markededge+3)%4; + + newid2.pnums[oldid.markededge] = newp[0]; + newid2.pnums[(oldid.markededge+3)%4] = newp[2]; + newid2.pnums[oldid.markededge+4] = newp[1]; + newid2.pnums[(oldid.markededge+3)%4+4] = newp[3]; + newid2.markededge = (oldid.markededge+1)%4; + } + + + int nm = oldid.marked - 1; + if (nm < 0) nm = 0; + newid1.marked = newid2.marked = nm; + + newid1.incorder = newid2.incorder = 0; + newid1.order = newid2.order = oldid.order; + } + + + + void BTBisectTri (const MarkedTri & oldtri, int newp, const PointGeomInfo & newpgi, + MarkedTri & newtri1, MarkedTri & newtri2) + { + int i; + + for (i = 0; i < 3; i++) + { + newtri1.pnums[i] = oldtri.pnums[i]; + newtri1.pgeominfo[i] = oldtri.pgeominfo[i]; + newtri2.pnums[i] = oldtri.pnums[i]; + newtri2.pgeominfo[i] = oldtri.pgeominfo[i]; + } + + int pe1, pe2; + pe1 = 0; + if (pe1 == oldtri.markededge) + pe1++; + pe2 = 3 - oldtri.markededge - pe1; + + newtri1.pnums[pe2] = newp; + newtri1.pgeominfo[pe2] = newpgi; + newtri1.markededge = pe2; + + newtri2.pnums[pe1] = newp; + newtri2.pgeominfo[pe1] = newpgi; + newtri2.markededge = pe1; + + + newtri1.surfid = oldtri.surfid; + newtri2.surfid = oldtri.surfid; + + int nm = oldtri.marked - 1; + if (nm < 0) nm = 0; + newtri1.marked = nm; + newtri2.marked = nm; + + newtri1.incorder = 0; + newtri1.order = oldtri.order; + newtri2.incorder = 0; + newtri2.order = oldtri.order; + + + } + + + void BTBisectQuad (const MarkedQuad & oldquad, + int newp1, const PointGeomInfo & npgi1, + int newp2, const PointGeomInfo & npgi2, + MarkedQuad & newquad1, MarkedQuad & newquad2) + { + int i; + + for (i = 0; i < 4; i++) + { + newquad1.pnums[i] = oldquad.pnums[i]; + newquad1.pgeominfo[i] = oldquad.pgeominfo[i]; + newquad2.pnums[i] = oldquad.pnums[i]; + newquad2.pgeominfo[i] = oldquad.pgeominfo[i]; + } + +/* if (oldquad.marked==1) // he/sz: 2d quads or 3d prism + { + newquad1.pnums[1] = newp1; + newquad1.pgeominfo[1] = npgi1; + newquad1.pnums[3] = newp2; + newquad1.pgeominfo[3] = npgi2; + + newquad2.pnums[0] = newp1; + newquad2.pgeominfo[0] = npgi1; + newquad2.pnums[2] = newp2; + newquad2.pgeominfo[2] = npgi2; + } + + else if (oldquad.marked==2) // he/sz: 2d quads only + { + newquad1.pnums[0] = newp1; + newquad1.pnums[1] = newp2; + newquad1.pnums[3] = oldquad.pnums[2]; + newquad1.pnums[2] = oldquad.pnums[0]; + newquad1.pgeominfo[0] = npgi1; + newquad1.pgeominfo[1] = npgi2; + newquad1.pgeominfo[3] = oldquad.pgeominfo[2]; + newquad1.pgeominfo[2] = oldquad.pgeominfo[0]; + + newquad2.pnums[0] = newp2; + newquad2.pnums[1] = newp1; + newquad2.pnums[3] = oldquad.pnums[1]; + newquad2.pnums[2] = oldquad.pnums[3]; + newquad2.pgeominfo[0] = npgi2; + newquad2.pgeominfo[1] = npgi1; + newquad2.pgeominfo[3] = oldquad.pgeominfo[1]; + newquad2.pgeominfo[2] = oldquad.pgeominfo[3]; + } + + */ + + if (oldquad.markededge==0 || oldquad.markededge==2) + { + newquad1.pnums[1] = newp1; + newquad1.pgeominfo[1] = npgi1; + newquad1.pnums[3] = newp2; + newquad1.pgeominfo[3] = npgi2; + + newquad2.pnums[0] = newp1; + newquad2.pgeominfo[0] = npgi1; + newquad2.pnums[2] = newp2; + newquad2.pgeominfo[2] = npgi2; + } + else // 1 || 3 + { + newquad1.pnums[2] = newp1; + newquad1.pgeominfo[2] = npgi1; + newquad1.pnums[3] = newp2; + newquad1.pgeominfo[3] = npgi2; + + newquad2.pnums[0] = newp1; + newquad2.pgeominfo[0] = npgi1; + newquad2.pnums[1] = newp2; + newquad2.pgeominfo[1] = npgi2; + } + newquad1.surfid = oldquad.surfid; + newquad2.surfid = oldquad.surfid; + + int nm = oldquad.marked - 1; + if (nm < 0) nm = 0; + + newquad1.marked = nm; + newquad2.marked = nm; + + if (nm==1) + { + newquad1.markededge=1; + newquad2.markededge=1; + } + else + { + newquad1.markededge=0; + newquad2.markededge=0; + } + + } + + + int MarkHangingIdentifications(T_MIDS & mids, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i, j; + + int hanging = 0; + for (i = 1; i <= mids.Size(); i++) + { + if (mids.Elem(i).marked) + { + hanging = 1; + continue; + } + + const int np = mids.Get(i).np; + + for(j = 0; j < np; j++) + { + INDEX_2 edge1(mids.Get(i).pnums[j], + mids.Get(i).pnums[(j+1) % np]); + INDEX_2 edge2(mids.Get(i).pnums[j+np], + mids.Get(i).pnums[((j+1) % np) + np]); + + edge1.Sort(); + edge2.Sort(); + if (cutedges.Used (edge1) || + cutedges.Used (edge2)) + { + mids.Elem(i).marked = 1; + hanging = 1; + } + } + } + + return hanging; + } + + + /* + void IdentifyCutEdges(Mesh & mesh, + INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i,j,k; + + ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps; + for(i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + idmaps.Append(new ARRAY<int,PointIndex::BASE>); + mesh.GetIdentifications().GetMap(i,*idmaps.Last()); + } + + + + for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) + { + const Element2d & el2d = mesh[sei]; + + for(i = 0; i < el2d.GetNP(); i++) + { + INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]); + e1.Sort(); + + if(!cutedges.Used(e1)) + continue; + + + for(k = 0; k < idmaps.Size(); k++) + { + INDEX_2 e2((*idmaps[k])[e1.I1()], + (*idmaps[k])[e1.I2()]); + + if(e2.I1() == 0 || e2.I2() == 0 || + e1.I1() == e2.I1() || e1.I2() == e2.I2()) + continue; + + e2.Sort(); + + if(cutedges.Used(e2)) + continue; + + Point3d np = Center(mesh.Point(e2.I1()), + mesh.Point(e2.I2())); + int newp = mesh.AddPoint(np); + cutedges.Set(e2,newp); + (*testout) << "DAAA" << endl; + } + } + } + + + for(i=0; i<idmaps.Size(); i++) + delete idmaps[i]; + idmaps.DeleteAll(); + } + */ + + + int MarkHangingTets (T_MTETS & mtets, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i, j, k; + + int hanging = 0; + for (i = 1; i <= mtets.Size(); i++) + { + MarkedTet & teti = mtets.Elem(i); + + if (teti.marked) + { + hanging = 1; + continue; + } + + for (j = 0; j < 3; j++) + for (k = j+1; k < 4; k++) + { + INDEX_2 edge(teti.pnums[j], + teti.pnums[k]); + edge.Sort(); + if (cutedges.Used (edge)) + { + teti.marked = 1; + hanging = 1; + } + } + } + + return hanging; + } + + + + int MarkHangingPrisms (T_MPRISMS & mprisms, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i, j, k; + + int hanging = 0; + for (i = 1; i <= mprisms.Size(); i++) + { + if (mprisms.Elem(i).marked) + { + hanging = 1; + continue; + } + + for (j = 0; j < 2; j++) + for (k = j+1; k < 3; k++) + { + INDEX_2 edge1(mprisms.Get(i).pnums[j], + mprisms.Get(i).pnums[k]); + INDEX_2 edge2(mprisms.Get(i).pnums[j+3], + mprisms.Get(i).pnums[k+3]); + edge1.Sort(); + edge2.Sort(); + if (cutedges.Used (edge1) || + cutedges.Used (edge2)) + { + mprisms.Elem(i).marked = 1; + hanging = 1; + } + } + } + return hanging; + } + + + + int MarkHangingTris (T_MTRIS & mtris, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i, j, k; + + int hanging = 0; + for (i = 1; i <= mtris.Size(); i++) + { + if (mtris.Get(i).marked) + { + hanging = 1; + continue; + } + for (j = 0; j < 2; j++) + for (k = j+1; k < 3; k++) + { + INDEX_2 edge(mtris.Get(i).pnums[j], + mtris.Get(i).pnums[k]); + edge.Sort(); + if (cutedges.Used (edge)) + { + mtris.Elem(i).marked = 1; + hanging = 1; + } + } + } + return hanging; + } + + + + int MarkHangingQuads (T_MQUADS & mquads, + const INDEX_2_CLOSED_HASHTABLE<int> & cutedges) + { + int i; + + int hanging = 0; + for (i = 1; i <= mquads.Size(); i++) + { + if (mquads.Elem(i).marked) + { + hanging = 1; + continue; + } + + INDEX_2 edge1(mquads.Get(i).pnums[0], + mquads.Get(i).pnums[1]); + INDEX_2 edge2(mquads.Get(i).pnums[2], + mquads.Get(i).pnums[3]); + edge1.Sort(); + edge2.Sort(); + if (cutedges.Used (edge1) || + cutedges.Used (edge2)) + { + mquads.Elem(i).marked = 1; + mquads.Elem(i).markededge = 0; + hanging = 1; + continue; + } + + // he/sz: second case: split horizontally + INDEX_2 edge3(mquads.Get(i).pnums[1], + mquads.Get(i).pnums[3]); + INDEX_2 edge4(mquads.Get(i).pnums[2], + mquads.Get(i).pnums[0]); + + edge3.Sort(); + edge4.Sort(); + if (cutedges.Used (edge3) || + cutedges.Used (edge4)) + { + mquads.Elem(i).marked = 1; + mquads.Elem(i).markededge = 1; + hanging = 1; + continue; + } + + } + return hanging; + } + + + + void ConnectToNodeRec (int node, int tonode, + const TABLE<int> & conto, ARRAY<int> & connecttonode) + { + int i, n2; + // (*testout) << "connect " << node << " to " << tonode << endl; + for (i = 1; i <= conto.EntrySize(node); i++) + { + n2 = conto.Get(node, i); + if (!connecttonode.Get(n2)) + { + connecttonode.Elem(n2) = tonode; + ConnectToNodeRec (n2, tonode, conto, connecttonode); + } + } + } + + + + + T_MTETS mtets; + T_MPRISMS mprisms; + T_MIDS mids; + T_MTRIS mtris; + T_MQUADS mquads; + + + void WriteMarkedElements(ostream & ost) + { + ost << "Marked Elements\n"; + + ost << mtets.Size() << "\n"; + for(int i=0; i<mtets.Size(); i++) + ost << mtets[i]; + + ost << mprisms.Size() << "\n"; + for(int i=0; i<mprisms.Size(); i++) + ost << mprisms[i]; + + ost << mids.Size() << "\n"; + for(int i=0; i<mids.Size(); i++) + ost << mids[i]; + + ost << mtris.Size() << "\n"; + for(int i=0; i<mtris.Size(); i++) + ost << mtris[i]; + + ost << mquads.Size() << "\n"; + for(int i=0; i<mquads.Size(); i++) + ost << mquads[i]; + ost << endl; + } + + bool ReadMarkedElements(istream & ist, const Mesh & mesh) + { + string auxstring(""); + if(ist) + ist >> auxstring; + + if(auxstring != "Marked") + return false; + + if(ist) + ist >> auxstring; + + if(auxstring != "Elements") + return false; + + int size; + + ist >> size; + mtets.SetSize(size); + for(int i=0; i<size; i++) + { + ist >> mtets[i]; + if(mtets[i].pnums[0] > mesh.GetNV() || + mtets[i].pnums[1] > mesh.GetNV() || + mtets[i].pnums[2] > mesh.GetNV() || + mtets[i].pnums[3] > mesh.GetNV()) + return false; + } + + ist >> size; + mprisms.SetSize(size); + for(int i=0; i<size; i++) + ist >> mprisms[i]; + + ist >> size; + mids.SetSize(size); + for(int i=0; i<size; i++) + ist >> mids[i]; + + ist >> size; + mtris.SetSize(size); + for(int i=0; i<size; i++) + ist >> mtris[i]; + + ist >> size; + mquads.SetSize(size); + for(int i=0; i<size; i++) + ist >> mquads[i]; + + return true; + } + + + + + + void BisectTetsCopyMesh (Mesh & mesh, const class CSGeometry *, + BisectionOptions & opt, + const ARRAY< ARRAY<int,PointIndex::BASE>* > & idmaps, + const string & refinfofile) + { + mtets.SetName ("bisection, tets"); + mprisms.SetName ("bisection, prisms"); + mtris.SetName ("bisection, trigs"); + mquads.SetName ("bisection, quads"); + mids.SetName ("bisection, identifications"); + + //int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int i, j, k, l, m; + + /* + if (mtets.Size() + mprisms.Size() == mesh.GetNE()) + return; + */ + + bool readok = false; + + if(refinfofile != "") + { + PrintMessage(3,"Reading marked-element information from \"",refinfofile,"\""); + ifstream ist(refinfofile.c_str()); + + readok = ReadMarkedElements(ist,mesh); + + ist.close(); + } + + if(!readok) + { + PrintMessage(3,"resetting marked-element information"); + mtets.SetSize(0); + mprisms.SetSize(0); + mids.SetSize(0); + mtris.SetSize(0); + mquads.SetSize(0); + + + INDEX_2_HASHTABLE<int> shortedges(100); + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + if (el.GetType() == PRISM || + el.GetType() == PRISM12) + { + for (j = 1; j <= 3; j++) + { + INDEX_2 se(el.PNum(j), el.PNum(j+3)); + se.Sort(); + shortedges.Set (se, 1); + } + } + } + + + + // INDEX_2_HASHTABLE<int> edgenumber(np); + INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse); + + BTSortEdges (mesh, idmaps, edgenumber); + + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + + switch (el.GetType()) + { + case TET: + case TET10: + { + // if tet has short edge, it is handled as degenerated prism + + int foundse = 0; + for (j = 1; j <= 3; j++) + for (k = j+1; k <= 4; k++) + { + INDEX_2 se(el.PNum(j), el.PNum(k)); + se.Sort(); + if (shortedges.Used (se)) + { + // cout << "tet converted to prism" << endl; + + foundse = 1; + int p3 = 1; + while (p3 == j || p3 == k) + p3++; + int p4 = 10 - j - k - p3; + + // even permutation ? + int pi[4]; + pi[0] = j; + pi[1] = k; + pi[2] = p3; + pi[3] = p4; + int cnt = 0; + for (l = 1; l <= 4; l++) + for (m = 0; m < 3; m++) + if (pi[m] > pi[m+1]) + { + Swap (pi[m], pi[m+1]); + cnt++; + } + if (cnt % 2) + Swap (p3, p4); + + Element hel = el; + hel.PNum(1) = el.PNum(j); + hel.PNum(2) = el.PNum(k); + hel.PNum(3) = el.PNum(p3); + hel.PNum(4) = el.PNum(p4); + + MarkedPrism mp; + BTDefineMarkedPrism (hel, edgenumber, mp); + mp.matindex = el.GetIndex(); + mprisms.Append (mp); + } + } + if (!foundse) + { + MarkedTet mt; + BTDefineMarkedTet (el, edgenumber, mt); + mt.matindex = el.GetIndex(); + mtets.Append (mt); + } + break; + } + case PYRAMID: + { + // eventually rotate + MarkedPrism mp; + + INDEX_2 se(el.PNum(1), el.PNum(2)); + se.Sort(); + if (shortedges.Used (se)) + { + Element hel = el; + hel.PNum(1) = el.PNum(2); + hel.PNum(2) = el.PNum(3); + hel.PNum(3) = el.PNum(4); + hel.PNum(4) = el.PNum(1); + BTDefineMarkedPrism (hel, edgenumber, mp); + } + else + { + BTDefineMarkedPrism (el, edgenumber, mp); + } + + mp.matindex = el.GetIndex(); + mprisms.Append (mp); + break; + } + case PRISM: + case PRISM12: + { + MarkedPrism mp; + BTDefineMarkedPrism (el, edgenumber, mp); + mp.matindex = el.GetIndex(); + mprisms.Append (mp); + break; + } + } + } + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (el.GetType() == TRIG || + el.GetType() == TRIG6) + { + MarkedTri mt; + BTDefineMarkedTri (el, edgenumber, mt); + mtris.Append (mt); + } + else + { + MarkedQuad mq; + BTDefineMarkedQuad (el, edgenumber, mq); + mquads.Append (mq); + } + + MarkedIdentification mi; + for(j=0; j<idmaps.Size(); j++) + if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi)) + mids.Append(mi); + } + } + + + + + mesh.mlparentelement.SetSize(ne); + for (i = 1; i <= ne; i++) + mesh.mlparentelement.Elem(i) = 0; + mesh.mlparentsurfaceelement.SetSize(nse); + for (i = 1; i <= nse; i++) + mesh.mlparentsurfaceelement.Elem(i) = 0; + + if (printmessage_importance>0) + { + ostringstream str1,str2; + str1 << "copied " << mtets.Size() << " tets, " << mprisms.Size() << " prisms"; + str2 << " " << mtris.Size() << " trigs, " << mquads.Size() << " quads"; + + PrintMessage(4,str1.str()); + PrintMessage(4,str2.str()); + } + } + + + /* + void UpdateEdgeMarks2(Mesh & mesh, + const ARRAY< ARRAY<int,PointIndex::BASE>* > & idmaps) + { + ARRAY< ARRAY<MarkedTet>*,PointIndex::BASE > mtets_old(mesh.GetNP()); + ARRAY< ARRAY<MarkedPrism>*,PointIndex::BASE > mprisms_old(mesh.GetNP()); + ARRAY< ARRAY<MarkedIdentification>*,PointIndex::BASE > mids_old(mesh.GetNP()); + ARRAY< ARRAY<MarkedTri>*,PointIndex::BASE > mtris_old(mesh.GetNP()); + ARRAY< ARRAY<MarkedQuad>*,PointIndex::BASE > mquads_old(mesh.GetNP()); + + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mtets_old[i] = new ARRAY<MarkedTet>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mprisms_old[i] = new ARRAY<MarkedPrism>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mids_old[i] = new ARRAY<MarkedIdentification>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mtris_old[i] = new ARRAY<MarkedTri>; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + mquads_old[i] = new ARRAY<MarkedQuad>; + + for(int i=0; i<mtets.Size(); i++) + mtets_old[mtets[i].pnums[0]]->Append(mtets[i]); + for(int i=0; i<mprisms.Size(); i++) + mprisms_old[mprisms[i].pnums[0]]->Append(mprisms[i]); + for(int i=0; i<mids.Size(); i++) + mids_old[mids[i].pnums[0]]->Append(mids[i]); + for(int i=0; i<mtris.Size(); i++) + { + (*testout) << "i " << i << endl; + (*testout) << "mtris[i] " << mtris[i].pnums[0] << " " << mtris[i].pnums[1] << " " << mtris[i].pnums[2] << endl; + mtris_old[mtris[i].pnums[0]]->Append(mtris[i]); + } + for(int i=0; i<mquads.Size(); i++) + mquads_old[mquads[i].pnums[0]]->Append(mquads[i]); + + + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int i, j, k, l, m; + + +// if (mtets.Size() + mprisms.Size() == mesh.GetNE()) +// return; + + + + mtets.SetSize(0); + mprisms.SetSize(0); + mids.SetSize(0); + mtris.SetSize(0); + mquads.SetSize(0); + + + INDEX_2_HASHTABLE<int> shortedges(100); + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + if (el.GetType() == PRISM || + el.GetType() == PRISM12) + { + for (j = 1; j <= 3; j++) + { + INDEX_2 se(el.PNum(j), el.PNum(j+3)); + se.Sort(); + shortedges.Set (se, 1); + } + } + } + + + + // INDEX_2_HASHTABLE<int> edgenumber(np); + INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse); + + BTSortEdges (mesh, idmaps, edgenumber); + + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + + switch (el.GetType()) + { + case TET: + case TET10: + { + // if tet has short edge, it is handled as degenerated prism + + int foundse = 0; + for (j = 1; j <= 3; j++) + for (k = j+1; k <= 4; k++) + { + INDEX_2 se(el.PNum(j), el.PNum(k)); + se.Sort(); + if (shortedges.Used (se)) + { +// cout << "tet converted to prism" << endl; + + foundse = 1; + int p3 = 1; + while (p3 == j || p3 == k) + p3++; + int p4 = 10 - j - k - p3; + + // even permutation ? + int pi[4]; + pi[0] = j; + pi[1] = k; + pi[2] = p3; + pi[3] = p4; + int cnt = 0; + for (l = 1; l <= 4; l++) + for (m = 0; m < 3; m++) + if (pi[m] > pi[m+1]) + { + Swap (pi[m], pi[m+1]); + cnt++; + } + if (cnt % 2) + Swap (p3, p4); + + Element hel = el; + hel.PNum(1) = el.PNum(j); + hel.PNum(2) = el.PNum(k); + hel.PNum(3) = el.PNum(p3); + hel.PNum(4) = el.PNum(p4); + + MarkedPrism mp; + + BTDefineMarkedPrism (hel, edgenumber, mp); + mp.matindex = el.GetIndex(); + mprisms.Append (mp); + } + } + if (!foundse) + { + MarkedTet mt; + + int oldind = -1; + for(l = 0; oldind < 0 && l<mtets_old[el[0]]->Size(); l++) + if(el[1] == (*mtets_old[el[0]])[l].pnums[1] && + el[2] == (*mtets_old[el[0]])[l].pnums[2] && + el[3] == (*mtets_old[el[0]])[l].pnums[3]) + oldind = l; + + if(oldind >= 0) + mtets.Append((*mtets_old[el[0]])[oldind]); + else + { + BTDefineMarkedTet (el, edgenumber, mt); + mt.matindex = el.GetIndex(); + mtets.Append (mt); + } + } + break; + } + case PYRAMID: + { + // eventually rotate + MarkedPrism mp; + + INDEX_2 se(el.PNum(1), el.PNum(2)); + se.Sort(); + if (shortedges.Used (se)) + { + Element hel = el; + hel.PNum(1) = el.PNum(2); + hel.PNum(2) = el.PNum(3); + hel.PNum(3) = el.PNum(4); + hel.PNum(4) = el.PNum(1); + BTDefineMarkedPrism (hel, edgenumber, mp); + } + else + { + BTDefineMarkedPrism (el, edgenumber, mp); + } + + mp.matindex = el.GetIndex(); + mprisms.Append (mp); + break; + } + case PRISM: + case PRISM12: + { + MarkedPrism mp; + BTDefineMarkedPrism (el, edgenumber, mp); + mp.matindex = el.GetIndex(); + mprisms.Append (mp); + break; + } + } + } + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + if (el.GetType() == TRIG || + el.GetType() == TRIG6) + { + MarkedTri mt; + BTDefineMarkedTri (el, edgenumber, mt); + mtris.Append (mt); + } + else + { + MarkedQuad mq; + BTDefineMarkedQuad (el, edgenumber, mq); + mquads.Append (mq); + } + + MarkedIdentification mi; + + + + for(j=0; j<idmaps.Size(); j++) + if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi)) + { + mids.Append(mi); + + int oldind = -1; + for(l = 0; oldind < 0 && l<mids_old[mi.pnums[0]]->Size(); l++) + { + bool equal = true; + for(int m = 1; equal && m < mi.np; m++) + equal = (mi.pnums[m] == (*mids_old[el[0]])[l].pnums[m]); + if(equal) + oldind = l; + } + + if(oldind >= 0) + mids.Last() = (*mids_old[mi.pnums[0]])[oldind]; + } + + } + + + + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mtets_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mprisms_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mids_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mtris_old[i]; + for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++) + delete mquads_old[i]; + } +*/ + + + void UpdateEdgeMarks (Mesh & mesh, + const ARRAY< ARRAY<int,PointIndex::BASE>* > & idmaps) + //const ARRAY < ARRAY<Element>* > & elements_before, + //const ARRAY < ARRAY<int>* > & markedelts_num, + // const ARRAY < ARRAY<Element2d>* > & surfelements_before, + // const ARRAY < ARRAY<int>* > & markedsurfelts_num) + { + T_MTETS mtets_old; mtets_old.Copy(mtets); + T_MPRISMS mprisms_old; mprisms_old.Copy(mprisms); + T_MIDS mids_old; mids_old.Copy(mids); + T_MTRIS mtris_old; mtris_old.Copy(mtris); + T_MQUADS mquads_old; mquads_old.Copy(mquads); + + + + + mtets.SetSize(0); + mprisms.SetSize(0); + mids.SetSize(0); + mtris.SetSize(0); + mquads.SetSize(0); + + //int nv = mesh.GetNV(); + + + INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*mesh.GetNE()+4*mesh.GetNSE()); + + int maxnum = BTSortEdges (mesh, idmaps, edgenumber); + + for(int m = 0; m < mtets_old.Size(); m++) + { + MarkedTet & mt = mtets_old[m]; + + //(*testout) << "old mt " << mt; + + INDEX_2 edge (mt.pnums[mt.tetedge1],mt.pnums[mt.tetedge2]); + edge.Sort(); + if(edgenumber.Used(edge)) + { + int val = edgenumber.Get(edge); + //(*testout) << "set voledge " << edge << " from " << val; + if(val <= maxnum) + { + val += 2*maxnum; + edgenumber.Set(edge,val); + } + else if(val <= 2*maxnum) + { + val += maxnum; + edgenumber.Set(edge,val); + } + //(*testout) << " to " << val << endl; + } + + for(int k=0; k<4; k++) + for(int i=0; i<3; i++) + for(int j=i+1; i != k && j<4; j++) + if(j != k && mt.faceedges[k] == 6-k-i-j) + { + edge[0] = mt.pnums[i]; + edge[1] = mt.pnums[j]; + edge.Sort(); + if(edgenumber.Used(edge)) + { + int val = edgenumber.Get(edge); + //(*testout) << "set faceedge " << edge << " from " << val; + if(val <= maxnum) + { + val += maxnum; + edgenumber.Set(edge,val); + } + //(*testout) << " to " << val << endl; + } + } + } + + + + + for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + { + const Element & el = mesh[ei]; + + //int pos = elements_before[el[0]]->Pos(el); + //int elnum = (pos >= 0) ? (*markedelts_num[el[0]])[pos] : -1; + + switch (el.GetType()) + { + case TET: + case TET10: + { + //if(elnum >= 0) + // { + // mtets.Append(mtets_old[elnum]); + // } + //else + // { + MarkedTet mt; + BTDefineMarkedTet (el, edgenumber, mt); + mt.matindex = el.GetIndex(); + + mtets.Append (mt); + + //(*testout) << "mtet " << mtets.Last() << endl; + break; + } + case PYRAMID: + { + cerr << "Refinement :: UpdateEdgeMarks not yet implemented for pyramids" + << endl; + break; + } + + case PRISM: + case PRISM12: + { + cerr << "Refinement :: UpdateEdgeMarks not yet implemented for prisms" + << endl; + break; + } + } + + } + + + + for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) + { + const Element2d & el = mesh[sei]; + + /* + for(int k=0; k<3; k++) + auxind3[k] = el[k]; + + auxind3.Sort(); + + int pos = oldfaces[auxind3[0]]->Pos(auxind3); + if(pos < 0) + cout << "UIUIUI" << endl; + */ + + switch (el.GetType()) + { + case TRIG: + case TRIG6: + { + MarkedTri mt; + BTDefineMarkedTri (el, edgenumber, mt); + mtris.Append (mt); + break; + } + + case QUAD: + case QUAD6: + { + MarkedQuad mt; + BTDefineMarkedQuad (el, edgenumber, mt); + mquads.Append (mt); + break; + } + } + + + MarkedIdentification mi; + for(int j=0; j<idmaps.Size(); j++) + if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi)) + mids.Append(mi); + + + /* + int pos = surfelements_before[el[0]]->Pos(el); + int elnum = (pos >= 0) ? (*markedsurfelts_num[el[0]])[pos] : -1; + + + switch (el.GetType()) + { + case TRIG: + case TRIG6: + { + if(elnum >= 0) + mtris.Append(mtris_old[elnum]); + else + { + MarkedTri mt; + BTDefineMarkedTri (el, edgenumber, mt); + mtris.Append (mt); + (*testout) << "(new) "; + } + (*testout) << "mtri " << mtris.Last(); + break; + } + + case QUAD: + case QUAD6: + { + if(elnum >= 0) + mquads.Append(mquads_old[elnum]); + else + { + MarkedQuad mt; + BTDefineMarkedQuad (el, edgenumber, mt); + mquads.Append (mt); + } + break; + } + } + */ + } + + /* + for(int i=0; i<oldfaces.Size(); i++) + { + delete oldfaces[i]; + delete oldmarkededges[i]; + } + */ + + } + + + + + void Refinement :: Bisect (Mesh & mesh, + BisectionOptions & opt, + ARRAY<double> * quality_loss) + { + PrintMessage(1,"Mesh bisection"); + PushStatus("Mesh bisection"); + + static int localizetimer = NgProfiler::CreateTimer("localize edgepoints"); + NgProfiler::RegionTimer * loct = new NgProfiler::RegionTimer(localizetimer); + LocalizeEdgePoints(mesh); + delete loct; + + ARRAY< ARRAY<int,PointIndex::BASE>* > idmaps; + for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) + { + idmaps.Append(new ARRAY<int,PointIndex::BASE>); + mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true); + } + } + + + string refelementinfofileread = ""; + string refelementinfofilewrite = ""; + + if(opt.refinementfilename) + { + ifstream inf(opt.refinementfilename); + string st; + inf >> st; + if(st == "refinementinfo") + { + while(inf) + { + while(inf && st != "markedelementsfile") + inf >> st; + + if(inf) + inf >> st; + + if(st == "read" && inf) + ReadEnclString(inf,refelementinfofileread,'\"'); + else if(st == "write" && inf) + ReadEnclString(inf,refelementinfofilewrite,'\"'); + } + } + inf.close(); + } + + + + if (mesh.mglevels == 1 || idmaps.Size() > 0) + BisectTetsCopyMesh(mesh, NULL, opt, idmaps, refelementinfofileread); + + + mesh.ComputeNVertices(); + + int np = mesh.GetNV(); + mesh.SetNP(np); + + // int ne = mesh.GetNE(); + // int nse = mesh.GetNSE(); + int i, j, l; + + // int initnp = np; + // int maxsteps = 3; + + mesh.mglevels++; + + /* + if (opt.refinementfilename || opt.usemarkedelements) + maxsteps = 3; + */ + + + + if (opt.refine_p) + { + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int ox,oy,oz; + for (ElementIndex ei = 0; ei < ne; ei++) + if (mesh[ei].TestRefinementFlag()) + { + mesh[ei].GetOrder(ox,oy,oz); + mesh[ei].SetOrder (ox+1,oy+1,oz+1); + if (mesh[ei].TestStrongRefinementFlag()) + mesh[ei].SetOrder (ox+2,oy+2,oz+2); + } + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + if (mesh[sei].TestRefinementFlag()) + { + mesh[sei].GetOrder(ox,oy); + mesh[sei].SetOrder(ox+1,oy+1); + if (mesh[sei].TestStrongRefinementFlag()) + mesh[sei].SetOrder(ox+2,oy+2); + } + + /* + #ifndef SABINE //Nachbarelemente mit ordx,ordy,ordz + + ARRAY<int,PointIndex::BASE> v_order (mesh.GetNP()); + v_order = 0; + + for (ElementIndex ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + if (mesh[ei].GetOrder() > v_order[mesh[ei][j]]) + v_order[mesh[ei][j]] = mesh[ei].GetOrder(); + + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + for (j = 0; j < mesh[sei].GetNP(); j++) + if (mesh[sei].GetOrder() > v_order[mesh[sei][j]]) + v_order[mesh[sei][j]] = mesh[sei].GetOrder(); + + for (ElementIndex ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + if (mesh[ei].GetOrder() < v_order[mesh[ei][j]]-1) + mesh[ei].SetOrder(v_order[mesh[ei][j]]-1); + + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + for (j = 0; j < mesh[sei].GetNP(); j++) + if (mesh[sei].GetOrder() < v_order[mesh[sei][j]]-1) + mesh[sei].SetOrder(v_order[mesh[sei][j]]-1); + + #endif + */ + + PopStatus(); + return; + } + + + + // INDEX_2_HASHTABLE<int> cutedges(10 + 5 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size())); + INDEX_2_CLOSED_HASHTABLE<int> cutedges(10 + 9 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size())); + + bool noprojection = false; + + for (l = 1; l <= 1; l++) + { + int marked = 0; + if (opt.refinementfilename) + { + ifstream inf(opt.refinementfilename); + PrintMessage(3,"load refinementinfo from file ",opt.refinementfilename); + + string st; + inf >> st; + if(st == "refinementinfo") + // new version + { + for(i=1; i<=mtets.Size(); i++) + mtets.Elem(i).marked = 0; + for(i=1; i<=mprisms.Size(); i++) + mprisms.Elem(i).marked = 0; + for(i=1; i<=mtris.Size(); i++) + mtris.Elem(i).marked = 0; + for(i=1; i<=mquads.Size(); i++) + mquads.Elem(i).marked = 0; + for(i=1; i<=mprisms.Size(); i++) + mids.Elem(i).marked = 0; + + inf >> st; + while(inf) + { + if(st[0] == '#') + { + inf.ignore(10000,'\n'); + inf >> st; + } + else if(st == "markedelementsfile") + { + inf >> st; + ReadEnclString(inf,st,'\"'); + inf >> st; + } + else if(st == "noprojection") + { + noprojection = true; + inf >> st; + } + else if(st == "refine") + { + inf >> st; + if(st == "elements") + { + inf >> st; + bool isint = true; + for(string::size_type ii=0; isint && ii<st.size(); ii++) + isint = (isdigit(st[ii]) != 0); + + while(inf && isint) + { + mtets.Elem(atoi(st.c_str())).marked = 3; + marked = 1; + + inf >> st; + isint = true; + for(string::size_type ii=0; isint && ii<st.size(); ii++) + isint = (isdigit(st[ii]) != 0); + } + } + else if(st == "orthobrick") + { + double bounds[6]; + for(i=0; i<6; i++) + inf >> bounds[i]; + + int cnt = 0; + + for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + { + const Element & el = mesh[ei]; + + // + Point<3> center(0,0,0); + for(i=0; i<el.GetNP(); i++) + { + const MeshPoint & point = mesh[el[i]]; + center(0) += point(0); + center(1) += point(1); + center(2) += point(2); + } + for(i=0; i<3; i++) + center(i) *= 1./double(el.GetNP()); + if(bounds[0] <= center(0) && center(0) <= bounds[3] && + bounds[1] <= center(1) && center(1) <= bounds[4] && + bounds[2] <= center(2) && center(2) <= bounds[5]) + { + mtets[ei].marked = 3; + cnt++; + } + + +// bool contained = false; +// for(int i=0; !contained && i<el.GetNP(); i++) +// { +// const MeshPoint & point = mesh[el[i]]; +// contained = (bounds[0] <= point.X() && point.X() <= bounds[3] && +// bounds[1] <= point.Y() && point.Y() <= bounds[4] && +// bounds[2] <= point.Z() && point.Z() <= bounds[5]); +// } +// if(contained) +// { +// mtets[ei].marked = 3; +// cnt++; +// } + } + + + ostringstream strstr; + strstr.precision(2); + strstr << "marked " << float(cnt)/float(mesh.GetNE())*100. +#ifdef WIN32 + << "%%" +#else + << "%" +#endif + <<" of the elements"; + PrintMessage(4,strstr.str()); + + if(cnt > 0) + marked = 1; + + + inf >> st; + } + else + { + throw NgException("something wrong with refinementinfo file"); + } + } + } + } + else + { + inf.close(); + inf.open(opt.refinementfilename); + + char ch; + for (i = 1; i <= mtets.Size(); i++) + { + inf >> ch; + if(!inf) + throw NgException("something wrong with refinementinfo file (old format)"); + mtets.Elem(i).marked = (ch == '1'); + } + marked = 1; + } + inf.close(); + } + + else if (opt.usemarkedelements) + { + int cntm = 0; + + // all in one ! + if (mprisms.Size()) + { + int cnttet = 0; + int cntprism = 0; + for (i = 1; i <= mesh.GetNE(); i++) + { + if (mesh.VolumeElement(i).GetType() == TET || + mesh.VolumeElement(i).GetType() == TET10) + { + cnttet++; + mtets.Elem(cnttet).marked = + 3 * mesh.VolumeElement(i).TestRefinementFlag(); + if (mtets.Elem(cnttet).marked) + cntm++; + } + else + { + cntprism++; + mprisms.Elem(cntprism).marked = + 2 * mesh.VolumeElement(i).TestRefinementFlag(); + if (mprisms.Elem(cntprism).marked) + cntm++; + } + + } + } + else + for (i = 1; i <= mtets.Size(); i++) + { + mtets.Elem(i).marked = + 3 * mesh.VolumeElement(i).TestRefinementFlag(); + if (mtets.Elem(i).marked) + cntm++; + } + + // (*testout) << "mtets = " << mtets << endl; + + /* + for (i = 1; i <= mtris.Size(); i++) + mtris.Elem(i).marked = 0; + for (i = 1; i <= mquads.Size(); i++) + mquads.Elem(i).marked = 0; + */ + + if (printmessage_importance>0) + { + ostringstream str; + str << "marked elements: " << cntm; + PrintMessage(4,str.str()); + } + + int cnttrig = 0; + int cntquad = 0; + for (i = 1; i <= mesh.GetNSE(); i++) + { + if (mesh.SurfaceElement(i).GetType() == TRIG || + mesh.SurfaceElement(i).GetType() == TRIG6) + { + cnttrig++; + mtris.Elem(cnttrig).marked = + mesh.SurfaceElement(i).TestRefinementFlag() ? 2 : 0; + // mtris.Elem(cnttrig).marked = 0; + if (mtris.Elem(cnttrig).marked) + cntm++; + } + else + { + cntquad++; + // 2d: marked=2, 3d prisms: marked=1 + mquads.Elem(cntquad).marked = + mesh.SurfaceElement(i).TestRefinementFlag() ? 4-mesh.GetDimension() : 0 ; + // mquads.Elem(cntquad).marked = 0; + if (mquads.Elem(cntquad).marked) + cntm++; + } + } + + if (printmessage_importance>0) + { + ostringstream str; + str << "with surface-elements: " << cntm; + PrintMessage(4,str.str()); + } + + // he/sz: das wird oben schon richtig gemacht. + // hier sind die quads vergessen! + /* + if (mesh.GetDimension() == 2) + { + cntm = 0; + for (i = 1; i <= mtris.Size(); i++) + { + mtris.Elem(i).marked = + 2 * mesh.SurfaceElement(i).TestRefinementFlag(); + // mtris.Elem(i).marked = 2; + if (mtris.Elem(i).marked) + cntm++; + } + + if (!cntm) + { + for (i = 1; i <= mtris.Size(); i++) + { + mtris.Elem(i).marked = 2; + cntm++; + } + } + cout << "trigs: " << mtris.Size() << " "; + cout << "marked: " << cntm << endl; + } + */ + + marked = (cntm > 0); + } + else + { + marked = BTMarkTets (mtets, mprisms, mesh); + } + + if (!marked) break; + + + //(*testout) << "mtets " << mtets << endl; + + if (opt.refine_p) + { + PrintMessage(3,"refine p"); + + for (i = 1; i <= mtets.Size(); i++) + mtets.Elem(i).incorder = mtets.Elem(i).marked ? 1 : 0; + + for (i = 1; i <= mtets.Size(); i++) + if (mtets.Elem(i).incorder) + mtets.Elem(i).marked = 0; + + + for (i = 1; i <= mprisms.Size(); i++) + mprisms.Elem(i).incorder = mprisms.Elem(i).marked ? 1 : 0; + + for (i = 1; i <= mprisms.Size(); i++) + if (mprisms.Elem(i).incorder) + mprisms.Elem(i).marked = 0; + + + for (i = 1; i <= mtris.Size(); i++) + mtris.Elem(i).incorder = mtris.Elem(i).marked ? 1 : 0; + + for (i = 1; i <= mtris.Size(); i++) + { + if (mtris.Elem(i).incorder) + mtris.Elem(i).marked = 0; + } + } + + if (opt.refine_hp) + { + PrintMessage(3,"refine hp"); + BitArray singv(np); + singv.Clear(); + + if (mesh.GetDimension() == 3) + { + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + singv.Set (seg.p1); + singv.Set (seg.p2); + } + /* + for ( i=1; i<= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + for(int j=1; j<=sel.GetNP(); j++) + singv.Set(sel.PNum(j)); + } + */ + } + else + { + // vertices with 2 different bnds + ARRAY<int> bndind(np); + bndind = 0; + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + for (j = 0; j < 2; j++) + { + int pi = (j == 0) ? seg.p1 : seg.p2; + if (bndind.Elem(pi) == 0) + bndind.Elem(pi) = seg.edgenr; + else if (bndind.Elem(pi) != seg.edgenr) + singv.Set (pi); + } + } + } + + + + for (i = 1; i <= mtets.Size(); i++) + mtets.Elem(i).incorder = 1; + for (i = 1; i <= mtets.Size(); i++) + { + if (!mtets.Elem(i).marked) + mtets.Elem(i).incorder = 0; + for (j = 0; j < 4; j++) + if (singv.Test (mtets.Elem(i).pnums[j])) + mtets.Elem(i).incorder = 0; + } + for (i = 1; i <= mtets.Size(); i++) + if (mtets.Elem(i).incorder) + mtets.Elem(i).marked = 0; + + + for (i = 1; i <= mprisms.Size(); i++) + mprisms.Elem(i).incorder = 1; + for (i = 1; i <= mprisms.Size(); i++) + { + if (!mprisms.Elem(i).marked) + mprisms.Elem(i).incorder = 0; + for (j = 0; j < 6; j++) + if (singv.Test (mprisms.Elem(i).pnums[j])) + mprisms.Elem(i).incorder = 0; + } + for (i = 1; i <= mprisms.Size(); i++) + if (mprisms.Elem(i).incorder) + mprisms.Elem(i).marked = 0; + + + for (i = 1; i <= mtris.Size(); i++) + mtris.Elem(i).incorder = 1; + for (i = 1; i <= mtris.Size(); i++) + { + if (!mtris.Elem(i).marked) + mtris.Elem(i).incorder = 0; + for (j = 0; j < 3; j++) + if (singv.Test (mtris.Elem(i).pnums[j])) + mtris.Elem(i).incorder = 0; + } + for (i = 1; i <= mtris.Size(); i++) + { + if (mtris.Elem(i).incorder) + mtris.Elem(i).marked = 0; + } + } + + + + + + int hangingvol, hangingsurf, hangingedge; + + //cout << "write?" << endl; + //string yn; + //cin >> yn; + + (*testout) << "refine volume elements" << endl; + do + { + // refine volume elements + + int nel = mtets.Size(); + for (i = 1; i <= nel; i++) + if (mtets.Elem(i).marked) + { + MarkedTet oldtet; + MarkedTet newtet1, newtet2; + int newp; + + + oldtet = mtets.Get(i); + //if(yn == "y") + // (*testout) << "bisected tet " << oldtet; + INDEX_2 edge(oldtet.pnums[oldtet.tetedge1], + oldtet.pnums[oldtet.tetedge2]); + edge.Sort(); + if (cutedges.Used (edge)) + { + newp = cutedges.Get(edge); + } + else + { + Point<3> npt = Center (mesh.Point (edge.I1()), + mesh.Point (edge.I2())); + newp = mesh.AddPoint (npt); + cutedges.Set (edge, newp); + } + + BTBisectTet (oldtet, newp, newtet1, newtet2); + + mtets.Elem(i) = newtet1; + mtets.Append (newtet2); + //if(yn == "y") + // (*testout) << "and got " << newtet1 << "and " << newtet2 << endl; + + mesh.mlparentelement.Append (i); + } + + int npr = mprisms.Size(); + for (i = 1; i <= npr; i++) + if (mprisms.Elem(i).marked) + { + MarkedPrism oldprism; + MarkedPrism newprism1, newprism2; + int newp1, newp2; + + oldprism = mprisms.Get(i); + int pi1 = 0; + if (pi1 == oldprism.markededge) + pi1++; + int pi2 = 3-pi1-oldprism.markededge; + + INDEX_2 edge1(oldprism.pnums[pi1], + oldprism.pnums[pi2]); + INDEX_2 edge2(oldprism.pnums[pi1+3], + oldprism.pnums[pi2+3]); + edge1.Sort(); + edge2.Sort(); + + if (cutedges.Used (edge1)) + newp1 = cutedges.Get(edge1); + else + { + Point<3> npt = Center (mesh.Point (edge1.I1()), + mesh.Point (edge1.I2())); + newp1 = mesh.AddPoint (npt); + cutedges.Set (edge1, newp1); + } + if (cutedges.Used (edge2)) + newp2 = cutedges.Get(edge2); + else + { + Point<3> npt = Center (mesh.Point (edge2.I1()), + mesh.Point (edge2.I2())); + newp2 = mesh.AddPoint (npt); + cutedges.Set (edge2, newp2); + } + + + BTBisectPrism (oldprism, newp1, newp2, newprism1, newprism2); + //if(yn == "y") + // (*testout) << "bisected prism " << oldprism << "and got " << newprism1 << "and " << newprism2 << endl; + mprisms.Elem(i) = newprism1; + mprisms.Append (newprism2); + } + + int nid = mids.Size(); + for (i = 1; i <= nid; i++) + if (mids.Elem(i).marked) + { + MarkedIdentification oldid,newid1,newid2; + ARRAY<int> newp; + + oldid = mids.Get(i); + + ARRAY<INDEX_2> edges; + edges.Append(INDEX_2(oldid.pnums[oldid.markededge], + oldid.pnums[(oldid.markededge+1)%oldid.np])); + edges.Append(INDEX_2(oldid.pnums[oldid.markededge + oldid.np], + oldid.pnums[(oldid.markededge+1)%oldid.np + oldid.np])); + + if(oldid.np == 4) + { + edges.Append(INDEX_2(oldid.pnums[(oldid.markededge+2)%oldid.np], + oldid.pnums[(oldid.markededge+3)%oldid.np])); + edges.Append(INDEX_2(oldid.pnums[(oldid.markededge+2)%oldid.np + oldid.np], + oldid.pnums[(oldid.markededge+3)%oldid.np + oldid.np])); + } + for (j = 0; j < edges.Size(); j++) + { + edges[j].Sort(); + + if(cutedges.Used(edges[j])) + newp.Append(cutedges.Get(edges[j])); + else + { + Point<3> npt = Center (mesh.Point (edges[j].I1()), + mesh.Point (edges[j].I2())); + newp.Append(mesh.AddPoint(npt)); + cutedges.Set(edges[j],newp[j]); + } + } + + BTBisectIdentification(oldid,newp,newid1,newid2); + mids.Elem(i) = newid1; + mids.Append(newid2); + } + + + //IdentifyCutEdges(mesh, cutedges); + + + hangingvol = + MarkHangingTets (mtets, cutedges) + + MarkHangingPrisms (mprisms, cutedges) + + MarkHangingIdentifications (mids, cutedges); + + + int nsel = mtris.Size(); + + for (i = 1; i <= nsel; i++) + if (mtris.Elem(i).marked) + { + MarkedTri oldtri; + MarkedTri newtri1, newtri2; + PointIndex newp; + + oldtri = mtris.Get(i); + int oldpi1 = oldtri.pnums[(oldtri.markededge+1)%3]; + int oldpi2 = oldtri.pnums[(oldtri.markededge+2)%3]; + INDEX_2 edge(oldpi1, oldpi2); + edge.Sort(); + + // cerr << "edge = " << edge.I1() << "-" << edge.I2() << endl; + + if (cutedges.Used (edge)) + { + newp = cutedges.Get(edge); + } + else + { + Point<3> npt = Center (mesh.Point (edge.I1()), + mesh.Point (edge.I2())); + newp = mesh.AddPoint (npt); + cutedges.Set (edge, newp); + } + // newp = cutedges.Get(edge); + + int si = mesh.GetFaceDescriptor (oldtri.surfid).SurfNr(); + // geom->GetSurface(si)->Project (mesh.Point(newp)); + PointGeomInfo npgi; + +// cerr << "project point " << newp << " old: " << mesh.Point(newp); + if (mesh[newp].Type() != EDGEPOINT) + PointBetween (mesh.Point (oldpi1), mesh.Point (oldpi2), + 0.5, si, + oldtri.pgeominfo[(oldtri.markededge+1)%3], + oldtri.pgeominfo[(oldtri.markededge+2)%3], + mesh.Point (newp), npgi); +// cerr << " new: " << mesh.Point(newp) << endl; + + BTBisectTri (oldtri, newp, npgi, newtri1, newtri2); + //if(yn == "y") + // (*testout) << "bisected tri " << oldtri << "and got " << newtri1 << "and " << newtri2 << endl; + + + mtris.Elem(i) = newtri1; + mtris.Append (newtri2); + mesh.mlparentsurfaceelement.Append (i); + } + + int nquad = mquads.Size(); + for (i = 1; i <= nquad; i++) + if (mquads.Elem(i).marked) + { + MarkedQuad oldquad; + MarkedQuad newquad1, newquad2; + int newp1, newp2; + + oldquad = mquads.Get(i); + /* + INDEX_2 edge1(oldquad.pnums[0], + oldquad.pnums[1]); + INDEX_2 edge2(oldquad.pnums[2], + oldquad.pnums[3]); + */ + INDEX_2 edge1, edge2; + PointGeomInfo pgi11, pgi12, pgi21, pgi22; + if (oldquad.markededge==0 || oldquad.markededge==2) + { + edge1.I1()=oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0]; + edge1.I2()=oldquad.pnums[1]; pgi12=oldquad.pgeominfo[1]; + edge2.I1()=oldquad.pnums[2]; pgi21=oldquad.pgeominfo[2]; + edge2.I2()=oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3]; + } + else // 3 || 1 + { + edge1.I1()=oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0]; + edge1.I2()=oldquad.pnums[2]; pgi12=oldquad.pgeominfo[2]; + edge2.I1()=oldquad.pnums[1]; pgi21=oldquad.pgeominfo[1]; + edge2.I2()=oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3]; + } + + edge1.Sort(); + edge2.Sort(); + + if (cutedges.Used (edge1)) + { + newp1 = cutedges.Get(edge1); + } + else + { + Point<3> np1 = Center (mesh.Point (edge1.I1()), + mesh.Point (edge1.I2())); + newp1 = mesh.AddPoint (np1); + cutedges.Set (edge1, newp1); + } + + if (cutedges.Used (edge2)) + { + newp2 = cutedges.Get(edge2); + } + else + { + Point<3> np2 = Center (mesh.Point (edge2.I1()), + mesh.Point (edge2.I2())); + newp2 = mesh.AddPoint (np2); + cutedges.Set (edge2, newp2); + } + + PointGeomInfo npgi1, npgi2; + + int si = mesh.GetFaceDescriptor (oldquad.surfid).SurfNr(); + // geom->GetSurface(si)->Project (mesh.Point(newp1)); + // geom->GetSurface(si)->Project (mesh.Point(newp2)); + +// (*testout) +// cerr << "project point 1 " << newp1 << " old: " << mesh.Point(newp1); + PointBetween (mesh.Point (edge1.I1()), mesh.Point (edge1.I2()), + 0.5, si, + pgi11, + pgi12, + mesh.Point (newp1), npgi1); +// (*testout) +// cerr << " new: " << mesh.Point(newp1) << endl; + + +// cerr << "project point 2 " << newp2 << " old: " << mesh.Point(newp2); + PointBetween (mesh.Point (edge2.I1()), mesh.Point (edge2.I2()), + 0.5, si, + pgi21, + pgi22, + mesh.Point (newp2), npgi2); +// cerr << " new: " << mesh.Point(newp2) << endl; + + + BTBisectQuad (oldquad, newp1, npgi1, newp2, npgi2, + newquad1, newquad2); + + mquads.Elem(i) = newquad1; + mquads.Append (newquad2); + } + + + hangingsurf = + MarkHangingTris (mtris, cutedges) + + MarkHangingQuads (mquads, cutedges); + + hangingedge = 0; + + int nseg = mesh.GetNSeg (); + for (i = 1; i <= nseg; i++) + { + Segment & seg = mesh.LineSegment (i); + INDEX_2 edge(seg.p1, seg.p2); + edge.Sort(); + if (cutedges.Used (edge)) + { + hangingedge = 1; + Segment nseg1 = seg; + Segment nseg2 = seg; + + int newpi = cutedges.Get(edge); + + nseg1.p2 = newpi; + nseg2.p1 = newpi; + + EdgePointGeomInfo newepgi; + + +// +// cerr << "move edgepoint " << newpi << " from " << mesh.Point(newpi); + PointBetween (mesh.Point (seg.p1), mesh.Point (seg.p2), + 0.5, seg.surfnr1, seg.surfnr2, + seg.epgeominfo[0], seg.epgeominfo[1], + mesh.Point (newpi), newepgi); +// cerr << " to " << mesh.Point (newpi) << endl; + + + nseg1.epgeominfo[1] = newepgi; + nseg2.epgeominfo[0] = newepgi; + + mesh.LineSegment (i) = nseg1; + mesh.AddSegment (nseg2); + } + } + } + while (hangingvol || hangingsurf || hangingedge); + + if (printmessage_importance>0) + { + ostringstream strstr; + strstr << mtets.Size() << " tets" << endl + << mtris.Size() << " trigs" << endl; + if (mprisms.Size()) + { + strstr << mprisms.Size() << " prisms" << endl + << mquads.Size() << " quads" << endl; + } + strstr << mesh.GetNP() << " points"; + PrintMessage(4,strstr.str()); + + } + } + + + // (*testout) << "mtets = " << mtets << endl; + + if (opt.refine_hp) + { + // + ARRAY<int> v_order (mesh.GetNP()); + v_order = 0; + if (mesh.GetDimension() == 3) + { + for (i = 1; i <= mtets.Size(); i++) + if (mtets.Elem(i).incorder) + mtets.Elem(i).order++; + + for (i = 0; i < mtets.Size(); i++) + for (j = 0; j < 4; j++) + if (int(mtets[i].order) > v_order.Elem(mtets[i].pnums[j])) + v_order.Elem(mtets[i].pnums[j]) = mtets[i].order; + for (i = 0; i < mtets.Size(); i++) + for (j = 0; j < 4; j++) + if (int(mtets[i].order) < v_order.Elem(mtets[i].pnums[j])-1) + mtets[i].order = v_order.Elem(mtets[i].pnums[j])-1; + } + else + { + for (i = 1; i <= mtris.Size(); i++) + if (mtris.Elem(i).incorder) + { + mtris.Elem(i).order++; + } + + for (i = 0; i < mtris.Size(); i++) + for (j = 0; j < 3; j++) + if (int(mtris[i].order) > v_order.Elem(mtris[i].pnums[j])) + v_order.Elem(mtris[i].pnums[j]) = mtris[i].order; + for (i = 0; i < mtris.Size(); i++) + { + for (j = 0; j < 3; j++) + if (int(mtris[i].order) < v_order.Elem(mtris[i].pnums[j])-1) + mtris[i].order = v_order.Elem(mtris[i].pnums[j])-1; + } + } + } + + mtets.SetAllocSize (mtets.Size()); + mprisms.SetAllocSize (mprisms.Size()); + mids.SetAllocSize (mids.Size()); + mtris.SetAllocSize (mtris.Size()); + mquads.SetAllocSize (mquads.Size()); + + + mesh.ClearVolumeElements(); + mesh.VolumeElements().SetAllocSize (mtets.Size()+mprisms.Size()); + for (i = 1; i <= mtets.Size(); i++) + { + Element el(TET); + el.SetIndex (mtets.Get(i).matindex); + for (j = 1; j <= 4; j++) + el.PNum(j) = mtets.Get(i).pnums[j-1]; + el.SetOrder (mtets.Get(i).order); + mesh.AddVolumeElement (el); + } + for (i = 1; i <= mprisms.Size(); i++) + { + Element el(PRISM); + el.SetIndex (mprisms.Get(i).matindex); + for (j = 1; j <= 6; j++) + el.PNum(j) = mprisms.Get(i).pnums[j-1]; + el.SetOrder (mprisms.Get(i).order); + + // degenerated prism ? + static const int map1[] = { 3, 2, 5, 6, 1 }; + static const int map2[] = { 1, 3, 6, 4, 2 }; + static const int map3[] = { 2, 1, 4, 5, 3 }; + + + const int * map = NULL; + int deg1 = 0, deg2 = 0, deg3 = 0; + // int deg = 0; + if (el.PNum(1) == el.PNum(4)) { map = map1; deg1 = 1; } + if (el.PNum(2) == el.PNum(5)) { map = map2; deg2 = 1; } + if (el.PNum(3) == el.PNum(6)) { map = map3; deg3 = 1; } + + switch (deg1+deg2+deg3) + { + case 1: + { + for (j = 1; j <= 5; j++) + el.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1]; + + el.SetType (PYRAMID); + break; + } + case 2: + { + static const int tetmap1[] = { 1, 2, 3, 4 }; + static const int tetmap2[] = { 2, 3, 1, 5 }; + static const int tetmap3[] = { 3, 1, 2, 6 }; + if (!deg1) map = tetmap1; + if (!deg2) map = tetmap2; + if (!deg3) map = tetmap3; + for (j = 1; j <= 4; j++) + el.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1]; + /* + if (!deg1) el.PNum(4) = el.PNum(4); + if (!deg2) el.PNum(4) = el.PNum(5); + if (!deg3) el.PNum(4) = el.PNum(6); + */ + el.SetType(TET); + break; + } + default: + ; + } + mesh.AddVolumeElement (el); + } + + mesh.ClearSurfaceElements(); + for (i = 1; i <= mtris.Size(); i++) + { + Element2d el(TRIG); + el.SetIndex (mtris.Get(i).surfid); + el.SetOrder (mtris.Get(i).order); + for (j = 1; j <= 3; j++) + { + el.PNum(j) = mtris.Get(i).pnums[j-1]; + el.GeomInfoPi(j) = mtris.Get(i).pgeominfo[j-1]; + } + mesh.AddSurfaceElement (el); + } + for (i = 1; i <= mquads.Size(); i++) + { + Element2d el(QUAD); + el.SetIndex (mquads.Get(i).surfid); + for (j = 1; j <= 4; j++) + el.PNum(j) = mquads.Get(i).pnums[j-1]; + Swap (el.PNum(3), el.PNum(4)); + mesh.AddSurfaceElement (el); + } + + + + // write multilevel hierarchy to mesh: + np = mesh.GetNP(); + mesh.mlbetweennodes.SetSize(np); + if (mesh.mglevels <= 2) + { + PrintMessage(4,"RESETTING mlbetweennodes"); + for (i = 1; i <= np; i++) + { + mesh.mlbetweennodes.Elem(i).I1() = 0; + mesh.mlbetweennodes.Elem(i).I2() = 0; + } + } + + /* + for (i = 1; i <= cutedges.GetNBags(); i++) + for (j = 1; j <= cutedges.GetBagSize(i); j++) + { + INDEX_2 edge; + int newpi; + cutedges.GetData (i, j, edge, newpi); + mesh.mlbetweennodes.Elem(newpi) = edge; + } + */ + + BitArray isnewpoint(np); + isnewpoint.Clear(); + + for (i = 1; i <= cutedges.Size(); i++) + if (cutedges.UsedPos(i)) + { + INDEX_2 edge; + int newpi; + cutedges.GetData (i, edge, newpi); + isnewpoint.Set(newpi); + mesh.mlbetweennodes.Elem(newpi) = edge; + } + + + /* + mesh.PrintMemInfo (cout); + cout << "tets "; + mtets.PrintMemInfo (cout); + cout << "prims "; + mprisms.PrintMemInfo (cout); + cout << "tris "; + mtris.PrintMemInfo (cout); + cout << "quads "; + mquads.PrintMemInfo (cout); + cout << "cutedges "; + cutedges.PrintMemInfo (cout); + */ + + + /* + + // find connected nodes (close nodes) + TABLE<int> conto(np); + for (i = 1; i <= mprisms.Size(); i++) + for (j = 1; j <= 6; j++) + { + int n1 = mprisms.Get(i).pnums[j-1]; + int n2 = mprisms.Get(i).pnums[(j+2)%6]; + // if (n1 != n2) + { + int found = 0; + for (k = 1; k <= conto.EntrySize(n1); k++) + if (conto.Get(n1, k) == n2) + { + found = 1; + break; + } + if (!found) + conto.Add (n1, n2); + } + } + mesh.connectedtonode.SetSize(np); + for (i = 1; i <= np; i++) + mesh.connectedtonode.Elem(i) = 0; + + + // (*testout) << "connection table: " << endl; + // for (i = 1; i <= np; i++) + // { + // (*testout) << "node " << i << ": "; + // for (j = 1; j <= conto.EntrySize(i); j++) + // (*testout) << conto.Get(i, j) << " "; + // (*testout) << endl; + // } + + + for (i = 1; i <= np; i++) + if (mesh.connectedtonode.Elem(i) == 0) + { + mesh.connectedtonode.Elem(i) = i; + ConnectToNodeRec (i, i, conto, mesh.connectedtonode); + } + */ + + // mesh.BuildConnectedNodes(); + + + + + mesh.ComputeNVertices(); + + + + // update identification tables + for (i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) + { + ARRAY<int,PointIndex::BASE> identmap; + + mesh.GetIdentifications().GetMap (i, identmap); + + + /* + for (j = 1; j <= cutedges.GetNBags(); j++) + for (k = 1; k <= cutedges.GetBagSize(j); k++) + { + INDEX_2 i2; + int newpi; + cutedges.GetData (j, k, i2, newpi); + INDEX_2 oi2(identmap.Get(i2.I1()), + identmap.Get(i2.I2())); + oi2.Sort(); + if (cutedges.Used (oi2)) + { + int onewpi = cutedges.Get(oi2); + mesh.GetIdentifications().Add (newpi, onewpi, i); + } + } + */ + + for (j = 1; j <= cutedges.Size(); j++) + if (cutedges.UsedPos(j)) + { + INDEX_2 i2; + int newpi; + cutedges.GetData (j, i2, newpi); + INDEX_2 oi2(identmap.Get(i2.I1()), + identmap.Get(i2.I2())); + oi2.Sort(); + if (cutedges.Used (oi2)) + { + int onewpi = cutedges.Get(oi2); + mesh.GetIdentifications().Add (newpi, onewpi, i); + } + } + } + + + + + + bool do_repair = true; + + //if(mesh.mglevels == 3) + // noprojection = true; + + //noprojection = true; + + if(noprojection) + { + do_repair = false; + for(int ii=1; ii<=mesh.GetNP(); ii++) + { + if(isnewpoint.Test(ii) && mesh.mlbetweennodes[ii][0] > 0) + { + mesh.Point(ii) = Center(mesh.Point(mesh.mlbetweennodes[ii][0]),mesh.Point(mesh.mlbetweennodes[ii][1])); + } + } + } + + + // Check/Repair + + //cout << "Hallo Welt" << endl; + //getchar(); + + static bool repaired_once; + if(mesh.mglevels == 1) + repaired_once = false; + + //mesh.Save("before.vol"); + + static int reptimer = NgProfiler::CreateTimer("check/repair"); + NgProfiler::RegionTimer * regt(NULL); + regt = new NgProfiler::RegionTimer(reptimer); + + ARRAY<ElementIndex> bad_elts; + ARRAY<double> pure_badness; + + if(do_repair || quality_loss != NULL) + { + pure_badness.SetSize(mesh.GetNP()+2); + GetPureBadness(mesh,pure_badness,isnewpoint); + } + + + if(do_repair) + { + const double max_worsening = 1; + + const bool uselocalworsening = false; + + bool repaired = false; + + Validate(mesh,bad_elts,pure_badness,max_worsening,uselocalworsening); + + if (printmessage_importance>0) + { + ostringstream strstr; + for(int ii=0; ii<bad_elts.Size(); ii++) + strstr << "bad element " << bad_elts[ii] << "\n"; + PrintMessage(1,strstr.str()); + } + if(repaired_once || bad_elts.Size() > 0) + { + clock_t t1(clock()); + + + // update id-maps + j=0; + for(i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) + { + mesh.GetIdentifications().GetMap(i,*idmaps[j],true); + j++; + } + } + + + // do the repair + try + { + RepairBisection(mesh,bad_elts,isnewpoint,*this, + pure_badness, + max_worsening,uselocalworsening, + idmaps); + repaired = true; + repaired_once = true; + } + catch(NgException & ex) + { + PrintMessage(1,string("Problem: ") + ex.What()); + } + + + if (printmessage_importance>0) + { + ostringstream strstr; + strstr << "Time for Repair: " << double(clock() - t1)/double(CLOCKS_PER_SEC) << endl + << "bad elements after repair: " << bad_elts << endl; + PrintMessage(1,strstr.str()); + } + + if(quality_loss != NULL) + Validate(mesh,bad_elts,pure_badness,1e100,uselocalworsening,quality_loss); + + if(idmaps.Size() == 0) + UpdateEdgeMarks(mesh,idmaps); + + /* + if(1==1) + UpdateEdgeMarks(mesh,idmaps); + else + mesh.mglevels = 1; + */ + + //mesh.ImproveMesh(); + + } + } + delete regt; + + + + + + + + for(i=0; i<idmaps.Size(); i++) + delete idmaps[i]; + idmaps.DeleteAll(); + + mesh.UpdateTopology(); + + if(refelementinfofilewrite != "") + { + PrintMessage(3,"writing marked-elements information to \"",refelementinfofilewrite,"\""); + ofstream ofst(refelementinfofilewrite.c_str()); + + WriteMarkedElements(ofst); + + ofst.close(); + } + + + PrintMessage (1, "Bisection done"); + + PopStatus(); + } + + + + + BisectionOptions :: BisectionOptions () + { + outfilename = NULL; + mlfilename = NULL; + refinementfilename = NULL; + femcode = NULL; + maxlevel = 50; + usemarkedelements = 0; + refine_hp = 0; + refine_p = 0; + } + + + Refinement :: Refinement () + { + optimizer2d = NULL; + } + + Refinement :: ~Refinement () + { + ; + } + + + void Refinement :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point<3> & newp, PointGeomInfo & newgi) + { + newp = p1+secpoint*(p2-p1); + } + + void Refinement :: PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point<3> & newp, EdgePointGeomInfo & newgi) + { + newp = p1+secpoint*(p2-p1); + } + + + Vec<3> Refinement :: GetTangent (const Point<3> & p, int surfi1, int surfi2, + const EdgePointGeomInfo & ap1) const + { + cerr << "Refinement::GetTangent not overloaded" << endl; + return Vec<3> (0,0,0); + } + + Vec<3> Refinement :: GetNormal (const Point<3> & p, int surfi1, + const PointGeomInfo & gi) const + { + cerr << "Refinement::GetNormal not overloaded" << endl; + return Vec<3> (0,0,0); + } + + + void Refinement :: ProjectToSurface (Point<3> & p, int surfi) + { + if (printmessage_importance>0) + cerr << "Refinement :: ProjectToSurface ERROR: no geometry set" << endl; + }; + + void Refinement :: ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const + { + cerr << "Refinement::ProjectToEdge not overloaded" << endl; + } +} diff --git a/contrib/Netgen/libsrc/meshing/bisect.hpp b/contrib/Netgen/libsrc/meshing/bisect.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e47033f255de9ce30e1f170767629b908328d5e3 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/bisect.hpp @@ -0,0 +1,99 @@ +#ifndef BISECT +#define BISECT + +class BisectionOptions +{ +public: + const char * outfilename; + const char * mlfilename; + const char * refinementfilename; + const char * femcode; + int maxlevel; + int usemarkedelements; + bool refine_hp; + bool refine_p; + BisectionOptions (); +}; + +class ZRefinementOptions +{ +public: + int minref; + ZRefinementOptions(); +}; + + +/* +extern void BisectTets (Mesh &, const CSGeometry *, + BisectionOptions & opt); +*/ + +extern void BisectTetsCopyMesh (Mesh &, const class CSGeometry *, + BisectionOptions & opt); + +extern void ZRefinement (Mesh &, const CSGeometry *, + ZRefinementOptions & opt); + + + + + +class Refinement +{ + MeshOptimize2d * optimizer2d; + +public: + Refinement (); + virtual ~Refinement (); + + void Refine (Mesh & mesh); + void Bisect (Mesh & mesh, class BisectionOptions & opt, ARRAY<double> * quality_loss = NULL); + void MakeSecondOrder (Mesh & mesh); + + virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, + int surfi, + const PointGeomInfo & gi1, + const PointGeomInfo & gi2, + Point<3> & newp, PointGeomInfo & newgi); + + virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, + int surfi1, int surfi2, + const EdgePointGeomInfo & ap1, + const EdgePointGeomInfo & ap2, + Point<3> & newp, EdgePointGeomInfo & newgi); + + virtual Vec<3> GetTangent (const Point<3> & p, int surfi1, int surfi2, + const EdgePointGeomInfo & egi) const; + + virtual Vec<3> GetNormal (const Point<3> & p, int surfi1, + const PointGeomInfo & gi) const; + + + virtual void ProjectToSurface (Point<3> & p, int surfi); + + virtual void ProjectToSurface (Point<3> & p, int surfi, const PointGeomInfo & /* gi */) + { + ProjectToSurface (p, surfi); + } + + virtual void ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const; + + + void ValidateSecondOrder (Mesh & mesh); + void ValidateRefinedMesh (Mesh & mesh, + ARRAY<INDEX_2> & parents); + + MeshOptimize2d * Get2dOptimizer(void) + { + return optimizer2d; + } + void Set2dOptimizer(MeshOptimize2d * opti) + { + optimizer2d = opti; + } + + + virtual void LocalizeEdgePoints(Mesh & mesh) const {;} +}; + +#endif diff --git a/contrib/Netgen/libsrc/meshing/boundarylayer.cpp b/contrib/Netgen/libsrc/meshing/boundarylayer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1dd3403807c843bf14ed69892c5c8c079a8e71a4 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/boundarylayer.cpp @@ -0,0 +1,92 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + +void InsertVirtualBoundaryLayer (Mesh & mesh) +{ + cout << "Insert virt. b.l." << endl; + + int surfid; + + cout << "Boundary Nr:"; + cin >> surfid; + + int i, j; + int np = mesh.GetNP(); + + cout << "Old NP: " << mesh.GetNP() << endl; + cout << "Trigs: " << mesh.GetNSE() << endl; + + BitArray bndnodes(np); + ARRAY<int> mapto(np); + + bndnodes.Clear(); + for (i = 1; i <= mesh.GetNSeg(); i++) + { + int snr = mesh.LineSegment(i).edgenr; + cout << "snr = " << snr << endl; + if (snr == surfid) + { + bndnodes.Set (mesh.LineSegment(i).p1); + bndnodes.Set (mesh.LineSegment(i).p2); + } + } + for (i = 1; i <= mesh.GetNSeg(); i++) + { + int snr = mesh.LineSegment(i).edgenr; + if (snr != surfid) + { + bndnodes.Clear (mesh.LineSegment(i).p1); + bndnodes.Clear (mesh.LineSegment(i).p2); + } + } + + for (i = 1; i <= np; i++) + { + if (bndnodes.Test(i)) + mapto.Elem(i) = mesh.AddPoint (mesh.Point (i)); + else + mapto.Elem(i) = 0; + } + + for (i = 1; i <= mesh.GetNSE(); i++) + { + Element2d & el = mesh.SurfaceElement(i); + for (j = 1; j <= el.GetNP(); j++) + if (mapto.Get(el.PNum(j))) + el.PNum(j) = mapto.Get(el.PNum(j)); + } + + + int nq = 0; + for (i = 1; i <= mesh.GetNSeg(); i++) + { + int snr = mesh.LineSegment(i).edgenr; + if (snr == surfid) + { + int p1 = mesh.LineSegment(i).p1; + int p2 = mesh.LineSegment(i).p2; + int p3 = mapto.Get (p1); + if (!p3) p3 = p1; + int p4 = mapto.Get (p2); + if (!p4) p4 = p2; + + Element2d el(QUAD); + el.PNum(1) = p1; + el.PNum(2) = p2; + el.PNum(3) = p3; + el.PNum(4) = p4; + el.SetIndex (2); + mesh.AddSurfaceElement (el); + nq++; + } + } + + cout << "New NP: " << mesh.GetNP() << endl; + cout << "Quads: " << nq << endl; +} + +} + diff --git a/contrib/Netgen/libsrc/meshing/boundarylayer.hpp b/contrib/Netgen/libsrc/meshing/boundarylayer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e5a047b6bb0239c3ebd3e7a839a4ee830bef2183 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/boundarylayer.hpp @@ -0,0 +1,9 @@ +#ifndef FILE_BOUNDARYLAYER +#define FILE_BOUNDARYLAYER + + +/// +extern void InsertVirtualBoundaryLayer (Mesh & mesh); + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/classifyhpel.hpp b/contrib/Netgen/libsrc/meshing/classifyhpel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..96bf1b62c43e43bc968e5463202119f01a361f87 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/classifyhpel.hpp @@ -0,0 +1,1713 @@ +HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint) +{ + int ep1(0), ep2(0), ep3(0), ep4(0), cp1(0), cp2(0), cp3(0), cp4(0), fp1, fp2, fp3, fp4; + int isedge1(0), isedge2(0), isedge3(0), isedge4(0), isedge5(0), isedge6(0); + int isfedge1, isfedge2, isfedge3, isfedge4, isfedge5, isfedge6; + int isface1(0), isface2(0), isface3(0), isface4(0); + + HPREF_ELEMENT_TYPE type = HP_NONE; + + + int debug = 0; + for (int j = 0;j < 4; j++) + { + if (el.pnums[j] == 444) debug++; + if (el.pnums[j] == 115) debug++; + if (el.pnums[j] == 382) debug++; + if (el.pnums[j] == 281) debug++; + } + if (debug < 4) debug = 0; + + + + for (int j = 0; j < 4; j++) + for (int k = 0; k < 4; k++) + { + if (j == k) continue; + if (type) break; + + int pi3 = 0; + while (pi3 == j || pi3 == k) pi3++; + int pi4 = 6 - j - k - pi3; + + // preserve orientation + int sort[4]; + sort[0] = j; sort[1] = k; sort[2] = pi3; sort[3] = pi4; + int cnt = 0; + for (int jj = 0; jj < 4; jj++) + for (int kk = 0; kk < 3; kk++) + if (sort[kk] > sort[kk+1]) + { + cnt++; + Swap (sort[kk], sort[kk+1]); + } + if (cnt % 2 == 1) Swap (pi3, pi4); + + ep1 = edgepoint.Test (el.pnums[j]); + ep2 = edgepoint.Test (el.pnums[k]); + ep3 = edgepoint.Test (el.pnums[pi3]); + ep4 = edgepoint.Test (el.pnums[pi4]); + + cp1 = cornerpoint.Test (el.pnums[j]); + cp2 = cornerpoint.Test (el.pnums[k]); + cp3 = cornerpoint.Test (el.pnums[pi3]); + cp4 = cornerpoint.Test (el.pnums[pi4]); + + isedge1 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[k])); + isedge2 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi3])); + isedge3 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi4])); + isedge4 = edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi3])); + isedge5 = edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi4])); + isedge6 = edges.Used (INDEX_2::Sort (el.pnums[pi3], el.pnums[pi4])); + + if (debug) + { + cout << "debug" << endl; + *testout << "debug" << endl; + *testout << "ep = " << ep1 << ep2 << ep3 << ep4 << endl; + *testout << "cp = " << cp1 << cp2 << cp3 << cp4 << endl; + *testout << "edge = " << isedge1 << isedge2 << isedge3 << isedge4 << isedge5 << isedge6 << endl; + } + + + isface1 = isface2 = isface3 = isface4 = 0; + for (int l = 0; l < 4; l++) + { + INDEX_3 i3(0,0,0); + switch (l) + { + case 0: i3.I1() = el.pnums[k]; i3.I1() = el.pnums[pi3]; i3.I1() = el.pnums[pi4]; break; + case 1: i3.I1() = el.pnums[j]; i3.I1() = el.pnums[pi3]; i3.I1() = el.pnums[pi4]; break; + case 2: i3.I1() = el.pnums[j]; i3.I1() = el.pnums[k]; i3.I1() = el.pnums[pi4]; break; + case 3: i3.I1() = el.pnums[j]; i3.I1() = el.pnums[k]; i3.I1() = el.pnums[pi3]; break; + } + i3.Sort(); + if (faces.Used (i3)) + { + int domnr = faces.Get(i3); + if (domnr == -1 || domnr == el.GetIndex()) + { + switch (l) + { + case 0: isface1 = 1; break; + case 1: isface2 = 1; break; + case 2: isface3 = 1; break; + case 3: isface4 = 1; break; + } + } + } + } + /* + isface1 = faces.Used (INDEX_3::Sort (el.pnums[k], el.pnums[pi3], el.pnums[pi4])); + isface2 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[pi3], el.pnums[pi4])); + isface3 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[k], el.pnums[pi4])); + isface4 = faces.Used (INDEX_3::Sort (el.pnums[j], el.pnums[k], el.pnums[pi3])); + */ + + isfedge1 = isfedge2 = isfedge3 = isfedge4 = isfedge5 = isfedge6 = 0; + for (int l = 0; l < 6; l++) + { + INDEX_2 i2(0,0); + switch (l) + { + case 0: i2.I1() = el.pnums[j]; i2.I2() = el[k]; break; + case 1: i2.I1() = el.pnums[j]; i2.I2() = el.pnums[pi3]; break; + case 2: i2.I1() = el.pnums[j]; i2.I2() = el.pnums[pi4]; break; + case 3: i2.I1() = el.pnums[k]; i2.I2() = el.pnums[pi3]; break; + case 4: i2.I1() = el.pnums[k]; i2.I2() = el.pnums[pi4]; break; + case 5: i2.I1() = el.pnums[pi3]; i2.I2() = el.pnums[pi4]; break; + } + i2.Sort(); + if (face_edges.Used (i2)) + { + int domnr = face_edges.Get(i2); + if (domnr == -1 || domnr == el.GetIndex()) + { + switch (l) + { + case 0: isfedge1 = 1; break; + case 1: isfedge2 = 1; break; + case 2: isfedge3 = 1; break; + case 3: isfedge4 = 1; break; + case 4: isfedge5 = 1; break; + case 5: isfedge6 = 1; break; + } + } + } + } + /* + isfedge1 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[k])); + isfedge2 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi3])); + isfedge3 = face_edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi4])); + isfedge4 = face_edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi3])); + isfedge5 = face_edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi4])); + isfedge6 = face_edges.Used (INDEX_2::Sort (el.pnums[pi3], el.pnums[pi4])); + */ + + fp1 = fp2 = fp3 = fp4 = 0; + for (int l = 0; l < 4; l++) + { + int pti(0); + switch (l) + { + case 0: pti = el.pnums[j]; break; + case 1: pti = el.pnums[k]; break; + case 2: pti = el.pnums[pi3]; break; + case 3: pti = el.pnums[pi4]; break; + } + int domnr = facepoint[pti]; + if (domnr == -1 || domnr == el.GetIndex()) + { + switch (l) + { + case 0: fp1 = 1; break; + case 1: fp2 = 1; break; + case 2: fp3 = 1; break; + case 3: fp4 = 1; break; + } + } + } + + /* + fp1 = facepoint[el.pnums[j]] != 0; + fp2 = facepoint[el.pnums[k]] != 0; + fp3 = facepoint[el.pnums[pi3]] != 0; + fp4 = facepoint[el.pnums[pi4]] != 0; + */ + + + switch (isface1+isface2+isface3+isface4) + { + case 0: + { + isedge1 |= isfedge1; + isedge2 |= isfedge2; + isedge3 |= isfedge3; + isedge4 |= isfedge4; + isedge5 |= isfedge5; + isedge6 |= isfedge6; + + ep1 |= fp1; + ep2 |= fp2; + ep3 |= fp3; + ep4 |= fp4; + + switch (isedge1+isedge2+isedge3+isedge4+isedge5+isedge6) + { + case 0: + { + if (!ep1 && !ep2 && !ep3 && !ep4) + type = HP_TET; + + if (ep1 && !ep2 && !ep3 && !ep4) + type = HP_TET_0E_1V; + + if (ep1 && ep2 && !ep3 && !ep4) + type = HP_TET_0E_2V; + + if (ep1 && ep2 && ep3 && !ep4) + type = HP_TET_0E_3V; + + if (ep1 && ep2 && ep3 && ep4) + type = HP_TET_0E_4V; + + break; + } + + case 1: + { + if (!isedge1) break; + + if (!cp1 && !cp2 && !ep3 && !ep4) + type = HP_TET_1E_0V; + + if (cp1 && !cp2 && !ep3 && !ep4) + type = HP_TET_1E_1VA; + + if (!cp1 && !cp2 && !ep3 && ep4) + type = HP_TET_1E_1VB; + + if (cp1 && cp2 && !ep3 && !ep4) + type = HP_TET_1E_2VA; + + if (cp1 && !cp2 && ep3 && !ep4) + type = HP_TET_1E_2VB; + + if (cp1 && !cp2 && !ep3 && ep4) + type = HP_TET_1E_2VC; + + if (!cp1 && !cp2 && ep3 && ep4) + type = HP_TET_1E_2VD; + + if (cp1 && cp2 && ep3 && !ep4) + type = HP_TET_1E_3VA; + + if (cp1 && !cp2 && ep3 && ep4) + type = HP_TET_1E_3VB; + + if (cp1 && cp2 && ep3 && ep4) + type = HP_TET_1E_4V; + + break; + } + case 2: + { + if (isedge1 && isedge2) + { + if (!cp2 && !cp3 && !ep4) + type = HP_TET_2EA_0V; + + if (cp2 && !cp3 && !ep4) + type = HP_TET_2EA_1VA; + if (!cp2 && cp3 && !ep4) + type = HP_TET_2EA_1VB; + + if (!cp2 && !cp3 && ep4) + type = HP_TET_2EA_1VC; + + if (cp2 && cp3 && !ep4) + type = HP_TET_2EA_2VA; + if (cp2 && !cp3 && ep4) + type = HP_TET_2EA_2VB; + if (!cp2 && cp3 && ep4) + type = HP_TET_2EA_2VC; + + if (cp2 && cp3 && ep4) + type = HP_TET_2EA_3V; + } + if (isedge1 && isedge6) + { + if (!cp1 && !cp2 && !cp3 && !cp4) + type = HP_TET_2EB_0V; + if (cp1 && !cp2 && !cp3 && !cp4) + type = HP_TET_2EB_1V; + if (cp1 && cp2 && !cp3 && !cp4) + type = HP_TET_2EB_2VA; + if (cp1 && !cp2 && cp3 && !cp4) + type = HP_TET_2EB_2VB; + if (cp1 && !cp2 && !cp3 && cp4) + type = HP_TET_2EB_2VC; + if (cp1 && cp2 && cp3 && !cp4) + type = HP_TET_2EB_3V; + if (cp1 && cp2 && cp3 && cp4) + type = HP_TET_2EB_4V; + } + break; + } + case 3: + { + if (isedge1 && isedge2 && isedge3) + { + if (!cp2 && !cp3 && !cp4) + type = HP_TET_3EA_0V; + if (cp2 && !cp3 && !cp4) + type = HP_TET_3EA_1V; + if (cp2 && cp3 && !cp4) + type = HP_TET_3EA_2V; + if (cp2 && cp3 && cp4) + type = HP_TET_3EA_3V; + } + if (isedge1 && isedge3 && isedge4) + { + if (!cp3 && !cp4) + type = HP_TET_3EB_0V; + if (cp3 && !cp4) + type = HP_TET_3EB_1V; + if (cp3 && cp4) + type = HP_TET_3EB_2V; + } + if (isedge1 && isedge2 && isedge5) + { + if (!cp3 && !cp4) + type = HP_TET_3EC_0V; + if (cp3 && !cp4) + type = HP_TET_3EC_1V; + if (cp3 && cp4) + type = HP_TET_3EC_2V; + } + break; + } + } + break; + } + + + + case 1: // one singular face + { + if (!isface1) break; + + switch (isfedge1+isfedge2+isfedge3+isedge4+isedge5+isedge6) + { + case 0: + { + if (!fp1 && !ep2 && !ep3 && !ep4) + type = HP_TET_1F_0E_0V; + if (fp1 && !ep2 && !ep3 && !ep4) + type = HP_TET_1F_0E_1VB; + if (!fp1 && ep2 && !ep3 & !ep4) + type = HP_TET_1F_0E_1VA; + break; + } + case 1: + { + if (isfedge1) + { + if (!ep1 && !ep3 && !ep4) + type = HP_TET_1F_1EA_0V; + } + if (isedge4) // V1-V3 + { + if (!ep1 && !cp2 && !cp3 && !ep4) + type = HP_TET_1F_1EB_0V; + } + break; + } + } + break; + } + + + case 2: // two singular faces + { + if (!isface1 || !isface2) break; + + switch (isfedge1+isedge2+isedge3+isedge4+isedge5) + { + case 0: + { + if (!ep1 && !ep2 && !cp3 && !cp4) + type = HP_TET_2F_0E_0V; + break; + } + } + break; + } + + + } + + if (type != HP_NONE) + { + int pnums[4]; + pnums[0] = el.pnums[j]; + pnums[1] = el.pnums[k]; + pnums[2] = el.pnums[pi3]; + pnums[3] = el.pnums[pi4]; + for(k=0;k<4;k++) el.pnums[k] = pnums[k]; + break; + } + } + + + if (debug) cout << "type = " << type << endl; + + if (type == HP_NONE) + { + // cnt_undef++; + (*testout) << "undefined element" << endl + << "cp = " << cp1 << cp2 << cp3 << cp4 << endl + << "ep = " << ep1 << ep2 << ep3 << ep4 << endl + << "isedge = " << isedge1 << isedge2 << isedge3 + << isedge4 << isedge5 << isedge6 << endl + << "isface = " << isface1 << isface2 << isface3 << isface4 << endl; + cout << "undefined element !!! " << endl; + + + } + return(type); +} + + + +HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint) +{ + + HPREF_ELEMENT_TYPE type = HP_NONE; + + int p[6]; + for(int m=1;m<=6;m++) + { + int point_sing[6]={0,0,0,0,0,0}; + int face_sing[5]={0,0,0,0,0}; + int edge_sing[9]={0,0,0,0,0,0,0,0,0}; + + if(m<4) + { + p[0]= m; p[1]=m%3+1; p[2]=(m%3+1)%3+1; + for(int l=3;l<6;l++) p[l]=p[l-3]+3; + } + else + { + p[0] = m; p[1]=(m%3+1)%3+4; p[2]=m%3+4; + for(int l=3;l<6;l++) p[l]=p[l-3]-3; + } + + for(int j=0;j<6;j++) + { + if(cornerpoint.Test(el.PNum(p[j]))) { point_sing[p[j]-1]=3;} + else if(edgepoint.Test(el.PNum(p[j]))) point_sing[p[j]-1]=2; + else if (facepoint[el.PNum(p[j])] == -1 || facepoint[el.PNum(p[j])] == el.GetIndex()) + point_sing[p[j]-1] = 1; + } + + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges (PRISM); + for(int k=0;k<9;k++) + { + INDEX_2 i2 = INDEX_2 :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1])); + if (edges.Used(i2)) edge_sing[k] = 2; + else edge_sing[k] = face_edges.Used(i2); + } + + const ELEMENT_FACE * elfaces = MeshTopology::GetFaces (PRISM); + for (int k=0;k<5;k++) + { + INDEX_3 i3; + + if(k<2) + i3 = INDEX_3::Sort(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], + el.pnums[p[elfaces[k][2]-1]-1]); + else + { + INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]); + i4.Sort(); + i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); + } + + if (faces.Used (i3)) + { + int domnr = faces.Get(i3); + if (domnr == -1 || domnr == el.GetIndex()) + face_sing[k] = 1; + + } + } + if (face_sing[1] > face_sing[0]) {m=m+2; continue;} + + + //int cp = 0; + + int qfsing = face_sing[2] + face_sing[3] + face_sing[4]; + int tfsing = face_sing[0] + face_sing[1]; + int evsing = edge_sing[6] + edge_sing[7] + edge_sing[8]; + int ehsing = edge_sing[0] + edge_sing[1] + edge_sing[2] + edge_sing[3] + edge_sing[4] + edge_sing[5]; + + if (qfsing + tfsing + evsing + ehsing == 0) + { type = HP_PRISM; break;} + + HPREF_ELEMENT_TYPE types[] = {HP_NONE,HP_NONE,HP_NONE}; + + int fb = (1-face_sing[4])* face_sing[3] * (face_sing[2] + face_sing[3]) + 3*face_sing[4]*face_sing[3]*face_sing[2]; + int sve[3] = {edge_sing[7] , edge_sing[8], edge_sing[6]}; + + + if(fb!=qfsing) continue; + + + switch(fb) + { + case 0: + if (evsing == 0 && ehsing==3*tfsing) + { + types[0] = HP_PRISM; + types[1] = HP_PRISM_1FA_0E_0V; + types[2] = HP_PRISM_2FA_0E_0V; + } + if(evsing > 0 && sve[0] == evsing) // 1 vertical edge 1-4 + { + types[0] = HP_PRISM_SINGEDGE; + types[1] = HP_PRISM_1FA_1E_0V; + types[2] = HP_PRISM_2FA_1E_0V; + } + + if(sve[0] > 0 && sve[1] > 0 && sve[2] == 0) + { + types[0] = HP_PRISM_SINGEDGE_V12; + types[1] = HP_PRISM_1FA_2E_0V; + types[2] = HP_PRISM_2FA_2E_0V; + } + if(sve[0] > 0 && sve[1] > 0 && sve[2] > 0) + { + types[0] = HP_PRISM_3E_0V; + types[1] = HP_PRISM_1FA_3E_0V; + types[2] = HP_PRISM_2FA_3E_0V; + + if ( edge_sing[0] > 1 && edge_sing[2] > 1 && + edge_sing[4] > 1 && edge_sing[5] > 1 && tfsing==0) + types[0] = HP_PRISM_3E_4EH; + } + + break; + case 1: + if(sve[0] <= 1 && sve[1] <= 1) + if(sve[2]==0) + { + types[0] = HP_PRISM_1FB_0E_0V; + types[1] = HP_PRISM_1FA_1FB_0E_0V; + types[2] = HP_PRISM_2FA_1FB_0E_0V; + } + else + { + types[0] = HP_PRISM_1FB_1EC_0V; + types[1] = HP_PRISM_1FA_1FB_1EC_0V; + types[2] = HP_PRISM_2FA_1FB_1EC_0V; + } + + if(sve[0] > 1 && sve[2] >= 1 && sve[1] <= 1) + { + types[0] = HP_PRISM_1FB_2EB_0V; + types[1] = HP_PRISM_1FA_1FB_2EB_0V; + types[2] = HP_PRISM_2FA_1FB_2EB_0V; + } + + if(sve[0] > 1 && sve[1] <= 1 && sve[2] == 0) // ea && !eb + { + types[0] = HP_PRISM_1FB_1EA_0V; + types[1] = HP_PRISM_1FA_1FB_1EA_0V; + types[2] = HP_PRISM_2FA_1FB_1EA_0V; + } + + if(sve[0] <= 1 && sve[1] > 1 && sve[2] == 0) + types[1] = HP_PRISM_1FA_1FB_1EB_0V; + + if(sve[0] > 1 && sve[1]>1) + if(sve[2] == 0) // ea && eb + { + types[0] = HP_PRISM_1FB_2EA_0V; + types[1] = HP_PRISM_1FA_1FB_2EA_0V; + types[2] = HP_PRISM_2FA_1FB_2EA_0V; + } + if(sve[0] <= 1 && sve[1] > 1 && sve[2] >0) + types[1] = HP_PRISM_1FA_1FB_2EC_0V; + + if(sve[0] > 1 && sve[1] > 1 && sve[2] >= 1) //sve[2] can also be a face-edge + { + types[0] = HP_PRISM_1FB_3E_0V; + types[1] = HP_PRISM_1FA_1FB_3E_0V; + types[2] = HP_PRISM_2FA_1FB_3E_0V; + } + + break; + + case 2: + if(sve[0] <= 1) + cout << " **** WARNING: Edge between to different singular faces should be marked singular " << endl; + + if(sve[1] <= 1) + if(sve[2] <=1) + { + types[0] = HP_PRISM_2FB_0E_0V; + types[1] = HP_PRISM_1FA_2FB_0E_0V; + types[2] = HP_PRISM_2FA_2FB_0E_0V; + } + else + { + types[0] = HP_PRISM_2FB_1EC_0V; + types[1] = HP_PRISM_1FA_2FB_1EC_0V; + types[2] = HP_PRISM_2FA_2FB_1EC_0V; + } + else + if(sve[2] <= 1) + types[1] = HP_PRISM_1FA_2FB_1EB_0V; + else + { + types[0] = HP_PRISM_2FB_3E_0V; + types[1] = HP_PRISM_1FA_2FB_3E_0V; + types[2] = HP_PRISM_2FA_2FB_3E_0V; + } + + break; + + case 3: + types[0] = HP_PRISM_3FB_0V; + types[1] = HP_PRISM_1FA_3FB_0V; + types[2] = HP_PRISM_2FA_3FB_0V; + break; + } + type = types[tfsing]; + + + if(type != HP_NONE) + break; + } + + /* + *testout << " Prism with pnums " << endl; + for(int j=0;j<6;j++) *testout << el.pnums[j] << "\t"; + *testout << endl; + */ + + if(type != HP_NONE) + { + int pnums[6]; + for(int j=0;j<6;j++) pnums[j] = el.PNum (p[j]); + for(int k=0;k<6;k++) el.pnums[k] = pnums[k]; + } + + /* *testout << " Classified Prism with pnums " << endl; + for(int j=0;j<6;j++) *testout << el.pnums[j] << "\t"; + *testout << endl; + */ + return(type); +} + + +// #ifdef SABINE +HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) + +{ + HPREF_ELEMENT_TYPE type = HP_NONE; + + int pnums[3]; + int p[3]; + + INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); + i3.Sort(); + bool sing_face = faces.Used (i3); + + // *testout << " facepoint " << facepoint << endl; + + + // Try all rotations of the trig + for (int j=0;j<3;j++) + { + int point_sing[3] = {0,0,0}; + int edge_sing[3] = {0,0,0}; + // *testout << " actual rotation of trig points " ; + for(int m=0;m<3;m++) + { + p[m] = (j+m)%3 +1; // local vertex number + pnums[m] = el.PNum(p[m]); // global vertex number + // *testout << pnums[m] << " \t "; + } + // *testout << endl ; + + if(dim == 3) + { + // face point + for(int k=0;k<3;k++) + if(!sing_face) + { + // *testout << " fp [" << k << "] = " << facepoint[pnums[k]] << endl; + // *testout << " fd.DomainIn()" << fd.DomainIn() << endl; + // *testout << " fd.DomainOut()" << fd.DomainOut() << endl; + if( facepoint[pnums[k]] && (facepoint[pnums[k]] ==-1 || + facepoint[pnums[k]] == fd.DomainIn() || facepoint[pnums[k]] == fd.DomainOut())) + point_sing[p[k]-1] = 1; + } + // if point is on face_edge in next step sing = 2 + + /* *testout << " pointsing NACH FACEPOints ... FALLS EDGEPOINT UMSETZEN" ; + for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; + *testout << endl; */ + } + + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges(TRIG); + + if(dim==3) + { + for(int k=0;k<3;k++) + { + int ep1=p[eledges[k][0]-1]; + int ep2=p[eledges[k][1]-1]; + INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); + + if(edges.Used(i2)) + { + + edge_sing[k]=2; + point_sing[ep1-1] = 2; + point_sing[ep2-1] = 2; + } + else // face_edge? + { + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1) // edge not face_edge acc. to surface in which trig lies + if(face_edges.Get(i2)==-1 ||face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut() ) + { + edge_sing[k]=1; + } + else + { + point_sing[ep1-1] = 0; // set to edge_point + point_sing[ep2-1] = 0; // set to edge_point + } + } + + /* *testout << " pointsing NACH edges UND FACEEDGES UMSETZEN ... " ; + for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; + *testout << endl; + */ + } + } + /* + *testout << " dim " << dim << endl; + *testout << " edgepoint_dom " << edgepoint_dom << endl; + */ + if(dim==2) + { + for(int k=0;k<3;k++) + { + int ep1=p[eledges[k][0]-1]; + int ep2=p[eledges[k][1]-1]; + + INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); + + if(edges.Used(i2)) + { + + if(edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep1-1])) || + edgepoint_dom.Used(INDEX_2(-1,pnums[ep1-1])) || + edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep2-1])) || + edgepoint_dom.Used(INDEX_2(-1,pnums[ep2-1]))) + { + edge_sing[k]=2; + point_sing[ep1-1] = 2; + point_sing[ep2-1] = 2; + } + } + + } + } + + + + for(int k=0;k<3;k++) + if(edgepoint.Test(pnums[k])) //edgepoint, but not member of sing_edge on trig -> cp + { + INDEX_2 i2a=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+1)%3])); + INDEX_2 i2b=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+2)%3])); + + if(!edges.Used(i2a) && !edges.Used(i2b)) + point_sing[p[k]-1] = 3; + } + + for(int k=0;k<3;k++) + if(cornerpoint.Test(el.PNum(p[k]))) + point_sing[p[k]-1] = 3; + + + if(edge_sing[0] + edge_sing[1] + edge_sing[2] == 0) + { + int ps = point_sing[0] + point_sing[1] + point_sing[2]; + + if(ps==0) + type = HP_TRIG; + else if(point_sing[p[0]-1] && !point_sing[p[1]-1] && !point_sing[p[2]-1]) + type = HP_TRIG_SINGCORNER; + else if(point_sing[p[0]-1] && point_sing[p[1]-1] && !point_sing[p[2]-1]) + type = HP_TRIG_SINGCORNER12; + else if(point_sing[p[0]-1] && point_sing[p[1]-1] && point_sing[p[2]-1]) + { + if(dim==2) type = HP_TRIG_SINGCORNER123_2D; + else type = HP_TRIG_SINGCORNER123; + } + } + else + if (edge_sing[2] && !edge_sing[0] && !edge_sing[1]) //E[2]=(1,2) + { + int code = 0; + if(point_sing[p[0]-1] > edge_sing[2]) code+=1; + if(point_sing[p[1]-1] > edge_sing[2]) code+=2; + if(point_sing[p[2]-1]) code+=4; + + HPREF_ELEMENT_TYPE types[] = + { + HP_TRIG_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER12, + HP_TRIG_SINGEDGECORNER3, + HP_TRIG_SINGEDGECORNER13, + HP_TRIG_SINGEDGECORNER23, + HP_TRIG_SINGEDGECORNER123, + }; + type = types[code]; + + } // E[0] = [0,2], E[1] =[1,2], E[2] = [0,1] + else + if(edge_sing[2] && !edge_sing[1] && edge_sing[0]) + { + if(point_sing[p[2]-1] <= edge_sing[0] ) + { + if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES; + else type = HP_TRIG_SINGEDGES2; + } + else + { + if(point_sing[p[1]-1]<= edge_sing[2]) + type = HP_TRIG_SINGEDGES3; + else type = HP_TRIG_SINGEDGES23; + } + } + else if (edge_sing[2] && edge_sing[1] && edge_sing[0]) + type = HP_TRIG_3SINGEDGES; + + // cout << " run for " << j << " gives type " << type << endl; + //*testout << " run for " << j << " gives type " << type << endl; + if(type!=HP_NONE) break; + } + + for(int k=0;k<3;k++) el[k] = pnums[k]; + /*if(type != HP_NONE) + { + + cout << " TRIG with pnums " << pnums[0] << "\t" << + pnums[1] << "\t" << pnums[2] << endl; + cout << " type " << type << endl; + } + */ + return(type); +} +#ifdef HPREF_OLD +HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) +{ + HPREF_ELEMENT_TYPE type = HP_NONE; + + int pnums[3]; + + INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); + i3.Sort(); + bool sing_face = faces.Used (i3); + + + for (int j = 1; j <= 3; j++) + { + int ep1 = edgepoint.Test (el.PNumMod (j)); + int ep2 = edgepoint.Test (el.PNumMod (j+1)); + int ep3 = edgepoint.Test (el.PNumMod (j+2)); + + if (dim == 2) + { + // JS, Dec 11 + ep1 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j))) || + edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j))); + ep2 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+1))) || + edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+1))); + ep3 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+2))) || + edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+2))); + /* + ep1 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j))); + ep2 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+1))); + ep3 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+2))); + */ + // ep3 = edgepoint_dom.Used (INDEX_2 (mesh.SurfaceElement(i).GetIndex(), el.PNumMod(j+2))); + } + + + + int cp1 = cornerpoint.Test (el.PNumMod (j)); + int cp2 = cornerpoint.Test (el.PNumMod (j+1)); + int cp3 = cornerpoint.Test (el.PNumMod (j+2)); + + ep1 |= cp1; + ep2 |= cp2; + ep3 |= cp3; + + + // (*testout) << "cp = " << cp1 << cp2 << cp3 << ", ep = " << ep1 << ep2 << ep3 << endl; + + int p[3] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2)}; + if(ep1) + { + INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); + INDEX_2 i2b=INDEX_2::Sort(p[0], p[2]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cp1 = 1; + } + if(ep2) + { + INDEX_2 i2a=INDEX_2::Sort(p[1], p[0]); + INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cp2 = 1; + } + if(ep3) + { + INDEX_2 i2a=INDEX_2::Sort(p[2], p[0]); + INDEX_2 i2b=INDEX_2::Sort(p[2], p[1]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cp3= 1; + } + + + int isedge1=0, isedge2=0, isedge3=0; + if(dim == 3 ) + { + INDEX_2 i2; + i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); + isedge1 = edges.Used (i2); + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && + (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) + { + isedge1=1; + ep1 = 1; ep2=1; + } + + i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); + isedge2 = edges.Used (i2); + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && + (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) + { + isedge2=1; + ep2 = 1; ep3=1; + } + i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); + isedge3 = edges.Used (i2); + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && + (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) + { + isedge3=1; + ep1 = 1; ep3=1; + } + + // cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; + + if (!sing_face) + { + /* + if (!isedge1) { cp1 |= ep1; cp2 |= ep2; } + if (!isedge2) { cp2 |= ep2; cp3 |= ep3; } + if (!isedge3) { cp3 |= ep3; cp1 |= ep1; } + */ + ep1 |= facepoint [el.PNumMod(j)] != 0; + ep2 |= facepoint [el.PNumMod(j+1)] != 0; + ep3 |= facepoint [el.PNumMod(j+2)] != 0; + + + isedge1 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))); + isedge2 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+1), el.PNumMod(j+2))); + isedge3 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+2), el.PNumMod(j+3))); + } + } + + if(dim ==2) + { + INDEX_2 i2; + i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); + i2.Sort(); + isedge1 = edges.Used (i2); + if(isedge1) + { + ep1 = 1; ep2=1; + } + + i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); + i2.Sort(); + isedge2 = edges.Used (i2); + if(isedge2) + { + ep2 = 1; ep3=1; + } + i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); + i2.Sort(); + isedge3 = edges.Used (i2); + if(isedge3) + { + ep1 = 1; ep3=1; + } + + + } + + + /* + cout << " used " << face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))) << endl; + + cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; + cout << " ep " << ep1 << "\t" << ep2 << " \t " << ep3 << endl; + cout << " cp " << cp1 << "\t" << cp2 << " \t " << cp3 << endl; + */ + + + + if (isedge1 + isedge2 + isedge3 == 0) + { + if (!ep1 && !ep2 && !ep3) + type = HP_TRIG; + + if (ep1 && !ep2 && !ep3) + type = HP_TRIG_SINGCORNER; + + if (ep1 && ep2 && !ep3) + type = HP_TRIG_SINGCORNER12; + + if (ep1 && ep2 && ep3) + { + if (dim == 2) + type = HP_TRIG_SINGCORNER123_2D; + else + type = HP_TRIG_SINGCORNER123; + } + + if (type != HP_NONE) + { + pnums[0] = el.PNumMod (j); + pnums[1] = el.PNumMod (j+1); + pnums[2] = el.PNumMod (j+2); + break; + } + } + + if (isedge1 && !isedge2 && !isedge3) + { + int code = 0; + if (cp1) code += 1; + if (cp2) code += 2; + if (ep3) code += 4; + + HPREF_ELEMENT_TYPE types[] = + { + HP_TRIG_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER12, + HP_TRIG_SINGEDGECORNER3, + HP_TRIG_SINGEDGECORNER13, + HP_TRIG_SINGEDGECORNER23, + HP_TRIG_SINGEDGECORNER123, + }; + type = types[code]; + pnums[0] = el.PNumMod (j); + pnums[1] = el.PNumMod (j+1); + pnums[2] = el.PNumMod (j+2); + break; + } + + + if (isedge1 && !isedge2 && isedge3) + { + if (!cp3) + { + if (!cp2) type = HP_TRIG_SINGEDGES; + else type = HP_TRIG_SINGEDGES2; + } + else + { + if (!cp2) type = HP_TRIG_SINGEDGES3; + else type = HP_TRIG_SINGEDGES23; + } + + pnums[0] = el.PNumMod (j); + pnums[1] = el.PNumMod (j+1); + pnums[2] = el.PNumMod (j+2); + break; + } + + if (isedge1 && isedge2 && isedge3) + { + type = HP_TRIG_3SINGEDGES; + pnums[0] = el.PNumMod (j); + pnums[1] = el.PNumMod (j+1); + pnums[2] = el.PNumMod (j+2); + break; + } + } + + for(int k=0;k<3;k++) el[k] = pnums[k]; + /*if(type != HP_NONE) + { + + cout << " TRIG with pnums " << pnums[0] << "\t" << + pnums[1] << "\t" << pnums[2] << endl; + cout << " type " << type << endl; + } + */ + return(type); +} +#endif +HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) +{ + HPREF_ELEMENT_TYPE type = HP_NONE; + + int ep1(-1), ep2(-1), ep3(-1), ep4(-1), cp1(-1), cp2(-1), cp3(-1), cp4(-1); + int isedge1, isedge2, isedge3, isedge4; + + for (int j = 1; j <= 4; j++) + { + ep1 = edgepoint.Test (el.PNumMod (j)); + ep2 = edgepoint.Test (el.PNumMod (j+1)); + ep3 = edgepoint.Test (el.PNumMod (j+2)); + ep4 = edgepoint.Test (el.PNumMod (j+3)); + + if (dim == 2) + { + ep1 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j))); + ep2 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+1))); + ep3 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+2))); + ep4 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+3))); + } + + cp1 = cornerpoint.Test (el.PNumMod (j)); + cp2 = cornerpoint.Test (el.PNumMod (j+1)); + cp3 = cornerpoint.Test (el.PNumMod (j+2)); + cp4 = cornerpoint.Test (el.PNumMod (j+3)); + + ep1 |= cp1; + ep2 |= cp2; + ep3 |= cp3; + ep4 |= cp4; + + int p[4] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2), el.PNumMod(j+4)}; + //int epp[4] = { ep1, ep2, ep3, ep4}; + int cpp[4] = { cp1, cp2, cp3, cp4}; + for(int k=0;k<0;k++) + { + INDEX_2 i2a=INDEX_2::Sort(p[k], p[(k+1)%4]); + INDEX_2 i2b=INDEX_2::Sort(p[k], p[(k-1)%4]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cpp[k] = 1; + } + cp1= cpp[0]; cp2=cpp[1]; cp3=cpp[2]; cp4=cpp[3]; + + + if(dim ==3) + { + INDEX_2 i2; + i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); + // i2.Sort(); + isedge1 = edges.Used (i2); + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && + (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) + { + isedge1=1; + ep1 = 1; ep2=1; + } + i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); + // i2.Sort(); + isedge2 = edges.Used (i2); + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && + (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) + { + isedge2=1; + ep2=1; ep3=1; + } + i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); + // i2.Sort(); + isedge3 = edges.Used (i2); + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) + { + isedge3=1; + ep3=1; ep4=1; + } + i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); + // i2.Sort(); + isedge4 = edges.Used (i2); + i2.Sort(); + if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && + (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) + { + isedge4=1; + ep4=1; ep1=1; + } + + +//MH*********************************************************************************************************** + if(ep1) + if(edgepoint.Test(p[0])) + { + INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); + INDEX_2 i2b=INDEX_2::Sort(p[0], p[3]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cp1 = 1; + } + if(ep2) + if(edgepoint.Test(p[1])) + { + INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); + INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cp2 = 1; + } + if(ep3) + if(edgepoint.Test(p[2])) + { + INDEX_2 i2a=INDEX_2::Sort(p[2], p[1]); + INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cp3 = 1; + } + if(ep4) + if(edgepoint.Test(p[3])) + { + INDEX_2 i2a=INDEX_2::Sort(p[0], p[3]); + INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); + if(!edges.Used(i2a) && !edges.Used(i2b)) + cp4 = 1; + } +//MH***************************************************************************************************************************** + } + else + { + INDEX_2 i2; + i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); + i2.Sort(); + isedge1 = edges.Used (i2); + if(isedge1) + { + ep1 = 1; ep2=1; + } + i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); + i2.Sort(); + isedge2 = edges.Used (i2); + if(isedge2) + { + ep2=1; ep3=1; + } + i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); + i2.Sort(); + isedge3 = edges.Used (i2); + + if(isedge3) + { + ep3=1; ep4=1; + } + i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); + i2.Sort(); + isedge4 = edges.Used (i2); + if(isedge4) + { + ep4=1; ep1=1; + } + } + + int sumcp = cp1 + cp2 + cp3 + cp4; + int sumep = ep1 + ep2 + ep3 + ep4; + int sumedge = isedge1 + isedge2 + isedge3 + isedge4; + + switch (sumedge) + { + case 0: + { + switch (sumep) + { + case 0: + type = HP_QUAD; + break; + case 1: + if (ep1) type = HP_QUAD_SINGCORNER; + break; + case 2: + { + if (ep1 && ep2) type = HP_QUAD_0E_2VA; + if (ep1 && ep3) type = HP_QUAD_0E_2VB; + break; + } + case 3: + if (!ep4) type = HP_QUAD_0E_3V; + break; + case 4: + type = HP_QUAD_0E_4V; + break; + } + break; + } + case 1: + { + if (isedge1) + { + switch (cp1+cp2+ep3+ep4) + { + case 0: + type = HP_QUAD_SINGEDGE; + break; + case 1: + { + if (cp1) type = HP_QUAD_1E_1VA; + if (cp2) type = HP_QUAD_1E_1VB; + if (ep3) type = HP_QUAD_1E_1VC; + if (ep4) type = HP_QUAD_1E_1VD; + break; + } + case 2: + { + if (cp1 && cp2) type = HP_QUAD_1E_2VA; + if (cp1 && ep3) type = HP_QUAD_1E_2VB; + if (cp1 && ep4) type = HP_QUAD_1E_2VC; + if (cp2 && ep3) type = HP_QUAD_1E_2VD; + if (cp2 && ep4) type = HP_QUAD_1E_2VE; + if (ep3 && ep4) type = HP_QUAD_1E_2VF; + break; + } + case 3: + { + if (cp1 && cp2 && ep3) type = HP_QUAD_1E_3VA; + if (cp1 && cp2 && ep4) type = HP_QUAD_1E_3VB; + if (cp1 && ep3 && ep4) type = HP_QUAD_1E_3VC; + if (cp2 && ep3 && ep4) type = HP_QUAD_1E_3VD; + break; + } + case 4: + { + type = HP_QUAD_1E_4V; + break; + } + } + } + break; + } + case 2: + { + if (isedge1 && isedge4) + { + if (!cp2 && !ep3 && !cp4) + type = HP_QUAD_2E; + + if (cp2 && !ep3 && !cp4) + type = HP_QUAD_2E_1VA; + if (!cp2 && ep3 && !cp4) + type = HP_QUAD_2E_1VB; + if (!cp2 && !ep3 && cp4) + type = HP_QUAD_2E_1VC; + + if (cp2 && ep3 && !cp4) + type = HP_QUAD_2E_2VA; + if (cp2 && !ep3 && cp4) + type = HP_QUAD_2E_2VB; + if (!cp2 && ep3 && cp4) + type = HP_QUAD_2E_2VC; + + if (cp2 && ep3 && cp4) + type = HP_QUAD_2E_3V; + } + if (isedge1 && isedge3) + { + switch (sumcp) + { + case 0: + type = HP_QUAD_2EB_0V; break; + case 1: + { + if (cp1) type = HP_QUAD_2EB_1VA; + if (cp2) type = HP_QUAD_2EB_1VB; + break; + } + case 2: + { + if (cp1 && cp2) { type = HP_QUAD_2EB_2VA; } + if (cp1 && cp3) { type = HP_QUAD_2EB_2VB; } + if (cp1 && cp4) { type = HP_QUAD_2EB_2VC; } + if (cp2 && cp4) { type = HP_QUAD_2EB_2VD; } + break; + } + case 3: + { + if (cp1 && cp2 && cp3) { type = HP_QUAD_2EB_3VA; } + if (cp1 && cp2 && cp4) { type = HP_QUAD_2EB_3VB; } + break; + } + case 4: + { + type = HP_QUAD_2EB_4V; break; + } + } + } + break; + } + + case 3: + { + if (isedge1 && isedge2 && isedge4) + { + if (!cp3 && !cp4) type = HP_QUAD_3E; + if (cp3 && !cp4) type = HP_QUAD_3E_3VA; + if (!cp3 && cp4) type = HP_QUAD_3E_3VB; + if (cp3 && cp4) type = HP_QUAD_3E_4V; + } + break; + } + + case 4: + { + type = HP_QUAD_4E; + break; + } + } + + if (type != HP_NONE) + { + int pnums[4]; + pnums[0] = el.PNumMod (j); + pnums[1] = el.PNumMod (j+1); + pnums[2] = el.PNumMod (j+2); + pnums[3] = el.PNumMod (j+3); + for (int k=0;k<4;k++) el[k] = pnums[k]; + + /* cout << " QUAD with pnums " << pnums[0] << "\t" << + pnums[1] << "\t" << pnums[2] << "\t" << pnums[3] + << endl << " of type " << type << endl; */ + + break; + } + } + if (type == HP_NONE) + { + (*testout) << "undefined element" << endl + << "cp = " << cp1 << cp2 << cp3 << cp4 << endl + << "ep = " << ep1 << ep2 << ep3 << ep4 << endl + << "isedge = " << isedge1 << isedge2 << isedge3 + << isedge4 << endl; + } + + + return(type); +} + + +HPREF_ELEMENT_TYPE ClassifyHex(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint) +{ + HPREF_ELEMENT_TYPE type = HP_NONE; + + // implementation only for HP_HEX_1F_0E_0V + // HP_HEX_1FA_1FB_0E_0V + // HP_HEX + // up to now other cases are refine dummies + + // indices of bot,top-faces combinations + int index[6][2] = {{0,1},{1,0},{2,4},{4,2},{3,5},{5,3}}; + int p[8]; + const ELEMENT_FACE * elfaces = MeshTopology::GetFaces (HEX); + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges (HEX); + + for(int m=0;m<6 && type == HP_NONE;m++) + for(int j=0;j<4 && type == HP_NONE;j++) + { + int point_sing[8]={0,0,0,0,0,0,0,0}; + int face_sing[6] = {0,0,0,0,0,0}; + int edge_sing[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + int spoint=0, sface=0, sedge=0; + for(int l=0;l<4;l++) + { + p[l] = elfaces[index[m][0]][(4-j-l)%4]; + p[l+4] = elfaces[index[m][1]][(j+l)%4]; + } + + for(int l=0;l<8;l++) + if(cornerpoint.Test(el.PNum(p[l]))) + { + point_sing[p[l]-1]=3; + spoint++; + } + else if(edgepoint.Test(el.PNum(p[l]))) point_sing[p[l]-1]=2; + else if (facepoint[el.PNum(p[l])] == -1 || facepoint[el.PNum(p[l])] == el.GetIndex()) + point_sing[p[l]-1] = 1; + + for(int k=0;k<12;k++) + { + INDEX_2 i2 = INDEX_2 :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1])); + if (edges.Used(i2)) + { + edge_sing[k] = 2; + sedge++; + } + else edge_sing[k] = face_edges.Used(i2); + } + + for (int k=0;k<6;k++) + { + INDEX_3 i3; + + + INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]); + i4.Sort(); + i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); + + if (faces.Used (i3)) + { + + int domnr = faces.Get(i3); + if (domnr == -1 || domnr == el.GetIndex()) + { + face_sing[k] = 1; + sface++; + } + + } + } + + if(!sface && !sedge && !spoint) type = HP_HEX; + if(!sedge && !spoint) + { + if(face_sing[0] && face_sing[2] && sface==2) + type = HP_HEX_1FA_1FB_0E_0V; + if (face_sing[0] && sface==1) + type = HP_HEX_1F_0E_0V; + } + + el.type=type; + + if(type != HP_NONE) + { + int pnums[8]; + for(int l=0;l<8;l++) pnums[l] = el[p[l]-1]; + for(int l=0;l<8;l++) el[l] = pnums[l]; + /* cout << " HEX with pnums " << pnums[0] << "\t" << + pnums[1] << "\t" << pnums[2] << "\t" << pnums[3] << "\t" << + pnums[4] << "\t" << pnums[5] << endl << " of type " << type << endl; */ + break; + } + } + + return (type); + +} + +HPREF_ELEMENT_TYPE ClassifySegm(HPRefElement & hpel, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint) +{ + + int cp1 = cornerpoint.Test (hpel[0]); + int cp2 = cornerpoint.Test (hpel[1]); + + INDEX_2 i2; + i2 = INDEX_2(hpel[0], hpel[1]); + i2.Sort(); + if (!edges.Used (i2)) + { + cp1 = edgepoint.Test (hpel[0]); + cp2 = edgepoint.Test (hpel[1]); + } + + if(!edges.Used(i2) && !face_edges.Used(i2)) + { + if(facepoint[hpel[0]]!=0) cp1=1; + if(facepoint[hpel[1]]!=0) cp2=1; + } + + if(edges.Used(i2) && !face_edges.Used(i2)) + { + if(facepoint[hpel[0]]) cp1 = 1; + if(facepoint[hpel[1]]) cp2 = 1; + } + + if (!cp1 && !cp2) + hpel.type = HP_SEGM; + else if (cp1 && !cp2) + hpel.type = HP_SEGM_SINGCORNERL; + else if (!cp1 && cp2) + hpel.type = HP_SEGM_SINGCORNERR; + else + hpel.type = HP_SEGM_SINGCORNERS; + + // cout << " SEGM found with " << hpel[0] << " \t" << hpel[1] << endl << " of type " << hpel.type << endl; + return(hpel.type) ; +} + + +HPREF_ELEMENT_TYPE ClassifyPyramid(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint) +{ + HPREF_ELEMENT_TYPE type = HP_NONE; + + // implementation only for HP_PYRAMID + // HP_PYRAMID_0E_1V + // HP_PYRAMID_EDGES + // HP_PYRAMID_1FB_0E_1VA + // up to now other cases are refine dummies + + // indices of bot,top-faces combinations + // int index[6][2] = {{0,1},{1,0},{2,4},{4,2},{3,5},{5,3}}; + + const ELEMENT_FACE * elfaces = MeshTopology::GetFaces (PYRAMID); + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges (PYRAMID); + + int point_sing[5]={0,0,0,0,0}; + int face_sing[5] = {0,0,0,0,0}; + int edge_sing[8] = {0,0,0,0,0,0,0,0}; + + int spoint=0, sedge=0, sface=0; + + for(int m=0;m<4 && type == HP_NONE;m++) + { + int p[5] = {m%4, m%4+1, m%4+2, m%4+3, 4}; + + for(int l=0;l<5;l++) + { + if(cornerpoint.Test(el.pnums[p[l]])) + point_sing[l]=3; + + else if(edgepoint.Test(el.pnums[p[l]])) + point_sing[l]=2; + + else if (facepoint[el.pnums[p[l]]] == -1 || facepoint[el.pnums[p[l]]] == el.GetIndex()) + point_sing[l] = 1; + + spoint += point_sing[l]; + } + + for(int k=0;k<8;k++) + { + INDEX_2 i2 = INDEX_2 :: Sort(el.pnums[p[eledges[k][0]-1]], + el.pnums[p[eledges[k][1]-1]]); + if (edges.Used(i2)) + edge_sing[k] = 2; + else + edge_sing[k] = face_edges.Used(i2); + + sedge += edge_sing[k]; + } + + for (int k=0;k<5;k++) + { + INDEX_3 i3; + INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]], el.pnums[p[elfaces[k][1]-1]], el.pnums[p[elfaces[k][2]-1]], + el.pnums[p[elfaces[k][3]-1]]); + i4.Sort(); + i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); + + if (faces.Used (i3)) + { + + int domnr = faces.Get(i3); + if (domnr == -1 || domnr == el.GetIndex()) + face_sing[k] = 1; + } + sface +=face_sing[k]; + } + + if(!sface && !spoint && !sedge) return(HP_PYRAMID); + + if(!sface && !sedge && point_sing[p[0]] == spoint) + type = HP_PYRAMID_0E_1V; + + if(!sface && edge_sing[0] + edge_sing[2] == sedge && + spoint == point_sing[0] + point_sing[1] + point_sing[3]) + type = HP_PYRAMID_EDGES; + + if(sface && sface == face_sing[0] && spoint == point_sing[4] + 2) + type = HP_PYRAMID_1FB_0E_1VA; + + + if(type != HP_NONE) + { + int pnums[8]; + for(int l=0;l<5;l++) pnums[l] = el[p[l]]; + for(int l=0;l<5;l++) el[l] = pnums[l]; + el.type=type; + break; + } + } + + return (type); + +} diff --git a/contrib/Netgen/libsrc/meshing/clusters.cpp b/contrib/Netgen/libsrc/meshing/clusters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da6c66fe3512b2531d0400db12c4753f3eb310fa --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/clusters.cpp @@ -0,0 +1,267 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +namespace netgen +{ + +AnisotropicClusters :: AnisotropicClusters (const Mesh & amesh) + : mesh(amesh) +{ + ; +} + +AnisotropicClusters :: ~AnisotropicClusters () +{ + ; +} + +void AnisotropicClusters :: Update() +{ + int i, j, k; + + const MeshTopology & top = mesh.GetTopology(); + + bool hasedges = top.HasEdges(); + bool hasfaces = top.HasFaces(); + + if (!hasedges || !hasfaces) return; + + + PrintMessage (3, "Update Clusters"); + + nv = mesh.GetNV(); + ned = top.GetNEdges(); + nfa = top.GetNFaces(); + ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + + cluster_reps.SetSize (nv+ned+nfa+ne); + + ARRAY<int> nnums, ednums, fanums; + int changed; + + for (i = 1; i <= cluster_reps.Size(); i++) + cluster_reps.Elem(i) = -1; + + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + ELEMENT_TYPE typ = el.GetType(); + + top.GetElementEdges (i, ednums); + top.GetElementFaces (i, fanums); + + int elnv = top.GetNVertices (typ); + int elned = ednums.Size(); + int elnfa = fanums.Size(); + + nnums.SetSize(elnv+elned+elnfa+1); + for (j = 1; j <= elnv; j++) + nnums.Elem(j) = el.PNum(j); + for (j = 1; j <= elned; j++) + nnums.Elem(elnv+j) = nv+ednums.Elem(j); + for (j = 1; j <= elnfa; j++) + nnums.Elem(elnv+elned+j) = nv+ned+fanums.Elem(j); + nnums.Elem(elnv+elned+elnfa+1) = nv+ned+nfa+i; + + for (j = 0; j < nnums.Size(); j++) + cluster_reps.Elem(nnums[j]) = nnums[j]; + } + + + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + ELEMENT_TYPE typ = el.GetType(); + + top.GetSurfaceElementEdges (i, ednums); + int fanum = top.GetSurfaceElementFace (i); + + int elnv = top.GetNVertices (typ); + int elned = ednums.Size(); + + nnums.SetSize(elnv+elned+1); + for (j = 1; j <= elnv; j++) + nnums.Elem(j) = el.PNum(j); + for (j = 1; j <= elned; j++) + nnums.Elem(elnv+j) = nv+ednums.Elem(j); + nnums.Elem(elnv+elned+1) = fanum; + + for (j = 0; j < nnums.Size(); j++) + cluster_reps.Elem(nnums[j]) = nnums[j]; + } + + static const int hex_cluster[] = + { + 1, 2, 3, 4, 1, 2, 3, 4, + 5, 6, 7, 8, 5, 6, 7, 8, 1, 2, 3, 4, + 9, 9, 5, 8, 6, 7, + 9 + }; + + static const int prism_cluster[] = + { + 1, 2, 3, 1, 2, 3, + 4, 5, 6, 4, 5, 6, 3, 1, 2, + 7, 7, 4, 5, 6, + 7 + }; + + static const int pyramid_cluster[] = + { + 1, 2, 2, 1, 3, + 4, 2, 1, 4, 6, 5, 5, 6, + 7, 5, 7, 6, 4, + 7 + }; + static const int tet_cluster14[] = + { 1, 2, 3, 1, 1, 4, 5, 4, 5, 6, 7, 5, 4, 7, 7 }; + + static const int tet_cluster12[] = + { 1, 1, 2, 3, 4, 4, 5, 1, 6, 6, 7, 7, 4, 6, 7 }; + + static const int tet_cluster13[] = + { 1, 2, 1, 3, 4, 6, 4, 5, 1, 5, 7, 4, 7, 5, 7 }; + + static const int tet_cluster23[] = + { 2, 1, 1, 3, 6, 5, 5, 4, 4, 1, 5, 7, 7, 4, 7 }; + + static const int tet_cluster24[] = + { 2, 1, 3, 1, 4, 1, 5, 4, 6, 5, 5, 7, 4, 7, 7 }; + + static const int tet_cluster34[] = + { 2, 3, 1, 1, 4, 5, 1, 6, 4, 5, 5, 4, 7, 7, 7 }; + + int cnt = 0; + + do + { + + cnt++; + changed = 0; + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + ELEMENT_TYPE typ = el.GetType(); + + top.GetElementEdges (i, ednums); + top.GetElementFaces (i, fanums); + + int elnv = top.GetNVertices (typ); + int elned = ednums.Size(); + int elnfa = fanums.Size(); + + nnums.SetSize(elnv+elned+elnfa+1); + for (j = 1; j <= elnv; j++) + nnums.Elem(j) = el.PNum(j); + for (j = 1; j <= elned; j++) + nnums.Elem(elnv+j) = nv+ednums.Elem(j); + for (j = 1; j <= elnfa; j++) + nnums.Elem(elnv+elned+j) = nv+ned+fanums.Elem(j); + nnums.Elem(elnv+elned+elnfa+1) = nv+ned+nfa+i; + + + const int * clustertab = NULL; + switch (typ) + { + case PRISM: + case PRISM12: + clustertab = prism_cluster; + break; + case HEX: + clustertab = hex_cluster; + break; + case PYRAMID: + clustertab = pyramid_cluster; + break; + case TET: + case TET10: + if (cluster_reps.Get(el.PNum(1)) == + cluster_reps.Get(el.PNum(2))) + clustertab = tet_cluster12; + else if (cluster_reps.Get(el.PNum(1)) == + cluster_reps.Get(el.PNum(3))) + clustertab = tet_cluster13; + else if (cluster_reps.Get(el.PNum(1)) == + cluster_reps.Get(el.PNum(4))) + clustertab = tet_cluster14; + else if (cluster_reps.Get(el.PNum(2)) == + cluster_reps.Get(el.PNum(3))) + clustertab = tet_cluster23; + else if (cluster_reps.Get(el.PNum(2)) == + cluster_reps.Get(el.PNum(4))) + clustertab = tet_cluster24; + else if (cluster_reps.Get(el.PNum(3)) == + cluster_reps.Get(el.PNum(4))) + clustertab = tet_cluster34; + + else + clustertab = NULL; + break; + default: + clustertab = NULL; + } + + if (clustertab) + for (j = 0; j < nnums.Size(); j++) + for (k = 0; k < j; k++) + if (clustertab[j] == clustertab[k]) + { + int jj = nnums[j]; + int kk = nnums[k]; + if (cluster_reps.Get(jj) < cluster_reps.Get(kk)) + { + cluster_reps.Elem(kk) = cluster_reps.Get(jj); + changed = 1; + } + else if (cluster_reps.Get(kk) < cluster_reps.Get(jj)) + { + cluster_reps.Elem(jj) = cluster_reps.Get(kk); + changed = 1; + } + } + + /* + if (clustertab) + { + if (typ == PYRAMID) + (*testout) << "pyramid"; + else if (typ == PRISM || typ == PRISM12) + (*testout) << "prism"; + else if (typ == TET || typ == TET10) + (*testout) << "tet"; + else + (*testout) << "unknown type" << endl; + + (*testout) << ", nnums = "; + for (j = 0; j < nnums.Size(); j++) + (*testout) << "node " << j << " = " << nnums[j] << ", rep = " + << cluster_reps.Get(nnums[j]) << endl; + } + */ + } + } + while (changed); + + /* + (*testout) << "cluster reps:" << endl; + for (i = 1; i <= cluster_reps.Size(); i++) + { + (*testout) << i << ": "; + if (i <= nv) + (*testout) << "v" << i << " "; + else if (i <= nv+ned) + (*testout) << "e" << i-nv << " "; + else if (i <= nv+ned+nfa) + (*testout) << "f" << i-nv-ned << " "; + else + (*testout) << "c" << i-nv-ned-nfa << " "; + (*testout) << cluster_reps.Get(i) << endl; + } + */ +} +} diff --git a/contrib/Netgen/libsrc/meshing/clusters.hpp b/contrib/Netgen/libsrc/meshing/clusters.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b0eea1b5e02b06a43fe4f9332029fe20574dea7e --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/clusters.hpp @@ -0,0 +1,42 @@ +#ifndef CLUSTERS +#define CLUSTERS + +/**************************************************************************/ +/* File: clusers.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 28. Apr. 01 */ +/**************************************************************************/ + +/* + Anisotropic clusters + + nodes, edges, faces, elements +*/ + + +class AnisotropicClusters +{ + const Mesh & mesh; + + int nv, ned, nfa, ne; + + // connected nodes, nodes = vertices, edges, faces, elements + ARRAY<int> cluster_reps; + +public: + AnisotropicClusters (const Mesh & amesh); + ~AnisotropicClusters(); + + void Update(); + + int GetVertexRepresentant (int vnr) const + { return cluster_reps.Get(vnr); } + int GetEdgeRepresentant (int ednr) const + { return cluster_reps.Get(nv+ednr); } + int GetFaceRepresentant (int fnr) const + { return cluster_reps.Get(nv+ned+fnr); } + int GetElementRepresentant (int enr) const + { return cluster_reps.Get(nv+ned+nfa+enr); } +}; + +#endif diff --git a/contrib/Netgen/libsrc/meshing/curvedelems.cpp b/contrib/Netgen/libsrc/meshing/curvedelems.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6db15893ae44b8d8299aabae40e42cdda4a5f7d3 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/curvedelems.cpp @@ -0,0 +1,2899 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#ifndef CURVEDELEMS_NEW + +namespace netgen +{ + + + // computes Gaussean integration formula on (0,1) with n points + // in: Numerical algs in C (or, was it the Fortran book ?) + void ComputeGaussRule (int n, ARRAY<double> & xi, ARRAY<double> & wi) + { + xi.SetSize (n); + wi.SetSize (n); + + int m = (n+1)/2; + double p1, p2, p3; + double pp, z, z1; + for (int i = 1; i <= m; i++) + { + z = cos ( M_PI * (i - 0.25) / (n + 0.5)); + while(1) + { + p1 = 1; p2 = 0; + for (int j = 1; j <= n; j++) + { + p3 = p2; p2 = p1; + p1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j; + } + // p1 is legendre polynomial + + pp = n * (z*p1-p2) / (z*z - 1); + z1 = z; + z = z1-p1/pp; + + if (fabs (z - z1) < 1e-14) break; + } + + xi[i-1] = 0.5 * (1 - z); + xi[n-i] = 0.5 * (1 + z); + wi[i-1] = wi[n-i] = 1.0 / ( (1 - z * z) * pp * pp); + } + } + + + + // ---------------------------------------------------------------------------- + // PolynomialBasis + // ---------------------------------------------------------------------------- + + + void PolynomialBasis :: CalcLegendrePolynomials (double x) + { + double p1 = 1.0, p2 = 0.0, p3; + + lp[0] = 1.0; + + for (int j=1; j<=order; j++) + { + p3=p2; p2=p1; + p1=((2.0*j-1.0)*(2*x-1)*p2-(j-1.0)*p3)/j; + lp[j] = p1; + } + } + + + void PolynomialBasis :: CalcScaledLegendrePolynomials (double x, double t) + { + double p1 = 1.0, p2 = 0.0, p3; + + lp[0] = 1.0; + + double x2mt = 2*x-t; + double t2 = t*t; + + for (int j=1; j<=order; j++) + { + p3=p2; p2=p1; + p1=((2.0*j-1.0)*x2mt*p2-t2*(j-1.0)*p3)/j; + lp[j] = p1; + } + } + + + void PolynomialBasis :: CalcDLegendrePolynomials (double x) + { + double p1 = 0., p2 = 0., p3; + + dlp[0] = 0.; + + for (int j = 1; j <= order-1; j++) + { + p3=p2; p2=p1; + p1=((2.*j-1.)*(2*lp[j-1]+(2*x-1)*p2)-(j-1.)*p3)/j; + dlp[j] = p1; + } + } + + + void PolynomialBasis :: CalcF (double x) + { + CalcLegendrePolynomials (x); + + for (int j = 0; j<=order-2; j++) + f[j] = (lp[j+2]-lp[j])/(2.0*(j+1)+1)/2.0; + } + + + void PolynomialBasis :: CalcDf (double x) + { + CalcLegendrePolynomials (x); + + for (int j = 0; j <= order-2; j++) + df[j] = lp[j+1]; + } + + + void PolynomialBasis :: CalcFDf (double x) + { + CalcLegendrePolynomials (x); + + for (int j = 0; j<=order-2; j++) + { + f[j] = (lp[j+2]-lp[j])/(2.0*(j+1)+1)/2.0; + df[j] = lp[j+1]; + } + } + + + void PolynomialBasis :: CalcDDf (double x) + { + CalcLegendrePolynomials (x); + CalcDLegendrePolynomials (x); + + for (int j = 0; j <= order-2; j++) ddf[j] = dlp[j+1]; + } + + + void PolynomialBasis :: CalcFScaled (double x, double t) + { + double tt = t*t; + double x2mt = 2*x-t; + + + + + double p1 = 0.5*x2mt, p2 = -0.5, p3 = 0.0; + for (int j=2; j<=order; j++) + { + p3=p2; p2=p1; + p1=((2.0*j-3.0) * x2mt * p2 - tt*(j-3.0)*p3)/j; + f[j-2] = p1; + } + + /* + CalcF (x/t); + double fac = t*t; + for (int j = 0; j<=order-2; j++, fac*=t) + f[j] *= fac; + */ + } + + void PolynomialBasis :: CalcFScaled (int p, double x, double t, double * values) + { + double tt = t*t; + double x2mt = 2*x-t; + + double p1 = 0.5*x2mt, p2 = -0.5, p3 = 0.0; + for (int j=2; j<=p; j++) + { + p3=p2; p2=p1; + p1=((2.0*j-3.0) * x2mt * p2 - tt*(j-3.0)*p3)/j; + values[j-2] = p1; + } + + /* + CalcF (x/t); + double fac = t*t; + for (int j = 0; j<=order-2; j++, fac*=t) + f[j] *= fac; + */ + } + + + + + // ---------------------------------------------------------------------------- + // BaseFiniteElement1D + // ---------------------------------------------------------------------------- + + + void BaseFiniteElement1D :: CalcVertexShapes () + { + vshape[0] = xi(0); + vshape[1] = 1-xi(0); + + vdshape[0] = 1; + vdshape[1] = -1; + + /* + if (edgeorient == -1) + { + Swap (vshape[0], vshape[1]); + Swap (vdshape[0], vdshape[1]); + } + */ + + } + + + void BaseFiniteElement1D :: CalcEdgeShapes () + { + b.SetOrder (edgeorder); + if (edgeorient == 1) + b.CalcFDf( 1-xi(0) ); + else + b.CalcFDf( xi(0) ); + + for (int k = 2; k <= edgeorder; k++) + { + eshape[k-2] = b.GetF(k); + edshape[k-2] = -b.GetDf(k); + } + } + + + void BaseFiniteElement1D :: CalcEdgeLaplaceShapes () + { + b.SetOrder (edgeorder); + if (edgeorient == 1) + b.CalcDDf( 1-xi(0) ); + else + b.CalcDDf( xi(0) ); + + for (int k = 2; k <= edgeorder; k++) + eddshape[k-2] = b.GetDDf(k); + } + + + + + // ---------------------------------------------------------------------------- + // BaseFiniteElement2D + // ---------------------------------------------------------------------------- + + + void BaseFiniteElement2D :: SetElementNumber (int aelnr) + { + int locmaxedgeorder = -1; + + BaseFiniteElement<2> :: SetElementNumber (aelnr); + const Element2d & elem = mesh[(SurfaceElementIndex) (elnr-1)]; + top.GetSurfaceElementEdges (elnr, &(edgenr[0]), &(edgeorient[0])); + facenr = top.GetSurfaceElementFace (elnr); + faceorient = top.GetSurfaceElementFaceOrientation (elnr); + + for (int v = 0; v < nvertices; v++) + vertexnr[v] = elem[v]; + + for (int e = 0; e < nedges; e++) + { + edgeorder[e] = curv.GetEdgeOrder (edgenr[e]-1); // 1-based + locmaxedgeorder = max2 (edgeorder[e], locmaxedgeorder); + } + + faceorder = curv.GetFaceOrder (facenr-1); // 1-based + CalcNFaceShapes (); + + if (locmaxedgeorder > maxedgeorder) + { + maxedgeorder = locmaxedgeorder; + eshape.SetSize(nedges * (maxedgeorder-1)); + edshape.SetSize(nedges * (maxedgeorder-1)); + } + + if (faceorder > maxfaceorder) + { + maxfaceorder = faceorder; + fshape.SetSize( nfaceshapes ); // number of face shape functions + fdshape.SetSize( nfaceshapes ); + fddshape.SetSize ( nfaceshapes ); + } + }; + + + // ---------------------------------------------------------------------------- + // BaseFiniteElement3D + // ---------------------------------------------------------------------------- + + + void BaseFiniteElement3D :: SetElementNumber (int aelnr) + { + int locmaxedgeorder = -1; + int locmaxfaceorder = -1; + int v, f, e; + + BaseFiniteElement<3> :: SetElementNumber (aelnr); + Element elem = mesh[(ElementIndex) (elnr-1)]; + top.GetElementEdges (elnr, &(edgenr[0]), &(edgeorient[0])); + top.GetElementFaces (elnr, &(facenr[0]), &(faceorient[0])); + + for (v = 0; v < nvertices; v++) + vertexnr[v] = elem[v]; + + for (f = 0; f < nfaces; f++) + { + surfacenr[f] = top.GetFace2SurfaceElement (facenr[f]); + // surfaceorient[f] = top.GetSurfaceElementFaceOrientation (surfacenr[f]); + } + + for (e = 0; e < nedges; e++) + { + edgeorder[e] = curv.GetEdgeOrder (edgenr[e]-1); // 1-based + locmaxedgeorder = max (edgeorder[e], locmaxedgeorder); + } + + for (f = 0; f < nfaces; f++) + { + faceorder[f] = curv.GetFaceOrder (facenr[f]-1); // 1-based + locmaxfaceorder = max (faceorder[f], locmaxfaceorder); + } + + CalcNFaceShapes (); + + if (locmaxedgeorder > maxedgeorder) + { + maxedgeorder = locmaxedgeorder; + eshape.SetSize(nedges * (maxedgeorder-1)); + edshape.SetSize(nedges * (maxedgeorder-1)); + } + + if (locmaxfaceorder > maxfaceorder) + { + maxfaceorder = locmaxfaceorder; + fshape.SetSize( nfaces * (maxfaceorder-1) * (maxfaceorder-1)); // number of face shape functions + fdshape.SetSize( nfaces * (maxfaceorder-1) * (maxfaceorder-1)); + } + }; + + + + + // ---------------------------------------------------------------------------- + // FETrig + // ---------------------------------------------------------------------------- + + + void FETrig :: SetReferencePoint (Point<2> axi) + { + BaseFiniteElement2D :: SetReferencePoint (axi); + lambda(0) = xi(0); + lambda(1) = xi(1); + lambda(2) = 1-xi(0)-xi(1); + + dlambda(0,0) = 1; dlambda(0,1) = 0; + dlambda(1,0) = 0; dlambda(1,1) = 1; + dlambda(2,0) = -1; dlambda(2,1) = -1; + } + + + void FETrig :: SetVertexSingularity (int v, int exponent) + { + int i; + if (1-lambda(v) < EPSILON) return; + + Point<3> lamold = lambda; + + Vec<2> dfac; + + double fac = pow(1-lambda(v),exponent-1); + + for (i = 0; i < 2; i++) + { + dfac(i) = -(exponent-1)*pow(1-lambda(v),exponent-2)*dlambda(v,i); + dlambda(v,i) *= exponent * pow(1-lambda(v),exponent-1); + } + + lambda(v) = 1-pow(1-lambda(v),exponent); + + for (i = 0; i < nvertices; i++) + { + if (i == v) continue; + for (int j = 0; j < 2; j++) + dlambda(i,j) = dlambda(i,j) * fac + lamold(i) * dfac(j); + + lambda(i) *= fac; + } + } + + + + void FETrig :: CalcVertexShapes () + { + for (int v = 0; v < nvertices; v++) + { + vshape[v] = lambda(v); + vdshape[v](0) = dlambda(v,0); + vdshape[v](1) = dlambda(v,1); + } + } + + + void FETrig :: CalcEdgeShapes () + { + int index = 0; + for (int e = 0; e < nedges; e++) + { + if (edgeorder[e] <= 1) continue; + + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + double arg = lambda(i0) + lambda(i1); // = 1-lambda[i2]; + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<2>(0,0); + index++; + } + continue; + } + + if (edgeorient[e] == -1) Swap (i0, i1); // reverse orientation + + double xi = lambda(i1)/arg; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double l0 = lambda(i0); + double l0x = dlambda(i0,0); + double l0y = dlambda(i0,1); + + double l1 = lambda(i1); + double l1x = dlambda(i1,0); + double l1y = dlambda(i1,1); + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + eshape[index] = b1.GetF (k) * decay; + edshape[index] = Vec<2> + (b1.GetDf(k) * (l1x*arg - l1*(l0x+l1x)) * + decay / (arg * arg) + b1.GetF(k) * ddecay * (l0x+l1x), + b1.GetDf(k) * (l1y*arg - l1*(l0y+l1y)) * + decay / (arg * arg) + b1.GetF(k) * ddecay * (l0y+l1y)); + index++; + } + } + // (*testout) << "index = " << index << endl; + // (*testout) << "eshape = " << eshape << ", edshape = " << edshape << endl; + + + // eshape = 0.0; + // edshape = 0.0; + + /* + int index = 0; + for (int e = 0; e < nedges; e++) + { + if (edgeorder[e] <= 1) continue; + + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + if (edgeorient[e] == -1) Swap (i0, i1); // reverse orientation + + double x = lambda(i1)-lambda(i0); + double y = 1-lambda(i0)-lambda(i1); + double fy = (1-y)*(1-y); + + // double p3 = 0, p3x = 0, p3y = 0; + // double p2 = -1, p2x = 0, p2y = 0; + // double p1 = x, p1x = 1, p1y = 0; + + double p3 = 0, p3x = 0, p3y = 0; + double p2 = -0.5, p2x = 0, p2y = 0; + double p1 = 0.5*x, p1x = 0.5, p1y = 0; + + for (int j=2; j<= edgeorder[e]; j++) + { + p3=p2; p3x = p2x; p3y = p2y; + p2=p1; p2x = p1x; p2y = p1y; + double c1 = (2.0*j-3) / j; + double c2 = (j-3.0) / j; + + p1 = c1 * x * p2 - c2 * fy * p3; + p1x = c1 * p2 + c1 * x * p2x - c2 * fy * p3x; + p1y = c1 * x * p2y - (c2 * 2 * (y-1) * p3 + c2 * fy * p3y); + + eshape[index] = p1; + for (int k = 0; k < 2; k++) + edshape[index](k) = + p1x * ( dlambda(i1,k) - dlambda(i0,k) ) + + p1y * (-dlambda(i1,k) - dlambda(i0,k) ); + index++; + } + + } + // (*testout) << "eshape = " << eshape << ", edshape = " << edshape << endl; + */ + } + + + void FETrig :: CalcFaceShapes () + { + int index = 0; + + int i0 = elface[0][0]-1; + int i1 = elface[0][1]-1; + int i2 = elface[0][2]-1; + + // sort lambda_i's by the corresponing vertex numbers + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + double arg = lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<2>(0,0); + index++; + } + return; + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (lambda(i0)); + b2.CalcFDf (lambda(i2)/arg); + + double decay = 1; + double ddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + + for (int n1 = 2; n1 < faceorder; n1++) + { + ddecay = (n1-1)*decay; + decay *= arg; + + for (int n0 = 2; n0 < faceorder-n1+2; n0++) + { + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay; + fdshape[index] = Vec<2> + (b1.GetDf(n0) * dl0x * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx, + b1.GetDf(n0) * dl0y * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy); + index++; + } + } + } + + + + void FETrig :: CalcFaceLaplaceShapes () + { + int index = 0; + + int i0 = elface[0][0]-1; + int i1 = elface[0][1]-1; + int i2 = elface[0][2]-1; + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + double arg = lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes; k++) + fddshape[k] = 0; + return; + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (lambda(i0)); + b1.CalcDDf (lambda(i0)); + b2.CalcFDf (lambda(i2)/arg); + b2.CalcDDf (lambda(i2)/arg); + + double decay = 1; + double ddecay = 0; + double dddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + + for (int n1 = 2; n1 < faceorder; n1++) + { + dddecay = (n1-1)*ddecay; + ddecay = (n1-1)*decay; + decay *= arg; + + for (int n0 = 2; n0 < faceorder-n1+2; n0++) + { + fddshape[index] = + + // b1.GetDf(n0) * dl0x * b2.GetF(n1) * decay .... derived + + b1.GetDDf(n0) * dl0x * dl0x * b2.GetF(n1) * decay + + b1.GetDf(n0) * dl0x * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetDf(n0) * dl0x * b2.GetF(n1) * ddecay * dargx + + + + // b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay ... derived + + b1.GetDf(n0) * dl0x * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDDf(n1) * pow((dl2x * arg - l2 * dargx)/(arg*arg),2) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (-2*dargx/arg) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * ddecay * dargx + + + + // b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx ... derived + + b1.GetDf(n0) * dl0x * b2.GetF(n1) * ddecay * dargx + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * ddecay * dargx + + b1.GetF(n0) * b2.GetF(n1) * dddecay * dargx * dargx + + + + // b1.GetDf(n0) * dl0y * b2.GetF(n1) * decay ... derived + + b1.GetDDf(n0) * dl0y * dl0y * b2.GetF(n1) * decay + + b1.GetDf(n0) * dl0y * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetDf(n0) * dl0y * b2.GetF(n1) * ddecay * dargy + + + + // b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay ... derived + + b1.GetDf(n0) * dl0y * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDDf(n1) * pow((dl2y * arg - l2 * dargy)/(arg*arg),2) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (-2*dargy/arg) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * ddecay * dargy + + + + // b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy ... derived + + b1.GetDf(n0) * dl0y * b2.GetF(n1) * ddecay * dargy + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * ddecay * dargy + + b1.GetF(n0) * b2.GetF(n1) * dddecay * dargy * dargy; + + index++; + } + } + } + + + + // ---------------------------------------------------------------------------- + // FEQuad + // ---------------------------------------------------------------------------- + + + void FEQuad :: CalcVertexShapes () + { + vshape[0] = (1-xi(0)) * (1-xi(1)); + vshape[1] = ( xi(0)) * (1-xi(1)); + vshape[2] = ( xi(0)) * ( xi(1)); + vshape[3] = (1-xi(0)) * ( xi(1)); + + vdshape[0] = Vec<2> ( -(1-xi(1)), -(1-xi(0)) ); + vdshape[1] = Vec<2> ( (1-xi(1)), -( xi(0)) ); + vdshape[2] = Vec<2> ( ( xi(1)), ( xi(0)) ); + vdshape[3] = Vec<2> ( -( xi(1)), (1-xi(0)) ); + } + + + void FEQuad :: CalcEdgeShapes () + { + int index = 0; + + double arg0[4] = { xi(0), 1-xi(0), 1-xi(1), xi(1) }; + double arg1[4] = { 1-xi(1), xi(1), 1-xi(0), xi(0) }; + double darg0[4] = { 1, -1, -1, 1 }; + double darg1[4] = { -1, 1, -1, 1 }; + + for (int e = 0; e < nedges; e++) + { + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (edgeorient[e] == 1 ? arg0[e] : 1-arg0[e]); + + double decay = arg1[e]; + double ddecay; + + for (int k = 2; k <= edgeorder[e]; k++, index++) + { + ddecay = k*decay; + decay *= arg1[e]; + // linear decay + eshape[index] = b1.GetF(k) * arg1[e]; + + if (e < 2) + edshape[index] = Vec<2> + (darg0[e] * edgeorient[e] * b1.GetDf(k) * arg1[e], + b1.GetF(k) * darg1[e]); + else + edshape[index] = Vec<2> + (b1.GetF(k) * darg1[e], + darg0[e] * edgeorient[e] * b1.GetDf(k) * arg1[e]); + + // exponential decay + /* eshape[index] = b1.GetF(k) * decay; + + if (e < 2) + edshape[index] = Vec<2> + (darg0[e] * edgeorient[e] * b1.GetDf(k) * decay, + b1.GetF(k) * ddecay * darg1[e]); + else + edshape[index] = Vec<2> + (b1.GetF(k) * ddecay * darg1[e], + darg0[e] * edgeorient[e] * b1.GetDf(k) * decay); + */ + } + } + } + + + void FEQuad :: CalcFaceShapes () + { + int index = 0; + + // find index of point with smallest number + + int i0 = 0; + for (int i = 1; i < 4; i++) + if (vertexnr[elface[0][i]-1] < vertexnr[elface[0][i0]-1]) i0 = i; + + double x; + double y; + double dxx; + double dxy; + double dyx; + double dyy; + + switch (i0) + { + case 0: + x = xi(0); y = xi(1); + dxx = 1; dxy = 0; + dyx = 0; dyy = 1; + break; + case 1: + x = xi(1); y = 1-xi(0); + dxx = 0; dxy = 1; + dyx = -1; dyy = 0; + break; + case 2: + x = 1-xi(0); y = 1-xi(1); + dxx = -1; dxy = 0; + dyx = 0; dyy = -1; + break; + case 3: + x = 1-xi(1); y = xi(0); + dxx = 0; dxy =-1; + dyx = 1; dyy = 0; + break; + } + + if (vertexnr[elface[0][(i0+1) % 4]-1] > vertexnr[elface[0][(i0+3) % 4]-1]) + { + Swap (x,y); + Swap (dxx, dyx); + Swap (dxy, dyy); + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (x); + b2.CalcFDf (y); + + for (int n0 = 2; n0 <= faceorder; n0++) + for (int n1 = 2; n1 <= faceorder; n1++) + { + fshape[index] = b1.GetF(n0) * b2.GetF(n1); + fdshape[index] = Vec<2> (b1.GetDf(n0) * dxx * b2.GetF(n1) + b1.GetF(n0) * b2.GetDf(n1) * dyx, + b1.GetDf(n0) * dxy * b2.GetF(n1) + b1.GetF(n0) * b2.GetDf(n1) * dyy); + index++; + } + } + + + void FEQuad :: CalcFaceLaplaceShapes () + { + int index = 0; + + // find index of point with smallest number + + int i0 = 0; + for (int i = 1; i < 4; i++) + if (vertexnr[elface[0][i]-1] < vertexnr[elface[0][i0]-1]) i0 = i; + + double x; + double y; + double dxx; + double dxy; + double dyx; + double dyy; + + switch (i0) + { + case 0: + x = xi(0); y = xi(1); + dxx = 1; dxy = 0; + dyx = 0; dyy = 1; + break; + case 1: + x = xi(1); y = 1-xi(0); + dxx = 0; dxy = 1; + dyx = -1; dyy = 0; + break; + case 2: + x = 1-xi(0); y = 1-xi(1); + dxx = -1; dxy = 0; + dyx = 0; dyy = -1; + break; + case 3: + x = 1-xi(1); y = xi(0); + dxx = 0; dxy =-1; + dyx = 1; dyy = 0; + break; + } + + if (vertexnr[elface[0][(i0+1) % 4]-1] > vertexnr[elface[0][(i0+3) % 4]-1]) + { + Swap (x,y); + Swap (dxx, dyx); + Swap (dxy, dyy); + } + + b1.SetOrder (faceorder); + b2.SetOrder (faceorder); + + b1.CalcFDf (x); + b1.CalcDDf (x); + b2.CalcFDf (y); + b2.CalcDDf (y); + + for (int n0 = 2; n0 <= faceorder; n0++) + for (int n1 = 2; n1 <= faceorder; n1++) + { + fddshape[index] = + b1.GetDDf(n0) * dxx * dxx * b2.GetF(n1) + + 2* b1.GetDf(n0) * dxx * b2.GetDf(n1) * dyx + + b1.GetF(n0) * b2.GetDDf(n1) * dyx * dyx + + + b1.GetDDf(n0) * dxy * dxy * b2.GetF(n1) + + 2* b1.GetDf(n0) * dxy * b2.GetDf(n1) * dyy + + b1.GetF(n0) * b2.GetDDf(n1) * dyy * dyy; + + index++; + } + } + + + + // ---------------------------------------------------------------------------- + // FETet + // ---------------------------------------------------------------------------- + + + void FETet :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + + lambda(0) = xi(0); + lambda(1) = xi(1); + lambda(2) = xi(2); + lambda(3) = 1-xi(0)-xi(1)-xi(2); + + dlambda(0,0) = 1; dlambda(0,1) = 0; dlambda(0,2) = 0; + dlambda(1,0) = 0; dlambda(1,1) = 1; dlambda(1,2) = 0; + dlambda(2,0) = 0; dlambda(2,1) = 0; dlambda(2,2) = 1; + dlambda(3,0) = -1; dlambda(3,1) = -1; dlambda(3,2) = -1; + } + + + void FETet :: CalcVertexShapes () + { + for (int v = 0; v < nvertices; v++) + { + vshape[v] = lambda(v); + vdshape[v](0) = dlambda(v,0); + vdshape[v](1) = dlambda(v,1); + vdshape[v](2) = dlambda(v,2); + } + } + + void FETet :: CalcVertexShapesOnly () + { + for (int v = 0; v < nvertices; v++) + vshape[v] = lambda(v); + } + + + void FETet :: CalcEdgeShapes () + { + int index = 0; + + for (int e = 0; e < nedges; e++) + { + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + double arg = lambda(i0)+lambda(i1); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + if (edgeorient[e] == -1) Swap (i0, i1); + + double xi = lambda[i1]/arg; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double l0 = lambda(i0); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl0z = dlambda(i0,2); + + double l1 = lambda(i1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl1z = dlambda(i1,2); + + double dargx = dl0x + dl1x; + double dargy = dl0y + dl1y; + double dargz = dl0z + dl1z; + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + eshape[index] = b1.GetF (k) * decay; + edshape[index] = Vec<3> + (b1.GetDf(k) * (dl1x*arg - l1*dargx) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargx, + b1.GetDf(k) * (dl1y*arg - l1*dargy) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargy, + b1.GetDf(k) * (dl1z*arg - l1*dargz) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargz); + + index++; + } + } + + + + /* + int index = 0; + for (int e = 0; e < nedges; e++) + { + if (edgeorder[e] <= 1) continue; + + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + if (edgeorient[e] == -1) Swap (i0, i1); // reverse orientation + + double x = lambda(i1)-lambda(i0); + double y = 1-lambda(i0)-lambda(i1); + double fy = (1-y)*(1-y); + + // double p3 = 0, p3x = 0, p3y = 0; + // double p2 = -1, p2x = 0, p2y = 0; + // double p1 = x, p1x = 1, p1y = 0; + + double p3 = 0, p3x = 0, p3y = 0; + double p2 = -0.5, p2x = 0, p2y = 0; + double p1 = 0.5*x, p1x = 0.5, p1y = 0; + + for (int j=2; j<= edgeorder[e]; j++) + { + p3=p2; p3x = p2x; p3y = p2y; + p2=p1; p2x = p1x; p2y = p1y; + double c1 = (2.0*j-3) / j; + double c2 = (j-3.0) / j; + + p1 = c1 * x * p2 - c2 * fy * p3; + p1x = c1 * p2 + c1 * x * p2x - c2 * fy * p3x; + p1y = c1 * x * p2y - (c2 * 2 * (y-1) * p3 + c2 * fy * p3y); + + eshape[index] = p1; + for (int k = 0; k < 3; k++) + edshape[index](k) = + p1x * ( dlambda(i1,k) - dlambda(i0,k) ) + + p1y * (-dlambda(i1,k) - dlambda(i0,k) ); + index++; + } + + } + + */ + + + + + } + + + + + void FETet :: CalcEdgeShapesOnly () + { + int index = 0; + + for (int e = 0; e < nedges; e++) + { + int i0 = eledge[e][0]-1; + int i1 = eledge[e][1]-1; + + if (edgeorient[e] == -1) Swap (i0, i1); + + double arg = lambda(i0)+lambda(i1); + double xi = lambda[i1]; + + /* + b1.SetOrder (edgeorder[e]); + b1.CalcFScaled (xi, arg); + + for (int k = 2; k <= edgeorder[e]; k++, index++) + eshape[index] = b1.GetF (k); + */ + b1.CalcFScaled (edgeorder[e], xi, arg, &eshape[index]); + index += edgeorder[e]-1; + } + } + + + + + + + void FETet :: CalcFaceShapes () + { + int index = 0; + + for (int f = 0; f < nfaces; f++) + { + if (faceorder[f] <= 2) continue; + + int i0 = elface[f][0]-1; + int i1 = elface[f][1]-1; + int i2 = elface[f][2]-1; + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + double arg = lambda(i1) + lambda(i2); + double arg2 = lambda(i0) + lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON || fabs(arg2) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + b1.SetOrder (faceorder[f]); + b2.SetOrder (faceorder[f]); + + b1.CalcFDf (lambda(i0)/arg2); + b2.CalcFDf (lambda(i2)/arg); + + double decay = 1; + double ddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl0z = dlambda(i0,2); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl1z = dlambda(i1,2); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + double dl2z = dlambda(i2,2); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + double dargz = dl1z + dl2z; + double darg2x = dl0x + dl1x + dl2x; + double darg2y = dl0y + dl1y + dl2y; + double darg2z = dl0z + dl1z + dl2z; + + for (int n1 = 2; n1 < faceorder[f]; n1++) + { + ddecay = (n1-1)*decay; + decay *= arg; + + double decay2 = arg2; + double ddecay2; + + for (int n0 = 2; n0 < faceorder[f]-n1+2; n0++) + { + ddecay2 = n0*decay2; + decay2 *= arg2; + + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay * decay2; + fdshape[index] = Vec<3> + (b1.GetDf(n0) * (dl0x * arg2 - l0 * darg2x)/(arg2*arg2) * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2x, + + b1.GetDf(n0) * (dl0y * arg2 - l0 * darg2y)/(arg2*arg2) * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2y, + + b1.GetDf(n0) * (dl0z * arg2 - l0 * darg2z)/(arg2*arg2) * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2z * arg - l2 * dargz)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargz * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2z); + + index++; + } + } + } + } + + + + + // ---------------------------------------------------------------------------- + // FEPrism + // ---------------------------------------------------------------------------- + + + void FEPrism :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + + lambda(0) = xi(0); + lambda(1) = xi(1); + lambda(2) = 1-xi(0)-xi(1); + lambda(3) = xi(2); + + dlambda(0,0) = 1; dlambda(0,1) = 0; dlambda(0,2) = 0; + dlambda(1,0) = 0; dlambda(1,1) = 1; dlambda(1,2) = 0; + dlambda(2,0) = -1; dlambda(2,1) = -1; dlambda(2,2) = 0; + dlambda(3,0) = 0; dlambda(3,1) = 0; dlambda(3,2) = 1; + } + + + void FEPrism :: CalcVertexShapes () + { + double zcomp = 1-lambda(3); + + for (int v = 0; v < nvertices; v++) + { + if (v == 3) zcomp = 1-zcomp; + + vshape[v] = lambda(v % 3) * zcomp; + vdshape[v](0) = dlambda(v % 3,0) * zcomp; + vdshape[v](1) = dlambda(v % 3,1) * zcomp; + vdshape[v](2) = lambda(v % 3) * (-dlambda(3,2)); + + if (v >= 3) vdshape[v](2) *= -1; + } + } + + + void FEPrism :: CalcEdgeShapes () + { + int index = 0; + int e; + // triangle edge shapes + + for (e = 0; e < 6; e++) + { + int i0 = (eledge[e][0]-1) % 3; + int i1 = (eledge[e][1]-1) % 3; + + double arg = lambda[i0]+lambda[i1]; + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + if (edgeorient[e] == -1) Swap (i0, i1); + + double xi = lambda[i1]/arg; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double zarg = e < 3 ? (1-lambda(3)) : lambda(3); + double zcomp = zarg; + double dzcomp; + + double l0 = lambda(i0); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + + double l1 = lambda(i1); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + + double dargx = dl0x + dl1x; + double dargy = dl0y + dl1y; + + + /* + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + dzcomp = k*zcomp; + zcomp *= zarg; + + eshape[index] = b1.GetF (k) * decay * zcomp; + edshape[index] = Vec<3> + ((b1.GetDf(k) * (dl1x*arg - l1*dargx) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargx) * zcomp, + (b1.GetDf(k) * (dl1y*arg - l1*dargy) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargy) * zcomp, + b1.GetF(k) * decay * dzcomp * (e < 3 ? -1 : 1)); + index++; + } + */ + + // JS linear in z-direction (for thin plates !) + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + // dzcomp = k*zcomp; + // zcomp *= zarg; + dzcomp = 1; + zcomp = zarg; + + eshape[index] = b1.GetF (k) * decay * zcomp; + edshape[index] = Vec<3> + ((b1.GetDf(k) * (dl1x*arg - l1*dargx) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargx) * zcomp, + (b1.GetDf(k) * (dl1y*arg - l1*dargy) * + decay / (arg * arg) + b1.GetF(k) * ddecay * dargy) * zcomp, + b1.GetF(k) * decay * dzcomp * (e < 3 ? -1 : 1)); + index++; + } + + + + } + + // rectangle edge shapes + + for (e = 6; e < nedges; e++) + { + int i0 = eledge[e][0]-1; + + double arg = lambda[i0]; + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0.; + edshape[index] = Vec<3>(0.,0.,0.); + index++; + } + continue; + } + + double xi = lambda[3]; + + if (edgeorient[e] == -1) xi = 1-xi; + + b1.SetOrder (edgeorder[e]); + b1.CalcFDf (xi); + + double decay = arg; + double ddecay; + + double l0 = lambda(i0); + double l0x = dlambda(i0,0); + double l0y = dlambda(i0,1); + + for (int k = 2; k <= edgeorder[e]; k++) + { + ddecay = k*decay; + decay *= arg; + + eshape[index] = b1.GetF (k) * decay; + edshape[index] = Vec<3> + (b1.GetF(k) * ddecay * l0x, + b1.GetF(k) * ddecay * l0y, + b1.GetDf(k) * edgeorient[e] * decay); + index++; + } + } + } + + + void FEPrism :: CalcFaceShapes () + { + int index = 0; + int f; + + // triangle face parts + + for (f = 0; f < 2; f++) + { + int i0 = elface[f][0]-1; + int i1 = elface[f][1]-1; + int i2 = elface[f][2]-1; + + if (vertexnr[i1] < vertexnr[i0]) Swap (i0, i1); + if (vertexnr[i2] < vertexnr[i0]) Swap (i0, i2); + if (vertexnr[i2] < vertexnr[i1]) Swap (i1, i2); + + i0 = i0 % 3; + i1 = i1 % 3; + i2 = i2 % 3; + + double arg = lambda(i1) + lambda(i2); + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + b1.SetOrder (faceorder[f]); + b2.SetOrder (faceorder[f]); + + b1.CalcFDf (lambda(i0)); + b2.CalcFDf (lambda(i2)/arg); + + double decay = 1; + double ddecay; + + double l0 = lambda(i0); + double l1 = lambda(i1); + double l2 = lambda(i2); + double dl0x = dlambda(i0,0); + double dl0y = dlambda(i0,1); + double dl0z = dlambda(i0,2); + double dl1x = dlambda(i1,0); + double dl1y = dlambda(i1,1); + double dl1z = dlambda(i1,2); + double dl2x = dlambda(i2,0); + double dl2y = dlambda(i2,1); + double dl2z = dlambda(i2,2); + + double dargx = dl1x + dl2x; + double dargy = dl1y + dl2y; + double dargz = dl1z + dl2z; + + double arg2 = f == 0 ? 1-xi(2) : xi(2); + double darg2z = f == 0 ? -1 : 1; + + for (int n1 = 2; n1 < faceorder[f]; n1++) + { + ddecay = (n1-1)*decay; + decay *= arg; + + double decay2 = arg2; + double ddecay2; + + for (int n0 = 2; n0 < faceorder[f]-n1+2; n0++) + { + ddecay2 = n0*decay2; + decay2 *= arg2; + + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay * decay2; + fdshape[index] = Vec<3> + (b1.GetDf(n0) * dl0x * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2x * arg - l2 * dargx)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx * decay2, + + b1.GetDf(n0) * dl0y * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2y * arg - l2 * dargy)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy * decay2, + + b1.GetDf(n0) * dl0z * b2.GetF(n1) * decay * decay2 + + b1.GetF(n0) * b2.GetDf(n1) * (dl2z * arg - l2 * dargz)/(arg*arg) * decay * decay2 + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargz * decay2 + + b1.GetF(n0) * b2.GetF(n1) * decay * ddecay2 * darg2z); + + index++; + } + } + } + + + // quad parts + + for (f = 2; f < nfaces; f++) + { + // find index of point with smallest number + + int i, i0 = 0; + for (i = 1; i < 4; i++) + if (vertexnr[elface[f][i]-1] < vertexnr[elface[f][i0]-1]) i0 = i; + + double arg = 0; + double dargx = 0; + double dargy = 0; + double dargz = 0; + for (i = 0; i < 4; i++) + { + arg += lambda((elface[f][i]-1) % 3)/2.0; + dargx += dlambda((elface[f][i]-1) % 3,0)/2.0; + dargy += dlambda((elface[f][i]-1) % 3,1)/2.0; + dargz += dlambda((elface[f][i]-1) % 3,2)/2.0; + } + + if (fabs(arg) < EPSILON) // division by 0 + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + continue; + } + + int i1 = (i0+3) % 4; + int j = (elface[f][i0]-1) % 3; + + double lam = lambda(j)/arg; + double dlamx = (dlambda(j,0)*arg-lambda(j)*dargx)/(arg*arg); + double dlamy = (dlambda(j,1)*arg-lambda(j)*dargy)/(arg*arg); + double dlamz = (dlambda(j,2)*arg-lambda(j)*dargz)/(arg*arg); + + double x; + double z; + double dxx; + double dxy; + double dxz; + double dzx; + double dzy; + double dzz; + + int ratvar; + /* + switch (i0) + { + case 0: + x = xi(2); z = lam; + + dxx = 0; dxy = 0; dxz = 1; + dzx = dlamx; dzy = dlamy; dzz = dlamz; + ratvar = 1; + break; + case 1: + x = 1-lam; z = xi(2); + dxx = -dlamx; dxy = -dlamy; dxz = -dlamz; + dzx = 0; dzy = 0; dzz = 1; + ratvar = 0; + break; + case 2: + x = 1-xi(2); z = 1-lam; + dxx = 0; dxy = 0; dxz = -1; + dzx = -dlamx; dzy = -dlamy; dzz = -dlamz; + ratvar = 1; + break; + case 3: + x = lam; z = 1-xi(2); + dxx = dlamx; dxy = dlamy; dxz = dlamz; + dzx = 0; dzy = 0; dzz = -1; + ratvar = 0; + break; + } + */ + + ratvar = 0; + x = 1-lam; + dxx = -dlamx; dxy = -dlamy; dxz = -dlamz; + if (i0 == 0 || i0 == 1) + { + z = xi(2); + dzx = 0; dzy = 0; dzz = 1; + } + else + { + z = 1-xi(2); + dzx = 0; dzy = 0; dzz = -1; + } + + int ix = i0 ^ 1; + int iz = 3-i0; + + if (vertexnr[elface[f][ix]-1] > vertexnr[elface[f][iz]-1]) + { + Swap (x,z); + Swap (dxx, dzx); + Swap (dxy, dzy); + Swap (dxz, dzz); + ratvar = 1-ratvar; + } + + b1.SetOrder (faceorder[f]); + b2.SetOrder (faceorder[f]); + + b1.CalcFDf (x); + b2.CalcFDf (z); + + double decay = arg; + double ddecay; + + for (int n0 = 2; n0 <= faceorder[f]; n0++) + { + ddecay = n0*decay; + decay *= arg; + + if (ratvar == 1) decay = arg; + + for (int n1 = 2; n1 <= faceorder[f]; n1++) + { + if (ratvar == 1) + { + ddecay = n1*decay; + decay *= arg; + } + + fshape[index] = b1.GetF(n0) * b2.GetF(n1) * decay; + fdshape[index] = Vec<3> + (b1.GetDf(n0) * dxx * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * dzx * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargx, + + b1.GetDf(n0) * dxy * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * dzy * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargy, + + b1.GetDf(n0) * dxz * b2.GetF(n1) * decay + + b1.GetF(n0) * b2.GetDf(n1) * dzz * decay + + b1.GetF(n0) * b2.GetF(n1) * ddecay * dargz); + + index++; + } + } + } + } + + + + // ---------------------------------------------------------------------------- + // FEPyramid + // ---------------------------------------------------------------------------- + + + void FEPyramid :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + } + + + void FEPyramid :: CalcVertexShapes () + { + double x = xi(0); + double y = xi(1); + double z = xi(2); + + if (z == 1.) z = 1-1e-10; + vshape[0] = (1-z-x)*(1-z-y) / (1-z); + vshape[1] = x*(1-z-y) / (1-z); + vshape[2] = x*y / (1-z); + vshape[3] = (1-z-x)*y / (1-z); + vshape[4] = z; + + double z1 = 1-z; + double z2 = z1*z1; + + vdshape[0] = Vec<3>( -(z1-y)/z1, -(z1-x)/z1, ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2 ); + vdshape[1] = Vec<3>( (z1-y)/z1, -x/z1, (-x*z1+x*(z1-y))/z2 ); + vdshape[2] = Vec<3>( y/z1, x/z1, x*y/z2 ); + vdshape[3] = Vec<3>( -y/z1, (z1-x)/z1, (-y*z1+y*(z1-x))/z2 ); + vdshape[4] = Vec<3>( 0, 0, 1 ); + } + + + void FEPyramid :: CalcEdgeShapes () + { + int index = 0; + + for (int e = 0; e < GetNEdges(); e++) + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + void FEPyramid :: CalcFaceShapes () + { + int index = 0; + + for (int f = 0; f < GetNFaces(); f++) + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + + + + // ---------------------------------------------------------------------------- + // FEHex + // ---------------------------------------------------------------------------- + + + void FEHex :: SetReferencePoint (Point<3> axi) + { + BaseFiniteElement3D :: SetReferencePoint (axi); + } + + + void FEHex :: CalcVertexShapes () + { + double x = xi(0); + double y = xi(1); + double z = xi(2); + + vshape[0] = (1-x)*(1-y)*(1-z); + vshape[1] = x *(1-y)*(1-z); + vshape[2] = x * y *(1-z); + vshape[3] = (1-x)* y *(1-z); + vshape[4] = (1-x)*(1-y)* z; + vshape[5] = x *(1-y)* z; + vshape[6] = x * y * z; + vshape[7] = (1-x)* y * z; + + vdshape[0] = Vec<3>(-(1-y)*(1-z), -(1-x)*(1-z), -(1-x)*(1-y)); + vdshape[1] = Vec<3>( (1-y)*(1-z), -x *(1-z), -x *(1-y)); + vdshape[2] = Vec<3>( y *(1-z), x *(1-z), -x * y); + vdshape[3] = Vec<3>( -y *(1-z), (1-x)*(1-z), -(1-x)*y); + vdshape[4] = Vec<3>(-(1-y)* z, -(1-x)* z, (1-x)*(1-y)); + vdshape[5] = Vec<3>( (1-y)* z, -x * z, x *(1-y)); + vdshape[6] = Vec<3>( y * z, x * z, x * y); + vdshape[7] = Vec<3>( -y * z, (1-x)* z, (1-x)*y); + + } + + + void FEHex :: CalcEdgeShapes () + { + int index = 0; + + for (int e = 0; e < GetNEdges(); e++) + { + for (int k = 2; k <= edgeorder[e]; k++) + { + eshape[index] = 0; + edshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + void FEHex :: CalcFaceShapes () + { + int index = 0; + + for (int f = 0; f < GetNFaces(); f++) + { + for (int k = 0; k < nfaceshapes[f]; k++) + { + fshape[index] = 0; + fdshape[index] = Vec<3>(0,0,0); + index++; + } + } + } + + + + + + + + + + int CurvedElements :: IsSurfaceElementCurved (int elnr) const + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(SurfaceElementIndex) elnr].hp_elnr]; + + return mesh.coarsemesh->GetCurvedElements().IsSurfaceElementCurved (hpref_el.coarse_elnr); + } + + + + + Element2d elem = mesh[(SurfaceElementIndex) elnr]; + + switch (elem.GetType()) + { + case TRIG: + { + FETrig fe2d(*this); + fe2d.SetElementNumber (elnr+1); + return (fe2d.IsCurved()); + break; + } + + case QUAD: + { + FEQuad fe2d(*this); + fe2d.SetElementNumber (elnr+1); + return (fe2d.IsCurved()); + break; + } + + } + return 0; + } + + + + int CurvedElements :: IsElementCurved (int elnr) const + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(ElementIndex) elnr].hp_elnr]; + + return mesh.coarsemesh->GetCurvedElements().IsElementCurved (hpref_el.coarse_elnr); + } + + + + Element elem = mesh[(ElementIndex) elnr]; + + switch (elem.GetType()) + { + case TET: + { + FETet fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + case PRISM: + { + FEPrism fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + case PYRAMID: + { + FEPyramid fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + case HEX: + { + FEHex fe3d(*this); + fe3d.SetElementNumber (elnr+1); + return (fe3d.IsCurved()); + break; + } + + } + + return 0; + } + + + void CurvedElements :: CalcSegmentTransformation (double xi, int segnr, + Point<3> * x, Vec<3> * dxdxi) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(SegmentIndex) segnr].hp_elnr]; + + // xi umrechnen + double lami[2]; + lami[0] = xi; + lami[1] = 1-xi; + + double coarse_xi = 0; + for (int i = 0; i < 2; i++) + coarse_xi += hpref_el.param[i][0] * lami[i]; + + mesh.coarsemesh->GetCurvedElements().CalcSegmentTransformation (coarse_xi, hpref_el.coarse_elnr, x, dxdxi); + return; + } + + + // xi = 1-xi; // or, this way ????? JS + FESegm segm (*this); + segm.SetElementNumber (segnr+1); + segm.SetReferencePoint (Point<1>(xi)); + + // segm.CalcVertexShapes (x != NULL, dxdxi != NULL); + segm.CalcVertexShapes (); + + if (x) + { + (*x) = Point<3>(0,0,0); + for (int v = 0; v < 2; v++) + (*x) = (*x) + segm.GetVertexShape(v) * mesh.Point(segm.GetVertexNr(v)); + } + + if (dxdxi) + { + (*dxdxi) = Vec<3>(0,0,0); + for (int v = 0; v < 2; v++) + (*dxdxi) = (*dxdxi) + segm.GetVertexDShape(v) * mesh.Point(segm.GetVertexNr(v)); + } + + if (segm.GetEdgeOrder() > 1) + { + // segm.CalcEdgeShapes (x != NULL, dxdxi != NULL); + segm.CalcEdgeShapes (); + + if (x) + { + int gindex = edgecoeffsindex[segm.GetEdgeNr()-1]; + for (int k = 2; k <= segm.GetEdgeOrder(); k++, gindex++) + (*x) = (*x) + segm.GetEdgeShape(k-2) * edgecoeffs[gindex]; + } + + if (dxdxi) + { + int gindex = edgecoeffsindex[segm.GetEdgeNr()-1]; + for (int k = 2; k <= segm.GetEdgeOrder(); k++, gindex++) + (*dxdxi) = (*dxdxi) + segm.GetEdgeDShape(k-2) * edgecoeffs[gindex]; + } + } + } + + + + void CurvedElements :: CalcMultiPointSegmentTransformation (ARRAY<double> * xi, int segnr, + ARRAY<Point<3> > * x, + ARRAY<Vec<3> > * dxdxi) + { + int size = xi->Size(); + + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(SegmentIndex) segnr].hp_elnr]; + + // xi umrechnen + ARRAY< Point<2> > lami; + lami.SetSize (size); + for (int i = 0; i<size; i++) + { + lami[i](0) = (*xi)[i]; + lami[i](1) = 1-(*xi)[i]; + } + + ARRAY<double> coarse_xi; + coarse_xi.SetSize (size); + coarse_xi = 0; + + + for (int j = 0; j < 2; j++) + for (int i = 0; i<size; i++) + coarse_xi[i] += hpref_el.param[j][0] * lami[i](j); + + mesh.coarsemesh->GetCurvedElements().CalcMultiPointSegmentTransformation + (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi); + return; + } + + + + FESegm segm (*this); + segm.SetElementNumber (segnr+1); + x->SetSize (size); + dxdxi->SetSize (size); + + for (int i = 0; i < size; i++) + { + segm.SetReferencePoint (Point<1>((*xi)[i])); + + // segm.CalcVertexShapes (x != NULL, dxdxi != NULL); + segm.CalcVertexShapes (); + + (*x)[i] = Point<3>(0,0,0); + (*dxdxi)[i] = Vec<3>(0,0,0); + + for (int v = 0; v < 2; v++) + { + (*x)[i] = (*x)[i] + segm.GetVertexShape(v) * mesh.Point(segm.GetVertexNr(v)); + (*dxdxi)[i] = (*dxdxi)[i] + segm.GetVertexDShape(v) * mesh.Point(segm.GetVertexNr(v)); + } + + if (segm.GetEdgeOrder() > 1) + { + // segm.CalcEdgeShapes (x != NULL, dxdxi != NULL); + segm.CalcEdgeShapes (); + + int gindex = edgecoeffsindex[segm.GetEdgeNr()-1]; + for (int k = 2; k <= segm.GetEdgeOrder(); k++, gindex++) + { + (*x)[i] = (*x)[i] + segm.GetEdgeShape(k-2) * edgecoeffs[gindex]; + (*dxdxi)[i] = (*dxdxi)[i] + segm.GetEdgeDShape(k-2) * edgecoeffs[gindex]; + } + } + } + } + + + + + + void CurvedElements :: CalcSurfaceTransformation (Point<2> xi, int elnr, + Point<3> * x, Mat<3,2> * dxdxi) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(SurfaceElementIndex) elnr].hp_elnr]; + + // xi umrechnen + double lami[4]; + FlatVector vlami(4, lami); + vlami = 0; + mesh[(SurfaceElementIndex) elnr] . GetShapeNew (xi, vlami); + + Mat<2,2> trans; + Mat<3,2> dxdxic; + if (dxdxi) + { + MatrixFixWidth<2> dlami(4); + dlami = 0; + mesh[(SurfaceElementIndex) elnr] . GetDShapeNew (xi, dlami); + + trans = 0; + for (int k = 0; k < 2; k++) + for (int l = 0; l < 2; l++) + { + double sum = 0; + for (int i = 0; i < 4; i++) + sum += hpref_el.param[i][l] * dlami(i, k); + trans(l,k) = sum; + } + } + + Point<2> coarse_xi(0,0); + for (int i = 0; i < 4; i++) + { + coarse_xi(0) += hpref_el.param[i][0] * lami[i]; + coarse_xi(1) += hpref_el.param[i][1] * lami[i]; + } + mesh.coarsemesh->GetCurvedElements().CalcSurfaceTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic); + + if (dxdxi) + *dxdxi = dxdxic * trans; + + return; + } + + + + + const Element2d & elem = mesh[(SurfaceElementIndex) elnr]; + + BaseFiniteElement2D * fe2d; + + // char locmem[max2(sizeof(FEQuad), sizeof(FETrig))]; + char locmemtrig[sizeof(FETrig)]; + char locmemquad[sizeof(FEQuad)]; + switch (elem.GetType()) + { + case TRIG: fe2d = new (locmemtrig) FETrig (*this); break; + case QUAD: fe2d = new (locmemquad) FEQuad (*this); break; + } + + // fe2d->SetElementNumber (elnr+1); + fe2d->SetReferencePoint (xi); + fe2d->CalcVertexShapes (); + + if (x) + { + (*x) = Point<3>(0,0,0); + for (int v = 0; v < fe2d->GetNVertices(); v++) + (*x) = (*x) + fe2d->GetVertexShape(v) * mesh.Point(elem[v]); + // (*x) = (*x) + fe2d->GetVertexShape(v) * mesh.Point(fe2d->GetVertexNr(v)); + } + + if (dxdxi) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) = 0; + + for (int v = 0; v < elem.GetNV(); v++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) += fe2d->GetVertexDShape(v)(j) * mesh.Point(elem[v]).X(i+1); + // (*dxdxi)(i,j) += fe2d->GetVertexDShape(v)(j) * mesh.Point(fe2d->GetVertexNr(v)).X(i+1); + } + + if (IsHighOrder()) + { + fe2d->SetElementNumber (elnr+1); + + // fe2d->CalcEdgeShapes (x != NULL, dxdxi != NULL); + fe2d->CalcEdgeShapes (); + if (x) + { + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + (*x) = (*x) + fe2d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + } + + if (dxdxi) + { + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) += fe2d->GetEdgeDShape(index)(j) * edgecoeffs[gindex](i); + } + } + + if (mesh.GetDimension() == 3) + { + // fe2d->CalcFaceShapes (x != NULL, dxdxi != NULL); + fe2d->CalcFaceShapes (); + + if (x) + { + int gindex = facecoeffsindex[fe2d->GetFaceNr()-1]; + for (int index = 0; index < fe2d->GetNFaceShapes(); index++, gindex++) + { + (*x) = (*x) + fe2d->GetFaceShape(index) * facecoeffs[gindex]; + } + } + + if (dxdxi) + { + int gindex = facecoeffsindex[fe2d->GetFaceNr()-1]; + for (int index = 0; index < fe2d->GetNFaceShapes(); index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)(i,j) += fe2d->GetFaceDShape(index)(j) * facecoeffs[gindex](i); + } + } + } + + fe2d -> ~BaseFiniteElement2D(); + } + + + + + + + + + void CurvedElements :: CalcMultiPointSurfaceTransformation (ARRAY< Point<2> > * xi, int elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,2> > * dxdxi) + { + + int size = xi->Size(); + + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(SurfaceElementIndex) elnr].hp_elnr]; + + // xi umrechnen + ARRAY< Point<2> > coarse_xi; + ARRAY< Mat<2,2> > trans; + ARRAY< Mat<3,2> > dxdxic; + + coarse_xi.SetSize (size); + coarse_xi = 0; + trans.SetSize (size); + dxdxic.SetSize (size); + + for (int mp = 0; mp<size; mp++) + { + double lami[4]; + FlatVector vlami(4, lami); + vlami = 0; + mesh[(SurfaceElementIndex) elnr] . GetShapeNew ((*xi)[mp], vlami); + + MatrixFixWidth<2> dlami(4); + dlami = 0; + mesh[(SurfaceElementIndex) elnr] . GetDShapeNew ((*xi)[mp], dlami); + + trans[mp] = 0; + for (int k = 0; k < 2; k++) + for (int l = 0; l < 2; l++) + { + double sum = 0; + for (int i = 0; i < 4; i++) + sum += hpref_el.param[i][l] * dlami(i, k); + trans[mp](l,k) = sum; + } + + for (int i = 0; i < 4; i++) + { + coarse_xi[mp](0) += hpref_el.param[i][0] * lami[i]; + coarse_xi[mp](1) += hpref_el.param[i][1] * lami[i]; + } + } + + mesh.coarsemesh->GetCurvedElements().CalcMultiPointSurfaceTransformation (&coarse_xi, hpref_el.coarse_elnr, x, &dxdxic); + + for (int mp = 0; mp < size; mp++) + { + (*dxdxi)[mp] = dxdxic[mp] * trans[mp]; + } + + return; + } + + + x->SetSize (size); + dxdxi->SetSize (size); + + const Element2d & elem = mesh[(SurfaceElementIndex) elnr]; + + BaseFiniteElement2D * fe2d; + + // char locmem[max2(sizeof(FEQuad), sizeof(FETrig))]; + char locmemtrig[sizeof(FETrig)]; + char locmemquad[sizeof(FEQuad)]; + switch (elem.GetType()) + { + case TRIG: fe2d = new (locmemtrig) FETrig (*this); break; + case QUAD: fe2d = new (locmemquad) FEQuad (*this); break; + } + + fe2d->SetElementNumber (elnr+1); + + for (int mp = 0; mp < size; mp++) + { + fe2d->SetReferencePoint ((*xi)[mp]); + fe2d->CalcVertexShapes (); + + (*x)[mp] = Point<3>(0,0,0); + + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)[mp](i,j) = 0; + + for (int v = 0; v < fe2d->GetNVertices(); v++) + { + (*x)[mp] = (*x)[mp] + fe2d->GetVertexShape(v) * mesh.Point(fe2d->GetVertexNr(v)); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)[mp](i,j) += fe2d->GetVertexDShape(v)(j) * mesh.Point(fe2d->GetVertexNr(v)).X(i+1); + } + + if (IsHighOrder()) + { + // fe2d->CalcEdgeShapes (x != NULL, dxdxi != NULL); + fe2d->CalcEdgeShapes (); + + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + { + (*x)[mp] = (*x)[mp] + fe2d->GetEdgeShape(index) * edgecoeffs[gindex]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)[mp](i,j) += fe2d->GetEdgeDShape(index)(j) * edgecoeffs[gindex](i); + } + } + + + if (mesh.GetDimension() == 3) + { + // fe2d->CalcFaceShapes (x != NULL, dxdxi != NULL); + fe2d->CalcFaceShapes (); + + int gindex = facecoeffsindex[fe2d->GetFaceNr()-1]; + for (int index = 0; index < fe2d->GetNFaceShapes(); index++, gindex++) + { + (*x)[mp] = (*x)[mp] + fe2d->GetFaceShape(index) * facecoeffs[gindex]; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 2; j++) + (*dxdxi)[mp](i,j) += fe2d->GetFaceDShape(index)(j) * facecoeffs[gindex](i); + } + } + } + } + + fe2d -> ~BaseFiniteElement2D(); + } + + + + + + + + + + + + + + + + + + + + void CurvedElements :: CalcElementTransformation (Point<3> xi, int elnr, + Point<3> * x, Mat<3,3> * dxdxi) + { + + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(ElementIndex) elnr].hp_elnr]; + + + /* + *testout << " Curved Element " << elnr << endl; + *testout << " hpref_el.coarse_elnr " << hpref_el.coarse_elnr << endl; + *testout << " hpref_el.param = " << endl; + for(int j=0;j< hpref_el.np; j++) + { + for(int k=0;k<3;k++) + *testout << hpref_el.param[j][k] << "\t"; + *testout << endl; + } + */ + + double lami[8]; + FlatVector vlami(8, lami); + vlami = 0; + mesh[(ElementIndex) elnr] . GetShapeNew (xi, vlami); + + Point<3> coarse_xi(0,0,0); + for (int i = 0; i < hpref_el.np; i++) + for (int l = 0; l < 3; l++) + coarse_xi(l) += hpref_el.param[i][l] * lami[i]; + + Mat<3,3> trans, dxdxic; + if (dxdxi) + { + MatrixFixWidth<3> dlami(8); + dlami = 0; + mesh[(ElementIndex) elnr] . GetDShapeNew (xi, dlami); + + trans = 0; + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + { + double sum = 0; + for (int i = 0; i < hpref_el.np; i++) + sum += hpref_el.param[i][l] * dlami(i, k); + trans(l,k) = sum; + } + } + /* + *testout << " x " << x << endl; + // << "\t" << x.X(2) << "\t" << x.X(3) << endl; + *testout << " Element Trafo " << coarse_xi(0) << " \t " << coarse_xi(1) << " \t " << coarse_xi(2) << endl; + */ + + + + mesh.coarsemesh->GetCurvedElements().CalcElementTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic); + + if (dxdxi) + *dxdxi = dxdxic * trans; + return; + } + + + + + + + + + + Element elem = mesh[(ElementIndex) elnr]; + BaseFiniteElement3D * fe3d; + + // char locmem[max2(sizeof(FETet), sizeof(FEPrism))]; + char locmemtet[sizeof(FETet)]; + char locmemprism[sizeof(FEPrism)]; + char locmempyramid[sizeof(FEPyramid)]; + char locmemhex[sizeof(FEHex)]; + switch (elem.GetType()) + { + case TET: fe3d = new (locmemtet) FETet (*this); break; + case PRISM: fe3d = new (locmemprism) FEPrism (*this); break; + case PYRAMID: fe3d = new (locmempyramid) FEPyramid (*this); break; + case HEX: fe3d = new (locmemhex) FEHex (*this); break; + } + + // fe3d->SetElementNumber (elnr+1); + fe3d->SetReferencePoint (xi); + + fe3d->CalcVertexShapes (); + // fe3d->CalcVertexShapes (x != NULL, dxdxi != NULL); + + + if (x) + { + (*x) = Point<3>(0,0,0); + for (int v = 0; v < fe3d->GetNVertices(); v++) + (*x) += fe3d->GetVertexShape(v) * Vec<3> (mesh.Point(elem[v])); + } + + if (dxdxi) + { + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) = 0; + + for (int v = 0; v < fe3d->GetNVertices(); v++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) += fe3d->GetVertexDShape(v)(j) * mesh.Point(elem[v]).X(i+1); + } + + if (IsHighOrder()) + { + fe3d->SetElementNumber (elnr+1); + // fe3d->CalcEdgeShapes (x != NULL, dxdxi != NULL); + fe3d->CalcEdgeShapes (); + + + if (x) + { + int index = 0; + for (int e = 0; e < fe3d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe3d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe3d->GetEdgeOrder(e); k++, index++, gindex++) + (*x) += fe3d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + } + + if (dxdxi) + { + int index = 0; + for (int e = 0; e < fe3d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe3d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe3d->GetEdgeOrder(e); k++, index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) += fe3d->GetEdgeDShape(index)(j) * edgecoeffs[gindex](i); + } + } + + + // cout << "switched off face mapping" << endl; + if (mesh.GetDimension() == 3) // JS + { + fe3d->CalcFaceShapes (); + // fe3d->CalcFaceShapes (x != NULL, dxdxi != NULL); + + if (x) + { + int index = 0; + for (int f = 0; f < fe3d->GetNFaces(); f++) + { + int gindex = facecoeffsindex[fe3d->GetFaceNr(f)-1]; + for (int k = 0; k < fe3d->GetNFaceShapes(f); k++, index++, gindex++) + (*x) += fe3d->GetFaceShape(index) * facecoeffs[gindex]; + } + } + + if (dxdxi) + { + int index = 0; + for (int f = 0; f < fe3d->GetNFaces(); f++) + { + int gindex = facecoeffsindex[fe3d->GetFaceNr(f)-1]; + for (int k = 0; k < fe3d->GetNFaceShapes(f); k++, index++, gindex++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(i,j) += fe3d->GetFaceDShape(index)(j) * facecoeffs[gindex](i); + } + } + } + } + + fe3d -> ~BaseFiniteElement3D(); + } + + + + + + + + + +#ifdef ROBERT + + void CurvedElements :: CalcMultiPointElementTransformation (ARRAY< Point<3> > * xi, int elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,3> > * dxdxi) + { + int size = (*xi).Size(); + x->SetSize (size); + + if (dxdxi) dxdxi->SetSize (size); + + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(ElementIndex) elnr].hp_elnr]; + + ARRAY< Mat<3,3> > trans, dxdxic; + if (dxdxi) + { + trans.SetSize (size); + dxdxic.SetSize (size); + } + + ARRAY<Point<3> > coarse_xi(size); + + double lami[8]; + FlatVector vlami(8, lami); + const Element & el = mesh[(ElementIndex) elnr]; + int el_np = el.GetNP(); + + for (int mp = 0; mp < size; mp++) + { + el.GetShapeNew ((*xi)[mp], vlami); + + Point<3> pc(0,0,0); + for (int i = 0; i < el_np; i++) + for (int l = 0; l < 3; l++) + pc(l) += hpref_el.param[i][l] * lami[i]; + + coarse_xi[mp] = pc; + + if (dxdxi) + { + MatrixFixWidth<3> dlami(8); + dlami = 0; + mesh[(ElementIndex) elnr] . GetDShapeNew ((*xi)[mp], dlami); + + trans[mp] = 0; + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + { + double sum = 0; + for (int i = 0; i < 8; i++) + sum += hpref_el.param[i][l] * dlami(i, k); + trans[mp](l,k) = sum; + } + } + } + + if (dxdxi) + mesh.coarsemesh->GetCurvedElements().CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, &dxdxic); + else + mesh.coarsemesh->GetCurvedElements().CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, 0); + + if (dxdxi) + for (int mp = 0; mp < size; mp++) + (*dxdxi)[mp] = dxdxic[mp] * trans[mp]; + + return; + } + + + + + + + + + + Element elem = mesh[(ElementIndex) elnr]; + BaseFiniteElement3D * fe3d; + + // char locmem[max2(sizeof(FETet), sizeof(FEPrism))]; + char locmemtet[sizeof(FETet)]; + char locmemprism[sizeof(FEPrism)]; + char locmempyramid[sizeof(FEPyramid)]; + char locmemhex[sizeof(FEHex)]; + switch (elem.GetType()) + { + case TET: fe3d = new (locmemtet) FETet (*this); break; + case PRISM: fe3d = new (locmemprism) FEPrism (*this); break; + case PYRAMID: fe3d = new (locmempyramid) FEPyramid (*this); break; + case HEX: fe3d = new (locmemhex) FEHex (*this); break; + } + + fe3d->SetElementNumber (elnr+1); + + + for (int mp = 0; mp < size; mp++) + { + fe3d->SetReferencePoint ((*xi)[mp]); + + fe3d->CalcVertexShapes (); + // fe3d->CalcVertexShapes (x != NULL, dxdxi != NULL); + + (*x)[mp] = Point<3>(0,0,0); + if (dxdxi) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)[mp](i,j) = 0; + + for (int v = 0; v < fe3d->GetNVertices(); v++) + { + (*x)[mp] += fe3d->GetVertexShape(v) * Vec<3> (mesh.Point(fe3d->GetVertexNr(v))); + if (dxdxi) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)[mp](i,j) += fe3d->GetVertexDShape(v)(j) * mesh.Point(fe3d->GetVertexNr(v)).X(i+1); + } + + + if (IsHighOrder()) + { + // fe3d->CalcEdgeShapes (x != NULL, dxdxi != NULL); + fe3d->CalcEdgeShapes (); + + int index = 0; + for (int e = 0; e < fe3d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe3d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe3d->GetEdgeOrder(e); k++, index++, gindex++) + { + (*x)[mp] += fe3d->GetEdgeShape(index) * edgecoeffs[gindex]; + if (dxdxi) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)[mp](i,j) += fe3d->GetEdgeDShape(index)(j) * edgecoeffs[gindex](i); + } + } + + if (mesh.GetDimension() == 3) + { + fe3d->CalcFaceShapes (); + // fe3d->CalcFaceShapes (x != NULL, dxdxi != NULL); + + int index = 0; + for (int f = 0; f < fe3d->GetNFaces(); f++) + { + int gindex = facecoeffsindex[fe3d->GetFaceNr(f)-1]; + for (int k = 0; k < fe3d->GetNFaceShapes(f); k++, index++, gindex++) + { + (*x)[mp] += fe3d->GetFaceShape(index) * facecoeffs[gindex]; + if (dxdxi) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)[mp](i,j) += fe3d->GetFaceDShape(index)(j) * facecoeffs[gindex](i); + } + } + } + } + } + + fe3d -> ~BaseFiniteElement3D(); + } + +#endif + + + + + + + void CurvedElements :: CalcMultiPointElementTransformation (ARRAY< Point<3> > * xi, int elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,3> > * dxdxi) + { + int size = (*xi).Size(); + x->SetSize (size); + + if (dxdxi) dxdxi->SetSize (size); + + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh[(ElementIndex) elnr].hp_elnr]; + + ARRAY< Mat<3,3> > trans, dxdxic; + if (dxdxi) + { + trans.SetSize (size); + dxdxic.SetSize (size); + } + + ARRAY<Point<3> > coarse_xi(size); + + double lami[8]; + FlatVector vlami(8, lami); + const Element & el = mesh[(ElementIndex) elnr]; + int el_np = el.GetNP(); + + for (int mp = 0; mp < size; mp++) + { + el.GetShapeNew ((*xi)[mp], vlami); + + Point<3> pc(0,0,0); + for (int i = 0; i < el_np; i++) + for (int l = 0; l < 3; l++) + pc(l) += hpref_el.param[i][l] * lami[i]; + + coarse_xi[mp] = pc; + + if (dxdxi) + { + MatrixFixWidth<3> dlami(8); + dlami = 0; + mesh[(ElementIndex) elnr] . GetDShapeNew ((*xi)[mp], dlami); + + trans[mp] = 0; + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + { + double sum = 0; + for (int i = 0; i < 8; i++) + sum += hpref_el.param[i][l] * dlami(i, k); + trans[mp](l,k) = sum; + } + } + } + + if (dxdxi) + mesh.coarsemesh->GetCurvedElements().CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, &dxdxic); + else + mesh.coarsemesh->GetCurvedElements().CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, 0); + + if (dxdxi) + for (int mp = 0; mp < size; mp++) + (*dxdxi)[mp] = dxdxic[mp] * trans[mp]; + + return; + } + + + + + + + + + + Element elem = mesh[(ElementIndex) elnr]; + BaseFiniteElement3D * fe3d; + + // char locmem[max2(sizeof(FETet), sizeof(FEPrism))]; + char locmemtet[sizeof(FETet)]; + char locmemprism[sizeof(FEPrism)]; + char locmempyramid[sizeof(FEPyramid)]; + char locmemhex[sizeof(FEHex)]; + switch (elem.GetType()) + { + case TET: fe3d = new (locmemtet) FETet (*this); break; + case PRISM: fe3d = new (locmemprism) FEPrism (*this); break; + case PYRAMID: fe3d = new (locmempyramid) FEPyramid (*this); break; + case HEX: fe3d = new (locmemhex) FEHex (*this); break; + } + + fe3d->SetElementNumber (elnr+1); + + if (dxdxi) + for (int mp = 0; mp < size; mp++) + (*dxdxi)[mp] = 0.0; + + Vec<3> vertices[8]; + ArrayMem<Vec<3>, 100> loc_edgecoefs(0); + ArrayMem<Vec<3>, 100> loc_facecoefs(0); + + for (int v = 0; v < fe3d->GetNVertices(); v++) + vertices[v] = Vec<3> (mesh.Point(fe3d->GetVertexNr(v))); + + if (IsHighOrder()) + { + for (int e = 0; e < fe3d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe3d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe3d->GetEdgeOrder(e); k++, gindex++) + loc_edgecoefs.Append (edgecoeffs[gindex]); + } + + if (mesh.GetDimension() == 3) + for (int f = 0; f < fe3d->GetNFaces(); f++) + { + int gindex = facecoeffsindex[fe3d->GetFaceNr(f)-1]; + for (int k = 0; k < fe3d->GetNFaceShapes(f); k++, gindex++) + loc_facecoefs.Append (facecoeffs[gindex]); + } + } + + + + if (!dxdxi) + + for (int mp = 0; mp < size; mp++) + { + fe3d->SetReferencePoint ((*xi)[mp]); + fe3d->CalcVertexShapesOnly (); + + if (IsHighOrder()) + { + fe3d->CalcEdgeShapesOnly (); + if (mesh.GetDimension() == 3) + fe3d->CalcFaceShapes (); + } + + Point<3> hp (0,0,0); + for (int v = 0; v < fe3d->GetNVertices(); v++) + hp += fe3d->GetVertexShape(v) * vertices[v]; + for (int index = 0; index < loc_edgecoefs.Size(); index++) + hp += fe3d->GetEdgeShape(index) * loc_edgecoefs[index]; + for (int index = 0; index < loc_facecoefs.Size(); index++) + hp += fe3d->GetFaceShape(index) * loc_facecoefs[index]; // edgecoeffs[gindex]; + (*x)[mp] = hp; + } + + else + + for (int mp = 0; mp < size; mp++) + { + fe3d->SetReferencePoint ((*xi)[mp]); + fe3d->CalcVertexShapes (); + + if (IsHighOrder()) + { + fe3d->CalcEdgeShapes (); + if (mesh.GetDimension() == 3) + fe3d->CalcFaceShapes (); + } + + Point<3> hp (0,0,0); + for (int v = 0; v < fe3d->GetNVertices(); v++) + hp += fe3d->GetVertexShape(v) * vertices[v]; + for (int index = 0; index < loc_edgecoefs.Size(); index++) + hp += fe3d->GetEdgeShape(index) * loc_edgecoefs[index]; + for (int index = 0; index < loc_facecoefs.Size(); index++) + hp += fe3d->GetFaceShape(index) * loc_facecoefs[index]; // edgecoeffs[gindex]; + (*x)[mp] = hp; + + + for (int v = 0; v < fe3d->GetNVertices(); v++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)[mp](i,j) += fe3d->GetVertexDShape(v)(j) * vertices[v](i); + + for (int index = 0; index < loc_edgecoefs.Size(); index++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)[mp](i,j) += fe3d->GetEdgeDShape(index)(j) * loc_edgecoefs[index](i); + + for (int index = 0; index < loc_facecoefs.Size(); index++) + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + (*dxdxi)[mp](i,j) += fe3d->GetFaceDShape(index)(j) * loc_facecoefs[index](i); + } + + fe3d -> ~BaseFiniteElement3D(); + } + + + + /* + class Init + { + PolynomialBasis b; + public: + Init (); + }; + + Init :: Init() + { + ofstream edge("edge.out"); + b.SetOrder(10); + for (double x = 0; x <= 1; x += 0.01) + { + b.CalcFScaled(x, 1); + edge << x; + for (int j = 2; j <= 5; j++) + edge << " " << b.GetF(j); + edge << endl; + } + } + + Init in; + */ + +} // namespace netgen + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/curvedelems.hpp b/contrib/Netgen/libsrc/meshing/curvedelems.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5e621f6d338eb56e3e157165b8dcc5f3ab01d7d5 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/curvedelems.hpp @@ -0,0 +1,868 @@ +#ifndef CURVEDELEMS +#define CURVEDELEMS + +/**************************************************************************/ +/* File: curvedelems.hpp */ +/* Author: Robert Gaisbauer */ +/* Date: 27. Sep. 02 (second version: 30. Jan. 03) */ +/**************************************************************************/ + +#include "bisect.hpp" +#include <iostream> + +#define EPSILON 1e-20 + + + +void ComputeGaussRule (int n, ARRAY<double> & xi, ARRAY<double> & wi); + + + + + +// ---------------------------------------------------------------------------- +// CurvedElements +// ---------------------------------------------------------------------------- + +class CurvedElements +{ + const Mesh & mesh; + const MeshTopology & top; + + bool isHighOrder; + int nvisualsubsecs; + int nIntegrationPoints; + + ARRAY<int> edgeorder; + ARRAY<int> faceorder; + + /* + + ARRAY< Vec<3> > edgecoeffs; + ARRAY< Vec<3> > facecoeffs; + + ARRAY<int> edgecoeffsindex; + ARRAY<int> facecoeffsindex; + + */ + + inline Vec<3> GetEdgeCoeff (int edgenr, int k); + inline Vec<3> GetFaceCoeff (int facenr, int k); + + + void CalcSegmentTransformation (double xi, int segnr, + Point<3> * x = NULL, Vec<3> * dxdxi = NULL); + + void CalcSurfaceTransformation (Point<2> xi, int elnr, + Point<3> * x = NULL, Mat<3,2> * dxdxi = NULL); + + void CalcElementTransformation (Point<3> xi, int elnr, + Point<3> * x = NULL, Mat<3,3> * dxdxi = NULL); + + + +public: + + Refinement * refinement; + + ARRAY< Vec<3> > edgecoeffs; + ARRAY< Vec<3> > facecoeffs; + + ARRAY<int> edgecoeffsindex; + ARRAY<int> facecoeffsindex; + + + + + + CurvedElements (const Mesh & amesh); + ~CurvedElements(); + + bool IsHighOrder() const + { return isHighOrder; }; + void SetHighOrder () { isHighOrder = 1; } + + + int GetNVisualSubsecs() const + { return nvisualsubsecs; }; + + const class Mesh & GetMesh() const + { return mesh; }; + + void BuildCurvedElements(Refinement * ref, int polydeg, bool rational=false); + + int GetEdgeOrder (int edgenr) const + { return edgeorder[edgenr]; }; + + int GetFaceOrder (int facenr) const + { return faceorder[facenr]; }; + + int IsEdgeCurved (int edgenr) const; + + int IsFaceCurved (int facenr) const; + + int IsSurfaceElementCurved (int elnr) const; + + int IsElementCurved (int elnr) const; + + + void CalcSegmentTransformation (double xi, int segnr, + Point<3> & x) + { CalcSegmentTransformation (xi, segnr, &x, NULL); }; + + void CalcSegmentTransformation (double xi, int segnr, + Vec<3> & dxdxi) + { CalcSegmentTransformation (xi, segnr, NULL, &dxdxi); }; + + void CalcSegmentTransformation (double xi, int segnr, + Point<3> & x, Vec<3> & dxdxi) + { CalcSegmentTransformation (xi, segnr, &x, &dxdxi); }; + + + void CalcSurfaceTransformation (const Point<2> & xi, int elnr, + Point<3> & x) + { CalcSurfaceTransformation (xi, elnr, &x, NULL); }; + + void CalcSurfaceTransformation (const Point<2> & xi, int elnr, + Mat<3,2> & dxdxi) + { CalcSurfaceTransformation (xi, elnr, NULL, &dxdxi); }; + + void CalcSurfaceTransformation (const Point<2> & xi, int elnr, + Point<3> & x, Mat<3,2> & dxdxi) + { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi); }; + + + void CalcElementTransformation (const Point<3> & xi, int elnr, + Point<3> & x) + { CalcElementTransformation (xi, elnr, &x, NULL); }; + + void CalcElementTransformation (const Point<3> & xi, int elnr, + Mat<3,3> & dxdxi) + { CalcElementTransformation (xi, elnr, NULL, &dxdxi); }; + + void CalcElementTransformation (const Point<3> & xi, int elnr, + Point<3> & x, Mat<3,3> & dxdxi) + { CalcElementTransformation (xi, elnr, &x, &dxdxi); }; + + + + + void CalcMultiPointSegmentTransformation (ARRAY<double> * xi, int segnr, + ARRAY<Point<3> > * x, + ARRAY<Vec<3> > * dxdxi); + + void CalcMultiPointSurfaceTransformation (ARRAY< Point<2> > * xi, int elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,2> > * dxdxi); + + void CalcMultiPointElementTransformation (ARRAY< Point<3> > * xi, int elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,3> > * dxdxi); + +}; + + + +// ---------------------------------------------------------------------------- +// PolynomialBasis +// ---------------------------------------------------------------------------- + +class PolynomialBasis +{ + int order; + int maxorder; + ArrayMem<double,20> f; + ArrayMem<double,20> df; + ArrayMem<double,20> ddf; + + ArrayMem<double,20> lp; + ArrayMem<double,20> dlp; + + inline void CalcLegendrePolynomials (double x); + // P_i(x/t) t^i + inline void CalcScaledLegendrePolynomials (double x, double t); + inline void CalcDLegendrePolynomials (double x); + +public: + + PolynomialBasis () + { maxorder = -1; }; + + ~PolynomialBasis () + {}; + + void SetOrder (int aorder) + { + order = aorder; + if (order > maxorder) + { + maxorder = order; + f.SetSize(order-1); + df.SetSize(order-1); + ddf.SetSize(order-1); + lp.SetSize(order+1); + dlp.SetSize(order); + }; + }; + + inline void CalcF (double x); + inline void CalcDf (double x); + inline void CalcDDf (double x); + + inline void CalcFDf (double x); + + // compute F_i(x/t) t^i + inline void CalcFScaled (double x, double t); + static inline void CalcFScaled (int p, double x, double t, double * values); + + double GetF (int p) { return f[p-2]; }; + double GetDf (int p) { return df[p-2]; }; + double GetDDf (int p) { return ddf[p-2]; }; +}; + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement +// ---------------------------------------------------------------------------- + +template <int DIM> +class BaseFiniteElement +{ +protected: + + Point<DIM> xi; + int elnr; + const CurvedElements & curv; + const Mesh & mesh; + const MeshTopology & top; + +public: + + BaseFiniteElement(const CurvedElements & acurv) + : curv(acurv), mesh(curv.GetMesh()), top(mesh.GetTopology()) + {}; + + virtual ~BaseFiniteElement() + {}; + + void SetElementNumber (int aelnr) + { elnr = aelnr; }; // 1-based arrays in netgen + + virtual void SetReferencePoint (Point<DIM> axi) + { xi = axi; }; +}; + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement1D +// ---------------------------------------------------------------------------- + +class BaseFiniteElement1D : public BaseFiniteElement<1> +{ +protected: + PolynomialBasis b; + + int vertexnr[2]; + int edgenr; + int edgeorient; + int edgeorder; + + int maxedgeorder; + + double vshape[2]; + double vdshape[2]; + ArrayMem<double,20> eshape; + ArrayMem<double,20> edshape; + ArrayMem<double,20> eddshape; + +public: + + BaseFiniteElement1D (const CurvedElements & acurv) : BaseFiniteElement<1>(acurv) + { maxedgeorder = 1; }; + + virtual ~BaseFiniteElement1D() + {}; + + int GetVertexNr (int v) + { return vertexnr[v]; }; + + int GetEdgeNr () + { return edgenr; }; + + int GetEdgeOrder () + { return edgeorder; }; + + int GetEdgeOrientation () + { return edgeorient; }; + + void CalcVertexShapes(); + void CalcEdgeShapes(); + void CalcEdgeLaplaceShapes(); + + double GetVertexShape (int v) + { return vshape[v]; }; + + double GetEdgeShape (int index) + { return eshape[index]; }; + + double GetVertexDShape (int v) + { return vdshape[v]; }; + + double GetEdgeDShape (int index) + { return edshape[index]; }; + + double GetEdgeLaplaceShape (int index) + { return eddshape[index]; }; + +}; + + + + +// ---------------------------------------------------------------------------- +// FESegm +// ---------------------------------------------------------------------------- + +class FESegm : public BaseFiniteElement1D +{ + +public: + + FESegm(const CurvedElements & acurv) : BaseFiniteElement1D(acurv) + {}; + + virtual ~FESegm() + {}; + + void SetElementNumber (int aelnr) + { + BaseFiniteElement<1> :: SetElementNumber (aelnr); + Segment s = mesh.LineSegment(elnr); + vertexnr[0] = s.p1; + vertexnr[1] = s.p2; + edgenr = top.GetSegmentEdge(elnr); + edgeorient = top.GetSegmentEdgeOrientation(elnr); + edgeorder = curv.GetEdgeOrder(edgenr-1); // 1-based arrays in netgen + + if (edgeorder > maxedgeorder) + { + maxedgeorder = edgeorder; + eshape.SetSize(maxedgeorder-1); + edshape.SetSize(maxedgeorder-1); + eddshape.SetSize(maxedgeorder-1); + } + }; + +}; + + + +// ---------------------------------------------------------------------------- +// FEEdge +// ---------------------------------------------------------------------------- + +class FEEdge : public BaseFiniteElement1D +{ + +public: + + FEEdge(const CurvedElements & acurv) : BaseFiniteElement1D(acurv) + {}; + + virtual ~FEEdge() + {}; + + void SetElementNumber (int aelnr) + { + BaseFiniteElement<1> :: SetElementNumber (aelnr); + top.GetEdgeVertices (elnr, vertexnr[0], vertexnr[1]); + edgenr = elnr; + edgeorient = 1; + edgeorder = curv.GetEdgeOrder(edgenr-1); // 1-based arrays in netgen + + if (edgeorder > maxedgeorder) + { + maxedgeorder = edgeorder; + eshape.SetSize(maxedgeorder-1); + edshape.SetSize(maxedgeorder-1); + eddshape.SetSize(maxedgeorder-1); + } + }; + +}; + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement2D +// ---------------------------------------------------------------------------- + +class BaseFiniteElement2D : public BaseFiniteElement<2> +{ +protected: + + int nvertices; + int nedges; + + int vertexnr[4]; + int edgenr[4]; + int edgeorient[4]; + int edgeorder[4]; + int facenr; + int faceorient; + int faceorder; + + int nfaceshapes; + + int maxedgeorder; + int maxfaceorder; + + PolynomialBasis b1, b2; + + double vshape[4]; + Vec<2> vdshape[4]; + ArrayMem<double,80> eshape; + ArrayMem< Vec<2>,80> edshape; + ArrayMem<double,400> fshape; + ArrayMem<Vec<2>,400> fdshape; + ArrayMem<double,400> fddshape; + + virtual void CalcNFaceShapes () = 0; + +public: + + BaseFiniteElement2D (const CurvedElements & acurv) : BaseFiniteElement<2>(acurv) + { maxedgeorder = maxfaceorder = -1; }; + + virtual ~BaseFiniteElement2D() + {}; + + void SetElementNumber (int aelnr); + + virtual void SetVertexSingularity (int v, int exponent) = 0; + + int GetVertexNr (int v) + { return vertexnr[v]; }; + + int GetEdgeNr (int e) + { return edgenr[e]; }; + + int GetFaceNr () + { return facenr; }; + + int GetEdgeOrder (int e) + { return edgeorder[e]; }; + + int GetFaceOrder () + { return faceorder; } + + int GetNVertices () + { return nvertices; }; + + int GetNEdges () + { return nedges; }; + + int GetNFaceShapes () + { return nfaceshapes; }; + + int IsCurved () + { + bool iscurved = 0; + int e; + + for (e = 0; e < GetNEdges(); e++) + iscurved = iscurved || (GetEdgeOrder(e) > 1); + + return iscurved || (GetFaceOrder() > 1); + } + + virtual void CalcVertexShapes() = 0; + virtual void CalcEdgeShapes() = 0; + virtual void CalcFaceShapes() = 0; + + virtual void CalcFaceLaplaceShapes() = 0; + + double GetVertexShape (int v) + { return vshape[v]; }; + + double GetEdgeShape (int index) + { return eshape[index]; }; + + double GetFaceShape (int index) + { return fshape[index]; }; + + Vec<2> GetVertexDShape (int v) + { return vdshape[v]; }; + + Vec<2> GetEdgeDShape (int index) + { return edshape[index]; }; + + Vec<2> GetFaceDShape (int index) + { return fdshape[index]; }; + + double GetFaceLaplaceShape (int index) + { return fddshape[index]; }; +}; + + + +// ---------------------------------------------------------------------------- +// FETrig +// ---------------------------------------------------------------------------- + +class FETrig : public BaseFiniteElement2D +{ + Point<3> lambda; + Mat<3,2> dlambda; + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { nfaceshapes = ((faceorder-1)*(faceorder-2))/2; }; + +public: + + FETrig (const CurvedElements & acurv) : BaseFiniteElement2D(acurv) + { + nvertices = 3; + nedges = 3; + eledge = MeshTopology :: GetEdges (TRIG); + elface = MeshTopology :: GetFaces (TRIG); + }; + + virtual ~FETrig() + {}; + + virtual void SetReferencePoint (Point<2> axi); + + virtual void SetVertexSingularity (int v, int exponent); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); + + virtual void CalcFaceLaplaceShapes(); +}; + + + +// ---------------------------------------------------------------------------- +// FEQuad +// ---------------------------------------------------------------------------- + +class FEQuad : public BaseFiniteElement2D +{ + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { nfaceshapes = (faceorder-1)*(faceorder-1); }; + +public: + + FEQuad (const CurvedElements & acurv) : BaseFiniteElement2D(acurv) + { + nvertices = 4; + nedges = 4; + elface = MeshTopology :: GetFaces (QUAD); + }; + + virtual ~FEQuad() + {}; + + virtual void SetVertexSingularity (int /* v */, int /* exponent */) + {}; + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); + + virtual void CalcFaceLaplaceShapes(); +}; + + + + +// ---------------------------------------------------------------------------- +// BaseFiniteElement3D +// ---------------------------------------------------------------------------- + +class BaseFiniteElement3D : public BaseFiniteElement<3> +{ +protected: + + int nvertices; + int nedges; + int nfaces; + + int vertexnr[8]; + int edgenr[12]; + int edgeorient[12]; + int edgeorder[12]; + int facenr[6]; + int faceorient[6]; + int faceorder[6]; + int surfacenr[6]; + // int surfaceorient[6]; + + int nfaceshapes[6]; + + int maxedgeorder; + int maxfaceorder; + + PolynomialBasis b1, b2; + + double vshape[8]; + Vec<3> vdshape[8]; + ArrayMem<double,120> eshape; + ArrayMem<Vec<3>,120> edshape; + ArrayMem<double,300> fshape; + ArrayMem<Vec<3>,300> fdshape; + + virtual void CalcNFaceShapes () = 0; + +public: + + int locmaxedgeorder; + int locmaxfaceorder; + + BaseFiniteElement3D (const CurvedElements & acurv) : BaseFiniteElement<3>(acurv) + { maxedgeorder = maxfaceorder = -1; }; + + void SetElementNumber (int aelnr); + + int GetVertexNr (int v) + { return vertexnr[v]; }; + + int GetEdgeNr (int e) + { return edgenr[e]; }; + + int GetFaceNr (int f) + { return facenr[f]; }; + + int GetNFaceShapes (int f) + { return nfaceshapes[f]; }; + + int GetEdgeOrder (int e) + { return edgeorder[e]; }; + + int GetFaceOrder (int f) + { return faceorder[f]; }; + + int GetNVertices () + { return nvertices; }; + + int GetNEdges () + { return nedges; }; + + int GetNFaces () + { return nfaces; }; + + int IsCurved () + { + bool iscurved = 0; + int e, f; + + for (e = 0; e < GetNEdges(); e++) + iscurved = iscurved || (GetEdgeOrder(e) > 1); + + for (f = 0; f < GetNFaces(); f++) + iscurved = iscurved || (GetFaceOrder(f) > 1); + + return iscurved; + } + + virtual void CalcVertexShapes() = 0; + virtual void CalcVertexShapesOnly() + { CalcVertexShapes(); } + + virtual void CalcEdgeShapes() = 0; + virtual void CalcEdgeShapesOnly() + { CalcEdgeShapes(); } + + virtual void CalcFaceShapes() = 0; + + double GetVertexShape (int v) + { return vshape[v]; }; + + double GetEdgeShape (int index) + { return eshape[index]; }; + + double GetFaceShape (int index) + { return fshape[index]; }; + + Vec<3> GetVertexDShape (int v) + { return vdshape[v]; }; + + Vec<3> GetEdgeDShape (int index) + { return edshape[index]; }; + + Vec<3> GetFaceDShape (int index) + { return fdshape[index]; }; +}; + + + +// ---------------------------------------------------------------------------- +// FETet +// ---------------------------------------------------------------------------- + +class FETet : public BaseFiniteElement3D +{ + Point<4> lambda; + Mat<4,3> dlambda; + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + for (int f = 0; f < nfaces; f++) + nfaceshapes[f] = ((faceorder[f]-1)*(faceorder[f]-2))/2; + }; + +public: + + FETet (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 4; + nedges = 6; + nfaces = 4; + eledge = MeshTopology :: GetEdges (TET); + elface = MeshTopology :: GetFaces (TET); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcVertexShapesOnly(); + virtual void CalcEdgeShapes(); + virtual void CalcEdgeShapesOnly(); + virtual void CalcFaceShapes(); +}; + + + +// ---------------------------------------------------------------------------- +// FEPrism +// ---------------------------------------------------------------------------- + +class FEPrism : public BaseFiniteElement3D +{ + Point<4> lambda; // mixed barycentric coordinates + Mat<4,3> dlambda; + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + int f; + for (f = 0; f < 2; f++) + nfaceshapes[f] = ((faceorder[f]-1)*(faceorder[f]-2))/2; + for (f = 2; f < nfaces; f++) + nfaceshapes[f] = (faceorder[f]-1)*(faceorder[f]-1); + }; + +public: + + FEPrism (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 6; + nedges = 9; + nfaces = 5; + eledge = MeshTopology :: GetEdges (PRISM); + elface = MeshTopology :: GetFaces (PRISM); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); +}; + + + + +// ---------------------------------------------------------------------------- +// FEPyramid +// ---------------------------------------------------------------------------- + +class FEPyramid : public BaseFiniteElement3D +{ + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + int f; + for (f = 0; f < 4; f++) + nfaceshapes[f] = ((faceorder[f]-1)*(faceorder[f]-2))/2; + for (f = 4; f < nfaces; f++) + nfaceshapes[f] = (faceorder[f]-1)*(faceorder[f]-1); + }; + +public: + + FEPyramid (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 5; + nedges = 8; + nfaces = 5; + eledge = MeshTopology :: GetEdges (PYRAMID); + elface = MeshTopology :: GetFaces (PYRAMID); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); +}; + + + + +// ---------------------------------------------------------------------------- +// FEHex +// ---------------------------------------------------------------------------- + +class FEHex : public BaseFiniteElement3D +{ + + const ELEMENT_EDGE * eledge; + const ELEMENT_FACE * elface; + + virtual void CalcNFaceShapes () + { + int f; + for (f = 0; f < 6; f++) + nfaceshapes[f] = (faceorder[f]-1)*(faceorder[f]-1); + }; + +public: + + FEHex (const CurvedElements & acurv) : BaseFiniteElement3D(acurv) + { + nvertices = 8; + nedges = 12; + nfaces = 6; + eledge = MeshTopology :: GetEdges (HEX); + elface = MeshTopology :: GetFaces (HEX); + }; + + void SetReferencePoint (Point<3> axi); + + virtual void CalcVertexShapes(); + virtual void CalcEdgeShapes(); + virtual void CalcFaceShapes(); +}; + + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/curvedelems2.cpp b/contrib/Netgen/libsrc/meshing/curvedelems2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b44b19e5f6c972b371d0ad675b21fd63cbcd5ff --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/curvedelems2.cpp @@ -0,0 +1,758 @@ + +#include <mystdlib.h> + +#include "meshing.hpp" +#ifndef CURVEDELEMS_NEW + +namespace netgen +{ + + +// ---------------------------------------------------------------------------- +// CurvedElements +// ---------------------------------------------------------------------------- + + CurvedElements :: CurvedElements (const Mesh & amesh) + : mesh(amesh), top(mesh.GetTopology()) + { + isHighOrder = 0; + nvisualsubsecs = 2; + nIntegrationPoints = 10; + } + + + CurvedElements :: ~CurvedElements () + { + ; + } + + + void CurvedElements :: BuildCurvedElements(Refinement * ref, int polydeg, bool rational) + { + if (mesh.coarsemesh) + { + mesh.coarsemesh->GetCurvedElements().BuildCurvedElements (ref, polydeg, rational); + SetHighOrder(); + return; + } + + PrintMessage (2, "Build curved elements, order = ", polydeg); + + NgLock lock(const_cast<Mesh&>(mesh).Mutex(), 1); + isHighOrder = 0; + lock.UnLock(); + + const_cast<Mesh &>(mesh).UpdateTopology(); + + // set order of edges and faces + + BaseFiniteElement2D * fe2d; + + FEEdge edge (*this); + FESegm segm (*this); + FETrig trig (*this); + FEQuad quad (*this); + + int i, k, e, f; + + ARRAY<bool> edgedone; + + edgedone.SetSize (top.GetNEdges()); + + edgeorder.SetSize (top.GetNEdges()); + faceorder.SetSize (top.GetNFaces()); + + int nedgestocurve = mesh.GetNSeg(); + + edgedone = 0; + edgeorder = 1; + faceorder = 1; + + if (polydeg == 1) + { + isHighOrder = 0; + return; + } + + + /* + for (e = 0; e < top.GetNEdges(); e++) + { + edgedone = 0; + edgeorder[e] = 1; + } + + for (f = 0; f < top.GetNFaces(); f++) + faceorder[f] = 1; + */ + + for (i = 1; i <= mesh.GetNSeg(); i++) + edgeorder[top.GetSegmentEdge(i)-1] = polydeg; + + + if (mesh.GetDimension() == 3) + { + for (i = 1; i <= mesh.GetNSE(); i++) + { + faceorder[top.GetSurfaceElementFace(i)-1] = polydeg; + + Element2d elem = mesh[(SurfaceElementIndex) (i-1)]; + + ARRAY<int> edgenrs; + top.GetSurfaceElementEdges(i, edgenrs); + + nedgestocurve += top.GetNEdges(elem.GetType()); + + for (int e = 0; e < top.GetNEdges(elem.GetType()); e++) + edgeorder[edgenrs[e]-1] = polydeg; + } + } + + + PrintMessage (1, "Building curved elements, order = ", polydeg); + PushStatusF ("curving edges"); + + + + // set edgecoeffs and facecoeffs arrays index and size + + edgecoeffsindex.SetSize (top.GetNEdges()+1); + facecoeffsindex.SetSize (top.GetNFaces()+1); + + edgecoeffsindex[0] = 0; + for (e = 2; e <= top.GetNEdges()+1; e++) + edgecoeffsindex[e-1] = edgecoeffsindex[e-2] + edgeorder[e-2]-1; + + facecoeffsindex[0] = 0; + for (f = 2; f <= top.GetNFaces()+1; f++) + { + switch (top.GetFaceType (f-1)) + { + case TRIG: + facecoeffsindex[f-1] = facecoeffsindex[f-2] + + (faceorder[f-2]-1)*(faceorder[f-2]-2)/2; + break; + case QUAD: + facecoeffsindex[f-1] = facecoeffsindex[f-2] + + (faceorder[f-2]-1)*(faceorder[f-2]-1); + break; + } + } + + edgecoeffs.SetSize(edgecoeffsindex[top.GetNEdges()]); + facecoeffs.SetSize(facecoeffsindex[top.GetNFaces()]); + + + + // evaluate edge points + + PointGeomInfo newgi; // dummy variable, only needed for function call + EdgePointGeomInfo newepgi; // dummy variable, only needed for function call + Point3d xexact; // new point to be stored in ARRAY edgepts + + ARRAY<double> xi, wi; + ComputeGaussRule(nIntegrationPoints, xi, wi); + + for (i=0; i<edgecoeffsindex[top.GetNEdges()]; i++) + edgecoeffs[i] = Vec<3>(0.,0.,0.); + + + + + // all edges belonging to segments + + for (i=0; i<mesh.GetNSeg(); i++) + { + if (multithread.terminate) return; + + SetThreadPercent( double(100*i/nedgestocurve) ); + + int edgenr = top.GetSegmentEdge(i+1); + + if (edgedone[edgenr-1]) continue; + + edgedone[edgenr-1] = 1; + + Segment s = mesh.LineSegment(i+1); + + segm.SetElementNumber (i+1); + + for (k = 2; k <= segm.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenr-1]+k-2] = Vec<3>(0.,0.,0.); + + for (int l = 0; l < nIntegrationPoints; l++) + { + segm.SetReferencePoint (Point<1>(xi[l])); + segm.CalcVertexShapes (); + segm.CalcEdgeLaplaceShapes (); + + Point<3> xv(0,0,0); + + for (int v = 0; v < 2; v++) + xv = xv + segm.GetVertexShape(v) * mesh.Point(segm.GetVertexNr(v)); + + double secpoint = xi[l]; + + ref->PointBetween (mesh.Point(segm.GetVertexNr(1)), + mesh.Point(segm.GetVertexNr(0)), secpoint, + s.surfnr2, s.surfnr1, + s.epgeominfo[1], s.epgeominfo[0], + xexact, newepgi); + + for (int k = 2; k <= segm.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenr-1]+k-2] -= + wi[l] * segm.GetEdgeLaplaceShape(k-2) * Vec<3>(xexact - xv); + + } + + for (k = 2; k <= segm.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenr-1]+k-2] = + (2.0*(k-1.0)+1.0)*edgecoeffs[edgecoeffsindex[edgenr-1]+k-2]; + + } + + + + + + // all edges belonging to surface elements + + if (mesh.GetDimension() == 3) + { + int nedgescurved = mesh.GetNSeg(); + for (int i=0; i<mesh.GetNSE(); i++) + { + if (multithread.terminate) return; + + // SetThreadPercent( double(100*(mesh.GetNSeg()+i)/nedgestocurve) ); + Element2d elem = mesh[(SurfaceElementIndex) i]; + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges(elem.GetType()); + + ARRAY<int> edgenrs; + ARRAY<int> orient; + top.GetSurfaceElementEdges(i+1, edgenrs); + top.GetSurfaceElementEdgeOrientations(i+1, orient); + + for (int e = 0; e < top.GetNEdges(elem.GetType()); e++) + { +// cout << "e = " << e << "/" << top.GetNEdges(elem.GetType()) << endl; + + nedgescurved++; + + if (edgedone[edgenrs[e]-1]) continue; + + edgedone[edgenrs[e]-1] = 1; + + SetThreadPercent( double(100*(nedgescurved)/nedgestocurve) ); + + edge.SetElementNumber (edgenrs[e]); + + for (k = 2; k <= edge.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2] = Vec<3>(0.,0.,0.); + + for (int l = 0; l < nIntegrationPoints; l++) + { +// cout << "." << flush; + edge.SetReferencePoint (Point<1>(xi[l])); + edge.CalcVertexShapes (); + edge.CalcEdgeLaplaceShapes (); + + Point<3> xv(0,0,0); + for (int v = 0; v < 2; v++) + xv = xv + edge.GetVertexShape(v) * mesh.Point(edge.GetVertexNr(v)); + + double secpoint = xi[l]; + + if (orient[e] == 1) + ref->PointBetween (mesh.Point(edge.GetVertexNr(1)), + mesh.Point(edge.GetVertexNr(0)), secpoint, + mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr(), + elem.GeomInfoPi(eledges[e][1]), + elem.GeomInfoPi(eledges[e][0]), + xexact, newgi); + else + ref->PointBetween (mesh.Point(edge.GetVertexNr(1)), + mesh.Point(edge.GetVertexNr(0)), secpoint, + mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr(), + elem.GeomInfoPi(eledges[e][0]), + elem.GeomInfoPi(eledges[e][1]), + xexact, newgi); + + for (k = 2; k <= edge.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2] -= + wi[l] * edge.GetEdgeLaplaceShape(k-2) * Vec<3>(xexact - xv); + } +// cout << endl; + for (k = 2; k <= edge.GetEdgeOrder(); k++) + edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2] = + (2.0*(k-1.0)+1.0)*edgecoeffs[edgecoeffsindex[edgenrs[e]-1]+k-2]; + + } + } + } + + + + +/* + + // L2-Projection for edges + + + cout << "WARNING: L2-Projection for edges" << endl; + + if (mesh.GetDimension() == 3) + { + for (int i=0; i<mesh.GetNSE(); i++) + { + Element2d elem = mesh[(SurfaceElementIndex) i]; + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges(elem.GetType()); + + ARRAY<int> edgenrs; + ARRAY<int> orient; + top.GetSurfaceElementEdges(i+1, edgenrs); + top.GetSurfaceElementEdgeOrientations(i+1, orient); + + for (int e = 0; e < top.GetNEdges(elem.GetType()); e++) + { + edge.SetElementNumber (edgenrs[e]); + + int npoints = edge.GetEdgeOrder()-1; + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int l = 0; l < nIntegrationPoints; l++) + { + double w = wi[l]; + + edge.SetReferencePoint (Point<1>(xi[l])); + edge.CalcVertexShapes (); + edge.CalcEdgeShapes (); + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, mat.Get(n+1,m+1) + + edge.GetEdgeShape(n) * edge.GetEdgeShape(m) * w); + + Point<3> xv(0,0,0); + for (int v = 0; v < 2; v++) + xv = xv + edge.GetVertexShape(v) * mesh.Point(edge.GetVertexNr(v)); + + double secpoint = xi[l]; + + ref->PointBetween (mesh.Point(edge.GetVertexNr(1)), + mesh.Point(edge.GetVertexNr(0)), secpoint, + mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr(), + elem.GeomInfoPi(eledges[e][1]), + elem.GeomInfoPi(eledges[e][0]), + xexact, newgi); + + for (int k = 2; k <= edge.GetEdgeOrder(); k++) + { + vec[0].Set(k-1, vec[0].Get(k-1) + Vec<3>(xexact - xv)(0)*edge.GetEdgeShape(k-2)*w ); + vec[1].Set(k-1, vec[1].Get(k-1) + Vec<3>(xexact - xv)(1)*edge.GetEdgeShape(k-2)*w ); + vec[2].Set(k-1, vec[2].Get(k-1) + Vec<3>(xexact - xv)(2)*edge.GetEdgeShape(k-2)*w ); + } + + } + + + CalcInverse(mat,inv); + + Vector a0, a1, a2; + + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + + int index = edgecoeffsindex[edge.GetEdgeNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + edgecoeffs[index] = Vec<3>(a0(n+1), a1(n+1), a2(n+1)); + } + } + } + + + for (int i=0; i<mesh.GetNSeg(); i++) + { + int edgenr = top.GetSegmentEdge(i+1); + + Segment s = mesh.LineSegment(i+1); + + segm.SetElementNumber (i+1); + + int npoints = segm.GetEdgeOrder()-1; + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int l = 0; l < nIntegrationPoints; l++) + { + double w = wi[l]; + + segm.SetReferencePoint (Point<1>(xi[l])); + segm.CalcVertexShapes (); + segm.CalcEdgeShapes (); + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, mat.Get(n+1,m+1) + + segm.GetEdgeShape(n) * segm.GetEdgeShape(m) * w); + + Point<3> xv(0,0,0); + for (int v = 0; v < 2; v++) + xv = xv + segm.GetVertexShape(v) * mesh.Point(segm.GetVertexNr(v)); + + double secpoint = xi[l]; + + if (segm.GetEdgeOrientation() == -1) secpoint = 1. - secpoint; // reverse orientation + + ref->PointBetween (mesh.Point(segm.GetVertexNr(1)), + mesh.Point(segm.GetVertexNr(0)), secpoint, + s.surfnr2, s.surfnr1, + s.epgeominfo[1], s.epgeominfo[0], + xexact, newepgi); + + for (int k = 2; k <= segm.GetEdgeOrder(); k++) + { + vec[0].Set(k-1, vec[0].Get(k-1) + Vec<3>(xexact - xv)(0)*segm.GetEdgeShape(k-2)*w ); + vec[1].Set(k-1, vec[1].Get(k-1) + Vec<3>(xexact - xv)(1)*segm.GetEdgeShape(k-2)*w ); + vec[2].Set(k-1, vec[2].Get(k-1) + Vec<3>(xexact - xv)(2)*segm.GetEdgeShape(k-2)*w ); + } + + } + + + CalcInverse(mat,inv); + + Vector a0, a1, a2; + + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + + int index = edgecoeffsindex[segm.GetEdgeNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + edgecoeffs[index] = Vec<3>(a0(n+1), a1(n+1), a2(n+1)); + + + + } + +*/ + + + + + + // evaluate face points + + if (mesh.GetDimension() == 3) + { + PopStatus (); + PushStatusF ("curving faces"); + + for (int j=0; j<facecoeffsindex[top.GetNFaces()]; j++) + facecoeffs[j] = Vec<3>(0.,0.,0.); + + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) // for all surface elements + { + if (multithread.terminate) return; + + SetThreadPercent( double(100*i/mesh.GetNSE()) ); + + Element2d elem = mesh[i]; + + if (elem.GetType() == TRIG) + fe2d = &trig; + else + fe2d = &quad; + + fe2d->SetElementNumber (i+1); + + int npoints = fe2d->GetNFaceShapes(); + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int j = 0; j < nIntegrationPoints; j++) + { + for (int k = 0; k < nIntegrationPoints; k++) + { + double w; + Point<2> xr; + + if (elem.GetType() == TRIG) + { + w = wi[j]*wi[k]*(1-xi[j]); + xr = Point<2> (xi[j], xi[k]*(1-xi[j])); + } + else + { + w = wi[j]*wi[k]; + xr = Point<2> (xi[j], xi[k]); + } + + fe2d->SetReferencePoint (xr); + fe2d->CalcFaceShapes (); + fe2d->CalcVertexShapes (); + fe2d->CalcEdgeShapes (); + fe2d->CalcFaceLaplaceShapes (); + + // integration over the product of the gradients of the face shapes + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, + mat.Get(n+1,m+1) + + fe2d->GetFaceDShape(n)*fe2d->GetFaceDShape(m)*w); + + // integration over the difference between the exact geometry and the one + // defined by vertex and edge shape functions times face shape + + // double giu = 0, giv = 0; + PointGeomInfo gi; + gi.trignum = elem.GeomInfoPi(1).trignum; + gi.u = 0.0; + gi.v = 0.0; + Point<3> xve(0.,0.,0.); + + // vertex shape functions + for (int v = 0; v < fe2d->GetNVertices(); v++) + { + xve = xve + fe2d->GetVertexShape(v) * mesh.Point(fe2d->GetVertexNr(v)); + gi.u += fe2d->GetVertexShape(v) * elem.GeomInfoPi(v+1).u; + gi.v += fe2d->GetVertexShape(v) * elem.GeomInfoPi(v+1).v; + } + + // edge shape functions + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + xve = xve + fe2d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + + // exact point + + Point<3> xexact = xve; + ref->ProjectToSurface (xexact, mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr(), gi); + + Vec<3> v2 = w*(Vec<3>(xexact)-Vec<3>(xve)); + + for (int k = 0; k < 3; k++) + for (int n = 0; n < npoints; n++) + vec[k].Set(n+1, vec[k].Get(n+1) - fe2d->GetFaceLaplaceShape(n)*v2(k)); + } + } + + CalcInverse(mat,inv); + + Vector a0(npoints), a1(npoints), a2(npoints); + + /* + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + */ + inv.Mult (vec[0], a0); + inv.Mult (vec[1], a1); + inv.Mult (vec[2], a2); + + int index = facecoeffsindex[fe2d->GetFaceNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + facecoeffs[index] = Vec<3>(a0.Elem(n+1), a1.Elem(n+1), a2.Elem(n+1)); + } + } + + + + +/* + cout << "WARNING: L2-Projection for faces" << endl; + + // evaluate face points + + if (mesh.GetDimension() == 3) + { + for (int i=0; i<facecoeffsindex[top.GetNFaces()]; i++) + facecoeffs[i] = Vec<3>(0.,0.,0.); + + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) // for all surface elements + { + Element2d elem = mesh[i]; + + if (elem.GetType() == TRIG) + fe2d = &trig; + else + fe2d = &quad; + + fe2d->SetElementNumber (i+1); + + int npoints = fe2d->GetNFaceShapes(); + + if (npoints == 0) continue; + + DenseMatrix mat(npoints); + DenseMatrix inv(npoints); + Vector vec[3]; + + for (int k = 0; k < 3; k++) + { + vec[k].SetSize(npoints); + for (int n = 1; n <= npoints; n++) vec[k].Set(n, 0.); + } + + for (int j = 0; j < nIntegrationPoints; j++) + { + for (int k = 0; k < nIntegrationPoints; k++) + { + double w; + Point<2> xr; + + if (elem.GetType() == TRIG) + { + w = wi[j]*wi[k]*(1-xi[j]); + xr = Point<2> (xi[j], xi[k]*(1-xi[j])); + } + else + { + w = wi[j]*wi[k]; + xr = Point<2> (xi[j], xi[k]); + } + + fe2d->SetReferencePoint (xr); +// fe2d->CalcFaceDShape (false, true); + fe2d->CalcFaceShapes (); + + // integration over the product of the gradients of the face shapes + + for (int n = 0; n < npoints; n++) + for (int m = 0; m < npoints; m++) + mat.Set(n+1, m+1, mat.Get(n+1,m+1) + + fe2d->GetFaceShape(n)*fe2d->GetFaceShape(m)*w); + + // integration over the difference between the exact geometry and the one + // defined by vertex and edge shape functions times face shape + + Point<3> xve(0.,0.,0.); + + // vertex shape functions + fe2d->CalcVertexShapes (); +// fe2d->CalcVertexShape (true, false); + for (int v = 0; v < fe2d->GetNVertices(); v++) + xve = xve + fe2d->GetVertexShape(v) * mesh.Point(fe2d->GetVertexNr(v)); + + // edge shape functions +// fe2d->CalcEdgeShape (true, false); + fe2d->CalcEdgeShapes (); + + int index = 0; + for (int e = 0; e < fe2d->GetNEdges(); e++) + { + int gindex = edgecoeffsindex[fe2d->GetEdgeNr(e)-1]; + + for (int k = 2; k <= fe2d->GetEdgeOrder(e); k++, index++, gindex++) + xve = xve + fe2d->GetEdgeShape(index) * edgecoeffs[gindex]; + } + + // exact point + + Point<3> xexact = xve; + ref->ProjectToSurface (xexact, mesh.GetFaceDescriptor(elem.GetIndex()).SurfNr()); + + Vec<3> v = w*(Vec<3>(xexact)-Vec<3>(xve)); + + fe2d->CalcFaceLaplaceShapes (); + + for (int k = 0; k < 3; k++) + for (int n = 0; n < npoints; n++) + vec[k].Set(n+1, vec[k].Get(n+1) + fe2d->GetFaceShape(n)*v(k)); + } + } + + CalcInverse(mat,inv); + + Vector a0, a1, a2; + + a0 = inv*vec[0]; + a1 = inv*vec[1]; + a2 = inv*vec[2]; + + int index = facecoeffsindex[fe2d->GetFaceNr()-1]; + + for (int n = 0; n < npoints; n++, index++) + facecoeffs[index] = Vec<3>(a0(n+1), a1(n+1), a2(n+1)); + } + } +*/ + + + PrintMessage (5, "reducing order"); + + for (e = 0; e < top.GetNEdges(); e++) + if (edgeorder[e] > 1) + { + int i; + double maxcoeff = 0.; + + for (i = edgecoeffsindex[e]; i < edgecoeffsindex[e+1]; i++) + maxcoeff = max2 (maxcoeff, edgecoeffs[i].Length()); + + if (maxcoeff < 1e-12) edgeorder[e] = 1; + } + + for (f = 0; f < top.GetNFaces(); f++) + if (faceorder[f] > 1) + { + int i; + double maxcoeff = 0.; + + for (i = facecoeffsindex[f]; i < facecoeffsindex[f+1]; i++) + maxcoeff = max (maxcoeff, facecoeffs[i].Length()); + + if (maxcoeff < 1e-12) faceorder[f] = 1; + } + + isHighOrder = 1; // true + + PrintMessage(1, "done"); + PopStatus(); + // cout << "finished" << endl; + } + +} // namespace netgen + +#endif diff --git a/contrib/Netgen/libsrc/meshing/curvedelems_new.cpp b/contrib/Netgen/libsrc/meshing/curvedelems_new.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26580bf73b27a4626cf0cab3a4f0140ed0a9b175 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/curvedelems_new.cpp @@ -0,0 +1,2820 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#ifdef CURVEDELEMS_NEW + +namespace netgen +{ + + // bool rational = true; + + + + static void ComputeGaussRule (int n, ARRAY<double> & xi, ARRAY<double> & wi) + { + xi.SetSize (n); + wi.SetSize (n); + + int m = (n+1)/2; + double p1, p2, p3; + double pp, z, z1; + for (int i = 1; i <= m; i++) + { + z = cos ( M_PI * (i - 0.25) / (n + 0.5)); + while(1) + { + p1 = 1; p2 = 0; + for (int j = 1; j <= n; j++) + { + p3 = p2; p2 = p1; + p1 = ((2 * j - 1) * z * p2 - (j - 1) * p3) / j; + } + // p1 is legendre polynomial + + pp = n * (z*p1-p2) / (z*z - 1); + z1 = z; + z = z1-p1/pp; + + if (fabs (z - z1) < 1e-14) break; + } + + xi[i-1] = 0.5 * (1 - z); + xi[n-i] = 0.5 * (1 + z); + wi[i-1] = wi[n-i] = 1.0 / ( (1 - z * z) * pp * pp); + } + } + + + + // compute edge bubbles up to order n, x \in (-1, 1) + static void CalcEdgeShape (int n, double x, double * shape) + { + double p1 = x, p2 = -1, p3 = 0; + for (int j=2; j<=n; j++) + { + p3=p2; p2=p1; + p1=( (2*j-3) * x * p2 - (j-3) * p3) / j; + shape[j-2] = p1; + } + } + + static void CalcEdgeDx (int n, double x, double * dshape) + { + double p1 = x, p2 = -1, p3 = 0; + double p1dx = 1, p2dx = 0, p3dx = 0; + + for (int j=2; j<=n; j++) + { + p3=p2; p2=p1; + p3dx = p2dx; p2dx = p1dx; + + p1=( (2*j-3) * x * p2 - (j-3) * p3) / j; + p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j; + + dshape[j-2] = p1dx; + } + } + + static void CalcEdgeShapeDx (int n, double x, double * shape, double * dshape) + { + double p1 = x, p2 = -1, p3 = 0; + double p1dx = 1, p2dx = 0, p3dx = 0; + + for (int j=2; j<=n; j++) + { + p3=p2; p2=p1; + p3dx = p2dx; p2dx = p1dx; + + p1=( (2*j-3) * x * p2 - (j-3) * p3) / j; + p1dx = ( (2*j-3) * (x * p2dx + p2) - (j-3) * p3dx) / j; + + shape[j-2] = p1; + dshape[j-2] = p1dx; + } + } + + // compute L_i(x/t) * t^i + static void CalcScaledEdgeShape (int n, double x, double t, double * shape) + { + double p1 = x, p2 = -1, p3 = 0; + for (int j=0; j<=n-2; j++) + { + p3=p2; p2=p1; + p1=( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2); + shape[j] = p1; + } + } + + template <int DIST> + static void CalcScaledEdgeShapeDxDt (int n, double x, double t, double * dshape) + { + double p1 = x, p2 = -1, p3 = 0; + double p1dx = 1, p1dt = 0; + double p2dx = 0, p2dt = 0; + double p3dx = 0, p3dt = 0; + + for (int j=0; j<=n-2; j++) + { + p3=p2; p3dx=p2dx; p3dt = p2dt; + p2=p1; p2dx=p1dx; p2dt = p1dt; + + p1 = ( (2*j+1) * x * p2 - t*t*(j-1) * p3) / (j+2); + p1dx = ( (2*j+1) * (x * p2dx + p2) - t*t*(j-1) * p3dx) / (j+2); + p1dt = ( (2*j+1) * x * p2dt - (j-1)* (t*t*p3dt+2*t*p3)) / (j+2); + + // shape[j] = p1; + dshape[DIST*j ] = p1dx; + dshape[DIST*j+1] = p1dt; + } + } + + + static void LegendrePolynomial (int n, double x, double * values) + { + switch (n) + { + case 0: + values[0] = 1; + break; + case 1: + values[0] = 1; + values[1] = x; + break; + + default: + + if (n < 0) return; + + double p1 = 1.0, p2 = 0.0, p3; + + values[0] = 1.0; + for (int j=1; j<=n; j++) + { + p3 = p2; p2 = p1; + p1 = ((2.0*j-1.0)*x*p2 - (j-1.0)*p3) / j; + values[j] = p1; + } + } + } + + + static void ScaledLegendrePolynomial (int n, double x, double t, double * values) + { + switch (n) + { + case 0: + values[0] = 1; + break; + + case 1: + values[0] = 1; + values[1] = x; + break; + + default: + + if (n < 0) return; + + double p1 = 1.0, p2 = 0.0, p3; + values[0] = 1.0; + for (int j=1; j<=n; j++) + { + p3 = p2; p2 = p1; + p1 = ((2.0*j-1.0)*x*p2 - t*t*(j-1.0)*p3) / j; + values[j] = p1; + } + } + } + + + // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 + static void CalcTrigShape (int n, double x, double y, double * shape) + { + if (n < 3) return; + double hx[20], hy[20]; + ScaledLegendrePolynomial (n-3, 2*x-1, 1-y, hx); + LegendrePolynomial (n-3, 2*y-1, hy); + + int ii = 0; + double bub = (1+x-y)*y*(1-x-y); + for (int iy = 0; iy <= n-3; iy++) + for (int ix = 0; ix <= n-3-iy; ix++) + shape[ii++] = bub * hx[ix]*hy[iy]; + } + + static void CalcTrigShapeDxDy (int n, double x, double y, double * dshape) + { + if (n < 3) return; + + int ndof = (n-1)*(n-2)/2; + double h1[20], h2[20]; + double eps = 1e-4; + + CalcTrigShape (n, x+eps, y, h1); + CalcTrigShape (n, x-eps, y, h2); + + for (int i = 0; i < ndof; i++) + dshape[2*i] = (h1[i]-h2[i])/(2*eps); + + CalcTrigShape (n, x, y+eps, h1); + CalcTrigShape (n, x, y-eps, h2); + + for (int i = 0; i < ndof; i++) + dshape[2*i+1] = (h1[i]-h2[i])/(2*eps); + } + + + // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 + static void CalcScaledTrigShape (int n, double x, double y, double t, double * shape) + { + if (n < 3) return; + + double hx[20], hy[20]; + ScaledLegendrePolynomial (n-3, (2*x-1), t-y, hx); + ScaledLegendrePolynomial (n-3, (2*y-1), t, hy); + + int ii = 0; + double bub = (t+x-y)*y*(t-x-y); + for (int iy = 0; iy <= n-3; iy++) + for (int ix = 0; ix <= n-3-iy; ix++) + shape[ii++] = bub * hx[ix]*hy[iy]; + } + + + // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 + static void CalcScaledTrigShapeDxDyDt (int n, double x, double y, double t, double * dshape) + { + if (n < 3) return; + double hvl[100], hvr[100]; + int nd = (n-1)*(n-2)/2; + + double eps = 1e-6; + + CalcScaledTrigShape (n, x-eps, y, t, hvl); + CalcScaledTrigShape (n, x+eps, y, t, hvr); + for (int i = 0; i < nd; i++) + dshape[3*i] = (hvr[i]-hvl[i])/(2*eps); + + CalcScaledTrigShape (n, x, y-eps, t, hvl); + CalcScaledTrigShape (n, x, y+eps, t, hvr); + for (int i = 0; i < nd; i++) + dshape[3*i+1] = (hvr[i]-hvl[i])/(2*eps); + + CalcScaledTrigShape (n, x, y, t-eps, hvl); + CalcScaledTrigShape (n, x, y, t+eps, hvr); + for (int i = 0; i < nd; i++) + dshape[3*i+2] = (hvr[i]-hvl[i])/(2*eps); + } + + + + + + CurvedElements :: CurvedElements (const Mesh & amesh) + : mesh (amesh) + { + order = 1; + rational = 0; + } + + + CurvedElements :: ~CurvedElements() + { + ; + } + + + void CurvedElements :: BuildCurvedElements(Refinement * ref, int aorder, + bool arational) + { + if (mesh.coarsemesh) + { + mesh.coarsemesh->GetCurvedElements().BuildCurvedElements (ref, aorder, arational); + order = aorder; + rational = arational; + return; + } + + PrintMessage (1, "Curve elements, order = ", aorder); + if (rational) PrintMessage (1, "curved elements with rational splines"); + + const_cast<Mesh&> (mesh).UpdateTopology(); + const MeshTopology & top = mesh.GetTopology(); + + + rational = arational; + + ARRAY<int> edgenrs; + + edgeorder.SetSize (top.GetNEdges()); + faceorder.SetSize (top.GetNFaces()); + + edgeorder = 1; + faceorder = 1; + + if (rational) + { + edgeweight.SetSize (top.GetNEdges()); + edgeweight = 1.0; + } + + + if (aorder <= 1) return; + + + if (rational) aorder = 2; + + + if (mesh.GetDimension() == 3) + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) + { + top.GetSurfaceElementEdges (i+1, edgenrs); + for (int j = 0; j < edgenrs.Size(); j++) + edgeorder[edgenrs[j]-1] = aorder; + faceorder[top.GetSurfaceElementFace (i+1)-1] = aorder; + } + for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++) + edgeorder[top.GetSegmentEdge (i+1)-1] = aorder; + + if (rational) + { + edgeorder = 2; + faceorder = 1; + } + + + edgecoeffsindex.SetSize (top.GetNEdges()+1); + int nd = 0; + for (int i = 0; i < top.GetNEdges(); i++) + { + edgecoeffsindex[i] = nd; + nd += max (0, edgeorder[i]-1); + } + edgecoeffsindex[top.GetNEdges()] = nd; + + edgecoeffs.SetSize (nd); + edgecoeffs = Vec<3> (0,0,0); + + + facecoeffsindex.SetSize (top.GetNFaces()+1); + nd = 0; + for (int i = 0; i < top.GetNFaces(); i++) + { + facecoeffsindex[i] = nd; + if (top.GetFaceType(i+1) == TRIG) + nd += max (0, (faceorder[i]-1)*(faceorder[i]-2)/2); + else + nd += max (0, sqr(faceorder[i]-1)); + } + facecoeffsindex[top.GetNFaces()] = nd; + + facecoeffs.SetSize (nd); + facecoeffs = Vec<3> (0,0,0); + + + if (!ref || aorder <= 1) + { + order = aorder; + return; + } + + ARRAY<double> xi, weight; + + ComputeGaussRule (aorder+4, xi, weight); // on (0,1) + + PrintMessage (3, "Curving edges"); + + if (mesh.GetDimension() == 3 || rational) + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) + { + SetThreadPercent(double(i)/mesh.GetNSE()*100.); + const Element2d & el = mesh[i]; + top.GetSurfaceElementEdges (i+1, edgenrs); + for (int j = 0; j < edgenrs.Size(); j++) + edgenrs[j]--; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (el.GetType()); + + for (int i2 = 0; i2 < edgenrs.Size(); i2++) + { + PointIndex pi1 = edges[i2][0]-1; + PointIndex pi2 = edges[i2][1]-1; + + bool swap = el[pi1] > el[pi2]; + + Point<3> p1 = mesh[el[pi1]]; + Point<3> p2 = mesh[el[pi2]]; + + int order1 = edgeorder[edgenrs[i2]]; + int ndof = max (0, order1-1); + + if (rational && order1 >= 2) + { + Point<3> pm = Center (p1, p2); + + int surfnr = mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(); + + Vec<3> n1 = ref -> GetNormal (p1, surfnr, el.GeomInfoPi(edges[i2][0])); + Vec<3> n2 = ref -> GetNormal (p2, surfnr, el.GeomInfoPi(edges[i2][1])); + + // p3 = pm + alpha1 n1 + alpha2 n2 + + Mat<2> mat, inv; + Vec<2> rhs, sol; + + mat(0,0) = n1*n1; + mat(0,1) = mat(1,0) = n1*n2; + mat(1,1) = n2*n2; + + rhs(0) = n1 * (p1-pm); + rhs(1) = n2 * (p2-pm); + + + Point<3> p3; + + if (fabs (Det (mat)) > 1e-10) + { + CalcInverse (mat, inv); + sol = inv * rhs; + + p3 = pm + sol(0) * n1 + sol(1) * n2; + } + else + p3 = pm; + + edgecoeffs[edgecoeffsindex[edgenrs[i2]]] = Vec<3> (p3); + + + double wold = 1, w = 1, dw = 0.1; + double dold = 1e99; + while (fabs (dw) > 1e-12) + { + Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2); + v05 /= 1 + (w-1) * 0.5; + Point<3> p05 (v05), pp05(v05); + ref -> ProjectToSurface (pp05, surfnr, el.GeomInfoPi(edges[i2][0])); + double d = Dist (pp05, p05); + + if (d < dold) + { + dold = d; + wold = w; + w += dw; + } + else + { + dw *= -0.7; + w = wold + dw; + } + } + + edgeweight[edgenrs[i2]] = w; + continue; + } + + Vector shape(ndof); + DenseMatrix mat(ndof, ndof), inv(ndof, ndof), + rhs(ndof, 3), sol(ndof, 3); + + rhs = 0.0; + mat = 0.0; + for (int j = 0; j < xi.Size(); j++) + { + Point<3> p; + Point<3> pp; + PointGeomInfo ppgi; + + if (swap) + { + p = p1 + xi[j] * (p2-p1); + ref -> PointBetween (p1, p2, xi[j], + mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(), + el.GeomInfoPi(edges[i2][0]), + el.GeomInfoPi(edges[i2][1]), + pp, ppgi); + } + else + { + p = p2 + xi[j] * (p1-p2); + ref -> PointBetween (p2, p1, xi[j], + mesh.GetFaceDescriptor(el.GetIndex()).SurfNr(), + el.GeomInfoPi(edges[i2][1]), + el.GeomInfoPi(edges[i2][0]), + pp, ppgi); + } + + Vec<3> dist = pp - p; + + CalcEdgeShape (order1, 2*xi[j]-1, &shape(0)); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < ndof; l++) + mat(k,l) += weight[j] * shape(k) * shape(l); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < 3; l++) + rhs(k,l) += weight[j] * shape(k) * dist(l); + } + + CalcInverse (mat, inv); + Mult (inv, rhs, sol); + + int first = edgecoeffsindex[edgenrs[i2]]; + for (int j = 0; j < ndof; j++) + for (int k = 0; k < 3; k++) + edgecoeffs[first+j](k) = sol(j,k); + } + } + + + + for (SegmentIndex i = 0; i < mesh.GetNSeg(); i++) + { + SetThreadPercent(double(i)/mesh.GetNSeg()*100.); + const Segment & seg = mesh[i]; + PointIndex pi1 = mesh[i].p1; + PointIndex pi2 = mesh[i].p2; + + bool swap = (pi1 > pi2); + + Point<3> p1 = mesh[pi1]; + Point<3> p2 = mesh[pi2]; + + int segnr = top.GetSegmentEdge (i+1)-1; + + int order1 = edgeorder[segnr]; + int ndof = max (0, order1-1); + + + if (rational) + { + Vec<3> tau1 = ref -> GetTangent (p1, seg.surfnr2, seg.surfnr1, seg.epgeominfo[0]); + Vec<3> tau2 = ref -> GetTangent (p2, seg.surfnr2, seg.surfnr1, seg.epgeominfo[1]); + // p1 + alpha1 tau1 = p2 + alpha2 tau2; + + Mat<3,2> mat; + Mat<2,3> inv; + Vec<3> rhs; + Vec<2> sol; + for (int j = 0; j < 3; j++) + { + mat(j,0) = tau1(j); + mat(j,1) = -tau2(j); + rhs(j) = p2(j)-p1(j); + } + CalcInverse (mat, inv); + sol = inv * rhs; + + Point<3> p3 = p1+sol(0) * tau1; + edgecoeffs[edgecoeffsindex[segnr]] = Vec<3> (p3); + + +// double dopt = 1e99; +// double wopt = 0; +// for (double w = 0; w <= 2; w += 0.0001) +// { +// Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2); +// v05 /= 1 + (w-1) * 0.5; +// Point<3> p05 (v05), pp05(v05); +// ref -> ProjectToEdge (pp05, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]); +// double d = Dist (pp05, p05); +// if (d < dopt) +// { +// wopt = w; +// dopt = d; +// } +// } + + double wold = 1, w = 1, dw = 0.1; + double dold = 1e99; + while (fabs (dw) > 1e-12) + { + Vec<3> v05 = 0.25 * Vec<3> (p1) + 0.5*w* Vec<3>(p3) + 0.25 * Vec<3> (p2); + v05 /= 1 + (w-1) * 0.5; + Point<3> p05 (v05), pp05(v05); + ref -> ProjectToEdge (pp05, seg.surfnr1, seg.surfnr2, seg.epgeominfo[0]); + double d = Dist (pp05, p05); + + if (d < dold) + { + dold = d; + wold = w; + w += dw; + } + else + { + dw *= -0.7; + w = wold + dw; + } + // *testout << "w = " << w << ", dw = " << dw << endl; + } + + // cout << "wopt = " << w << ", dopt = " << dold << endl; + edgeweight[segnr] = w; + +// cout << "p1 = " << p1 << ", tau1 = " << tau1 << ", alpha1 = " << sol(0) << endl; +// cout << "p2 = " << p2 << ", tau2 = " << tau2 << ", alpha2 = " << -sol(1) << endl; +// cout << "p+alpha tau = " << p1 + sol(0) * tau1 +// << " =?= " << p2 +sol(1) * tau2 << endl; + + } + + else + + { + + Vector shape(ndof); + DenseMatrix mat(ndof, ndof), inv(ndof, ndof), + rhs(ndof, 3), sol(ndof, 3); + + rhs = 0.0; + mat = 0.0; + for (int j = 0; j < xi.Size(); j++) + { + Point<3> p; + + Point<3> pp; + EdgePointGeomInfo ppgi; + + if (swap) + { + p = p1 + xi[j] * (p2-p1); + ref -> PointBetween (p1, p2, xi[j], + seg.surfnr2, seg.surfnr1, + seg.epgeominfo[0], seg.epgeominfo[1], + pp, ppgi); + } + else + { + p = p2 + xi[j] * (p1-p2); + ref -> PointBetween (p2, p1, xi[j], + seg.surfnr2, seg.surfnr1, + seg.epgeominfo[1], seg.epgeominfo[0], + pp, ppgi); + } + + Vec<3> dist = pp - p; + + CalcEdgeShape (order1, 2*xi[j]-1, &shape(0)); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < ndof; l++) + mat(k,l) += weight[j] * shape(k) * shape(l); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < 3; l++) + rhs(k,l) += weight[j] * shape(k) * dist(l); + } + + CalcInverse (mat, inv); + Mult (inv, rhs, sol); + + int first = edgecoeffsindex[segnr]; + for (int j = 0; j < ndof; j++) + for (int k = 0; k < 3; k++) + edgecoeffs[first+j](k) = sol(j,k); + } + } + + + + + PrintMessage (3, "Curving faces"); + + if (mesh.GetDimension() == 3) + for (SurfaceElementIndex i = 0; i < mesh.GetNSE(); i++) + { + SetThreadPercent(double(i)/mesh.GetNSE()*100.); + const Element2d & el = mesh[i]; + int facenr = top.GetSurfaceElementFace (i+1)-1; + + if (el.GetType() == TRIG && order >= 3) + { + int fnums[] = { 0, 1, 2 }; + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + + int order1 = faceorder[facenr]; + int ndof = max (0, (order1-1)*(order1-2)/2); + + Vector shape(ndof); + DenseMatrix mat(ndof, ndof), inv(ndof, ndof), + rhs(ndof, 3), sol(ndof, 3); + + rhs = 0.0; + mat = 0.0; + + for (int jx = 0; jx < xi.Size(); jx++) + for (int jy = 0; jy < xi.Size(); jy++) + { + double y = xi[jy]; + double x = (1-y) * xi[jx]; + double lami[] = { x, y, 1-x-y }; + double wi = weight[jx]*weight[jy]*(1-y); + + Point<2> xii (x, y); + Point<3> p1, p2; + CalcSurfaceTransformation (xii, i, p1); + p2 = p1; + ref -> ProjectToSurface (p2, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr()); + + Vec<3> dist = p2-p1; + + CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]], + 1-lami[fnums[1]]-lami[fnums[0]], &shape(0)); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < ndof; l++) + mat(k,l) += wi * shape(k) * shape(l); + + for (int k = 0; k < ndof; k++) + for (int l = 0; l < 3; l++) + rhs(k,l) += wi * shape(k) * dist(l); + } + + CalcInverse (mat, inv); + Mult (inv, rhs, sol); + + int first = facecoeffsindex[facenr]; + for (int j = 0; j < ndof; j++) + for (int k = 0; k < 3; k++) + facecoeffs[first+j](k) = sol(j,k); + } + } + + PrintMessage (3, "Complete"); + + + // compress edge and face tables + int newbase = 0; + for (int i = 0; i < edgeorder.Size(); i++) + { + bool curved = 0; + int oldbase = edgecoeffsindex[i]; + nd = edgecoeffsindex[i+1] - edgecoeffsindex[i]; + + for (int j = 0; j < nd; j++) + if (edgecoeffs[oldbase+j].Length() > 1e-10) + curved = 1; + if (rational) curved = 1; + + if (curved && newbase != oldbase) + for (int j = 0; j < nd; j++) + edgecoeffs[newbase+j] = edgecoeffs[oldbase+j]; + + edgecoeffsindex[i] = newbase; + if (!curved) edgeorder[i] = 1; + if (curved) newbase += nd; + } + edgecoeffsindex.Last() = newbase; + + + newbase = 0; + for (int i = 0; i < faceorder.Size(); i++) + { + bool curved = 0; + int oldbase = facecoeffsindex[i]; + nd = facecoeffsindex[i+1] - facecoeffsindex[i]; + + for (int j = 0; j < nd; j++) + if (facecoeffs[oldbase+j].Length() > 1e-10) + curved = 1; + + if (curved && newbase != oldbase) + for (int j = 0; j < nd; j++) + facecoeffs[newbase+j] = facecoeffs[oldbase+j]; + + facecoeffsindex[i] = newbase; + if (!curved) faceorder[i] = 1; + if (curved) newbase += nd; + } + facecoeffsindex.Last() = newbase; + + order = aorder; + + // (*testout) << "edgecoeffs = " << endl << edgecoeffs << endl; + // (*testout) << "facecoeffs = " << endl << facecoeffs << endl; + } + + + + + + + + + + + // *********************** Transform edges ***************************** + + + bool CurvedElements :: IsSegmentCurved (SegmentIndex elnr) const + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + return mesh.coarsemesh->GetCurvedElements().IsSegmentCurved (hpref_el.coarse_elnr); + } + + SegmentInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = 2; + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + info.edgenr = top.GetSegmentEdge (elnr+1)-1; + info.ndof += edgeorder[info.edgenr]-1; + } + + return (info.ndof > info.nv); + } + + + + + + void CurvedElements :: + CalcSegmentTransformation (double xi, SegmentIndex elnr, + Point<3> * x, Vec<3> * dxdxi, bool * curved) + { + if (mesh.coarsemesh) + { + *testout << "calcSegmentTrafo, coarse edge" << endl; + + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[2] = { xi, 1-xi }; + double dlami[2] = { 1, -1 }; + + double coarse_xi = 0; + double trans = 0; + for (int i = 0; i < 2; i++) + { + coarse_xi += hpref_el.param[i][0] * lami[i]; + trans += hpref_el.param[i][0] * dlami[i]; + } + + mesh.coarsemesh->GetCurvedElements().CalcSegmentTransformation (coarse_xi, hpref_el.coarse_elnr, x, dxdxi, curved); + if (dxdxi) *dxdxi *= trans; + + return; + } + + + Vector shapes, dshapes; + ARRAY<Vec<3> > coefs; + + SegmentInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = 2; + + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + info.edgenr = top.GetSegmentEdge (elnr+1)-1; + info.ndof += edgeorder[info.edgenr]-1; + } + + CalcElementShapes (info, xi, shapes); + GetCoefficients (info, coefs); + + *x = 0; + for (int i = 0; i < shapes.Size(); i++) + *x += shapes(i) * coefs[i]; + + + if (dxdxi) + { + CalcElementDShapes (info, xi, dshapes); + + *dxdxi = 0; + for (int i = 0; i < shapes.Size(); i++) + for (int j = 0; j < 3; j++) + (*dxdxi)(j) += dshapes(i) * coefs[i](j); + } + + if (curved) + *curved = (info.order > 1); + } + + + + + void CurvedElements :: + CalcElementShapes (SegmentInfo & info, double xi, Vector & shapes) const + { + if (rational && info.order == 2) + { + shapes.SetSize(3); + double w = edgeweight[info.edgenr]; + shapes(0) = xi*xi; + shapes(1) = (1-xi)*(1-xi); + shapes(2) = 2*w*xi*(1-xi); + shapes *= 1.0 / (1 + (w-1) *2*xi*(1-xi)); + return; + } + + + shapes.SetSize(info.ndof); + shapes(0) = xi; + shapes(1) = 1-xi; + + if (info.order >= 2) + { + if (mesh[info.elnr].p1 > mesh[info.elnr].p2) + xi = 1-xi; + CalcEdgeShape (edgeorder[info.edgenr], 2*xi-1, &shapes(2)); + } + } + + void CurvedElements :: + CalcElementDShapes (SegmentInfo & info, double xi, Vector & dshapes) const + { + if (rational && info.order == 2) + { + dshapes.SetSize(3); + double wi = edgeweight[info.edgenr]; + double shapes[3]; + shapes[0] = xi*xi; + shapes[1] = (1-xi)*(1-xi); + shapes[2] = 2*wi*xi*(1-xi); + double w = 1 + (wi-1) *2*xi*(1-xi); + double dw = (wi-1) * (2 - 4*xi); + + dshapes(0) = 2*xi; + dshapes(1) = 2*(xi-1); + dshapes(2) = 2*wi*(1-2*xi); + + for (int j = 0;j < 3; j++) + dshapes(j) = dshapes(j) / w - shapes[j] * dw / (w*w); + return; + } + + + + + + + dshapes.SetSize(info.ndof); + dshapes = 0; + dshapes(0) = 1; + dshapes(1) = -1; + + // int order = edgeorder[info.edgenr]; + + if (info.order >= 2) + { + double fac = 2; + if (mesh[info.elnr].p1 > mesh[info.elnr].p2) + { + xi = 1-xi; + fac *= -1; + } + CalcEdgeDx (edgeorder[info.edgenr], 2*xi-1, &dshapes(2)); + for (int i = 2; i < dshapes.Size(); i++) + dshapes(i) *= fac; + } + + // ??? not implemented ???? + } + + void CurvedElements :: + GetCoefficients (SegmentInfo & info, ARRAY<Vec<3> > & coefs) const + { + const Segment & el = mesh[info.elnr]; + + coefs.SetSize(info.ndof); + + coefs[0] = Vec<3> (mesh[el.p1]); + coefs[1] = Vec<3> (mesh[el.p2]); + + if (info.order >= 2) + { + int first = edgecoeffsindex[info.edgenr]; + int next = edgecoeffsindex[info.edgenr+1]; + for (int i = 0; i < next-first; i++) + coefs[i+2] = edgecoeffs[first+i]; + } + } + + + + + + + + + + + + + + // ********************** Transform surface elements ******************* + + + bool CurvedElements :: IsSurfaceElementCurved (SurfaceElementIndex elnr) const + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + return mesh.coarsemesh->GetCurvedElements().IsSurfaceElementCurved (hpref_el.coarse_elnr); + } + + const Element2d & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + SurfaceElementInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = (type == TRIG) ? 3 : 4; + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + + top.GetSurfaceElementEdges (elnr+1, info.edgenrs); + for (int i = 0; i < info.edgenrs.Size(); i++) + info.edgenrs[i]--; + info.facenr = top.GetSurfaceElementFace (elnr+1)-1; + + for (int i = 0; i < info.edgenrs.Size(); i++) + info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; + info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; + } + + return (info.ndof > info.nv); + } + + void CurvedElements :: + CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr, + Point<3> * x, Mat<3,2> * dxdxi, bool * curved) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[4]; + FlatVector vlami(4, lami); + vlami = 0; + mesh[elnr].GetShapeNew (xi, vlami); + + Mat<2,2> trans; + Mat<3,2> dxdxic; + if (dxdxi) + { + MatrixFixWidth<2> dlami(4); + dlami = 0; + mesh[elnr].GetDShapeNew (xi, dlami); + + trans = 0; + for (int k = 0; k < 2; k++) + for (int l = 0; l < 2; l++) + for (int i = 0; i < hpref_el.np; i++) + trans(l,k) += hpref_el.param[i][l] * dlami(i, k); + } + + Point<2> coarse_xi(0,0); + for (int i = 0; i < hpref_el.np; i++) + for (int j = 0; j < 2; j++) + coarse_xi(j) += hpref_el.param[i][j] * lami[i]; + + mesh.coarsemesh->GetCurvedElements().CalcSurfaceTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic, curved); + + if (dxdxi) + *dxdxi = dxdxic * trans; + + return; + } + + + + Vector shapes; + DenseMatrix dshapes; + ARRAY<Vec<3> > coefs; + + const Element2d & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + SurfaceElementInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = (type == TRIG) ? 3 : 4; + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + + top.GetSurfaceElementEdges (elnr+1, info.edgenrs); + for (int i = 0; i < info.edgenrs.Size(); i++) + info.edgenrs[i]--; + info.facenr = top.GetSurfaceElementFace (elnr+1)-1; + + + bool firsttry = true; + bool problem = false; + + while(firsttry || problem) + { + problem = false; + + for (int i = 0; !problem && i < info.edgenrs.Size(); i++) + { + if(info.edgenrs[i]+1 >= edgecoeffsindex.Size()) + problem = true; + else + info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; + } + if(info.facenr+1 >= facecoeffsindex.Size()) + problem = true; + else + info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; + + if(problem && !firsttry) + throw NgException("something wrong with curved elements"); + + if(problem) + BuildCurvedElements(NULL,order,rational); + + firsttry = false; + } + } + + CalcElementShapes (info, xi, shapes); + GetCoefficients (info, coefs); + + *x = 0; + for (int i = 0; i < coefs.Size(); i++) + *x += shapes(i) * coefs[i]; + + if (dxdxi) + { + CalcElementDShapes (info, xi, dshapes); + + *dxdxi = 0; + for (int i = 0; i < coefs.Size(); i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 2; k++) + (*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j); + } + + if (curved) + *curved = (info.ndof > info.nv); + } + + + + + void CurvedElements :: + CalcElementShapes (SurfaceElementInfo & info, const Point<2> & xi, Vector & shapes) const + { + const Element2d & el = mesh[info.elnr]; + + shapes.SetSize(info.ndof); + shapes = 0; + + if (rational && info.order >= 2) + { + shapes.SetSize(6); + double w = 1; + double lami[3] = { xi(0), xi(1), 1-xi(0)-xi(1) }; + for (int j = 0; j < 3; j++) + shapes(j) = lami[j] * lami[j]; + + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG); + for (int j = 0; j < 3; j++) + { + double wi = edgeweight[info.edgenrs[j]]; + shapes(j+3) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + } + + shapes *= 1.0 / w; + return; + } + + switch (el.GetType()) + { + case TRIG: + { + shapes(0) = xi(0); + shapes(1) = xi(1); + shapes(2) = 1-xi(0)-xi(1); + + if (info.order == 1) return; + + int ii = 3; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG); + + for (int i = 0; i < 3; i++) + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii)); + ii += eorder-1; + } + } + + int forder = faceorder[info.facenr]; + if (forder >= 3) + { + int fnums[] = { 0, 1, 2 }; + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + + CalcTrigShape (forder, + shapes(fnums[1])-shapes(fnums[0]), + 1-shapes(fnums[1])-shapes(fnums[0]), &shapes(ii)); + } + break; + } + + case QUAD: + { + shapes(0) = (1-xi(0))*(1-xi(1)); + shapes(1) = xi(0) *(1-xi(1)); + shapes(2) = xi(0) * xi(1) ; + shapes(3) = (1-xi(0))* xi(1) ; + + if (info.order == 1) return; + + double mu[4] = { + 1 - xi(0) + 1 - xi(1), + xi(0) + 1 - xi(1), + xi(0) + xi(1), + 1 - xi(0) + xi(1), + }; + + int ii = 4; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (QUAD); + + for (int i = 0; i < 4; i++) + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcEdgeShape (eorder, mu[vi1]-mu[vi2], &shapes(ii)); + double lame = shapes(vi1)+shapes(vi2); + for (int j = 0; j < order-1; j++) + shapes(ii+j) *= lame; + ii += eorder-1; + } + } + + for (int i = ii; i < info.ndof; i++) + shapes(i) = 0; + + break; + } + }; + } + + + void CurvedElements :: + CalcElementDShapes (SurfaceElementInfo & info, const Point<2> & xi, DenseMatrix & dshapes) const + { + const Element2d & el = mesh[info.elnr]; + ELEMENT_TYPE type = el.GetType(); + + double lami[4]; + + dshapes.SetSize(info.ndof,2); + dshapes = 0; + + + + if (rational && info.order >= 2) + { + double w = 1; + double dw[2] = { 0, 0 }; + + + lami[0] = xi(0); lami[1] = xi(1); lami[2] = 1-xi(0)-xi(1); + double dlami[3][2] = { { 1, 0 }, { 0, 1 }, { -1, -1 }}; + double shapes[6]; + + for (int j = 0; j < 3; j++) + { + shapes[j] = lami[j] * lami[j]; + dshapes(j,0) = 2 * lami[j] * dlami[j][0]; + dshapes(j,1) = 2 * lami[j] * dlami[j][1]; + } + + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG); + for (int j = 0; j < 3; j++) + { + double wi = edgeweight[info.edgenrs[j]]; + + shapes[j+3] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + for (int k = 0; k < 2; k++) + dshapes(j+3,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); + + w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + for (int k = 0; k < 2; k++) + dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); + } + // shapes *= 1.0 / w; + dshapes *= 1.0 / w; + for (int i = 0; i < 6; i++) + for (int j = 0; j < 2; j++) + dshapes(i,j) -= shapes[i] * dw[j] / (w*w); + return; + } + + + + + + switch (type) + { + case TRIG: + { + dshapes(0,0) = 1; + dshapes(1,1) = 1; + dshapes(2,0) = -1; + dshapes(2,1) = -1; + + if (info.order == 1) return; + + lami[0] = xi(0); + lami[1] = xi(1); + lami[2] = 1-xi(0)-xi(1); + + int ii = 3; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TRIG); + + for (int i = 0; i < 3; i++) + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcScaledEdgeShapeDxDt<2> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0)); + + Mat<2,2> trans; + for (int j = 0; j < 2; j++) + { + trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j); + trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j); + } + + for (int j = 0; j < eorder-1; j++) + { + double ddx = dshapes(ii+j,0); + double ddt = dshapes(ii+j,1); + dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); + dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); + } + + ii += eorder-1; + } + } + + int forder = faceorder[info.facenr]; + if (forder >= 3) + { + int fnums[] = { 0, 1, 2 }; + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + + CalcTrigShapeDxDy (forder, + lami[fnums[1]]-lami[fnums[0]], + 1-lami[fnums[1]]-lami[fnums[0]], &dshapes(ii,0)); + + int nd = (forder-1)*(forder-2)/2; + Mat<2,2> trans; + for (int j = 0; j < 2; j++) + { + trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j); + trans(1,j) = -dshapes(fnums[1],j)-dshapes(fnums[0],j); + } + + for (int j = 0; j < nd; j++) + { + double ddx = dshapes(ii+j,0); + double ddt = dshapes(ii+j,1); + dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); + dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); + } + } + + break; + } + case QUAD: + { + dshapes(0,0) = -(1-xi(1)); + dshapes(0,1) = -(1-xi(0)); + dshapes(1,0) = (1-xi(1)); + dshapes(1,1) = -xi(0); + dshapes(2,0) = xi(1); + dshapes(2,1) = xi(0); + dshapes(3,0) = -xi(1); + dshapes(3,1) = (1-xi(0)); + + if (info.order == 1) return; + + double shapes[4] = { + (1-xi(0))*(1-xi(1)), + xi(0) *(1-xi(1)), + xi(0) * xi(1) , + (1-xi(0))* xi(1) + }; + + double mu[4] = { + 1 - xi(0) + 1 - xi(1), + xi(0) + 1 - xi(1), + xi(0) + xi(1), + 1 - xi(0) + xi(1), + }; + + double dmu[4][2] = { + { -1, -1 }, + { 1, -1 }, + { 1, 1 }, + { -1, 1 } }; + + // double hshapes[20], hdshapes[20]; + ArrayMem<double, 20> hshapes(order+1), hdshapes(order+1); + + int ii = 4; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (QUAD); + + for (int i = 0; i < 4; i++) + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcEdgeShapeDx (eorder, mu[vi1]-mu[vi2], &hshapes[0], &hdshapes[0]); + + double lame = shapes[vi1]+shapes[vi2]; + double dlame[2] = { + dshapes(vi1, 0) + dshapes(vi2, 0), + dshapes(vi1, 1) + dshapes(vi2, 1) }; + + for (int j = 0; j < eorder-1; j++) + for (int k = 0; k < 2; k++) + dshapes(ii+j, k) = + lame * hdshapes[j] * (dmu[vi1][k]-dmu[vi2][k]) + + dlame[k] * hshapes[j]; + + ii += eorder-1; + } + } + + /* + *testout << "quad, dshape = " << endl << dshapes << endl; + for (int i = 0; i < 2; i++) + { + Point<2> xil = xi, xir = xi; + Vector shapesl(dshapes.Height()), shapesr(dshapes.Height()); + xil(i) -= 1e-6; + xir(i) += 1e-6; + CalcElementShapes (info, xil, shapesl); + CalcElementShapes (info, xir, shapesr); + + for (int j = 0; j < dshapes.Height(); j++) + dshapes(j,i) = 1.0 / 2e-6 * (shapesr(j)-shapesl(j)); + } + + *testout << "quad, num dshape = " << endl << dshapes << endl; + */ + break; + } + }; + } + + + + void CurvedElements :: + GetCoefficients (SurfaceElementInfo & info, ARRAY<Vec<3> > & coefs) const + { + const Element2d & el = mesh[info.elnr]; + + coefs.SetSize (info.ndof); + // coefs = Vec<3> (0,0,0); + + for (int i = 0; i < info.nv; i++) + coefs[i] = Vec<3> (mesh[el[i]]); + + if (info.order == 1) return; + + int ii = info.nv; + + for (int i = 0; i < info.edgenrs.Size(); i++) + { + int first = edgecoeffsindex[info.edgenrs[i]]; + int next = edgecoeffsindex[info.edgenrs[i]+1]; + for (int j = first; j < next; j++, ii++) + coefs[ii] = edgecoeffs[j]; + } + + int first = facecoeffsindex[info.facenr]; + int next = facecoeffsindex[info.facenr+1]; + for (int j = first; j < next; j++, ii++) + coefs[ii] = facecoeffs[j]; + } + + + + + + + + // ********************** Transform volume elements ******************* + + + bool CurvedElements :: IsElementCurved (ElementIndex elnr) const + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + return mesh.coarsemesh->GetCurvedElements().IsElementCurved (hpref_el.coarse_elnr); + } + + const Element & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + ElementInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = MeshTopology::GetNVertices (type); + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + + info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); + for (int i = 0; i < info.nedges; i++) + info.edgenrs[i]--; + + info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); + for (int i = 0; i < info.nfaces; i++) + info.facenrs[i]--; + + for (int i = 0; i < info.nedges; i++) + info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; + for (int i = 0; i < info.nfaces; i++) + info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; + } + + return (info.ndof > info.nv); + } + + + + + + + void CurvedElements :: + CalcElementTransformation (Point<3> xi, ElementIndex elnr, + Point<3> * x, Mat<3,3> * dxdxi, // bool * curved, + void * buffer, bool valid) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[8]; + FlatVector vlami(8, lami); + vlami = 0; + mesh[elnr].GetShapeNew (xi, vlami); + + Mat<3,3> trans, dxdxic; + if (dxdxi) + { + MatrixFixWidth<3> dlami(8); + dlami = 0; + mesh[elnr].GetDShapeNew (xi, dlami); + + trans = 0; + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + for (int i = 0; i < hpref_el.np; i++) + trans(l,k) += hpref_el.param[i][l] * dlami(i, k); + } + + Point<3> coarse_xi(0,0,0); + for (int i = 0; i < hpref_el.np; i++) + for (int j = 0; j < 3; j++) + coarse_xi(j) += hpref_el.param[i][j] * lami[i]; + + mesh.coarsemesh->GetCurvedElements().CalcElementTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic /* , curved */); + + if (dxdxi) + *dxdxi = dxdxic * trans; + + return; + } + + + Vector shapes; + MatrixFixWidth<3> dshapes; + + const Element & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + ElementInfo hinfo; + ElementInfo & info = (buffer) ? *static_cast<ElementInfo*> (buffer) : hinfo; + + + if (!valid) + { + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = MeshTopology::GetNVertices (type); + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + + info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); + for (int i = 0; i < info.nedges; i++) + info.edgenrs[i]--; + + info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); + for (int i = 0; i < info.nfaces; i++) + info.facenrs[i]--; + + for (int i = 0; i < info.nedges; i++) + info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; + for (int i = 0; i < info.nfaces; i++) + info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; + } + } + + CalcElementShapes (info, xi, shapes); + + Vec<3> * coefs = (info.ndof <= 10) ? + &info.hcoefs[0] : new Vec<3> [info.ndof]; + + if (info.ndof > 10 || !valid) + GetCoefficients (info, coefs); + + if (x) + { + *x = 0; + for (int i = 0; i < shapes.Size(); i++) + *x += shapes(i) * coefs[i]; + } + + if (dxdxi) + { + if (valid && info.order == 1 && info.nv == 4) // a linear tet + { + *dxdxi = info.hdxdxi; + } + else + { + CalcElementDShapes (info, xi, dshapes); + + *dxdxi = 0; + for (int i = 0; i < shapes.Size(); i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + (*dxdxi)(j,k) += dshapes(i,k) * coefs[i](j); + + info.hdxdxi = *dxdxi; + } + } + + // *testout << "curved_elements, dshapes = " << endl << dshapes << endl; + + // if (curved) *curved = (info.ndof > info.nv); + + if (info.ndof > 10) delete [] coefs; + } + + + + + void CurvedElements :: CalcElementShapes (ElementInfo & info, const Point<3> & xi, Vector & shapes) const + { + const Element & el = mesh[info.elnr]; + + if (rational && info.order >= 2) + { + shapes.SetSize(10); + double w = 1; + double lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) }; + for (int j = 0; j < 4; j++) + shapes(j) = lami[j] * lami[j]; + + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET); + for (int j = 0; j < 6; j++) + { + double wi = edgeweight[info.edgenrs[j]]; + shapes(j+4) = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + } + + shapes *= 1.0 / w; + return; + } + + shapes.SetSize(info.ndof); + + switch (el.GetType()) + { + case TET: + { + shapes(0) = xi(0); + shapes(1) = xi(1); + shapes(2) = xi(2); + shapes(3) = 1-xi(0)-xi(1)-xi(2); + + if (info.order == 1) return; + + int ii = 4; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET); + for (int i = 0; i < 6; i++) + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcScaledEdgeShape (eorder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii)); + ii += eorder-1; + } + } + const ELEMENT_FACE * faces = MeshTopology::GetFaces (TET); + for (int i = 0; i < 4; i++) + { + int forder = faceorder[info.facenrs[i]]; + if (forder >= 3) + { + int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + + CalcScaledTrigShape (forder, + shapes(fnums[1])-shapes(fnums[0]), shapes(fnums[2]), + shapes(fnums[0])+shapes(fnums[1])+shapes(fnums[2]), &shapes(ii)); + ii += (forder-1)*(forder-2)/2; + // CalcScaledEdgeShape (forder, shapes(vi1)-shapes(vi2), shapes(vi1)+shapes(vi2), &shapes(ii)); + // ii += forder-1; + } + } + + + break; + } + case PRISM: + { + double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) }; + double lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) }; + for (int i = 0; i < 6; i++) + shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) ); + for (int i = 6; i < info.ndof; i++) + shapes(i) = 0; + + if (info.order == 1) return; + + + int ii = 6; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PRISM); + for (int i = 0; i < 6; i++) // horizontal edges + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = (edges[i][0]-1) % 3, vi2 = (edges[i][1]-1) % 3; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcScaledEdgeShape (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapes(ii)); + double facz = (i < 3) ? (1-xi(2)) : xi(2); + for (int j = 0; j < eorder-1; j++) + shapes(ii+j) *= facz; + + ii += eorder-1; + } + } + + for (int i = 6; i < 9; i++) // vertical edges + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1); + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + double bubz = lamiz[vi1]*lamiz[vi2]; + double polyz = lamiz[vi1] - lamiz[vi2]; + double bubxy = lami[(vi1)%3]; + + for (int j = 0; j < eorder-1; j++) + { + shapes(ii+j) = bubxy * bubz; + bubz *= polyz; + } + ii += eorder-1; + } + } + + // FACE SHAPES + const ELEMENT_FACE * faces = MeshTopology::GetFaces (PRISM); + for (int i = 0; i < 2; i++) + { + int forder = faceorder[info.facenrs[i]]; + if ( forder < 3 ) continue; + int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; + if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); + if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]); + if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); + + CalcTrigShape (forder, + lami[fav[2]]-lami[fav[1]], lami[fav[0]], + &shapes(ii)); + + int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1); + for ( int j = 0; j < ndf; j++ ) + shapes(ii+j) *= lamiz[fav[1]]; + ii += ndf; + } + break; + } + + case PYRAMID: + { + shapes = 0.0; + double x = xi(0); + double y = xi(1); + double z = xi(2); + + if (z == 1.) z = 1-1e-10; + shapes[0] = (1-z-x)*(1-z-y) / (1-z); + shapes[1] = x*(1-z-y) / (1-z); + shapes[2] = x*y / (1-z); + shapes[3] = (1-z-x)*y / (1-z); + shapes[4] = z; + + if (info.order == 1) return; + + int ii = 5; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PYRAMID); + for (int i = 0; i < 4; i++) // horizontal edges + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1); + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcScaledEdgeShape (eorder, shapes[vi1]-shapes[vi2], shapes[vi1]+shapes[vi2], &shapes(ii)); + double fac = (shapes[vi1]+shapes[vi2]) / (1-z); + for (int j = 0; j < eorder-1; j++) + shapes(ii+j) *= fac; + + ii += eorder-1; + } + } + + + + break; + } + + case HEX: + { + shapes = 0.0; + double x = xi(0); + double y = xi(1); + double z = xi(2); + + shapes[0] = (1-x)*(1-y)*(1-z); + shapes[1] = x *(1-y)*(1-z); + shapes[2] = x * y *(1-z); + shapes[3] = (1-x)* y *(1-z); + shapes[4] = (1-x)*(1-y)*(z); + shapes[5] = x *(1-y)*(z); + shapes[6] = x * y *(z); + shapes[7] = (1-x)* y *(z); + break; + } + }; + } + + + void CurvedElements :: + CalcElementDShapes (ElementInfo & info, const Point<3> & xi, MatrixFixWidth<3> & dshapes) const + { + const Element & el = mesh[info.elnr]; + + dshapes.SetSize(info.ndof); + dshapes = 0.0; + + + + if (rational && info.order >= 2) + { + double w = 1; + double dw[3] = { 0, 0, 0 }; + + double lami[4] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) }; + double dlami[4][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, -1, -1 }}; + double shapes[10]; + + for (int j = 0; j < 4; j++) + { + shapes[j] = lami[j] * lami[j]; + dshapes(j,0) = 2 * lami[j] * dlami[j][0]; + dshapes(j,1) = 2 * lami[j] * dlami[j][1]; + dshapes(j,2) = 2 * lami[j] * dlami[j][2]; + } + + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET); + for (int j = 0; j < 6; j++) + { + double wi = edgeweight[info.edgenrs[j]]; + + shapes[j+4] = 2 * wi * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + for (int k = 0; k < 3; k++) + dshapes(j+4,k) = 2*wi* (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); + + w += (wi-1) * 2 * lami[edges[j][0]-1] * lami[edges[j][1]-1]; + for (int k = 0; k < 3; k++) + dw[k] += 2*(wi-1) * (lami[edges[j][0]-1] * dlami[edges[j][1]-1][k] + + lami[edges[j][1]-1] * dlami[edges[j][0]-1][k]); + } + // shapes *= 1.0 / w; + dshapes *= 1.0 / w; + for (int i = 0; i < 10; i++) + for (int j = 0; j < 3; j++) + dshapes(i,j) -= shapes[i] * dw[j] / (w*w); + return; + } + + switch (el.GetType()) + { + case TET: + { + dshapes(0,0) = 1; + dshapes(1,1) = 1; + dshapes(2,2) = 1; + dshapes(3,0) = -1; + dshapes(3,1) = -1; + dshapes(3,2) = -1; + + if (info.order == 1) return; + + double lami[] = { xi(0), xi(1), xi(2), 1-xi(0)-xi(1)-xi(2) }; + int ii = 4; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (TET); + for (int i = 0; i < 6; i++) + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = edges[i][0]-1, vi2 = edges[i][1]-1; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + CalcScaledEdgeShapeDxDt<3> (eorder, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0)); + + Mat<2,3> trans; + for (int j = 0; j < 3; j++) + { + trans(0,j) = dshapes(vi1,j)-dshapes(vi2,j); + trans(1,j) = dshapes(vi1,j)+dshapes(vi2,j); + } + + for (int j = 0; j < order-1; j++) + { + double ddx = dshapes(ii+j,0); + double ddt = dshapes(ii+j,1); + dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); + dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); + dshapes(ii+j,2) = ddx * trans(0,2) + ddt * trans(1,2); + } + + ii += eorder-1; + } + } + + const ELEMENT_FACE * faces = MeshTopology::GetFaces (TET); + for (int i = 0; i < 4; i++) + { + int forder = faceorder[info.facenrs[i]]; + if (forder >= 3) + { + int fnums[] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + if (el[fnums[1]] > el[fnums[2]]) swap (fnums[1], fnums[2]); + if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]); + + CalcScaledTrigShapeDxDyDt (forder, + lami[fnums[1]]-lami[fnums[0]], + lami[fnums[2]], lami[fnums[0]]+lami[fnums[1]]+lami[fnums[2]], + &dshapes(ii,0)); + + Mat<3,3> trans; + for (int j = 0; j < 3; j++) + { + trans(0,j) = dshapes(fnums[1],j)-dshapes(fnums[0],j); + trans(1,j) = dshapes(fnums[2],j); + trans(2,j) = dshapes(fnums[0],j)+dshapes(fnums[1],j)+dshapes(fnums[2],j); + } + + int nfd = (forder-1)*(forder-2)/2; + for (int j = 0; j < nfd; j++) + { + double ddx = dshapes(ii+j,0); + double ddy = dshapes(ii+j,1); + double ddt = dshapes(ii+j,2); + dshapes(ii+j,0) = ddx * trans(0,0) + ddy * trans(1,0) + ddt * trans(2,0); + dshapes(ii+j,1) = ddx * trans(0,1) + ddy * trans(1,1) + ddt * trans(2,1); + dshapes(ii+j,2) = ddx * trans(0,2) + ddy * trans(1,2) + ddt * trans(2,2); + } + + ii += nfd; + } + } + + break; + } + case PRISM: + { + double lami[6] = { xi(0), xi(1), 1-xi(0)-xi(1), xi(0), xi(1), 1-xi(0)-xi(1) }; + double lamiz[6] = { 1-xi(2), 1-xi(2), 1-xi(2), xi(2), xi(2), xi(2) }; + double dlamiz[6] = { -1, -1, -1, 1, 1, 1 }; + double dlami[6][2] = + { { 1, 0, }, + { 0, 1, }, + { -1, -1 }, + { 1, 0, }, + { 0, 1, }, + { -1, -1 } }; + for (int i = 0; i < 6; i++) + { + // shapes(i) = lami[i%3] * ( (i < 3) ? (1-xi(2)) : xi(2) ); + dshapes(i,0) = dlami[i%3][0] * ( (i < 3) ? (1-xi(2)) : xi(2) ); + dshapes(i,1) = dlami[i%3][1] * ( (i < 3) ? (1-xi(2)) : xi(2) ); + dshapes(i,2) = lami[i%3] * ( (i < 3) ? -1 : 1 ); + } + + int ii = 6; + + if (info.order == 1) return; + + + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (PRISM); + for (int i = 0; i < 6; i++) // horizontal edges + { + int order = edgeorder[info.edgenrs[i]]; + if (order >= 2) + { + int vi1 = (edges[i][0]-1) % 3, vi2 = (edges[i][1]-1) % 3; + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + Vector shapei(order+1); + CalcScaledEdgeShapeDxDt<3> (order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &dshapes(ii,0) ); + CalcScaledEdgeShape(order, lami[vi1]-lami[vi2], lami[vi1]+lami[vi2], &shapei(0) ); + + Mat<2,2> trans; + for (int j = 0; j < 2; j++) + { + trans(0,j) = dlami[vi1][j]-dlami[vi2][j]; + trans(1,j) = dlami[vi1][j]+dlami[vi2][j]; + } + + for (int j = 0; j < order-1; j++) + { + double ddx = dshapes(ii+j,0); + double ddt = dshapes(ii+j,1); + dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); + dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); + } + + + + double facz = (i < 3) ? (1-xi(2)) : xi(2); + double dfacz = (i < 3) ? (-1) : 1; + for (int j = 0; j < order-1; j++) + { + dshapes(ii+j,0) *= facz; + dshapes(ii+j,1) *= facz; + dshapes(ii+j,2) = shapei(j) * dfacz; + } + + ii += order-1; + } + } + for (int i = 6; i < 9; i++) // vertical edges + { + int eorder = edgeorder[info.edgenrs[i]]; + if (eorder >= 2) + { + int vi1 = (edges[i][0]-1), vi2 = (edges[i][1]-1); + if (el[vi1] > el[vi2]) swap (vi1, vi2); + + double bubz = lamiz[vi1] * lamiz[vi2]; + double dbubz = dlamiz[vi1]*lamiz[vi2] + lamiz[vi1]*dlamiz[vi2]; + double polyz = lamiz[vi1] - lamiz[vi2]; + double dpolyz = dlamiz[vi1] - dlamiz[vi2]; + double bubxy = lami[(vi1)%3]; + double dbubxydx = dlami[(vi1)%3][0]; + double dbubxydy = dlami[(vi1)%3][1]; + + for (int j = 0; j < eorder-1; j++) + { + dshapes(ii+j,0) = dbubxydx * bubz; + dshapes(ii+j,1) = dbubxydy * bubz; + dshapes(ii+j,2) = bubxy * dbubz; + + dbubz = bubz * dpolyz + dbubz * polyz; + bubz *= polyz; + } + ii += eorder-1; + } + } + + + if (info.order == 2) return; + // FACE SHAPES + const ELEMENT_FACE * faces = MeshTopology::GetFaces (PRISM); + for (int i = 0; i < 2; i++) + { + int forder = faceorder[info.facenrs[i]]; + if ( forder < 3 ) continue; + int ndf = (forder+1)*(forder+2)/2 - 3 - 3*(forder-1); + + int fav[3] = { faces[i][0]-1, faces[i][1]-1, faces[i][2]-1 }; + if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); + if(el[fav[1]] > el[fav[2]]) swap(fav[1],fav[2]); + if(el[fav[0]] > el[fav[1]]) swap(fav[0],fav[1]); + + MatrixFixWidth<2> dshapei(ndf); + Vector shapei(ndf); + + CalcTrigShapeDxDy (forder, + lami[fav[2]]-lami[fav[1]], lami[fav[0]], + &dshapei(0,0)); + CalcTrigShape (forder, lami[fav[2]]-lami[fav[1]], lami[fav[0]], + &shapei(0)); + + Mat<2,2> trans; + for (int j = 0; j < 2; j++) + { + trans(0,j) = dlami[fav[2]][j]-dlami[fav[1]][j]; + trans(1,j) = dlami[fav[0]][j]; + } + + for (int j = 0; j < order-1; j++) + { + double ddx = dshapes(ii+j,0); + double ddt = dshapes(ii+j,1); + dshapes(ii+j,0) = ddx * trans(0,0) + ddt * trans(1,0); + dshapes(ii+j,1) = ddx * trans(0,1) + ddt * trans(1,1); + } + + for ( int j = 0; j < ndf; j++ ) + { + dshapes(ii+j,0) *= lamiz[fav[1]]; + dshapes(ii+j,1) *= lamiz[fav[1]]; + dshapes(ii+j,2) = shapei(j) * dlamiz[fav[1]]; + } + ii += ndf; + } + + break; + + } + + case PYRAMID: + { + dshapes = 0.0; + double x = xi(0); + double y = xi(1); + double z = xi(2); + + if (z == 1.) z = 1-1e-10; + double z1 = 1-z; + double z2 = z1*z1; + + dshapes(0,0) = -(z1-y)/z1; + dshapes(0,1) = -(z1-x)/z1; + dshapes(0,2) = ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2; + + dshapes(1,0) = (z1-y)/z1; + dshapes(1,1) = -x/z1; + dshapes(1,2) = (-x*z1+x*(z1-y))/z2; + + dshapes(2,0) = y/z1; + dshapes(2,1) = x/z1; + dshapes(2,2) = x*y/z2; + + dshapes(3,0) = -y/z1; + dshapes(3,1) = (z1-x)/z1; + dshapes(3,2) = (-y*z1+y*(z1-x))/z2; + + dshapes(4,0) = 0; + dshapes(4,1) = 0; + dshapes(4,2) = 1; + /* old: + vdshape[0] = Vec<3>( -(z1-y)/z1, -(z1-x)/z1, ((x+y+2*z-2)*z1+(z1-y)*(z1-x))/z2 ); + vdshape[1] = Vec<3>( (z1-y)/z1, -x/z1, (-x*z1+x*(z1-y))/z2 ); + vdshape[2] = Vec<3>( y/z1, x/z1, x*y/z2 ); + vdshape[3] = Vec<3>( -y/z1, (z1-x)/z1, (-y*z1+y*(z1-x))/z2 ); + vdshape[4] = Vec<3>( 0, 0, 1 ); + */ + break; + } + + case HEX: + { + dshapes = 0.0; + + double x = xi(0); + double y = xi(1); + double z = xi(2); + + // shapes[0] = (1-x)*(1-y)*(1-z); + dshapes(0,0) = - (1-y)*(1-z); + dshapes(0,1) = (1-x) * (-1) * (1-z); + dshapes(0,2) = (1-x) * (1-y) * (-1); + + // shapes[1] = x *(1-y)*(1-z); + dshapes(1,0) = (1-y)*(1-z); + dshapes(1,1) = -x * (1-z); + dshapes(1,2) = -x * (1-y); + + // shapes[2] = x * y *(1-z); + dshapes(2,0) = y * (1-z); + dshapes(2,1) = x * (1-z); + dshapes(2,2) = -x * y; + + // shapes[3] = (1-x)* y *(1-z); + dshapes(3,0) = -y * (1-z); + dshapes(3,1) = (1-x) * (1-z); + dshapes(3,2) = -(1-x) * y; + + // shapes[4] = (1-x)*(1-y)*z; + dshapes(4,0) = - (1-y)*z; + dshapes(4,1) = (1-x) * (-1) * z; + dshapes(4,2) = (1-x) * (1-y) * 1; + + // shapes[5] = x *(1-y)*z; + dshapes(5,0) = (1-y)*z; + dshapes(5,1) = -x * z; + dshapes(5,2) = x * (1-y); + + // shapes[6] = x * y *z; + dshapes(6,0) = y * z; + dshapes(6,1) = x * z; + dshapes(6,2) = x * y; + + // shapes[7] = (1-x)* y *z; + dshapes(7,0) = -y * z; + dshapes(7,1) = (1-x) * z; + dshapes(7,2) = (1-x) * y; + + break; + } + } + + /* + DenseMatrix dshapes2 (info.ndof, 3); + Vector shapesl(info.ndof); + Vector shapesr(info.ndof); + + double eps = 1e-6; + for (int i = 0; i < 3; i++) + { + Point<3> xl = xi; + Point<3> xr = xi; + + xl(i) -= eps; + xr(i) += eps; + CalcElementShapes (info, xl, shapesl); + CalcElementShapes (info, xr, shapesr); + + for (int j = 0; j < info.ndof; j++) + dshapes2(j,i) = (shapesr(j)-shapesl(j)) / (2*eps); + } + (*testout) << "dshapes = " << endl << dshapes << endl; + (*testout) << "dshapes2 = " << endl << dshapes2 << endl; + dshapes2 -= dshapes; + (*testout) << "diff = " << endl << dshapes2 << endl; + */ + } + + + + void CurvedElements :: + GetCoefficients (ElementInfo & info, Vec<3> * coefs) const + { + // cout << "getcoeffs, info.elnr = " << info.elnr << endl; + // cout << "getcoeffs, info.nv = " << info.nv << endl; + + const Element & el = mesh[info.elnr]; + + /* + coefs.SetSize (info.ndof); + coefs = Vec<3> (0,0,0); + */ + /* + for (int i = 0; i < info.ndof; i++) + coefs[i] = Vec<3> (0,0,0); + */ + for (int i = 0; i < info.nv; i++) + coefs[i] = Vec<3> (mesh[el[i]]); + + if (info.order == 1) return; + + int ii = info.nv; + + for (int i = 0; i < info.nedges; i++) + { + int first = edgecoeffsindex[info.edgenrs[i]]; + int next = edgecoeffsindex[info.edgenrs[i]+1]; + for (int j = first; j < next; j++, ii++) + coefs[ii] = edgecoeffs[j]; + } + for (int i = 0; i < info.nfaces; i++) + { + int first = facecoeffsindex[info.facenrs[i]]; + int next = facecoeffsindex[info.facenrs[i]+1]; + for (int j = first; j < next; j++, ii++) + coefs[ii] = facecoeffs[j]; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void CurvedElements :: + CalcMultiPointSegmentTransformation (ARRAY<double> * xi, SegmentIndex segnr, + ARRAY<Point<3> > * x, + ARRAY<Vec<3> > * dxdxi) + { + ; + } + + void CurvedElements :: + CalcMultiPointSurfaceTransformation (ARRAY< Point<2> > * xi, SurfaceElementIndex elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,2> > * dxdxi) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[4]; + FlatVector vlami(4, lami); + + ArrayMem<Point<2>, 50> coarse_xi (xi->Size()); + + for (int pi = 0; pi < xi->Size(); pi++) + { + vlami = 0; + mesh[elnr].GetShapeNew ( (*xi)[pi], vlami); + + Point<2> cxi(0,0); + for (int i = 0; i < hpref_el.np; i++) + for (int j = 0; j < 2; j++) + cxi(j) += hpref_el.param[i][j] * lami[i]; + + coarse_xi[pi] = cxi; + } + + mesh.coarsemesh->GetCurvedElements(). + CalcMultiPointSurfaceTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi); + + + Mat<2,2> trans; + Mat<3,2> dxdxic; + if (dxdxi) + { + MatrixFixWidth<2> dlami(4); + dlami = 0; + + for (int pi = 0; pi < xi->Size(); pi++) + { + mesh[elnr].GetDShapeNew ( (*xi)[pi], dlami); + + trans = 0; + for (int k = 0; k < 2; k++) + for (int l = 0; l < 2; l++) + for (int i = 0; i < hpref_el.np; i++) + trans(l,k) += hpref_el.param[i][l] * dlami(i, k); + + dxdxic = (*dxdxi)[pi]; + (*dxdxi)[pi] = dxdxic * trans; + } + } + + return; + } + + + + + + Vector shapes; + DenseMatrix dshapes; + ARRAY<Vec<3> > coefs; + + + const Element2d & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + SurfaceElementInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = (type == TRIG) ? 3 : 4; + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + + top.GetSurfaceElementEdges (elnr+1, info.edgenrs); + for (int i = 0; i < info.edgenrs.Size(); i++) + info.edgenrs[i]--; + info.facenr = top.GetSurfaceElementFace (elnr+1)-1; + + for (int i = 0; i < info.edgenrs.Size(); i++) + info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; + info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; + } + + GetCoefficients (info, coefs); + + if (x) + { + for (int j = 0; j < xi->Size(); j++) + { + CalcElementShapes (info, (*xi)[j], shapes); + (*x)[j] = 0; + for (int i = 0; i < coefs.Size(); i++) + (*x)[j] += shapes(i) * coefs[i]; + } + } + + if (dxdxi) + { + for (int ip = 0; ip < xi->Size(); ip++) + { + CalcElementDShapes (info, (*xi)[ip], dshapes); + + (*dxdxi)[ip] = 0; + for (int i = 0; i < coefs.Size(); i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 2; k++) + (*dxdxi)[ip](j,k) += dshapes(i,k) * coefs[i](j); + } + } + } + + void CurvedElements :: + CalcMultiPointElementTransformation (ARRAY< Point<3> > * xi, ElementIndex elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,3> > * dxdxi) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[8]; + FlatVector vlami(8, lami); + + + ArrayMem<Point<3>, 50> coarse_xi (xi->Size()); + + for (int pi = 0; pi < xi->Size(); pi++) + { + vlami = 0; + mesh[elnr].GetShapeNew ( (*xi)[pi], vlami); + + Point<3> cxi(0,0,0); + for (int i = 0; i < hpref_el.np; i++) + for (int j = 0; j < 3; j++) + cxi(j) += hpref_el.param[i][j] * lami[i]; + + coarse_xi[pi] = cxi; + } + + mesh.coarsemesh->GetCurvedElements(). + CalcMultiPointElementTransformation (&coarse_xi, hpref_el.coarse_elnr, x, dxdxi); + + + Mat<3,3> trans, dxdxic; + if (dxdxi) + { + MatrixFixWidth<3> dlami(8); + dlami = 0; + + for (int pi = 0; pi < xi->Size(); pi++) + { + mesh[elnr].GetDShapeNew ( (*xi)[pi], dlami); + + trans = 0; + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + for (int i = 0; i < hpref_el.np; i++) + trans(l,k) += hpref_el.param[i][l] * dlami(i, k); + + dxdxic = (*dxdxi)[pi]; + (*dxdxi)[pi] = dxdxic * trans; + } + } + + return; + } + + + + + + + + + Vector shapes; + MatrixFixWidth<3> dshapes; + + + const Element & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + ElementInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = MeshTopology::GetNVertices (type); + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + + info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); + for (int i = 0; i < info.nedges; i++) + info.edgenrs[i]--; + + info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); + for (int i = 0; i < info.nfaces; i++) + info.facenrs[i]--; + + for (int i = 0; i < info.nedges; i++) + info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; + for (int i = 0; i < info.nfaces; i++) + info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; + // info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; + } + + ARRAY<Vec<3> > coefs(info.ndof); + GetCoefficients (info, &coefs[0]); + if (x) + { + for (int j = 0; j < xi->Size(); j++) + { + CalcElementShapes (info, (*xi)[j], shapes); + (*x)[j] = 0; + for (int i = 0; i < coefs.Size(); i++) + (*x)[j] += shapes(i) * coefs[i]; + } + } + if (dxdxi) + { + for (int ip = 0; ip < xi->Size(); ip++) + { + CalcElementDShapes (info, (*xi)[ip], dshapes); + + (*dxdxi)[ip] = 0; + for (int i = 0; i < coefs.Size(); i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + (*dxdxi)[ip](j,k) += dshapes(i,k) * coefs[i](j); + } + } + } + + + + + void CurvedElements :: + CalcMultiPointElementTransformation (ElementIndex elnr, int n, + const double * xi, int sxi, + double * x, int sx, + double * dxdxi, int sdxdxi) + { + if (mesh.coarsemesh) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [mesh[elnr].hp_elnr]; + + // xi umrechnen + double lami[8]; + FlatVector vlami(8, lami); + + + ArrayMem<double, 100> coarse_xi (3*n); + + for (int pi = 0; pi < n; pi++) + { + vlami = 0; + Point<3> pxi; + for (int j = 0; j < 3; j++) + pxi(j) = xi[pi*sxi+j]; + + mesh[elnr].GetShapeNew ( pxi, vlami); + + Point<3> cxi(0,0,0); + for (int i = 0; i < hpref_el.np; i++) + for (int j = 0; j < 3; j++) + cxi(j) += hpref_el.param[i][j] * lami[i]; + + for (int j = 0; j < 3; j++) + coarse_xi[3*pi+j] = cxi(j); + } + + mesh.coarsemesh->GetCurvedElements(). + CalcMultiPointElementTransformation (hpref_el.coarse_elnr, n, + &coarse_xi[0], 3, + x, sx, + dxdxi, sdxdxi); + + Mat<3,3> trans, dxdxic; + if (dxdxi) + { + MatrixFixWidth<3> dlami(8); + dlami = 0; + + for (int pi = 0; pi < n; pi++) + { + Point<3> pxi; + for (int j = 0; j < 3; j++) + pxi(j) = xi[pi*sxi+j]; + + mesh[elnr].GetDShapeNew (pxi, dlami); + + trans = 0; + for (int k = 0; k < 3; k++) + for (int l = 0; l < 3; l++) + for (int i = 0; i < hpref_el.np; i++) + trans(l,k) += hpref_el.param[i][l] * dlami(i, k); + + Mat<3> mat_dxdxic, mat_dxdxi; + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + mat_dxdxic(j,k) = dxdxi[pi*sdxdxi+3*j+k]; + + mat_dxdxi = mat_dxdxic * trans; + + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + dxdxi[pi*sdxdxi+3*j+k] = mat_dxdxi(j,k); + + // dxdxic = (*dxdxi)[pi]; + // (*dxdxi)[pi] = dxdxic * trans; + } + } + return; + } + + + + + + + + + Vector shapes; + MatrixFixWidth<3> dshapes; + + + const Element & el = mesh[elnr]; + ELEMENT_TYPE type = el.GetType(); + + ElementInfo info; + info.elnr = elnr; + info.order = order; + info.ndof = info.nv = MeshTopology::GetNVertices (type); + if (info.order > 1) + { + const MeshTopology & top = mesh.GetTopology(); + + info.nedges = top.GetElementEdges (elnr+1, info.edgenrs, 0); + for (int i = 0; i < info.nedges; i++) + info.edgenrs[i]--; + + info.nfaces = top.GetElementFaces (elnr+1, info.facenrs, 0); + for (int i = 0; i < info.nfaces; i++) + info.facenrs[i]--; + + for (int i = 0; i < info.nedges; i++) + info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]]; + for (int i = 0; i < info.nfaces; i++) + info.ndof += facecoeffsindex[info.facenrs[i]+1] - facecoeffsindex[info.facenrs[i]]; + // info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr]; + } + + ARRAY<Vec<3> > coefs(info.ndof); + GetCoefficients (info, &coefs[0]); + if (x) + { + for (int j = 0; j < n; j++) + { + Point<3> xij, xj; + for (int k = 0; k < 3; k++) + xij(k) = xi[j*sxi+k]; + + CalcElementShapes (info, xij, shapes); + xj = 0; + for (int i = 0; i < coefs.Size(); i++) + xj += shapes(i) * coefs[i]; + + for (int k = 0; k < 3; k++) + x[j*sx+k] = xj(k); + } + } + if (dxdxi) + { + for (int ip = 0; ip < n; ip++) + { + Point<3> xij; + for (int k = 0; k < 3; k++) + xij(k) = xi[ip*sxi+k]; + + CalcElementDShapes (info, xij, dshapes); + + Mat<3> dxdxij; + dxdxij = 0.0; + for (int i = 0; i < coefs.Size(); i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + dxdxij(j,k) += dshapes(i,k) * coefs[i](j); + + + for (int j = 0; j < 3; j++) + for (int k = 0; k < 3; k++) + dxdxi[ip*sdxdxi+3*j+k] = dxdxij(j,k); + } + } + } + + + + + + + + + +}; + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/curvedelems_new.hpp b/contrib/Netgen/libsrc/meshing/curvedelems_new.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ff9cd88071d0f799d80ed31486313c23e3088d7b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/curvedelems_new.hpp @@ -0,0 +1,205 @@ +#ifndef CURVEDELEMS_NEWH +#define CURVEDELEMS_NEWH + +/**************************************************************************/ +/* File: curvedelems.hpp */ +/* Author: Robert Gaisbauer (first version) */ +/* redesign by Joachim Schoeberl */ +/* Date: 27. Sep. 02, Feb 2006 */ +/**************************************************************************/ + + + + +class Refinement; + + +class CurvedElements +{ + const Mesh & mesh; + + ARRAY<int> edgeorder; + ARRAY<int> faceorder; + + ARRAY<int> edgecoeffsindex; + ARRAY<int> facecoeffsindex; + + ARRAY< Vec<3> > edgecoeffs; + ARRAY< Vec<3> > facecoeffs; + + ARRAY< double > edgeweight; // for rational 2nd order splines + + int order; + bool rational; + +public: + CurvedElements (const Mesh & amesh); + ~CurvedElements(); + + bool IsHighOrder() const { return order > 1; } + + void SetHighOrder (int aorder) { order=aorder; } + + void BuildCurvedElements(Refinement * ref, int aorder, bool arational = false); + + int GetOrder () { return order; } + + + bool IsSegmentCurved (SegmentIndex segnr) const; + bool IsSurfaceElementCurved (SurfaceElementIndex sei) const; + bool IsElementCurved (ElementIndex ei) const; + + + void CalcSegmentTransformation (double xi, SegmentIndex segnr, + Point<3> & x) + { CalcSegmentTransformation (xi, segnr, &x, NULL); }; + + void CalcSegmentTransformation (double xi, SegmentIndex segnr, + Vec<3> & dxdxi) + { CalcSegmentTransformation (xi, segnr, NULL, &dxdxi); }; + + void CalcSegmentTransformation (double xi, SegmentIndex segnr, + Point<3> & x, Vec<3> & dxdxi) + { CalcSegmentTransformation (xi, segnr, &x, &dxdxi, NULL); }; + + void CalcSegmentTransformation (double xi, SegmentIndex segnr, + Point<3> & x, Vec<3> & dxdxi, bool & curved) + { CalcSegmentTransformation (xi, segnr, &x, &dxdxi, &curved); }; + + + + void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, + Point<3> & x) + { CalcSurfaceTransformation (xi, elnr, &x, NULL); }; + + void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, + Mat<3,2> & dxdxi) + { CalcSurfaceTransformation (xi, elnr, NULL, &dxdxi); }; + + void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, + Point<3> & x, Mat<3,2> & dxdxi) + { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi, NULL); }; + + void CalcSurfaceTransformation (const Point<2> & xi, SurfaceElementIndex elnr, + Point<3> & x, Mat<3,2> & dxdxi, bool & curved) + { CalcSurfaceTransformation (xi, elnr, &x, &dxdxi, &curved); }; + + + + + + void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, + Point<3> & x) + { CalcElementTransformation (xi, elnr, &x, NULL); }; + + void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, + Mat<3,3> & dxdxi) + { CalcElementTransformation (xi, elnr, NULL, &dxdxi); }; + + void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, + Point<3> & x, Mat<3,3> & dxdxi) + { CalcElementTransformation (xi, elnr, &x, &dxdxi /* , NULL */ ); }; + + void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, + Point<3> & x, Mat<3,3> & dxdxi, + void * buffer, bool valid) + { CalcElementTransformation (xi, elnr, &x, &dxdxi, /* NULL, */ buffer, valid ); }; + + // void CalcElementTransformation (const Point<3> & xi, ElementIndex elnr, + // Point<3> & x, Mat<3,3> & dxdxi) // , bool & curved) + // { CalcElementTransformation (xi, elnr, &x, &dxdxi /* , &curved * ); } + + + + void CalcMultiPointSegmentTransformation (ARRAY<double> * xi, SegmentIndex segnr, + ARRAY<Point<3> > * x, + ARRAY<Vec<3> > * dxdxi); + + void CalcMultiPointSurfaceTransformation (ARRAY< Point<2> > * xi, SurfaceElementIndex elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,2> > * dxdxi); + + void CalcMultiPointElementTransformation (ARRAY< Point<3> > * xi, ElementIndex elnr, + ARRAY< Point<3> > * x, + ARRAY< Mat<3,3> > * dxdxi); + + void CalcMultiPointElementTransformation (ElementIndex elnr, int n, + const double * xi, int sxi, + double * x, int sx, + double * dxdxi, int sdxdxi); + + + + +private: + + void CalcSegmentTransformation (double xi, SegmentIndex segnr, + Point<3> * x = NULL, Vec<3> * dxdxi = NULL, bool * curved = NULL); + + void CalcSurfaceTransformation (Point<2> xi, SurfaceElementIndex elnr, + Point<3> * x = NULL, Mat<3,2> * dxdxi = NULL, bool * curved = NULL); + + void CalcElementTransformation (Point<3> xi, ElementIndex elnr, + Point<3> * x = NULL, Mat<3,3> * dxdxi = NULL, // bool * curved = NULL, + void * buffer = NULL, bool valid = 0); + + + + + + + class SegmentInfo + { + public: + SegmentIndex elnr; + int order; + int nv; + int ndof; + int edgenr; + }; + + void CalcElementShapes (SegmentInfo & elnr, double xi, Vector & shapes) const; + void GetCoefficients (SegmentInfo & elnr, ARRAY<Vec<3> > & coefs) const; + void CalcElementDShapes (SegmentInfo & elnr, double xi, Vector & dshapes) const; + + + class ElementInfo + { + public: + ElementIndex elnr; + int order; + int nv; + int ndof; + int nedges; + int nfaces; + int edgenrs[12]; + int facenrs[6]; + Mat<3> hdxdxi; + Vec<3> hcoefs[10]; // enough for second order tets + }; + + + void CalcElementShapes (ElementInfo & info, const Point<3> & xi, Vector & shapes) const; + void GetCoefficients (ElementInfo & info, Vec<3> * coefs) const; + void CalcElementDShapes (ElementInfo & info, const Point<3> & xi, MatrixFixWidth<3> & dshapes) const; + + + class SurfaceElementInfo + { + public: + SurfaceElementIndex elnr; + int order; + int nv; + int ndof; + ArrayMem<int,4> edgenrs; + int facenr; + }; + + void CalcElementShapes (SurfaceElementInfo & elinfo, const Point<2> & xi, Vector & shapes) const; + void GetCoefficients (SurfaceElementInfo & elinfo, ARRAY<Vec<3> > & coefs) const; + void CalcElementDShapes (SurfaceElementInfo & elinfo, const Point<2> & xi, DenseMatrix & dshapes) const; +}; + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/delaunay.cpp b/contrib/Netgen/libsrc/meshing/delaunay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e74afec32b67c6a60115bfe470ee4a1e18556289 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/delaunay.cpp @@ -0,0 +1,1676 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + + +namespace netgen +{ + + + static const int deltetfaces[][3] = + { { 1, 2, 3 }, + { 2, 0, 3 }, + { 0, 1, 3 }, + { 1, 0, 2 } }; + + + + + + + class DelaunayTet + { + PointIndex pnums[4]; + int nb[4]; + + public: + DelaunayTet () { ; } + + DelaunayTet (const DelaunayTet & el) + { + for (int i = 0; i < 4; i++) + pnums[i] = el[i]; + } + + DelaunayTet (const Element & el) + { + for (int i = 0; i < 4; i++) + pnums[i] = el[i]; + } + + PointIndex & operator[] (int i) { return pnums[i]; } + PointIndex operator[] (int i) const { return pnums[i]; } + + int & NB1(int i) { return nb[i-1]; } + int NB1(int i) const { return nb[i-1]; } + + int & NB(int i) { return nb[i]; } + int NB(int i) const { return nb[i]; } + + + int FaceNr (INDEX_3 & face) const // which face nr is it ? + { + for (int i = 0; i < 3; i++) + if (pnums[i] != face.I1() && + pnums[i] != face.I2() && + pnums[i] != face.I3()) + return i; + return 3; + } + + void GetFace1 (int i, INDEX_3 & face) const + { + face.I(1) = pnums[deltetfaces[i-1][0]]; + face.I(2) = pnums[deltetfaces[i-1][1]]; + face.I(3) = pnums[deltetfaces[i-1][2]]; + } + + void GetFace (int i, INDEX_3 & face) const + { + face.I(1) = pnums[deltetfaces[i][0]]; + face.I(2) = pnums[deltetfaces[i][1]]; + face.I(3) = pnums[deltetfaces[i][2]]; + } + + INDEX_3 GetFace1 (int i) const + { + return INDEX_3 (pnums[deltetfaces[i-1][0]], + pnums[deltetfaces[i-1][1]], + pnums[deltetfaces[i-1][2]]); + } + + INDEX_3 GetFace (int i) const + { + return INDEX_3 (pnums[deltetfaces[i][0]], + pnums[deltetfaces[i][1]], + pnums[deltetfaces[i][2]]); + } + + void GetFace1 (int i, Element2d & face) const + { + // face.SetType(TRIG); + face[0] = pnums[deltetfaces[i-1][0]]; + face[1] = pnums[deltetfaces[i-1][1]]; + face[2] = pnums[deltetfaces[i-1][2]]; + } + }; + + + + + + + + + + /* + Table to maintain neighbour elements + */ + class MeshNB + { + // face nodes -> one element + INDEX_3_CLOSED_HASHTABLE<int> faces; + + // + ARRAY<DelaunayTet> & tets; + + public: + + // estimated number of points + MeshNB (ARRAY<DelaunayTet> & atets, int np) + : faces(200), tets(atets) + { ; } + + // add element with 4 nodes + void Add (int elnr); + + // delete element with 4 nodes + void Delete (int elnr) + { + DelaunayTet & el = tets.Elem(elnr); + for (int i = 0; i < 4; i++) + faces.Set (el.GetFace(i).Sort(), el.NB(i)); + } + + // get neighbour of element elnr in direction fnr + int GetNB (int elnr, int fnr) + { + return tets.Get(elnr).NB1(fnr); + } + + // + void ResetFaceHT (int size) + { + faces.SetSize (size); + } + }; + + + + void MeshNB :: Add (int elnr) + { + DelaunayTet & el = tets.Elem(elnr); + + for (int i = 0; i < 4; i++) + { + INDEX_3 i3 = INDEX_3::Sort (el.GetFace(i)); + + int posnr; + + if (!faces.PositionCreate (i3, posnr)) + { + // face already in use + int othertet = faces.GetData (posnr); + + el.NB(i) = othertet; + if (othertet) + { + int fnr = tets.Get(othertet).FaceNr (i3); + tets.Elem(othertet).NB(fnr) = elnr; + } + } + else + { + faces.SetData (posnr, elnr); + el.NB(i) = 0; + } + } + } + + + + + + + /* + connected lists of cosphereical elements + */ + class SphereList + { + ARRAY<int> links; + public: + SphereList () + { ; } + + void AddElement (int elnr) + { + if (elnr > links.Size()) + links.Append (1); + links.Elem(elnr) = elnr; + } + + void DeleteElement (int elnr) + { + links.Elem(elnr) = 0; + } + + void ConnectElement (int eli, int toi) + { + links.Elem (eli) = links.Get (toi); + links.Elem (toi) = eli; + } + + void GetList (int eli, ARRAY<int> & linked) const; + }; + + + void SphereList :: GetList (int eli, ARRAY<int> & linked) const + { + linked.SetSize (0); + int pi = eli; + + do + { + if (pi <= 0 || pi > links.Size()) + { + cerr << "link, error " << endl; + cerr << "pi = " << pi << " linked.s = " << linked.Size() << endl; + exit(1); + } + if (linked.Size() > links.Size()) + { + cerr << "links have loop" << endl; + exit(1); + } + + linked.Append (pi); + pi = links.Get(pi); + } + while (pi != eli); + } + + + + + + void AddDelaunayPoint (PointIndex newpi, const Point3d & newp, + ARRAY<DelaunayTet> & tempels, + Mesh & mesh, + Box3dTree & tettree, + MeshNB & meshnb, + ARRAY<Point<3> > & centers, ARRAY<double> & radi2, + ARRAY<int> & connected, ARRAY<int> & treesearch, + ARRAY<int> & freelist, SphereList & list, + IndexSet & insphere, IndexSet & closesphere) + { + /* + find any sphere, such that newp is contained in + */ + + DelaunayTet el; + int cfelind = -1; + + const Point<3> * pp[4]; + Point<3> pc; + double r2; + Point3d tpmin, tpmax; + + tettree.GetIntersecting (newp, newp, treesearch); + + double quot,minquot(1e20); + + for (int j = 0; j < treesearch.Size(); j++) + { + int jjj = treesearch[j]; + quot = Dist2 (centers.Get(jjj), newp) / radi2.Get(jjj); + + if((cfelind == -1 || quot < 0.99*minquot) && quot < 1) + { + minquot = quot; + el = tempels.Get(jjj); + cfelind = jjj; + if(minquot < 0.917632) + break; + } + } + + + /* + int i, j, k, l; + if (!felind) + { + cerr << "not in any sphere, 1" << endl; + // old, non tree search + + double mindist = 1e10; + for (j = 1; j <= tempels.Size(); j++) + { + if (tempels.Get(j).PNum(1)) + { + double toofar = + Dist2 (centers.Get(j), newp) - radi2.Get(j); + if (toofar < mindist || toofar < 1e-7) + { + mindist = toofar; + cout << " dist2 = " << Dist2 (centers.Get(j), newp) + << " radi2 = " << radi2.Get(j) << endl; + } + if (toofar < 0) + { + el = tempels.Get(j); + felind = j; + cout << "sphere found !" << endl; + break; + } + } + } + cout << "point is too far from sheres: " << mindist << endl; + } + */ + + if (cfelind == -1) + { + PrintWarning ("Delaunay, point not in any sphere"); + return; + } + + + /* + insphere: point is in sphere -> delete element + closesphere: point is close to sphere -> considered for same center + */ + + // save overestimate + insphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP()); + closesphere.SetMaxIndex (2 * tempels.Size() + 5 * mesh.GetNP()); + + insphere.Clear(); + closesphere.Clear(); + + + insphere.Add (cfelind); + + int changed = 1; + int nstarti = 1, starti; + + + while (changed) + { + changed = 0; + starti = nstarti; + nstarti = insphere.Array().Size()+1; + + + // if point in sphere, then it is also closesphere + for (int j = starti; j < nstarti; j++) + { + int helind = insphere.Array().Get(j); + if (!closesphere.IsIn (helind)) + closesphere.Add (helind); + } + + // add connected spheres to insphere - list + for (int j = starti; j < nstarti; j++) + { + list.GetList (insphere.Array().Get(j), connected); + for (int k = 0; k < connected.Size(); k++) + { + int celind = connected[k]; + + if (tempels.Get(celind)[0] != -1 && + !insphere.IsIn (celind)) + { + changed = 1; + insphere.Add (celind); + } + } + } + + // check neighbour-tets + for (int j = starti; j < nstarti; j++) + for (int k = 1; k <= 4; k++) + { + int helind = insphere.Array().Get(j); + int nbind = meshnb.GetNB (helind, k); + + if (nbind && !insphere.IsIn (nbind) ) + { + //changed + //int prec = testout->precision(); + //testout->precision(12); + //(*testout) << "val1 " << Dist2 (centers.Get(nbind), newp) + // << " val2 " << radi2.Get(nbind) * (1+1e-8) + // << " val3 " << radi2.Get(nbind) + // << " val1 / val3 " << Dist2 (centers.Get(nbind), newp)/radi2.Get(nbind) << endl; + //testout->precision(prec); + if (Dist2 (centers.Get(nbind), newp) + < radi2.Get(nbind) * (1+1e-8) ) + closesphere.Add (nbind); + + if (Dist2 (centers.Get(nbind), newp) + < radi2.Get(nbind) * (1 + 1e-12)) + { + // point is in sphere -> remove tet + insphere.Add (nbind); + changed = 1; + } + else + { + /* + Element2d face; + tempels.Get(helind).GetFace (k, face); + + const Point3d & p1 = mesh.Point (face.PNum(1)); + const Point3d & p2 = mesh.Point (face[1]); + const Point3d & p3 = mesh.Point (face[2]); + */ + + INDEX_3 i3 = tempels.Get(helind).GetFace (k-1); + + const Point3d & p1 = mesh.Point ( PointIndex (i3.I1())); + const Point3d & p2 = mesh.Point ( PointIndex (i3.I2())); + const Point3d & p3 = mesh.Point ( PointIndex (i3.I3())); + + + Vec3d v1(p1, p2); + Vec3d v2(p1, p3); + Vec3d n = Cross (v1, v2); + n /= n.Length(); + + if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k-1])) > 0) + n *= -1; + + double dist = n * Vec3d (p1, newp); + + + if (dist > -1e-10) // 1e-10 + { + insphere.Add (nbind); + changed = 1; + } + + + } + } + } + } // while (changed) + + // (*testout) << "newels: " << endl; + ARRAY<Element> newels; + + Element2d face(TRIG); + + for (int j = 1; j <= insphere.Array().Size(); j++) + for (int k = 1; k <= 4; k++) + { + // int elind = insphere.Array().Get(j); + int celind = insphere.Array().Get(j); + int nbind = meshnb.GetNB (celind, k); + + if (!nbind || !insphere.IsIn (nbind)) + { + tempels.Get (celind).GetFace1 (k, face); + + Element newel(TET); + for (int l = 0; l < 3; l++) + newel[l] = face[l]; + newel[3] = newpi; + + newels.Append (newel); + + Vec<3> v1 = mesh[face[1]] - mesh[face[0]]; + Vec<3> v2 = mesh[face[2]] - mesh[face[0]]; + Vec<3> n = Cross (v1, v2); + + n.Normalize(); + if (n * Vec3d(mesh.Point (face[0]), + mesh.Point (tempels.Get(insphere.Array().Get(j))[k-1])) + > 0) + n *= -1; + + double hval = n * ( newp - mesh[face[0]]); + + if (hval > -1e-12) + { + cerr << "vec to outer" << endl; + (*testout) << "vec to outer, hval = " << hval << endl; + (*testout) << "v1 x v2 = " << Cross (v1, v2) << endl; + (*testout) << "facep: " + << mesh.Point (face[0]) << " " + << mesh.Point (face[1]) << " " + << mesh.Point (face[2]) << endl; + } + } + } + + meshnb.ResetFaceHT (10*insphere.Array().Size()+1); + + for (int j = 1; j <= insphere.Array().Size(); j++) + { + // int elind = + int celind = insphere.Array().Get(j); + + meshnb.Delete (celind); + list.DeleteElement (celind); + + for (int k = 0; k < 4; k++) + tempels.Elem(celind)[k] = -1; + + ((ADTree6&)tettree.Tree()).DeleteElement (celind); + freelist.Append (celind); + } + + + int hasclose = 0; + for (int j = 1; j <= closesphere.Array().Size(); j++) + { + int ind = closesphere.Array().Get(j); + if (!insphere.IsIn(ind) && + fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 ) + hasclose = 1; + } + + for (int j = 1; j <= newels.Size(); j++) + { + int nelind; + + if (!freelist.Size()) + { + tempels.Append (newels.Get(j)); + nelind = tempels.Size(); + } + else + { + nelind = freelist.Last(); + freelist.DeleteLast(); + + tempels.Elem(nelind) = newels.Get(j); + } + + meshnb.Add (nelind); + list.AddElement (nelind); + + for (int k = 0; k < 4; k++) + pp[k] = &mesh.Point (newels.Get(j)[k]); + + if (CalcSphereCenter (&pp[0], pc) ) + { + PrintSysError ("Delaunay: New tet is flat"); + + (*testout) << "new tet is flat" << endl; + for (int k = 1; k <= 4; k++) + (*testout) << newels.Get(j).PNum(k) << " "; + (*testout) << endl; + for (int k = 1; k <= 4; k++) + (*testout) << *pp[k-1] << " "; + (*testout) << endl; + } + + r2 = Dist2 (*pp[0], pc); + if (hasclose) + for (int k = 1; k <= closesphere.Array().Size(); k++) + { + int csameind = closesphere.Array().Get(k); + if (!insphere.IsIn(csameind) && + fabs (r2 - radi2.Get(csameind)) < 1e-10 && + Dist (pc, centers.Get(csameind)) < 1e-10) + { + pc = centers.Get(csameind); + r2 = radi2.Get(csameind); + list.ConnectElement (nelind, csameind); + break; + } + } + + if (centers.Size() < nelind) + { + centers.Append (pc); + radi2.Append (r2); + } + else + { + centers.Elem(nelind) = pc; + radi2.Elem(nelind) = r2; + } + + closesphere.Add (nelind); + + tpmax = tpmin = *pp[0]; + for (int k = 1; k <= 3; k++) + { + tpmin.SetToMin (*pp[k]); + tpmax.SetToMax (*pp[k]); + } + tpmax = tpmax + 0.01 * (tpmax - tpmin); + tettree.Insert (tpmin, tpmax, nelind); + } + } + + + + + + + void Delaunay1 (Mesh & mesh, const MeshingParameters & mp, AdFront3 * adfront, + ARRAY<DelaunayTet> & tempels, + int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax) + { + int i, j, k; + const Point<3> * pp[4]; + + ARRAY<Point<3> > centers; + ARRAY<double> radi2; + + Point3d tpmin, tpmax; + + + // new: local box + mesh.GetBox (pmax, pmin); // lower bound for pmax, upper for pmin + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & face = adfront->GetFace(i); + for (j = 0; j < face.GetNP(); j++) + { + pmin.SetToMin (mesh.Point (face[j])); + pmax.SetToMax (mesh.Point (face[j])); + } + } + + for (i = 0; i < mesh.LockedPoints().Size(); i++) + { + pmin.SetToMin (mesh.Point (mesh.LockedPoints()[i])); + pmax.SetToMax (mesh.Point (mesh.LockedPoints()[i])); + } + + + + Vec3d vdiag(pmin, pmax); + // double r1 = vdiag.Length(); + double r1 = sqrt (3.0) * max3(vdiag.X(), vdiag.Y(), vdiag.Z()); + vdiag = Vec3d (r1, r1, r1); + //double r2; + + Point3d pmin2 = pmin - 8 * vdiag; + Point3d pmax2 = pmax + 8 * vdiag; + + Point3d cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2); + cp2.X() = pmin2.X(); + cp3.Y() = pmin2.Y(); + cp4.Z() = pmin2.Z(); + + + + + int np = mesh.GetNP(); + + startel[0] = mesh.AddPoint (cp1); + startel[1] = mesh.AddPoint (cp2); + startel[2] = mesh.AddPoint (cp3); + startel[3] = mesh.AddPoint (cp4); + + // flag points to use for Delaunay: + BitArrayChar<PointIndex::BASE> usep(np); + usep.Clear(); + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & face = adfront->GetFace(i); + for (j = 0; j < face.GetNP(); j++) + usep.Set (face[j]); + } + + for (i = oldnp + PointIndex::BASE; + i < np + PointIndex::BASE; i++) + usep.Set (i); + + for (i = 0; i < mesh.LockedPoints().Size(); i++) + usep.Set (mesh.LockedPoints()[i]); + + + ARRAY<int> freelist; + + + int cntp = 0; + + MeshNB meshnb (tempels, mesh.GetNP() + 5); + SphereList list; + + pmin2 = pmin2 + 0.1 * (pmin2 - pmax2); + pmax2 = pmax2 + 0.1 * (pmax2 - pmin2); + + Box3dTree tettree(pmin2, pmax2); + + + tempels.Append (startel); + meshnb.Add (1); + list.AddElement (1); + ARRAY<int> connected, treesearch; + + + tpmin = tpmax = mesh.Point(startel[0]); + for (k = 1; k < 4; k++) + { + tpmin.SetToMin (mesh.Point (startel[k])); + tpmax.SetToMax (mesh.Point (startel[k])); + } + tpmax = tpmax + 0.01 * (tpmax - tpmin); + tettree.Insert (tpmin, tpmax, 1); + + + Point<3> pc; + + for (k = 0; k < 4; k++) + { + pp[k] = &mesh.Point (startel[k]); + } + + CalcSphereCenter (&pp[0], pc); + + centers.Append (pc); + radi2.Append (Dist2 (*pp[0], pc)); + + + IndexSet insphere(mesh.GetNP()); + IndexSet closesphere(mesh.GetNP()); + + + + // "random" reordering of points (speeds a factor 3 - 5 !!!) + + ARRAY<int> mixed(np); + int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 }; + int prim; + + i = 0; + while (np % prims[i] == 0) i++; + prim = prims[i]; + + for (i = 1; i <= np; i++) + mixed.Elem(i) = (prim * i) % np + PointIndex::BASE; + + for (i = 1; i <= np; i++) + { + if (i % 1000 == 0) + { + if (i % 10000 == 0) + PrintDot ('+'); + else + PrintDot ('.'); + } + + multithread.percent = 100.0 * i / np; + if (multithread.terminate) + break; + + PointIndex newpi = mixed.Get(i); + + if (!usep.Test(newpi)) + continue; + + cntp++; + + const Point3d & newp = mesh.Point(newpi); + + AddDelaunayPoint (newpi, newp, tempels, mesh, + tettree, meshnb, centers, radi2, + connected, treesearch, freelist, list, insphere, closesphere); + } + + for (i = tempels.Size(); i >= 1; i--) + if (tempels.Get(i)[0] <= 0) + tempels.DeleteElement (i); + + PrintDot ('\n'); + + PrintMessage (3, "Points: ", cntp); + PrintMessage (3, "Elements: ", tempels.Size()); + // (*mycout) << cntp << " / " << tempels.Size() << " points/elements" << endl; + + /* + cout << "tempels: "; + tempels.PrintMemInfo(cout); + cout << "Searchtree: "; + tettree.Tree().PrintMemInfo(cout); + cout << "MeshNB: "; + meshnb.PrintMemInfo(cout); + */ + } + + + + + + + void Meshing3 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp) + { + int np, ne; + + PrintMessage (1, "Delaunay meshing"); + PrintMessage (3, "number of points: ", mesh.GetNP()); + PushStatus ("Delaunay meshing"); + + + ARRAY<DelaunayTet> tempels; + Point3d pmin, pmax; + + DelaunayTet startel; + + int oldnp = mesh.GetNP(); + if (mp.blockfill) + { + BlockFillLocalH (mesh, mp); + PrintMessage (3, "number of points: ", mesh.GetNP()); + } + + np = mesh.GetNP(); + + Delaunay1 (mesh, mp, adfront, tempels, oldnp, startel, pmin, pmax); + + { + // improve delaunay - mesh by swapping !!!! + + Mesh tempmesh; + for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) + tempmesh.AddPoint (mesh[pi]); + + for (int i = 1; i <= tempels.Size(); i++) + { + Element el(4); + for (int j = 0; j < 4; j++) + el[j] = tempels.Elem(i)[j]; + + el.SetIndex (1); + + const Point3d & lp1 = mesh.Point (el[0]); + const Point3d & lp2 = mesh.Point (el[1]); + const Point3d & lp3 = mesh.Point (el[2]); + const Point3d & lp4 = mesh.Point (el[3]); + Vec3d v1(lp1, lp2); + Vec3d v2(lp1, lp3); + Vec3d v3(lp1, lp4); + + Vec3d n = Cross (v1, v2); + double vol = n * v3; + if (vol > 0) swap (el[2], el[3]); + + tempmesh.AddVolumeElement (el); + } + + + MeshQuality3d (tempmesh); + + tempmesh.AddFaceDescriptor (FaceDescriptor (1, 1, 0, 0)); + tempmesh.AddFaceDescriptor (FaceDescriptor (2, 1, 0, 0)); + + + + for (int i = 1; i <= mesh.GetNOpenElements(); i++) + { + Element2d sel = mesh.OpenElement(i); + sel.SetIndex(1); + tempmesh.AddSurfaceElement (sel); + swap (sel[1], sel[2]); + tempmesh.AddSurfaceElement (sel); + } + + + for (int i = 1; i <= 4; i++) + { + Element2d self(TRIG); + self.SetIndex (1); + startel.GetFace1 (i, self); + tempmesh.AddSurfaceElement (self); + } + + + // for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++) + // tempmesh.AddLockedPoint (i); + for (PointIndex pi = PointIndex::BASE; + pi < tempmesh.GetNP() + PointIndex::BASE; pi++) + tempmesh.AddLockedPoint (pi); + + // tempmesh.PrintMemInfo(cout); + // tempmesh.Save ("tempmesh.vol"); + + for (int i = 1; i <= 2; i++) + { + tempmesh.FindOpenElements (); + + PrintMessage (5, "Num open: ", tempmesh.GetNOpenElements()); + tempmesh.CalcSurfacesOfNode (); + + tempmesh.FreeOpenElementsEnvironment (1); + + MeshOptimize3d meshopt; + // tempmesh.CalcSurfacesOfNode(); + meshopt.SwapImprove(tempmesh, OPT_CONFORM); + } + + MeshQuality3d (tempmesh); + + tempels.SetSize(0); + for (int i = 1; i <= tempmesh.GetNE(); i++) + tempels.Append (tempmesh.VolumeElement(i)); + } + + + + // remove degenerated + + BitArray badnode(mesh.GetNP()); + badnode.Clear(); + int ndeg = 0; + for (int i = 1; i <= tempels.Size(); i++) + { + Element el(4); + for (int j = 0; j < 4; j++) + el[j] = tempels.Elem(i)[j]; + // Element & el = tempels.Elem(i); + const Point3d & lp1 = mesh.Point (el[0]); + const Point3d & lp2 = mesh.Point (el[1]); + const Point3d & lp3 = mesh.Point (el[2]); + const Point3d & lp4 = mesh.Point (el[3]); + Vec3d v1(lp1, lp2); + Vec3d v2(lp1, lp3); + Vec3d v3(lp1, lp4); + Vec3d n = Cross (v1, v2); + double vol = n * v3; + + double h = v1.Length() + v2.Length() + v3.Length(); + if (fabs (vol) < 1e-8 * (h * h * h) && + (el[0] <= np && el[1] <= np && + el[2] <= np && el[3] <= np) ) // old: 1e-12 + { + badnode.Set(el[0]); + badnode.Set(el[1]); + badnode.Set(el[2]); + badnode.Set(el[3]); + ndeg++; + (*testout) << "vol = " << vol << " h = " << h << endl; + } + + if (vol > 0) + Swap (el[2], el[3]); + } + + ne = tempels.Size(); + for (int i = ne; i >= 1; i--) + { + const DelaunayTet & el = tempels.Get(i); + if (badnode.Test(el[0]) || + badnode.Test(el[1]) || + badnode.Test(el[2]) || + badnode.Test(el[3]) ) + tempels.DeleteElement(i); + } + + + PrintMessage (3, ndeg, " degenerated elements removed"); + + // find surface triangles which are no face of any tet + + INDEX_3_HASHTABLE<int> openeltab(mesh.GetNOpenElements()+3); + ARRAY<int> openels; + for (int i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & tri = mesh.OpenElement(i); + INDEX_3 i3(tri[0], tri[1], tri[2]); + i3.Sort(); + openeltab.Set (i3, i); + } + + for (int i = 1; i <= tempels.Size(); i++) + { + for (int j = 0; j < 4; j++) + { + INDEX_3 i3 = tempels.Get(i).GetFace (j); + i3.Sort(); + if (openeltab.Used(i3)) + openeltab.Set (i3, 0); + } + } + + // and store them in openels + for (int i = 1; i <= openeltab.GetNBags(); i++) + for (int j = 1; j <= openeltab.GetBagSize(i); j++) + { + INDEX_3 i3; + int fnr; + openeltab.GetData (i, j, i3, fnr); + if (fnr) + openels.Append (fnr); + } + + + + + + // find open triangle with close edge (from halfening of surface squares) + + INDEX_2_HASHTABLE<INDEX_2> twotrias(mesh.GetNOpenElements()+5); + // for (i = 1; i <= mesh.GetNOpenElements(); i++) + for (int ii = 1; ii <= openels.Size(); ii++) + { + int i = openels.Get(ii); + const Element2d & el = mesh.OpenElement(i); + for (int j = 1; j <= 3; j++) + { + INDEX_2 hi2 (el.PNumMod (j), el.PNumMod(j+1)); + hi2.Sort(); + if (twotrias.Used(hi2)) + { + INDEX_2 hi3; + hi3 = twotrias.Get (hi2); + hi3.I2() = el.PNumMod (j+2); + twotrias.Set (hi2, hi3); + } + else + { + INDEX_2 hi3(el.PNumMod (j+2), 0); + twotrias.Set (hi2, hi3); + } + } + } + + INDEX_2_HASHTABLE<int> tetedges(tempels.Size() + 5); + for (int i = 1; i <= tempels.Size(); i++) + { + const DelaunayTet & el = tempels.Get(i); + INDEX_2 i2; + for (int j = 1; j <= 6; j++) + { + switch (j) + { + case 1: i2.I1()=el[0]; i2.I2()=el[1]; break; + case 2: i2.I1()=el[0]; i2.I2()=el[2]; break; + case 3: i2.I1()=el[0]; i2.I2()=el[3]; break; + case 4: i2.I1()=el[1]; i2.I2()=el[2]; break; + case 5: i2.I1()=el[1]; i2.I2()=el[3]; break; + case 6: i2.I1()=el[2]; i2.I2()=el[3]; break; + default: i2.I1()=i2.I2()=0; break; + } + i2.Sort(); + tetedges.Set (i2, 1); + } + } + // cout << "tetedges:"; + // tetedges.PrintMemInfo (cout); + + + for (INDEX_2_HASHTABLE<INDEX_2>::Iterator it = twotrias.Begin(); + it != twotrias.End(); it++) + { + INDEX_2 hi2, hi3; + twotrias.GetData (it, hi2, hi3); + hi3.Sort(); + if (tetedges.Used (hi3)) + { + const Point3d & p1 = mesh.Point ( PointIndex (hi2.I1())); + const Point3d & p2 = mesh.Point ( PointIndex (hi2.I2())); + const Point3d & p3 = mesh.Point ( PointIndex (hi3.I1())); + const Point3d & p4 = mesh.Point ( PointIndex (hi3.I2())); + Vec3d v1(p1, p2); + Vec3d v2(p1, p3); + Vec3d v3(p1, p4); + Vec3d n = Cross (v1, v2); + double vol = n * v3; + + double h = v1.Length() + v2.Length() + v3.Length(); + if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12 + { + badnode.Set(hi3.I1()); + badnode.Set(hi3.I2()); + } + } + } + + /* + for (i = 1; i <= twotrias.GetNBags(); i++) + for (j = 1; j <= twotrias.GetBagSize (i); j++) + { + INDEX_2 hi2, hi3; + twotrias.GetData (i, j, hi2, hi3); + hi3.Sort(); + if (tetedges.Used (hi3)) + { + const Point3d & p1 = mesh.Point (hi2.I1()); + const Point3d & p2 = mesh.Point (hi2.I2()); + const Point3d & p3 = mesh.Point (hi3.I1()); + const Point3d & p4 = mesh.Point (hi3.I2()); + Vec3d v1(p1, p2); + Vec3d v2(p1, p3); + Vec3d v3(p1, p4); + Vec3d n = Cross (v1, v2); + double vol = n * v3; + + double h = v1.Length() + v2.Length() + v3.Length(); + if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12 + { + badnode.Set(hi3.I1()); + badnode.Set(hi3.I2()); + } + } + } + */ + + ne = tempels.Size(); + for (int i = ne; i >= 1; i--) + { + const DelaunayTet & el = tempels.Get(i); + if (badnode.Test(el[0]) || + badnode.Test(el[1]) || + badnode.Test(el[2]) || + badnode.Test(el[3]) ) + tempels.DeleteElement(i); + } + + + + + // find intersecting: + PrintMessage (3, "Remove intersecting"); + if (openels.Size()) + { + Box3dTree setree(pmin, pmax); + + /* + cout << "open elements in search tree: " << openels.Size() << endl; + cout << "pmin, pmax = " << pmin << " - " << pmax << endl; + */ + + for (int i = 1; i <= openels.Size(); i++) + { + int fnr; + fnr = openels.Get(i); + if (fnr) + { + const Element2d & tri = mesh.OpenElement(fnr); + + Point3d ltpmin (mesh.Point(tri[0])); + Point3d ltpmax (ltpmin); + + for (int k = 2; k <= 3; k++) + { + ltpmin.SetToMin (mesh.Point (tri.PNum(k))); + ltpmax.SetToMax (mesh.Point (tri.PNum(k))); + } + setree.Insert (ltpmin, ltpmax, fnr); + } + } + + ARRAY<int> neartrias; + for (int i = 1; i <= tempels.Size(); i++) + { + const Point<3> *pp[4]; + int tetpi[4]; + DelaunayTet & el = tempels.Elem(i); + + int intersect = 0; + + for (int j = 0; j < 4; j++) + { + pp[j] = &mesh.Point(el[j]); + tetpi[j] = el[j]; + } + + Point3d tetpmin(*pp[0]); + Point3d tetpmax(tetpmin); + for (int j = 1; j < 4; j++) + { + tetpmin.SetToMin (*pp[j]); + tetpmax.SetToMax (*pp[j]); + } + tetpmin = tetpmin + 0.01 * (tetpmin - tetpmax); + tetpmax = tetpmax + 0.01 * (tetpmax - tetpmin); + + setree.GetIntersecting (tetpmin, tetpmax, neartrias); + + + // for (j = 1; j <= mesh.GetNSE(); j++) + // { + for (int jj = 1; jj <= neartrias.Size(); jj++) + { + int j = neartrias.Get(jj); + + const Element2d & tri = mesh.OpenElement(j); + const Point<3> *tripp[3]; + int tripi[3]; + + for (int k = 1; k <= 3; k++) + { + tripp[k-1] = &mesh.Point (tri.PNum(k)); + tripi[k-1] = tri.PNum(k); + } + + if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi)) + { + /* + int il1, il2; + (*testout) << "intersect !" << endl; + (*testout) << "triind: "; + for (il1 = 0; il1 < 3; il1++) + (*testout) << " " << tripi[il1]; + (*testout) << endl; + (*testout) << "tetind: "; + for (il2 = 0; il2 < 4; il2++) + (*testout) << " " << tetpi[il2]; + (*testout) << endl; + + (*testout) << "trip: "; + for (il1 = 0; il1 < 3; il1++) + (*testout) << " " << *tripp[il1]; + (*testout) << endl; + (*testout) << "tetp: "; + for (il2 = 0; il2 < 4; il2++) + (*testout) << " " << *pp[il2]; + (*testout) << endl; + */ + + + intersect = 1; + break; + } + } + + + if (intersect) + { + tempels.DeleteElement(i); + i--; + } + } + } + + + + + PrintMessage (3, "Remove outer"); + + // find connected tets (with no face between, and no hole due + // to removed intersecting tets. + // INDEX_3_HASHTABLE<INDEX_2> innerfaces(np); + + + INDEX_3_HASHTABLE<int> boundaryfaces(mesh.GetNOpenElements()/3+1); + for (int i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & tri = mesh.OpenElement(i); + INDEX_3 i3 (tri[0], tri[1], tri[2]); + i3.Sort(); + boundaryfaces.PrepareSet (i3); + } + boundaryfaces.AllocateElements(); + for (int i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & tri = mesh.OpenElement(i); + INDEX_3 i3 (tri[0], tri[1], tri[2]); + i3.Sort(); + boundaryfaces.Set (i3, 1); + } + + for (int i = 0; i < tempels.Size(); i++) + for (int j = 0; j < 4; j++) + tempels[i].NB(j) = 0; + + TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP()); + for (int i = 0; i < tempels.Size(); i++) + { + const DelaunayTet & el = tempels[i]; + INDEX_4 i4(el[0], el[1], el[2], el[3]); + i4.Sort(); + elsonpoint.IncSizePrepare (i4.I1()); + elsonpoint.IncSizePrepare (i4.I2()); + } + + elsonpoint.AllocateElementsOneBlock(); + + for (int i = 0; i < tempels.Size(); i++) + { + const DelaunayTet & el = tempels[i]; + INDEX_4 i4(el[0], el[1], el[2], el[3]); + i4.Sort(); + elsonpoint.Add (i4.I1(), i+1); + elsonpoint.Add (i4.I2(), i+1); + } + + // cout << "elsonpoint mem: "; + // elsonpoint.PrintMemInfo(cout); + + INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht(100); + + Element2d hel(TRIG); + for (PointIndex pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + { + faceht.SetSize (4 * elsonpoint[pi].Size()); + for (int ii = 0; ii < elsonpoint[pi].Size(); ii++) + { + int i = elsonpoint[pi][ii]; + const DelaunayTet & el = tempels.Get(i); + + for (int j = 1; j <= 4; j++) + { + el.GetFace1 (j, hel); + hel.Invert(); + hel.NormalizeNumbering(); + + if (hel[0] == pi) + { + INDEX_3 i3(hel[0], hel[1], hel[2]); + + if (!boundaryfaces.Used (i3)) + { + if (faceht.Used (i3)) + { + INDEX_2 i2 = faceht.Get(i3); + + tempels.Elem(i).NB1(j) = i2.I1(); + tempels.Elem(i2.I1()).NB1(i2.I2()) = i; + } + else + { + hel.Invert(); + hel.NormalizeNumbering(); + INDEX_3 i3i(hel[0], hel[1], hel[2]); + INDEX_2 i2(i, j); + faceht.Set (i3i, i2); + } + } + } + } + } + } + + /* + for (i = 1; i <= tempels.Size(); i++) + { + const DelaunayTet & el = tempels.Get(i); + for (j = 1; j <= 4; j++) + { + INDEX_3 i3; + Element2d face; + el.GetFace1 (j, face); + for (int kk = 1; kk <= 3; kk++) + i3.I(kk) = face.PNum(kk); + + i3.Sort(); + if (!boundaryfaces.Used (i3)) + { + if (innerfaces.Used(i3)) + { + INDEX_2 i2; + i2 = innerfaces.Get(i3); + i2.I2() = i; + innerfaces.Set (i3, i2); + } + else + { + INDEX_2 i2; + i2.I1() = i; + i2.I2() = 0; + innerfaces.Set (i3, i2); + } + } + } + } + */ + + /* + (*testout) << "nb elements:" << endl; + for (i = 1; i <= tempels.Size(); i++) + { + (*testout) << i << " "; + for (j = 1; j <= 4; j++) + (*testout) << tempels.Get(i).NB1(j) << " "; + (*testout) << endl; + } + + (*testout) << "pairs:" << endl; + for (i = 1; i <= innerfaces.GetNBags(); i++) + for (j = 1; j <= innerfaces.GetBagSize(i); j++) + { + INDEX_3 i3; + INDEX_2 i2; + innerfaces.GetData (i, j, i3, i2); + (*testout) << i2 << endl; + } + */ + + + + + + + + /* + cout << "innerfaces: "; + innerfaces.PrintMemInfo (cout); + */ + + // cout << "boundaryfaces: "; + // boundaryfaces.PrintMemInfo (cout); + + + PrintMessage (5, "tables filled"); + + + ne = tempels.Size(); + BitArray inner(ne), outer(ne); + inner.Clear(); + outer.Clear(); + ARRAY<int> elstack; + + /* + int starti = 0; + for (i = 1; i <= ne; i++) + { + const Element & el = tempels.Get(i); + for (j = 1; j <= 4; j++) + for (k = 1; k <= 4; k++) + if (el.PNum(j) == startel.PNum(k)) + { + outer.Set(i); + starti = i; + } + } + */ + + while (1) + { + int inside; + bool done = 1; + + int i; + for (i = 1; i <= ne; i++) + if (!inner.Test(i) && !outer.Test(i)) + { + done = 0; + break; + } + + if (done) break; + + const DelaunayTet & el = tempels.Get(i); + const Point3d & p1 = mesh.Point (el[0]); + const Point3d & p2 = mesh.Point (el[1]); + const Point3d & p3 = mesh.Point (el[2]); + const Point3d & p4 = mesh.Point (el[3]); + + Point3d ci = Center (p1, p2, p3, p4); + + inside = adfront->Inside (ci); + + /* + cout << "startel: " << i << endl; + cout << "inside = " << inside << endl; + cout << "ins2 = " << adfront->Inside (Center (ci, p1)) << endl; + cout << "ins3 = " << adfront->Inside (Center (ci, p2)) << endl; + */ + + elstack.SetSize(0); + elstack.Append (i); + + while (elstack.Size()) + { + int ei = elstack.Last(); + elstack.DeleteLast(); + + if (!inner.Test(ei) && !outer.Test(ei)) + { + if (inside) + inner.Set(ei); + else + outer.Set(ei); + + + for (int j = 1; j <= 4; j++) + { + INDEX_3 i3 = tempels.Get(ei).GetFace1(j); + /* + Element2d face; + tempels.Get(ei).GetFace(j, face); + for (int kk = 1; kk <= 3; kk++) + i3.I(kk) = face.PNum(kk); + */ + i3.Sort(); + + + if (tempels.Get(ei).NB1(j)) + elstack.Append (tempels.Get(ei).NB1(j)); + + /* + if (innerfaces.Used(i3)) + { + INDEX_2 i2 = innerfaces.Get(i3); + int other = i2.I1() + i2.I2() - ei; + + if (other != tempels.Get(ei).NB1(j)) + cerr << "different1 !!" << endl; + + if (other) + { + elstack.Append (other); + } + } + else + if (tempels.Get(ei).NB1(j)) + cerr << "different2 !!" << endl; + */ + + } + } + } + } + + + + // check outer elements + if (debugparam.slowchecks) + { + for (int i = 1; i <= ne; i++) + { + const DelaunayTet & el = tempels.Get(i); + const Point3d & p1 = mesh.Point (el[0]); + const Point3d & p2 = mesh.Point (el[1]); + const Point3d & p3 = mesh.Point (el[2]); + const Point3d & p4 = mesh.Point (el[3]); + + Point3d ci = Center (p1, p2, p3, p4); + + // if (adfront->Inside (ci) != adfront->Inside (Center (ci, p1))) + // cout << "ERROR: outer test unclear !!!" << endl; + + if (inner.Test(i) != adfront->Inside (ci)) + { + /* + cout << "ERROR: outer test wrong !!!" + << "inner = " << int(inner.Test(i)) + << "outer = " << int(outer.Test(i)) + << endl; + + cout << "Vol = " << Determinant(Vec3d(p1, p2), + Vec3d(p1, p3), + Vec3d(p1, p4)) << endl; + + */ + for (int j = 1; j <= 4; j++) + { + Point3d hp; + switch (j) + { + case 1: hp = Center (ci, p1); break; + case 2: hp = Center (ci, p2); break; + case 3: hp = Center (ci, p3); break; + case 4: hp = Center (ci, p4); break; + } + // cout << "inside(" << hp << ") = " << adfront->Inside(hp) << endl; + } + + } + + if (adfront->Inside(ci)) + outer.Clear(i); + else + outer.Set(i); + } + } + + + /* + + // find bug in innerfaces + + tempmesh.DeleteVolumeElements(); + + for (i = 1; i <= innerfaces.GetNBags(); i++) + for (j = 1; j <= innerfaces.GetBagSize(i); j++) + { + INDEX_3 i3; + INDEX_2 i2; + innerfaces.GetData (i, j, i3, i2); + if (i2.I2()) + { + if (outer.Test(i2.I1()) != outer.Test(i2.I2())) + { + tempmesh.AddVolumeElement (tempels.Get(i2.I1())); + tempmesh.AddVolumeElement (tempels.Get(i2.I2())); + cerr << "outer flag different for connected els" << endl; + } + } + } + + + cout << "Check intersectiong once more" << endl; + + for (i = 1; i <= openels.Size(); i++) + { + tempmesh.SurfaceElement(2*openels.Get(i)).SetIndex(2); + tempmesh.SurfaceElement(2*openels.Get(i)-1).SetIndex(2); + } + + // for (i = 1; i <= tempmesh.GetNE(); i++) + // for (j = 1; j <= tempmesh.GetNSE(); j++) + i = 6; j = 403; + if (i <= tempmesh.GetNE() && j <= tempmesh.GetNSE()) + if (tempmesh.SurfaceElement(j).GetIndex()==2) + { + const Element & el = tempmesh.VolumeElement(i); + const Element2d & sel = tempmesh.SurfaceElement(j); + + const Point3d *tripp[3]; + const Point3d *pp[4]; + int tetpi[4], tripi[3]; + + for (k = 1; k <= 4; k++) + { + pp[k-1] = &tempmesh.Point(el.PNum(k)); + tetpi[k-1] = el.PNum(k); + } + + for (k = 1; k <= 3; k++) + { + tripp[k-1] = &tempmesh.Point (sel.PNum(k)); + tripi[k-1] = sel.PNum(k); + } + + (*testout) << "Check Triangle " << j << ":"; + for (k = 1; k <= 3; k++) + (*testout) << " " << sel.PNum(k); + for (k = 1; k <= 3; k++) + (*testout) << " " << tempmesh.Point(sel.PNum(k)); + (*testout) << endl; + + (*testout) << "Check Tet " << i << ":"; + for (k = 1; k <= 4; k++) + (*testout) << " " << el.PNum(k); + for (k = 1; k <= 4; k++) + (*testout) << " " << tempmesh.Point(el.PNum(k)); + (*testout) << endl; + + if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi)) + { + cout << "Intesection detected !!" << endl; + } + } + + tempmesh.Save ("temp.vol"); + + // end bug search + */ + + + for (int i = ne; i >= 1; i--) + { + if (outer.Test(i)) + tempels.DeleteElement(i); + } + + + // mesh.points.SetSize(mesh.points.Size()-4); + + for (int i = 0; i < tempels.Size(); i++) + { + Element el(4); + for (int j = 0; j < 4; j++) + el[j] = tempels[i][j]; + mesh.AddVolumeElement (el); + } + + PrintMessage (5, "outer removed"); + + mesh.FindOpenElements(domainnr); + + mesh.Compress(); + + PopStatus (); + } +} diff --git a/contrib/Netgen/libsrc/meshing/findip.cpp b/contrib/Netgen/libsrc/meshing/findip.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7be0ee913d1b295fa5fda890a675a689543504d7 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/findip.cpp @@ -0,0 +1,115 @@ +// find inner point + +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + +template <typename POINTARRAY, typename FACEARRAY> +int FindInnerPoint (POINTARRAY & points, + FACEARRAY & faces, + Point3d & p) +{ + int i, j; + ARRAY<Vec3d> a; + ARRAY<double> c; + Point3d p1, pmin; + int i1, i2, i3, i4; + int nf; + DenseMatrix m(3), inv(3); + Vector rs(3), x(3); + double f, fmin, hd, hmax; + + nf = faces.Size(); + + // testout << "#faces = " << faces.Size() << endl; + // testout << "#points = " << points.Size() << endl; + + a.SetSize (nf); + c.SetSize (nf); + + for (i = 1; i <= nf; i++) + { + p1 = points.Get(faces.Get(i).PNum(1)); + a.Elem(i) = Cross (points.Get(faces.Get(i).PNum(2)) - points.Get(faces.Get(i).PNum(1)), + points.Get(faces.Get(i).PNum(3)) - points.Get(faces.Get(i).PNum(1))); + a.Elem(i) /= a.Get(i).Length(); + c.Elem(i) = - (a.Get(i).X() * p1.X() + a.Get(i).Y() * p1.Y() + a.Get(i).Z() * p1.Z()); + } + + + hmax = 0; + for (i = 1; i <= nf; i++) + { + const Element2d & el = faces.Get(i); + for (j = 1; j <= 3; j++) + { + double hi = Dist (points.Get(el.PNumMod(j)), + points.Get(el.PNumMod(j+1))); + if (hi > hmax) hmax = hi; + } + } + + + fmin = 100; + pmin = Point3d (0, 0, 0); + + for (i1 = 1; i1 <= nf; i1++) + for (i2 = i1+1; i2 <= nf; i2++) + for (i3 = i2+1; i3 <= nf; i3++) + for (i4 = i3+1; i4 <= nf; i4++) + { + m.Elem(1, 1) = a.Get(i1).X() - a.Get(i2).X(); + m.Elem(1, 2) = a.Get(i1).Y() - a.Get(i2).Y(); + m.Elem(1, 3) = a.Get(i1).Z() - a.Get(i2).Z(); + rs.Elem(1) = c.Get(i2) - c.Get(i1); + + m.Elem(2, 1) = a.Get(i1).X() - a.Get(i3).X(); + m.Elem(2, 2) = a.Get(i1).Y() - a.Get(i3).Y(); + m.Elem(2, 3) = a.Get(i1).Z() - a.Get(i3).Z(); + rs.Elem(2) = c.Get(i3) - c.Get(i1); + + m.Elem(3, 1) = a.Get(i1).X() - a.Get(i4).X(); + m.Elem(3, 2) = a.Get(i1).Y() - a.Get(i4).Y(); + m.Elem(3, 3) = a.Get(i1).Z() - a.Get(i4).Z(); + rs.Elem(3) = c.Get(i4) - c.Get(i1); + + + if (fabs (m.Det()) > 1e-10) + { + CalcInverse (m, inv); + inv.Mult (rs, x); + + // testout << "x = " << x << endl; + + + f = -1e10; + for (i = 1; i <= nf; i++) + { + hd = x.Elem(1) * a.Get(i).X() + + x.Elem(2) * a.Get(i).Y() + + x.Elem(3) * a.Get(i).Z() + + c.Get(i); + if (hd > f) f = hd; + } + + if (f < fmin) + { + fmin = f; + pmin.X() = x.Elem(1); + pmin.Y() = x.Elem(2); + pmin.Z() = x.Elem(3); + } + } + } + + // testout << "fmin = " << fmin << endl; + // testout << "pmin = " << pmin << endl; + + p = pmin; + return (fmin < -1e-3 * hmax) ? 1 : 0; + // return (fmin < 0) ? 1 : 0; +} +} diff --git a/contrib/Netgen/libsrc/meshing/findip.hpp b/contrib/Netgen/libsrc/meshing/findip.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2d9058fc5c8c65f7b962533142ad79a4dc254224 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/findip.hpp @@ -0,0 +1,192 @@ +// find inner point + + + +inline void Minimize (const ARRAY<Vec3d> & a, + const ARRAY<double> & c, + int * act, + Vec<3> & x, double & f, + int * sol) +{ + int act1[4]; + Mat<3> m, inv; + Vec<3> rs, xmax, center; + + f = 1e99; + + for (int j = 0; j < 5; j++) + { + for (int hk = 0, k = 0; hk < 4; hk++) + { + if (hk == j) k++; + act1[hk] = act[k]; + k++; + } + + for (int k = 0; k < 3; k++) + { + m(k, 0) = a[act1[0]].X() - a[act1[k+1]].X(); + m(k, 1) = a[act1[0]].Y() - a[act1[k+1]].Y(); + m(k, 2) = a[act1[0]].Z() - a[act1[k+1]].Z(); + rs(k) = c[act1[k+1]] - c[act1[0]]; + } + + /* + (*testout) << "act1 = " + << act1[0] << " " + << act1[1] << " " + << act1[2] << " " + << act1[3] << endl; + (*testout) << "Det = " << Det(m) << endl; + */ + + if (fabs (Det (m)) > 1e-10) + { + CalcInverse (m, inv); + xmax = inv * rs; + + double fmax = -1e10; + for (int k = 0; k < 5; k++) + { + double hd = + xmax(0) * a[act[k]].X() + xmax(1) * a[act[k]].Y() + xmax(2) * a[act[k]].Z() + c[act[k]]; + if (hd > fmax) fmax = hd; + } + + if (fmax < f) + { + f = fmax; + x = xmax; + for (int k = 0; k < 4; k++) + sol[k] = act1[k]; + } + } + } +} + + + + +template <typename POINTARRAY, typename FACEARRAY> +inline int FindInnerPoint (POINTARRAY & points, + FACEARRAY & faces, + Point3d & p) +{ + static int timer = NgProfiler::CreateTimer ("FindInnerPoint"); + NgProfiler::RegionTimer reg (timer); + + ARRAY<Vec3d> a; + ARRAY<double> c; + Mat<3> m, inv; + Vec<3> rs, x, center; + double f; + + int nf = faces.Size(); + + // minimize_x max_i a_i x + c_i + + a.SetSize (nf+4); + c.SetSize (nf+4); + + for (int i = 0; i < nf; i++) + { + Point3d p1 = points.Get(faces[i][0]); + a[i] = Cross (points.Get(faces[i][1]) - p1, + points.Get(faces[i][2]) - p1); + a[i] /= a[i].Length(); + c[i] = - (a[i].X() * p1.X() + a[i].Y() * p1.Y() + a[i].Z() * p1.Z()); + } + + /* + center = 0; + for (int i = 0; i < points.Size(); i++) + center += Vec<3> (points[i]); + center /= points.Size(); + */ + + center = 0; + for (int i = 0; i < faces.Size(); i++) + for (int j = 0; j < 3; j++) + center += Vec<3> (points.Get(faces[i][j])); + center /= (3*faces.Size()); + + + // (*testout) << "center = " << center << endl; + + double hmax = 0; + for (int i = 0; i < nf; i++) + { + // const Element2d & el = faces[i]; + // (*testout) << "el[" << i << "] = " << el << endl; + for (int j = 1; j <= 3; j++) + { + double hi = Dist (points.Get(faces[i].PNumMod(j)), + points.Get(faces[i].PNumMod(j+1))); + if (hi > hmax) hmax = hi; + } + } + + // (*testout) << "hmax = " << hmax << endl; + + a[nf] = Vec<3> (1, 0, 0); + c[nf] = -center(0) - hmax; + a[nf+1] = Vec<3> (0, 1, 0); + c[nf+1] = -center(1) - hmax; + a[nf+2] = Vec<3> (0, 0, 1); + c[nf+2] = -center(2) - hmax; + a[nf+3] = Vec<3> (-1, -1, -1); + c[nf+3] = center(0)+center(1)+center(2)-3*hmax; + + /* + (*testout) << "findip, a now = " << endl << a << endl; + (*testout) << "findip, c now = " << endl << c << endl; + */ + + int act[5] = { 0, nf, nf+1, nf+2, nf+3 }; + int sol[4]; + + while (1) + { + /* + (*testout) << "try "; + for (int j = 0; j < 5; j++) + (*testout) << act[j] << " "; + */ + + Minimize (a, c, act, x, f, sol); + + /* + (*testout) << endl << "sol = "; + for (int j = 0; j < 4; j++) + (*testout) << sol[j] << " "; + + (*testout) << " fmin = " << f << endl; + */ + for (int j = 0; j < 4; j++) act[j] = sol[j]; + + bool found = 0; + double maxval = f; + for (int j = 0; j < nf; j++) + { + double val = x(0) * a[j].X() + x(1) * a[j].Y() + x(2) * a[j].Z() + c[j]; + if (val > maxval + hmax * 1e-6) + { + found = 1; + maxval = val; + act[4] = j; + } + } + + // (*testout) << "maxval = " << maxval << endl; + if (!found) break; + } + + // cout << "converged, f = " << f << endl; + + p = Point3d (x(0), x(1), x(2)); + // (*testout) << "findip, f = " << f << ", hmax = " << hmax << endl; + return (f < -1e-5 * hmax); +} + + + diff --git a/contrib/Netgen/libsrc/meshing/findip2.hpp b/contrib/Netgen/libsrc/meshing/findip2.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fa9215d95c25264943e5d09adc7ecd4691c59982 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/findip2.hpp @@ -0,0 +1,95 @@ +// find inner point + +template <typename POINTARRAY, typename FACEARRAY> +inline int FindInnerPoint2 (POINTARRAY & points, + FACEARRAY & faces, + Point3d & p) +{ + static int timer = NgProfiler::CreateTimer ("FindInnerPoint2"); + NgProfiler::RegionTimer reg (timer); + + ARRAY<Vec3d> a; + ARRAY<double> c; + Mat<3> m, inv; + Vec<3> rs, x, pmin; + + int nf = faces.Size(); + + a.SetSize (nf); + c.SetSize (nf); + + for (int i = 0; i < nf; i++) + { + Point3d p1 = points.Get(faces[i][0]); + a[i] = Cross (points.Get(faces[i][1]) - p1, + points.Get(faces[i][2]) - p1); + a[i] /= a[i].Length(); + c[i] = - (a[i].X() * p1.X() + a[i].Y() * p1.Y() + a[i].Z() * p1.Z()); + } + + + x = 0; + + + double hmax = 0; + for (int i = 0; i < nf; i++) + { + const Element2d & el = faces[i]; + for (int j = 1; j <= 3; j++) + { + double hi = Dist (points.Get(el.PNumMod(j)), + points.Get(el.PNumMod(j+1))); + if (hi > hmax) hmax = hi; + } + } + + double fmin = 0; + + for (int i1 = 1; i1 <= nf; i1++) + for (int i2 = i1+1; i2 <= nf; i2++) + for (int i3 = i2+1; i3 <= nf; i3++) + for (int i4 = i3+1; i4 <= nf; i4++) + { + m(0, 0) = a.Get(i1).X() - a.Get(i2).X(); + m(0, 1) = a.Get(i1).Y() - a.Get(i2).Y(); + m(0, 2) = a.Get(i1).Z() - a.Get(i2).Z(); + rs(0) = c.Get(i2) - c.Get(i1); + + m(1, 0) = a.Get(i1).X() - a.Get(i3).X(); + m(1, 1) = a.Get(i1).Y() - a.Get(i3).Y(); + m(1, 2) = a.Get(i1).Z() - a.Get(i3).Z(); + rs(1) = c.Get(i3) - c.Get(i1); + + m(2, 0) = a.Get(i1).X() - a.Get(i4).X(); + m(2, 1) = a.Get(i1).Y() - a.Get(i4).Y(); + m(2, 2) = a.Get(i1).Z() - a.Get(i4).Z(); + rs(2) = c.Get(i4) - c.Get(i1); + + + if (fabs (Det (m)) > 1e-10) + { + CalcInverse (m, inv); + x = inv * rs; + + double f = -1e10; + for (int i = 0; i < nf; i++) + { + double hd = + x(0) * a[i].X() + x(1) * a[i].Y() + x(2) * a[i].Z() + c[i]; + if (hd > f) f = hd; + if (hd > fmin) break; + } + + if (f < fmin) + { + fmin = f; + pmin = x; + } + } + } + + p = Point3d (pmin(0), pmin(1), pmin(2)); + (*testout) << "fmin = " << fmin << endl; + return (fmin < -1e-3 * hmax); +} + diff --git a/contrib/Netgen/libsrc/meshing/geomsearch.cpp b/contrib/Netgen/libsrc/meshing/geomsearch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bedd23ccb899fbf48bbd61c524ded8eab8e4a5a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/geomsearch.cpp @@ -0,0 +1,263 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + GeomSearch3d :: GeomSearch3d() + { + size.i1 = 0; size.i2 = 0; size.i3 = 0; + }; + + GeomSearch3d :: ~GeomSearch3d() + { + //delete old Hashtable: + if (size.i1 != 0) + { + for (int i = 0; i < size.i1*size.i2*size.i3; i++) + delete hashtable[i]; + } + } + + void GeomSearch3d :: Init (ARRAY <FrontPoint3,PointIndex::BASE> *pointsi, ARRAY <FrontFace> *facesi) + { + points = pointsi; + faces = facesi; + size.i1 = 0; size.i2 = 0; size.i3 = 0; + reset = 1; + hashcount = 1; + } + + void GeomSearch3d :: ElemMaxExt(Point3d& minp, Point3d& maxp, const MiniElement2d& elem) + { + maxp.X()=(*points)[elem.PNum(1)].P()(0); + maxp.Y()=(*points)[elem.PNum(1)].P()(1); + maxp.Z()=(*points)[elem.PNum(1)].P()(2); + minp.X()=(*points)[elem.PNum(1)].P()(0); + minp.Y()=(*points)[elem.PNum(1)].P()(1); + minp.Z()=(*points)[elem.PNum(1)].P()(2); + + for (int i=2; i <= 3; i++) + { + maxp.X()=max2((*points)[elem.PNum(i)].P()(0),maxp.X()); + maxp.Y()=max2((*points)[elem.PNum(i)].P()(1),maxp.Y()); + maxp.Z()=max2((*points)[elem.PNum(i)].P()(2),maxp.Z()); + minp.X()=min2((*points)[elem.PNum(i)].P()(0),minp.X()); + minp.Y()=min2((*points)[elem.PNum(i)].P()(1),minp.Y()); + minp.Z()=min2((*points)[elem.PNum(i)].P()(2),minp.Z()); + } + } + + void GeomSearch3d :: MinCoords(const Point3d& p1, Point3d& p2) + { + p2.X()=min2(p1.X(),p2.X()); + p2.Y()=min2(p1.Y(),p2.Y()); + p2.Z()=min2(p1.Z(),p2.Z()); + } + + void GeomSearch3d :: MaxCoords(const Point3d& p1, Point3d& p2) + { + p2.X()=max2(p1.X(),p2.X()); + p2.Y()=max2(p1.Y(),p2.Y()); + p2.Z()=max2(p1.Z(),p2.Z()); + } + + void GeomSearch3d :: Create() + { + INDEX i,j,k; + if (reset) + { + const double hashelemsizefactor = 4; + reset = 0; + /* + minext=Point3d(MAXDOUBLE, MAXDOUBLE, MAXDOUBLE); + maxext=Point3d(MINDOUBLE, MINDOUBLE, MINDOUBLE); + */ + ElemMaxExt(minext, maxext, faces->Get(1).Face()); + Point3d maxp, minp; + Vec3d midext(0,0,0); + + //get max Extension of Frontfaces + for (i = 1; i <= faces->Size(); i++) + { + ElemMaxExt(minp, maxp, faces->Get(i).Face()); + MinCoords(minp, minext); + MaxCoords(maxp, maxext); + midext+=maxp-minp; + } + + + maxextreal = maxext; + maxext = maxext + 1e-4 * (maxext - minext); + + midext*=1./faces->Size(); + Vec3d boxext = maxext - minext; + + //delete old Hashtable: + if (size.i1 != 0) + { + for (i = 1; i <= size.i1*size.i2*size.i3; i++) + { + delete hashtable.Get(i); + } + } + + size.i1 = int (boxext.X()/midext.X()/hashelemsizefactor+1); + size.i2 = int (boxext.Y()/midext.Y()/hashelemsizefactor+1); + size.i3 = int (boxext.Z()/midext.Z()/hashelemsizefactor+1); + // PrintMessage (5, "hashsizes = ", size.i1, ", ", size.i2, ", ", size.i3); + + elemsize.X()=boxext.X()/size.i1; + elemsize.Y()=boxext.Y()/size.i2; + elemsize.Z()=boxext.Z()/size.i3; + + //create Hasharrays: + hashtable.SetSize(size.i1*size.i2*size.i3); + for (i = 1; i <= size.i1; i++) + { + for (j = 1; j <= size.i2; j++) + { + for (k = 1; k <= size.i3; k++) + { + INDEX ind=i+(j-1)*size.i1+(k-1)*size.i2*size.i1; + hashtable.Elem(ind) = new ARRAY <int> (); + } + } + } + } + else + { + //Clear all Hash-Arrays + for (i = 1; i <= size.i1; i++) + { + for (j = 1; j <= size.i2; j++) + { + for (k = 1; k <= size.i3; k++) + { + INDEX ind=i+(j-1)*size.i1+(k-1)*size.i2*size.i1; + hashtable.Elem(ind)->SetSize(0); + } + } + } + } + + //Faces in Hashtable einfuegen: + for (i = 1; i <= faces->Size(); i++) + { + AddElem(faces->Get(i).Face(),i); + } + + } + + void GeomSearch3d :: AddElem(const MiniElement2d& elem, INDEX elemnum) + { + Point3d minp, maxp; + ElemMaxExt(minp, maxp, elem); + int sx = int ((minp.X()-minext.X())/elemsize.X()+1.); + int ex = int ((maxp.X()-minext.X())/elemsize.X()+1.); + int sy = int ((minp.Y()-minext.Y())/elemsize.Y()+1.); + int ey = int ((maxp.Y()-minext.Y())/elemsize.Y()+1.); + int sz = int ((minp.Z()-minext.Z())/elemsize.Z()+1.); + int ez = int ((maxp.Z()-minext.Z())/elemsize.Z()+1.); + + for (int ix = sx; ix <= ex; ix++) + for (int iy = sy; iy <= ey; iy++) + for (int iz = sz; iz <= ez; iz++) + { + INDEX ind=ix+(iy-1)*size.i1+(iz-1)*size.i2*size.i1; + if (ind < 1 || ind > size.i1 * size.i2 * size.i3) + { + cerr << "Illegal hash-position"; + cerr << "Position: " << ix << "," << iy << "," << iz << endl; + throw NgException ("Illegal position in Geomsearch"); + } + hashtable.Elem(ind)->Append(elemnum); + } + } + + void GeomSearch3d :: GetLocals(ARRAY<MiniElement2d> & locfaces, ARRAY<INDEX> & findex, + INDEX fstind, const Point3d& p0, double xh) + { + hashcount++; + + Point3d minp, maxp, midp; + + minp=p0-Vec3d(xh,xh,xh); //lay cube over sphere + maxp=p0+Vec3d(xh,xh,xh); + + MaxCoords(minext,minp); //cube may not be out of hash-region + MinCoords(maxextreal,maxp); + + + int cluster = faces->Get(fstind).Cluster(); + + int sx = int((minp.X()-minext.X())/elemsize.X()+1.); + int ex = int((maxp.X()-minext.X())/elemsize.X()+1.); + int sy = int((minp.Y()-minext.Y())/elemsize.Y()+1.); + int ey = int((maxp.Y()-minext.Y())/elemsize.Y()+1.); + int sz = int((minp.Z()-minext.Z())/elemsize.Z()+1.); + int ez = int((maxp.Z()-minext.Z())/elemsize.Z()+1.); + int ix,iy,iz,i,k; + + int cnt1 = 0; // test, how efficient hashtable is + int cnt2 = 0; + int cnt3 = 0; + + for (ix = sx; ix <= ex; ix++) + { + for (iy = sy; iy <= ey; iy++) + { + for (iz = sz; iz <= ez; iz++) + { + INDEX ind=ix+(iy-1)*size.i1+(iz-1)*size.i2*size.i1; + + //go through all elements in one hash area + const ARRAY <int> & area = *hashtable.Elem(ind); + for (k = 1; k <= area.Size(); k++) + { + cnt2++; + i = area.Get(k); + if (faces->Get(i).Cluster() == cluster && + faces->Get(i).Valid() && + faces->Get(i).HashValue() != hashcount && + i != fstind) + { + cnt1++; + const MiniElement2d & face = faces->Get(i).Face(); + + const Point3d & p1 = (*points)[face.PNum(1)].P(); + const Point3d & p2 = (*points)[face.PNum(2)].P(); + const Point3d & p3 = (*points)[face.PNum(3)].P(); + + midp = Center (p1, p2, p3); + + // if (Dist2 (midp, p0) <= xh*xh) + if((Dist2 (p1, p0) <= xh*xh) || + (Dist2 (p2, p0) <= xh*xh) || + (Dist2 (p3, p0) <= xh*xh) || + (Dist2 (midp, p0) <= xh*xh) ) // by Jochen Wild + { + cnt3++; + locfaces.Append(faces->Get(i).Face()); + findex.Append(i); + faces->Elem(i).SetHashValue(hashcount); + } + } + } + } + } + } + /* + if (faces->Size() != 0 && hashcount % 200 == 0) + { + (*mycout) << "n.o.f= " << faces->Size(); + (*mycout) << ", n.o.lf= " << locfaces.Size(); + (*mycout) << ", hashf= " << (double)cnt2/(double)faces->Size(); + (*mycout) << " (" << (double)cnt1/(double)faces->Size(); + (*mycout) << ", " << (double)cnt3/(double)faces->Size() << ")" << endl; + } + */ + + } + +} diff --git a/contrib/Netgen/libsrc/meshing/geomsearch.hpp b/contrib/Netgen/libsrc/meshing/geomsearch.hpp new file mode 100644 index 0000000000000000000000000000000000000000..236c98b13f35b25ca395e86d7dd734f6a6810d22 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/geomsearch.hpp @@ -0,0 +1,117 @@ +#ifndef FILE_GEOMSEARCH +#define FILE_GEOMSEARCH + +/**************************************************************************/ +/* File: geomsearch.hh */ +/* Author: Johannes Gerstmayr */ +/* Date: 19. Nov. 97 */ +/**************************************************************************/ + +class FrontPoint3; +class FrontFace; +class MiniElement2d; + + /// class for quick access of 3D-elements; class cannot delete elements, but only append +class GeomSearch3d +{ + +public: + /// + GeomSearch3d(); + /// + virtual ~GeomSearch3d(); + + /// + void Init (ARRAY <FrontPoint3,PointIndex::BASE> *pointsi, ARRAY <FrontFace> *facesi); + + ///get elements max extension + void ElemMaxExt(Point3d& minp, Point3d& maxp, const MiniElement2d& elem); + + ///get minimum coordinates of two points ->p2 + void MinCoords(const Point3d& p1, Point3d& p2); + + ///get minimum coordinates of two points ->p2 + void MaxCoords(const Point3d& p1, Point3d& p2); + + ///create a hashtable from an existing array of triangles + ///sizei = number of pieces in one direction + void Create(); + + ///add new element to Hashtable + void AddElem(const MiniElement2d& elem, INDEX elemnum); + + ///GetLocal faces in sphere with radius xh and middlepoint p + void GetLocals(ARRAY<MiniElement2d> & locfaces, ARRAY<INDEX> & findex, + INDEX fstind, const Point3d& p0, double xh); + +private: + + ARRAY <FrontFace> *faces; // Pointers to Arrays in Adfront + ARRAY <FrontPoint3,PointIndex::BASE> *points; + + ARRAY <ARRAY <int>*> hashtable; + + Point3d minext; //extension of Hashdomain + Point3d maxext; + Point3d maxextreal; + Vec3d elemsize; //size of one Hash-Element + + threeint size; // size of Hashtable in each direction + int reset; + int hashcount; +}; + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/Netgen/libsrc/meshing/global.cpp b/contrib/Netgen/libsrc/meshing/global.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60a1fbe51d15b2846c108725384962b23b62b614 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/global.cpp @@ -0,0 +1,53 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + ostream * testout = &cout; + + ostream * mycout = &cout; + ostream * myerr = &cerr; + + + // Flags globflags; // not used anymoure + Flags parameters; + + + int silentflag = 0; + int testmode = 0; + + MeshingParameters mparam; + volatile multithreadt multithread; + + string ngdir = "."; + + ARRAY<int> tets_in_qualclass; + + + multithreadt :: multithreadt() + { + pause =0; + testmode = 0; + redraw = 0; + drawing = 0; + terminate = 0; + running = 0; + percent = 0; + task = ""; + } + + DebugParameters debugparam; + bool verbose = 0; + + int timestamp = 0; + int GetTimeStamp() + { + return timestamp; + } + + int NextTimeStamp() + { + timestamp++; + return timestamp; + } +} diff --git a/contrib/Netgen/libsrc/meshing/global.hpp b/contrib/Netgen/libsrc/meshing/global.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1019624518a27d15530e48a6910bb4838b45627b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/global.hpp @@ -0,0 +1,54 @@ +#ifndef FILE_GLOBAL +#define FILE_GLOBAL + + +/**************************************************************************/ +/* File: global.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +/* + global functions and variables +*/ + +/// +extern double GetTime (); +extern void ResetTime (); + +/// +extern int testmode; + +// extern ostream * testout; +// extern AutoPtr<ostream> testout; + +/// calling parameters +extern Flags parameters; + +extern MeshingParameters mparam; + +extern ARRAY<int> tets_in_qualclass; + + +class multithreadt +{ +public: + int pause; + int testmode; + int redraw; + int drawing; + int terminate; + int running; + double percent; + const char * task; + bool demorunning; + multithreadt(); +}; + +extern volatile multithreadt multithread; + +extern string ngdir; +extern DebugParameters debugparam; +extern bool verbose; + +#endif diff --git a/contrib/Netgen/libsrc/meshing/hpref_hex.hpp b/contrib/Netgen/libsrc/meshing/hpref_hex.hpp new file mode 100644 index 0000000000000000000000000000000000000000..11e3f86e4949da4beccb772f2c2d4beeff066e8d --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_hex.hpp @@ -0,0 +1,236 @@ +// SZ + +// HP_HEX ... no refinement +int refhex_splitedges[][3] = + { + { 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE refhex_newelstypes[] = + { + HP_HEX, + HP_NONE, + }; +int refhex_newels[][8] = + { + { 1, 2, 3, 4, 5, 6, 7, 8 } + }; +HPRef_Struct refhex = + { + HP_HEX, + refhex_splitedges, + 0, 0, + refhex_newelstypes, + refhex_newels + }; + +// HP_HEX_1F ... face (1 - 4 - 3 -2) singular +int refhex_1f_0e_0v_splitedges[][3] = + { + { 1, 5, 9 }, + { 2, 6, 10 }, + { 3, 7, 11 }, + { 4, 8, 12 }, + { 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE refhex_1f_0e_0v_newelstypes[] = + { + HP_HEX, + HP_HEX_1F_0E_0V, + HP_NONE, + }; +int refhex_1f_0e_0v_newels[][8] = + { + { 9, 10, 11, 12, 5, 6, 7, 8 }, + { 1, 2, 3, 4, 9, 10, 11, 12} + }; +HPRef_Struct refhex_1f_0e_0v = + { + HP_HEX, + refhex_1f_0e_0v_splitedges, + 0, 0, + refhex_1f_0e_0v_newelstypes, + refhex_1f_0e_0v_newels + }; + + + +// HP_HEX_1FA_1FB ... face (1 - 4 - 3 -2) and face (1-2-6-5) singular +int refhex_1fa_1fb_0e_0v_splitedges[][3] = + { + { 1, 5, 9 }, + { 2, 6, 10 }, + { 3, 7, 11 }, + { 4, 8, 12 }, + { 1, 4, 13 }, + { 2, 3, 14 }, + { 6, 7, 15 }, + { 5, 8, 16 }, + { 0, 0, 0 } + }; + +int refhex_1fa_1fb_0e_0v_splitfaces[][4] = + { + { 2, 3, 6, 17 }, + { 1, 4, 5, 18 }, + { 0, 0, 0, 0 }, + }; +HPREF_ELEMENT_TYPE refhex_1fa_1fb_0e_0v_newelstypes[] = + { + HP_HEX, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_NONE, + }; +int refhex_1fa_1fb_0e_0v_newels[][8] = + { + {18, 17, 11, 12, 16, 15, 7, 8}, + {13, 14, 3, 4, 18, 17, 11, 12}, + { 5, 6, 10, 9, 16, 15, 17, 18}, + { 1, 2, 14, 13, 9, 10, 17, 18} + }; +HPRef_Struct refhex_1fa_1fb_0e_0v = + { + HP_HEX, + refhex_1fa_1fb_0e_0v_splitedges, + refhex_1fa_1fb_0e_0v_splitfaces, 0, + refhex_1fa_1fb_0e_0v_newelstypes, + refhex_1fa_1fb_0e_0v_newels + }; + + + +// Refine Dummies + // HP_HEX_0E_1V + int refhex_0e_1v_splitedges[][3] = + { + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refhex_0e_1v_newelstypes[] = + { + HP_TET_0E_1V, + HP_TET, + HP_TET, + HP_TET, + HP_TET, + HP_TET, + HP_NONE, + }; + int refhex_0e_1v_newels[][8] = + { + { 1, 5, 2, 4 }, + { 7, 3, 6, 8 }, + { 2, 8, 5, 6 }, + { 2, 8, 6, 3 }, + { 2, 8, 3, 4 }, + { 2, 8, 4, 5 }, + }; + HPRef_Struct refhex_0e_1v = + { + HP_HEX, + refhex_0e_1v_splitedges, + 0, 0, + refhex_0e_1v_newelstypes, + refhex_0e_1v_newels + }; + + + +// Refine Dummies + // HP_HEX_1E_1V + int refhex_1e_1v_splitedges[][3] = + { + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refhex_1e_1v_newelstypes[] = + { + HP_TET_1E_1VA, + HP_TET, + HP_TET_0E_1V, + HP_TET_0E_1V, + HP_TET_0E_1V, + HP_TET_0E_1V, + HP_NONE, + }; + int refhex_1e_1v_newels[][8] = + { + // { 1, 5, 2, 4 }, + { 1, 2, 4, 5 }, + { 7, 3, 6, 8 }, + { 2, 8, 5, 6 }, + { 2, 8, 6, 3 }, + { 2, 8, 3, 4 }, + { 2, 8, 4, 5 }, + }; + HPRef_Struct refhex_1e_1v = + { + HP_HEX, + refhex_1e_1v_splitedges, + 0, 0, + refhex_1e_1v_newelstypes, + refhex_1e_1v_newels + }; + + +// Refine Dummies + // HP_HEX_3E_0V + int refhex_3e_0v_splitedges[][3] = + { + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refhex_3e_0v_newelstypes[] = + { + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_TET_0E_1V, + HP_TET, + HP_NONE, + }; + int refhex_3e_0v_newels[][8] = + { + { 1, 2, 3, 6 }, + { 1, 4, 8, 3 }, + { 1, 5, 6, 8 }, + { 1, 6, 3, 8 }, + { 3, 8, 6, 7 }, + }; + HPRef_Struct refhex_3e_0v = + { + HP_HEX, + refhex_3e_0v_splitedges, + 0, 0, + refhex_3e_0v_newelstypes, + refhex_3e_0v_newels + }; + + + +// Refine Dummies + // HP_HEX_1E_0V + int refhex_1e_0v_splitedges[][3] = + { + { 0, 0, 0 } + }; + + HPREF_ELEMENT_TYPE refhex_1e_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, // HP_PRISM_SINGEDGE_H1, + HP_PRISM, + HP_NONE, + }; + int refhex_1e_0v_newels[][8] = + { + { 1, 4, 5, 2, 3, 6 }, + { 5, 4, 8, 6, 3, 7 }, + }; + HPRef_Struct refhex_1e_0v = + { + HP_HEX, + refhex_1e_0v_splitedges, + 0, 0, + refhex_1e_0v_newelstypes, + refhex_1e_0v_newels + }; + + diff --git a/contrib/Netgen/libsrc/meshing/hpref_prism.hpp b/contrib/Netgen/libsrc/meshing/hpref_prism.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3cceb44a5726d52fa25f5c0af623fe375bd096a0 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_prism.hpp @@ -0,0 +1,3405 @@ + + // HP_PRISM ... no refinement + int refprism_splitedges[][3] = + { + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_newelstypes[] = + { + HP_PRISM, + HP_NONE, + }; + int refprism_newels[][8] = + { + { 1, 2, 3, 4, 5, 6 } + }; + HPRef_Struct refprism = + { + HP_PRISM, + refprism_splitedges, + 0, 0, + refprism_newelstypes, + refprism_newels + }; + + + + // HP_PRISM_SINGEDGE ... vertical edge 1-4 is singular + int refprism_singedge_splitedges[][3] = + { + { 1, 2, 7 }, + { 1, 3, 8 }, + { 4, 5, 9 }, + { 4, 6, 10 }, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_singedge_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_NONE, + }; + int refprism_singedge_newels[][8] = + { + { 1, 7, 8, 4, 9, 10 }, + { 3, 8, 7, 2, 6, 10, 9, 5 } + }; + HPRef_Struct refprism_singedge = + { + HP_PRISM, + refprism_singedge_splitedges, + 0, 0, + refprism_singedge_newelstypes, + refprism_singedge_newels + }; + + + + + + + // HP_PRISM_SINGEDGE_V12 vertical edges 1-4 and 2-5 are singular + int refprism_singedge_v12_splitedges[][3] = + { + { 1, 2, 7 }, + { 1, 3, 8 }, + { 2, 1, 9 }, + { 2, 3, 10 }, + { 4, 5, 11 }, + { 4, 6, 12 }, + { 5, 4, 13 }, + { 5, 6, 14}, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_singedge_v12_newelstypes[] = + { + HP_HEX, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_NONE, + }; + int refprism_singedge_v12_newels[][8] = + { + { 7, 9, 10, 8, 11, 13, 14, 12 }, + { 1, 7, 8, 4, 11, 12 }, + { 2, 10, 9, 5, 14, 13 }, + { 3, 8, 10, 6, 12, 14 }, + }; + HPRef_Struct refprism_singedge_v12 = + { + HP_PRISM, + refprism_singedge_v12_splitedges, + 0, 0, + refprism_singedge_v12_newelstypes, + refprism_singedge_v12_newels + }; + + + + + + + // HP_PRISM_SINGEDGE_H12 + int refprism_singedge_h12_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 3, 1, 10 }, + + { 4, 6, 12 }, + { 5, 4, 13 }, + { 5, 6, 14 }, + { 6, 4, 15 }, + + { 0, 0, 0 } + }; + + int refprism_singedge_h12_splitfaces[][4] = + { + { 2, 1, 3, 11 }, + { 5, 4, 6, 16 }, + { 0, 0, 0, 0 }, + }; + + HPREF_ELEMENT_TYPE refprism_singedge_h12_newelstypes[] = + { + HP_HEX, + HP_HEX, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_NONE, + }; + int refprism_singedge_h12_newels[][8] = + { + { 1, 8, 11, 7, 4, 13, 16, 12 }, + { 9, 3, 10, 11, 14, 6, 15, 16 }, + { 7, 11, 10, 12, 16, 15 }, + { 2, 9, 11, 5, 14, 16 }, + { 8, 2, 11, 13, 5, 16 } + }; + HPRef_Struct refprism_singedge_h12 = + { + HP_PRISM, + refprism_singedge_h12_splitedges, + refprism_singedge_h12_splitfaces, + 0, + refprism_singedge_h12_newelstypes, + refprism_singedge_h12_newels + }; + + + + + + + // HP_PRISM_SINGEDGE_H1 + int refprism_singedge_h1_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 4, 6, 9 }, + { 5, 6, 10 }, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_singedge_h1_newelstypes[] = + { + HP_HEX, + HP_PRISM, + HP_NONE, + }; + int refprism_singedge_h1_newels[][8] = + { + { 1, 2, 8, 7, 4, 5, 10, 9 }, + { 3, 7, 8, 6, 9, 10 } + }; + HPRef_Struct refprism_singedge_h1 = + { + HP_PRISM, + refprism_singedge_h1_splitedges, + 0, 0, + refprism_singedge_h1_newelstypes, + refprism_singedge_h1_newels + }; + + + +// HP_PRISM_1FA_0E_0V + int refprism_1fa_0e_0v_splitedges[][3] = + { + { 1, 4, 16 }, + { 2, 5, 17 }, + { 3, 6, 18 }, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_1fa_0e_0v_newelstypes[] = + { + HP_PRISM, + HP_PRISM_1FA_0E_0V, + HP_NONE, + }; + int refprism_1fa_0e_0v_newels[][8] = + { + { 16, 17, 18, 4, 5, 6 }, + { 1, 2, 3, 16, 17, 18 } + }; + HPRef_Struct refprism_1fa_0e_0v = + { + HP_PRISM, + refprism_1fa_0e_0v_splitedges, + 0, 0, + refprism_1fa_0e_0v_newelstypes, + refprism_1fa_0e_0v_newels + }; + +// HP_PRISM_1FA_1E_0V + int refprism_1fa_1e_0v_splitedges[][3] = + { + { 1, 4, 16 }, + { 2, 5, 17 }, + { 3, 6, 18 }, + { 1, 2, 7}, + { 1, 3, 12}, + { 4, 6, 45}, + { 4, 5, 40}, + { 0, 0, 0 } + }; + int refprism_1fa_1e_0v_splitfaces[][4] = + { + {1,2,4,19}, + {1,3,4,24}, + {0,0,0,0} + }; + + HPREF_ELEMENT_TYPE refprism_1fa_1e_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_NONE, + }; + int refprism_1fa_1e_0v_newels[][8] = + { + { 16, 19, 24, 4, 40, 45 }, + { 24, 19, 17, 18, 45 , 40, 5, 6 }, + { 1, 7 , 12 , 16, 19, 24 }, + { 7, 2, 3, 12, 19, 17, 18, 24 } + }; + HPRef_Struct refprism_1fa_1e_0v = + { + HP_PRISM, + refprism_1fa_1e_0v_splitedges, + refprism_1fa_1e_0v_splitfaces, + 0, + refprism_1fa_1e_0v_newelstypes, + refprism_1fa_1e_0v_newels + }; + +// HP_PRISM_2FA_1E_0V + int refprism_2fa_1e_0v_splitedges[][3] = + { + { 1, 4, 16 }, + { 2, 5, 17 }, + { 3, 6, 18 }, + { 1, 2, 7}, + { 1, 3, 12}, + { 4, 6, 45}, + { 4, 5, 40}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 0, 0, 0 } + }; + int refprism_2fa_1e_0v_splitfaces[][4] = + { + {1,2,4,19}, + {1,3,4,24}, + {4,1,5,31}, + {4,1,6,36}, + {0,0,0,0} + }; + + HPREF_ELEMENT_TYPE refprism_2fa_1e_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_NONE, + }; + int refprism_2fa_1e_0v_newels[][8] = + { + { 16, 19, 24, 28, 31, 36 }, + { 24, 19, 17, 18, 36, 31, 29, 30 }, + { 1, 7 , 12 , 16, 19, 24 }, + { 12, 7, 2, 3, 24, 19, 17, 18 }, + { 4, 45, 40, 28, 36, 31 }, + { 40, 45, 6, 5, 31, 36, 30, 29,} + }; + HPRef_Struct refprism_2fa_1e_0v = + { + HP_PRISM, + refprism_2fa_1e_0v_splitedges, + refprism_2fa_1e_0v_splitfaces, + 0, + refprism_2fa_1e_0v_newelstypes, + refprism_2fa_1e_0v_newels + }; + +// HP_PRISM_1FB_0E_0V ... quad face 1-2-4-5 + int refprism_1fb_0e_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 4, 6, 9 }, + { 5, 6, 10 }, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_1fb_0e_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PRISM, + HP_NONE, + }; + int refprism_1fb_0e_0v_newels[][8] = + { + { 1, 4, 5, 2, 7, 9, 10, 8 }, + { 7, 8, 3, 9, 10, 6 } + }; + HPRef_Struct refprism_1fb_0e_0v = + { + HP_PRISM, + refprism_1fb_0e_0v_splitedges, + + 0, 0, + refprism_1fb_0e_0v_newelstypes, + refprism_1fb_0e_0v_newels + }; + + +// HP_PRISM_1FB_1EA_0V ... quad face 1-2-4-5 + int refprism_1fb_1ea_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 4, 6, 9 }, + { 5, 6, 10 }, + { 1, 2, 11 }, + { 4, 5, 12 }, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_1fb_1ea_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM, + HP_NONE, + }; + int refprism_1fb_1ea_0v_newels[][8] = + { + { 11, 12, 5, 2, 7, 9, 10, 8 }, + { 1, 11, 7, 4, 12, 9 }, + { 7, 8, 3, 9, 10, 6 } + }; + HPRef_Struct refprism_1fb_1ea_0v = + { + HP_PRISM, + refprism_1fb_1ea_0v_splitedges, + 0, 0, + refprism_1fb_1ea_0v_newelstypes, + refprism_1fb_1ea_0v_newels + }; + +// HP_PRISM_1FB_1EC_0V ... quad face 1-2-4-5 with singular edge 3-6 + int refprism_1fb_1ec_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {3,2,10}, + {3,1,11}, + {5,6,42}, + {4,6,45}, + {6,5,43}, + {6,4,44}, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_1fb_1ec_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_HEX_1F_0E_0V, + HP_NONE, + }; + int refprism_1fb_1ec_0v_newels[][8] = + { + { 3, 11, 10, 6, 44, 43}, + { 12, 9, 10, 11, 45, 42, 43, 44}, + { 4, 5, 2, 1, 45, 42, 9, 12 } + }; + HPRef_Struct refprism_1fb_1ec_0v = + { + HP_PRISM, + refprism_1fb_1ec_0v_splitedges, + 0, 0, + refprism_1fb_1ec_0v_newelstypes, + refprism_1fb_1ec_0v_newels + }; + +// HP_PRISM_1FA_1FB_1EC_0V ... bot-trig face, quad face 1-2-4-5 with singular edge 3-6 + int refprism_1fa_1fb_1ec_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {3,2,10}, + {3,1,11}, + {5,6,42}, + {4,6,45}, + {6,5,43}, + {6,4,44}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + { 0, 0, 0 } + }; + + int refprism_1fa_1fb_1ec_0v_splitfaces[][4] = + { + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {0,0,0,0} + }; + HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ec_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_NONE, + }; + int refprism_1fa_1fb_1ec_0v_newels[][8] = + { + { 18, 23, 22, 6, 44, 43}, + { 24, 21, 22, 23, 45, 42, 43, 44}, + { 4, 5, 17, 16, 45, 42, 21, 24}, + { 3, 11, 10, 18, 23, 22}, + { 12, 9, 10, 11, 24, 21, 22, 23}, + { 1, 2, 9, 12, 16, 17, 21, 24} + }; + HPRef_Struct refprism_1fa_1fb_1ec_0v = + { + HP_PRISM, + refprism_1fa_1fb_1ec_0v_splitedges, + refprism_1fa_1fb_1ec_0v_splitfaces, 0, + refprism_1fa_1fb_1ec_0v_newelstypes, + refprism_1fa_1fb_1ec_0v_newels + }; + + +// HP_PRISM_1FA_1FB_2EB_0V + int refprism_1fa_1fb_2eb_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {3,2,10}, + {3,1,11}, + {5,6,42}, + {4,6,45}, + {6,5,43}, + {6,4,44}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + { 4, 5, 40}, + { 4, 6, 45}, + { 1, 2, 7}, + { 0, 0, 0 } + }; + + int refprism_1fa_1fb_2eb_0v_splitfaces[][4] = + { + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {1,2,4,19}, + {0,0,0,0} + }; + HPREF_ELEMENT_TYPE refprism_1fa_1fb_2eb_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_NONE, + }; + int refprism_1fa_1fb_2eb_0v_newels[][8] = + { + { 18, 23, 22, 6, 44, 43}, + { 24, 21, 22, 23, 45, 42, 43, 44}, + { 40, 5, 17, 19, 45, 42, 21, 24}, + { 3, 11, 10, 18, 23, 22}, + { 12, 9, 10, 11, 24, 21, 22, 23}, + { 7, 2, 9, 12, 19, 17, 21, 24}, + {16,19,24,4,40,45}, + {1,7,12,16,19,24} + }; + HPRef_Struct refprism_1fa_1fb_2eb_0v = + { + HP_PRISM, + refprism_1fa_1fb_2eb_0v_splitedges, + refprism_1fa_1fb_2eb_0v_splitfaces, 0, + refprism_1fa_1fb_2eb_0v_newelstypes, + refprism_1fa_1fb_2eb_0v_newels + }; + + // HP_PRISM_1FA_1FB_2EC_0V + int refprism_1fa_1fb_2ec_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {3,2,10}, + {3,1,11}, + {5,6,42}, + {4,6,45}, + {6,5,43}, + {6,4,44}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,4,41}, + {2,1,8}, + { 0, 0, 0 } + }; + + int refprism_1fa_1fb_2ec_0v_splitfaces[][4] = + { + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {2,1,5,20}, + {0,0,0,0} + }; + HPREF_ELEMENT_TYPE refprism_1fa_1fb_2ec_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FB_1EA_0V, + HP_NONE, + }; + int refprism_1fa_1fb_2ec_0v_newels[][8] = + { + { 18, 23, 22, 6, 44, 43}, + { 24, 21, 22, 23, 45, 42, 43, 44}, + { 4, 41, 20, 16, 45, 42, 21, 24}, + { 3, 11, 10, 18, 23, 22}, + { 12, 9, 10, 11, 24, 21, 22, 23}, + { 1, 8, 9, 12, 16, 20, 21, 24}, + {8,2,9,20,17,21}, + {5,41,42,17,20,21} + }; + HPRef_Struct refprism_1fa_1fb_2ec_0v = + { + HP_PRISM, + refprism_1fa_1fb_2ec_0v_splitedges, + refprism_1fa_1fb_2ec_0v_splitfaces, + 0, + refprism_1fa_1fb_2ec_0v_newelstypes, + refprism_1fa_1fb_2ec_0v_newels + }; + + + + + + + +// HP_PRISM_2FA_1FB_1EC_0V ... trig faces, quad face 1-2-4-5 with singular edge 3-6 + int refprism_2fa_1fb_1ec_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {3,2,10}, + {3,1,11}, + {5,6,42}, + {4,6,45}, + {6,5,43}, + {6,4,44}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 0, 0, 0 } + }; + + int refprism_2fa_1fb_1ec_0v_splitfaces[][4] = + { + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {5,2,6,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + {0,0,0,0} + }; + HPREF_ELEMENT_TYPE refprism_2fa_1fb_1ec_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_NONE, + }; + int refprism_2fa_1fb_1ec_0v_newels[][8] = + { + { 18, 23, 22, 30, 35, 34}, + { 24, 21, 22, 23, 36, 33, 34, 35}, + { 28, 29, 17, 16, 36, 33, 21, 24}, + { 3, 11, 10, 18, 23, 22}, + { 12, 9, 10, 11, 24, 21, 22, 23}, + { 1, 2, 9, 12, 16, 17, 21, 24}, + { 6, 43, 44, 30, 34, 35}, + { 44, 43, 42, 45, 35, 34, 33, 36}, + { 5, 4, 45, 42, 29, 28, 36, 33 }, + }; + HPRef_Struct refprism_2fa_1fb_1ec_0v = + { + HP_PRISM, + refprism_2fa_1fb_1ec_0v_splitedges, + refprism_2fa_1fb_1ec_0v_splitfaces, + 0, + refprism_2fa_1fb_1ec_0v_newelstypes, + refprism_2fa_1fb_1ec_0v_newels + }; + +// HP_PRISM_2FA_1FB_2EB_0V + int refprism_2fa_1fb_2eb_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {3,2,10}, + {3,1,11}, + {5,6,42}, + {4,6,45}, + {6,5,43}, + {6,4,44}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + {4,5,40}, + {1,2,7}, + { 0, 0, 0 } + }; + + int refprism_2fa_1fb_2eb_0v_splitfaces[][4] = + { + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {5,6,2,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + {4,1,5,31}, + {1,2,4,19}, + {0,0,0,0} + }; + HPREF_ELEMENT_TYPE refprism_2fa_1fb_2eb_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_NONE, + }; + int refprism_2fa_1fb_2eb_0v_newels[][8] = + { + { 18, 23, 22, 30, 35, 34}, + { 24, 21, 22, 23, 36, 33, 34, 35}, + { 31, 29, 17, 19, 36, 33, 21, 24}, + { 3, 11, 10, 18, 23, 22}, + { 12, 9, 10, 11, 24, 21, 22, 23}, + { 7, 2, 9, 12, 19, 17, 21, 24}, + { 6, 43, 44, 30, 34, 35}, + { 44, 43, 42, 45, 35, 34, 33, 36}, + { 5, 40, 45, 42, 29, 31, 36, 33 }, + { 1, 7, 12, 16, 19, 24 }, + { 16, 19, 24, 28, 31, 36 }, + { 40, 4, 45, 31, 28, 36 }, + }; + HPRef_Struct refprism_2fa_1fb_2eb_0v = + { + HP_PRISM, + refprism_2fa_1fb_2eb_0v_splitedges, + refprism_2fa_1fb_2eb_0v_splitfaces, 0, + refprism_2fa_1fb_2eb_0v_newelstypes, + refprism_2fa_1fb_2eb_0v_newels + }; + +// HP_PRISM_1FB_2EA_0V ... quad face 1-2-4-5 with singular edges 1-4, 2-5 + int refprism_1fb_2ea_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 1, 2, 9 }, + { 2, 1, 10 }, + { 4, 6, 11 }, + { 5, 6, 12 }, + { 4, 5, 13 }, + { 5, 4, 14 }, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_1fb_2ea_0v_newelstypes[] = + { + HP_PRISM, + HP_PRISM_1FB_1EA_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_NONE, + }; + int refprism_1fb_2ea_0v_newels[][8] = + { + { 7, 8, 3, 11, 12, 6 }, + { 1, 9, 7, 4, 13, 11 }, + { 13, 14, 10, 9, 11, 12, 8, 7 }, + { 5, 14, 12, 2, 10, 8 }, + }; + HPRef_Struct refprism_1fb_2ea_0v = + { + HP_PRISM, + refprism_1fb_2ea_0v_splitedges, + 0, 0, + refprism_1fb_2ea_0v_newelstypes, + refprism_1fb_2ea_0v_newels + }; + +// HP_PRISM_1FB_2EB_0V ... quad face 1-2-4-5 with singular edges 1-4, 3-6 + int refprism_1fb_2eb_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 4, 5, 40}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE refprism_1fb_2eb_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_PRISM_1FB_1EA_0V, + HP_HEX_1F_0E_0V, + HP_NONE, + }; + int refprism_1fb_2eb_0v_newels[][8] = + { + { 3, 11, 10, 6, 44, 43 }, + { 12, 9, 10, 11, 45, 42, 43, 44}, + { 1, 7, 12, 4, 40, 45}, + { 40, 5, 2, 7, 45, 42, 9, 12} + }; + HPRef_Struct refprism_1fb_2eb_0v = + { + HP_PRISM, + refprism_1fb_2eb_0v_splitedges, + 0, 0, + refprism_1fb_2eb_0v_newelstypes, + refprism_1fb_2eb_0v_newels + }; + +// HP_PRISM_1FB_3E_0V ... quad face 1-2-4-5 with singular edges 1-4, 3-6 + int refprism_1fb_3e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_1fb_3e_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_HEX, + HP_PRISM_1FB_1EA_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_NONE, + }; + int refprism_1fb_3e_0v_newels[][8] = + { + { 3, 11, 10, 6, 44, 43 }, + { 12, 9, 10, 11, 45, 42, 43, 44}, + { 1, 7, 12, 4, 40, 45 }, + { 40, 41, 8, 7, 45, 42, 9, 12}, + { 5, 41, 42, 2, 8, 9}, + }; + HPRef_Struct refprism_1fb_3e_0v = + { + HP_PRISM, + refprism_1fb_3e_0v_splitedges, + 0, 0, + refprism_1fb_3e_0v_newelstypes, + refprism_1fb_3e_0v_newels + }; + + + +// HP_PRISM_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 + int refprism_2fb_0e_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 1, 2, 9 }, + { 3, 2, 10 }, + { 4, 6, 11 }, + { 5, 6, 12 }, + { 4, 5, 13 }, + { 6, 5, 14 }, + { 0, 0, 0 } + }; + int refprism_2fb_0e_0v_splitfaces[][4] = + { + { 1, 2, 3, 15 }, + { 4, 5, 6, 16 }, + { 0, 0, 0, 0 }, + }; + HPREF_ELEMENT_TYPE refprism_2fb_0e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_NONE, + }; + int refprism_2fb_0e_0v_newels[][8] = + { + { 15, 8, 10, 16, 12, 14 }, + { 13, 5, 2, 9, 16, 12, 8, 15}, + { 11, 7, 3, 6, 16, 15, 10, 14 }, + { 1, 9, 15, 4, 13, 16 }, + { 4, 11, 16, 1,7, 15 } + }; + HPRef_Struct refprism_2fb_0e_0v = + { + HP_PRISM, + refprism_2fb_0e_0v_splitedges, + refprism_2fb_0e_0v_splitfaces, + 0, + refprism_2fb_0e_0v_newelstypes, + refprism_2fb_0e_0v_newels + }; + +// HP_PRISM_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 and sing edge 3-6 + int refprism_2fb_1ec_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 1, 2, 9 }, + { 3, 2, 10 }, + { 4, 6, 11 }, + { 5, 6, 12 }, + { 4, 5, 13 }, + { 6, 5, 14 }, + { 3, 1, 17}, + { 6, 4, 18}, + { 0, 0, 0 } + }; + int refprism_2fb_1ec_0v_splitfaces[][4] = + { + { 1, 2, 3, 15 }, + { 4, 5, 6, 16 }, + { 0, 0, 0, 0 }, + }; + HPREF_ELEMENT_TYPE refprism_2fb_1ec_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_NONE, + }; + int refprism_2fb_1ec_0v_newels[][8] = + { + { 15, 8, 10, 16, 12, 14 }, + { 13, 5, 2, 9, 16, 12, 8, 15}, + { 11, 7, 17, 18, 16, 15, 10, 14 }, + { 1, 9, 15, 4, 13, 16 }, + { 4, 11, 16, 1,7, 15 }, + { 3, 17, 10, 6, 18, 14 } + }; + HPRef_Struct refprism_2fb_1ec_0v = + { + HP_PRISM, + refprism_2fb_1ec_0v_splitedges, + refprism_2fb_1ec_0v_splitfaces, + 0, + refprism_2fb_1ec_0v_newelstypes, + refprism_2fb_1ec_0v_newels + }; + + + +// HP_PRISM_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 and 3 sing edges + int refprism_2fb_3e_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 1, 2, 9 }, + { 3, 2, 10 }, + { 4, 6, 11 }, + { 5, 6, 12 }, + { 4, 5, 13 }, + { 6, 5, 14 }, + { 3, 1, 17}, + { 6, 4, 18}, + { 2, 1, 19}, + { 5, 4, 20}, + { 0, 0, 0 } + }; + int refprism_2fb_3e_0v_splitfaces[][4] = + { + { 1, 2, 3, 15 }, + { 4, 5, 6, 16 }, + { 0, 0, 0, 0 }, + }; + HPREF_ELEMENT_TYPE refprism_2fb_3e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_NONE, + }; + int refprism_2fb_3e_0v_newels[][8] = + { + { 15, 8, 10, 16, 12, 14 }, + { 13, 20, 19, 9, 16, 12, 8, 15}, + { 11, 7, 17, 18, 16, 15, 10, 14 }, + { 1, 9, 15, 4, 13, 16 }, + { 4, 11, 16, 1,7, 15 }, + { 3, 17, 10, 6, 18, 14 }, + { 5, 20, 12, 2, 19, 8 } + }; + HPRef_Struct refprism_2fb_3e_0v = + { + HP_PRISM, + refprism_2fb_3e_0v_splitedges, + refprism_2fb_3e_0v_splitfaces, 0, + refprism_2fb_3e_0v_newelstypes, + refprism_2fb_3e_0v_newels + }; + + + +// HP_PRISM_1FA_1FB_0E_0V ... quad face 1-2-4-5 and trig face 1-2-3 + int refprism_1fa_1fb_0e_0v_splitedges[][3] = + { + {1,4,16}, + {2,5,17}, + {3,6,18}, + {2,3,9}, + {1,3,12}, + {5,6,42}, + {4,6,45}, + {0,0,0} + }; + int refprism_1fa_1fb_0e_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + { 0, 0, 0, 0 } + }; + +HPREF_ELEMENT_TYPE refprism_1fa_1fb_0e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_NONE, + }; + int refprism_1fa_1fb_0e_0v_newels[][8] = + { + { 24, 21, 18, 45, 42, 6 }, + { 4, 5, 17, 16, 45, 42, 21, 24 }, + { 12, 9, 3, 24, 21, 18 }, + { 1, 2, 9, 12, 16, 17, 21, 24 } + }; + HPRef_Struct refprism_1fa_1fb_0e_0v = + { + HP_PRISM, + refprism_1fa_1fb_0e_0v_splitedges, + + refprism_1fa_1fb_0e_0v_splitfaces, 0, + refprism_1fa_1fb_0e_0v_newelstypes, + refprism_1fa_1fb_0e_0v_newels + }; + +/* +// HP_PRISM_1FA_1FB_1EC_0V ... quad face 1-2-4-5 and trig face 1-2-3 +int refprism_1fa_1fb_1ec_0v_splitedges[][3] = + { + {1,4,16}, + {2,5,17}, + {3,6,18}, + {2,3,9}, + {1,3,12}, + {5,6,42}, + {4,6,45}, + {6,5,43}, + {6,4,44}, + {3,2,10}, + {3,1,11}, + {0,0,0} + }; + int refprism_1fa_1fb_1ec_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + { 0, 0, 0, 0 } + }; + + HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ec_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_SINGEDGE, + HP_PRISM_1FA_1E_0V, + HP_PRISM_ + HP_NONE, + }; + int refprism_1fa_1fb_0e_0v_newels[][8] = + { + { 24, 21, 18, 45, 42, 6 }, + { 4, 5, 17, 16, 45, 42, 21, 24 }, + { 12, 9, 3, 24, 21, 18 }, + { 1, 2, 9, 12, 16, 17, 21, 24 } + }; + HPRef_Struct refprism_1fa_1fb_0e_0v = + { + HP_PRISM, + refprism_1fa_1fb_1ec_0v_splitedges, + + refprism_1fa_1fb_1ec_0v_splitfaces, 0, + refprism_1fa_1fb_1ec_0v_newelstypes, + refprism_1fa_1fb_1ec_0v_newels + }; + + +*/ + + + + +// HP_PRISM_2FA_1FB_0E_0V ... quad face 1-2-4-5 and trig face 1-2-3 + int refprism_2fa_1fb_0e_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {4,1,28}, + {5,2,29}, + {6,3,30}, + {0,0,0} + + }; + int refprism_2fa_1fb_0e_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {5,6,2,33}, + {4,1,6,36}, + {0,0,0,0} + }; + + HPREF_ELEMENT_TYPE refprism_2fa_1fb_0e_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PRISM, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_NONE, + }; + int refprism_2fa_1fb_0e_0v_newels[][8] = + { + {28,29,17,16,36,33,21,24}, + {24,21,18, 36, 33, 30}, + {12,9,3,24,21,18}, + {1,2,9,12,16,17,21,24}, + {6,42,45,30,33,36}, + {4,5,29,28,45,42,33,36} + }; + HPRef_Struct refprism_2fa_1fb_0e_0v = + { + HP_PRISM, + refprism_2fa_1fb_0e_0v_splitedges, + + refprism_2fa_1fb_0e_0v_splitfaces, 0, + refprism_2fa_1fb_0e_0v_newelstypes, + refprism_2fa_1fb_0e_0v_newels + }; + + +// HP_PRISM_1FA_1FB_1EA_0V ... quad face 1-2-4-5 and trig face 1-2-3 + int refprism_1fa_1fb_1ea_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {4,5,40}, + {1,2,7}, + {0,0,0}, + }; + int refprism_1fa_1fb_1ea_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {1,2,4,19}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_1fa_1fb_1ea_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PRISM, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_NONE + }; + int refprism_1fa_1fb_1ea_0v_newels[][8] = + { + {40,5,17,19,45,42,21,24}, + {24,21,18,45,42,6}, + {12,9,3,24,21,18}, + {7,2,9,12,19,17,21,24}, + {16,19,24,4,40,45}, + {1,7,12,16,19,24} + + }; + HPRef_Struct refprism_1fa_1fb_1ea_0v = + { + HP_PRISM, + refprism_1fa_1fb_1ea_0v_splitedges, + refprism_1fa_1fb_1ea_0v_splitfaces, 0, + refprism_1fa_1fb_1ea_0v_newelstypes, + refprism_1fa_1fb_1ea_0v_newels + }; + +// HP_PRISM_2FA_1FB_1EA_0V + int refprism_2fa_1fb_1ea_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {4,1,28}, + {5,2,29}, + {6,3,30}, + {4,5,40}, + {1,2,7}, + {0,0,0}, + }; + int refprism_2fa_1fb_1ea_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {1,2,4,19}, + {4,1,6,36}, + {4,1,5,31}, + {5,6,2,33}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_2fa_1fb_1ea_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_NONE + }; + int refprism_2fa_1fb_1ea_0v_newels[][8] = + { + { 18, 24, 21, 30, 36, 33}, + { 31, 29, 17, 19, 36, 33, 21, 24}, + { 16,19, 24, 28, 31, 36 }, + { 3, 12, 9, 18, 24, 21 }, + { 7, 2, 9, 12, 19, 17, 21, 24}, + { 1, 7, 12, 16, 19, 24 }, + { 6, 42, 45, 30, 33, 36 }, + { 40, 5, 29, 31, 45, 42, 33, 36 }, + { 40, 4, 45, 31, 28, 36} + }; + HPRef_Struct refprism_2fa_1fb_1ea_0v = + { + HP_PRISM, + refprism_2fa_1fb_1ea_0v_splitedges, + refprism_2fa_1fb_1ea_0v_splitfaces, 0, + refprism_2fa_1fb_1ea_0v_newelstypes, + refprism_2fa_1fb_1ea_0v_newels + }; + + +// HP_PRISM_2FA_1FB_2EA_0V + int refprism_2fa_1fb_2ea_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {4,1,28}, + {5,2,29}, + {6,3,30}, + {4,5,40}, + {1,2,7}, + { 5, 4, 41}, + { 2, 1, 8}, + {0,0,0}, + }; + int refprism_2fa_1fb_2ea_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {1,2,4,19}, + {4,1,6,36}, + {4,1,5,31}, + {5,6,2,33}, + {5,4,2,32}, + {2,1,5,20}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_2fa_1fb_2ea_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_NONE + }; + int refprism_2fa_1fb_2ea_0v_newels[][8] = + { + { 18, 24, 21, 30, 36, 33}, + { 31, 32, 20, 19, 36, 33, 21, 24}, + { 16,19, 24, 28, 31, 36 }, + { 3, 12, 9, 18, 24, 21 }, + {7,8,9,12,19,20,21,24}, + { 1, 7, 12, 16, 19, 24 }, + { 6, 42, 45, 30, 33, 36 }, + { 40, 41, 32, 31, 45, 42, 33, 36}, + { 40, 4, 45, 31, 28, 36}, + { 8, 2, 9, 20, 17, 21 }, + { 29, 32, 33, 17, 20, 21 }, + { 5, 41, 42, 29, 32, 33 }, + }; + HPRef_Struct refprism_2fa_1fb_2ea_0v = + { + HP_PRISM, + refprism_2fa_1fb_2ea_0v_splitedges, + refprism_2fa_1fb_2ea_0v_splitfaces, 0, + refprism_2fa_1fb_2ea_0v_newelstypes, + refprism_2fa_1fb_2ea_0v_newels + }; + +// HP_PRISM_2FA_1FB_3E_0V + int refprism_2fa_1fb_3e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + {0,0,0}, + }; + int refprism_2fa_1fb_3e_0v_splitfaces[][4] = + { + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,1,5,31}, + {5,4,2,32}, + {5,6,2,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_2fa_1fb_3e_0v_newelstypes[] = + { + HP_HEX, + HP_PRISM_SINGEDGE, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_HEX_1FA_1FB_0E_0V, + + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_HEX_1FA_1FB_0E_0V, + + HP_NONE + }; + int refprism_2fa_1fb_3e_0v_newels[][8] = + { + {24, 21, 22, 23, 36, 33, 34, 35}, + {18, 23, 22, 30, 35, 34}, + { 31, 32, 20, 19, 36, 33, 21, 24}, + { 16,19, 24, 28, 31, 36 }, + { 29, 32, 33, 17, 20, 21}, + + + { 12, 9,10,11, 24, 21, 22, 23 }, + { 3, 11, 10, 18,23,22}, + { 1, 7, 12 , 16, 19, 24}, + { 8,2,9, 20, 17,21}, + { 7,8,9,12,19, 20, 21, 24}, + + { 44, 43, 42, 45, 35, 34, 33, 36}, + { 6, 43, 44, 30, 34, 35}, + { 40, 4, 45, 31,28, 36}, + { 5, 41,42, 29, 32, 33}, + { 40, 41, 32, 31, 45, 42, 33, 36}, + }; + HPRef_Struct refprism_2fa_1fb_3e_0v = + { + HP_PRISM, + refprism_2fa_1fb_3e_0v_splitedges, + + refprism_2fa_1fb_3e_0v_splitfaces, 0, + refprism_2fa_1fb_3e_0v_newelstypes, + refprism_2fa_1fb_3e_0v_newels + }; + + + + +// HP_PRISM_1FA_1FB_1EB_0V ... quad face 1-2-4-5 and trig face 1-2-3 + int refprism_1fa_1fb_1eb_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {5,4,41}, + {2,1,8}, + {0,0,0}, + }; + int refprism_1fa_1fb_1eb_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {2,1,5,20}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_1fa_1fb_1eb_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PRISM, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V , + HP_NONE + }; + int refprism_1fa_1fb_1eb_0v_newels[][8] = + { + {4,41,20,16,45,42,21,24}, + {24,21,18,45,42,6}, + {12,9,3,24,21,18}, + {1,8,9,12,16,20,21,24}, + {5,41,42,17,20,21}, + {8,2,9,20,17,21} + }; + HPRef_Struct refprism_1fa_1fb_1eb_0v = + { + HP_PRISM, + refprism_1fa_1fb_1eb_0v_splitedges, + + refprism_1fa_1fb_1eb_0v_splitfaces, 0, + refprism_1fa_1fb_1eb_0v_newelstypes, + refprism_1fa_1fb_1eb_0v_newels + }; + + +// HP_PRISM_1FA_1FB_2EA_0V ... quad face 1-2-4-5 and trig face 1-2-3 + int refprism_1fa_1fb_2ea_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {5,4,41}, + {2,1,8}, + {4,5,40}, + {1,2,7}, + {0,0,0}, + + }; + int refprism_1fa_1fb_2ea_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {2,1,5,20}, + {1,2,4,19}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_1fa_1fb_2ea_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PRISM, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V , + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_NONE + }; + int refprism_1fa_1fb_2ea_0v_newels[][8] = + { + {40,41,20,19,45,42,21,24}, + {24,21,18,45,42,6}, + {12,9,3,24,21,18}, + {7,8,9,12,19,20,21,24}, + {5,41,42,17,20,21}, + {8,2,9,20,17,21}, + {16,19,24,4,40,45}, + {1,7,12,16,19,24} + }; + HPRef_Struct refprism_1fa_1fb_2ea_0v = + { + HP_PRISM, + refprism_1fa_1fb_2ea_0v_splitedges, + + refprism_1fa_1fb_2ea_0v_splitfaces, 0, + refprism_1fa_1fb_2ea_0v_newelstypes, + refprism_1fa_1fb_2ea_0v_newels + }; + + +// HP_PRISM_1FA_1FB_3E_0V + int refprism_1fa_1fb_3e_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {5,4,41}, + {2,1,8}, + {4,5,40}, + {1,2,7}, + { 3, 2, 10}, + { 3, 1, 11}, + { 6, 5, 43}, + { 6, 4, 44}, + {0,0,0}, + + }; + int refprism_1fa_1fb_3e_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {2,1,5,20}, + {1,2,4,19}, + {3,2,6,22}, + {3,1,6,23}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_1fa_1fb_3e_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_HEX, + HP_PRISM_SINGEDGE, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V , + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_NONE + }; + int refprism_1fa_1fb_3e_0v_newels[][8] = + { + {40,41,20,19,45,42,21,24}, + {24, 21, 22, 23, 45, 42, 43, 44}, + {18, 23, 22, 6, 44, 43}, + {12, 9, 10, 11, 24, 21, 22, 23}, + {3, 11, 10, 18, 23, 22}, + {7,8,9,12,19,20,21,24}, + {5,41,42,17,20,21}, + {8,2,9,20,17,21}, + {16,19,24,4,40,45}, + {1,7,12,16,19,24} + }; + HPRef_Struct refprism_1fa_1fb_3e_0v = + { + HP_PRISM, + refprism_1fa_1fb_3e_0v_splitedges, + + refprism_1fa_1fb_3e_0v_splitfaces, 0, + refprism_1fa_1fb_3e_0v_newelstypes, + refprism_1fa_1fb_3e_0v_newels + }; + + + + + + + + +// HP_PRISM_2FA_0E_0V singular trig faces + int refprism_2fa_0e_0v_splitedges[][3] = + { + {1,4,16}, + {2,5,17}, + {3,6,18}, + {4,1,28}, + {5,2,29}, + {6,3,30}, + {0,0,0} + }; + +HPREF_ELEMENT_TYPE refprism_2fa_0e_0v_newelstypes[] = + { + HP_PRISM, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_NONE + }; + int refprism_2fa_0e_0v_newels[][8] = + { + {16,17,18,28,29,30}, + {1,2,3,16,17,18}, + {4,6,5,28,30,29}, + }; + +HPRef_Struct refprism_2fa_0e_0v = + + { + HP_PRISM, + refprism_2fa_0e_0v_splitedges, + 0, 0, + refprism_2fa_0e_0v_newelstypes, + refprism_2fa_0e_0v_newels + }; + + + + + +// HP_PRISM_1FA_2FB ... quad face 1-2-4-5 and quad face 1-4-6-3 +int refprism_1fa_2fb_0e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 3, 9}, + { 3, 2, 10}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 5, 40}, + { 5, 6, 42}, + { 6, 5, 43}, + { 4, 6, 45}, + { 0, 0, 0 } + }; +int refprism_1fa_2fb_0e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {1,2,4,19}, + {2,3,5,21}, + {3,2,6,22}, + {1,3,4,24}, + {4,5,6,46}, + { 0, 0, 0, 0 } + }; +int refprism_1fa_2fb_0e_0v_splitelement[][5] = + { + {1,2,3,4,25}, + {0,0,0,0,0} + }; + +HPREF_ELEMENT_TYPE refprism_1fa_2fb_0e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_NONE, + }; + int refprism_1fa_2fb_0e_0v_newels[][8] = + { + { 25, 21, 22, 46, 42, 43 }, + { 40, 5, 17, 19, 46, 42, 21, 25 }, + { 24, 18, 6, 45, 25, 22, 43, 46}, + { 16, 19, 25, 4, 40, 46 }, + { 4, 45, 46, 16, 24, 25 }, + { 13, 9, 10, 25, 21, 22 }, + { 7, 2, 9, 13, 19, 17, 21, 25 }, + { 3, 12, 13, 10, 18, 24, 25, 22 }, + { 1, 7, 13, 16, 19, 25 }, + { 12, 1, 13, 24, 16, 25 } + + }; + HPRef_Struct refprism_1fa_2fb_0e_0v = + { + HP_PRISM, + refprism_1fa_2fb_0e_0v_splitedges, + refprism_1fa_2fb_0e_0v_splitfaces, + refprism_1fa_2fb_0e_0v_splitelement, + refprism_1fa_2fb_0e_0v_newelstypes, + refprism_1fa_2fb_0e_0v_newels + }; + +// HP_PRISM_1FA_2FB_1EC ... quad face 1-2-4-5 and quad face 1-4-6-3 +int refprism_1fa_2fb_1ec_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 5, 40}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0 } + }; +int refprism_1fa_2fb_1ec_0v_splitfaces[][4] = + { + {1,2,3,13}, + {1,2,4,19}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,5,6,46}, + { 0, 0, 0, 0 } + }; +int refprism_1fa_2fb_1ec_0v_splitelement[][5] = + { + {1,2,3,4,25}, + {0,0,0,0,0} + }; + +HPREF_ELEMENT_TYPE refprism_1fa_2fb_1ec_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + + HP_NONE, + }; + int refprism_1fa_2fb_1ec_0v_newels[][8] = + { + { 25, 21, 22, 46, 42, 43 }, + { 40, 5, 17, 19, 46, 42, 21, 25 }, + { 24, 23, 44, 45, 25, 22, 43, 46}, + { 16, 19, 25, 4, 40, 46 }, + { 4, 45, 46, 16, 24, 25 }, + { 18, 23, 22, 6, 44, 43}, + + + { 13, 9, 10, 25, 21, 22 }, + { 7, 2, 9, 13, 19, 17, 21, 25 }, + { 11, 12, 13, 10, 23, 24, 25, 22 }, + { 1, 7, 13, 16, 19, 25 }, + { 12, 1, 13, 24, 16, 25 }, + { 3, 11, 10, 18, 23, 22}, + + }; + HPRef_Struct refprism_1fa_2fb_1ec_0v = + { + HP_PRISM, + refprism_1fa_2fb_1ec_0v_splitedges, + refprism_1fa_2fb_1ec_0v_splitfaces, + refprism_1fa_2fb_1ec_0v_splitelement, + refprism_1fa_2fb_1ec_0v_newelstypes, + refprism_1fa_2fb_1ec_0v_newels + }; + + +// HP_PRISM_1FA_2FB_3E ... quad face 1-2-4-5 and quad face 1-4-6-3 +int refprism_1fa_2fb_3e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0 } + }; +int refprism_1fa_2fb_3e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,5,6,46}, + { 0, 0, 0, 0 } + }; +int refprism_1fa_2fb_3e_0v_splitelement[][5] = + { + {1,2,3,4,25}, + {0,0,0,0,0} + }; + +HPREF_ELEMENT_TYPE refprism_1fa_2fb_3e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_NONE, + }; + int refprism_1fa_2fb_3e_0v_newels[][8] = + { + { 25, 21, 22, 46, 42, 43 }, + { 40, 41, 20, 19, 46, 42, 21, 25 }, + { 24, 23, 44, 45, 25, 22, 43, 46}, + { 16, 19, 25, 4, 40, 46 }, + { 4, 45, 46, 16, 24, 25 }, + { 18, 23, 22, 6, 44, 43}, + { 5, 41, 42, 17, 20, 21}, + + + { 13, 9, 10, 25, 21, 22 }, + { 7, 8, 9, 13, 19, 20, 21, 25 }, + { 11, 12, 13, 10, 23, 24, 25, 22 }, + { 1, 7, 13, 16, 19, 25 }, + + { 12, 1, 13, 24, 16, 25 }, + { 3, 11, 10, 18, 23, 22}, + { 8, 2, 9, 20, 17, 21}, + + }; + HPRef_Struct refprism_1fa_2fb_3e_0v = + { + HP_PRISM, + refprism_1fa_2fb_3e_0v_splitedges, + refprism_1fa_2fb_3e_0v_splitfaces, + refprism_1fa_2fb_3e_0v_splitelement, + refprism_1fa_2fb_3e_0v_newelstypes, + refprism_1fa_2fb_3e_0v_newels + }; + + + + + + + + + +// HP_PRISM_1FA_2FB_1eb ... quad face 1-2-4-5 and quad face 1-4-6-3 +int refprism_1fa_2fb_1eb_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 4, 6, 45}, + { 0, 0, 0 } + }; +int refprism_1fa_2fb_1eb_0v_splitfaces[][4] = + { + {1,2,3,13}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {1,3,4,24}, + {4,5,6,46}, + { 0, 0, 0, 0 } + }; +int refprism_1fa_2fb_1eb_0v_splitelement[][5] = + { + {1,2,3,4,25}, + {0,0,0,0,0} + }; + + +HPREF_ELEMENT_TYPE refprism_1fa_2fb_1eb_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_NONE, + }; + + int refprism_1fa_2fb_1eb_0v_newels[][8] = + { + { 25, 21, 22, 46, 42, 43 }, + { 40, 41, 20, 19, 46, 42, 21, 25 }, + { 24, 18, 6, 45, 25, 22, 43, 46}, + { 16, 19, 25, 4, 40, 46 }, + { 4, 45, 46, 16, 24, 25 }, + { 5, 41, 42, 17, 20, 21 }, + + + { 13, 9, 10, 25, 21, 22 }, + { 7, 8, 9, 13, 19, 20, 21, 25 }, + { 3, 12, 13, 10, 18, 24, 25, 22 }, + { 1, 7, 13, 16, 19, 25 }, + { 12, 1, 13, 24, 16, 25 }, + { 8, 2, 9, 20, 17, 21}, + + }; + HPRef_Struct refprism_1fa_2fb_1eb_0v = + { + HP_PRISM, + refprism_1fa_2fb_1eb_0v_splitedges, + refprism_1fa_2fb_1eb_0v_splitfaces, + refprism_1fa_2fb_1eb_0v_splitelement, + refprism_1fa_2fb_1eb_0v_newelstypes, + refprism_1fa_2fb_1eb_0v_newels + }; + + + + + + +// HP_PRISM_2FA_2FB +int refprism_2fa_2fb_0e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 3, 9}, + { 3, 2, 10}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 5, 40}, + { 5, 6, 42}, + { 6, 5, 43}, + { 4, 6, 45}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 0, 0, 0 } + }; +int refprism_2fa_2fb_0e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {1,2,4,19}, + {2,3,5,21}, + {3,2,6,22}, + {1,3,4,24}, + {4,5,6,46}, + {4,1,5,31}, + {5,6,2,33}, + {6,5,3,34}, + {4,1,6,36}, + { 0, 0, 0, 0 } + }; +int refprism_2fa_2fb_0e_0v_splitelement[][5] = + { + {1,2,3,4,25}, + {4,1,6,5,37}, + {0,0,0,0,0} + }; + +HPREF_ELEMENT_TYPE refprism_2fa_2fb_0e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + + HP_NONE, + }; + int refprism_2fa_2fb_0e_0v_newels[][8] = + { + { 25, 21, 22, 37, 33, 34}, + { 31, 29, 17, 19, 37, 33, 21, 25}, + { 36, 24, 18, 30, 37, 25, 22, 34}, + { 16, 19, 25, 28, 31, 37}, + { 28, 36, 37, 16, 24, 25}, + + { 13, 9, 10, 25, 21, 22 }, + { 7, 2, 9, 13, 19, 17, 21, 25 }, + { 3, 12, 13, 10, 18, 24, 25, 22 }, + { 1, 7, 13, 16, 19, 25 }, + { 12, 1, 13, 24, 16, 25 }, + + { 46, 43, 42 ,37, 34, 33}, + { 40, 5, 29, 31, 46, 42, 33, 37 }, + { 6, 45, 36, 30, 43, 46, 37, 34 }, + { 40, 4, 46, 31, 28, 37 }, + { 4, 45, 46, 28, 36, 37}, + + }; + HPRef_Struct refprism_2fa_2fb_0e_0v = + { + HP_PRISM, + refprism_2fa_2fb_0e_0v_splitedges, + refprism_2fa_2fb_0e_0v_splitfaces, + refprism_2fa_2fb_0e_0v_splitelement, + refprism_2fa_2fb_0e_0v_newelstypes, + refprism_2fa_2fb_0e_0v_newels + }; + + +// HP_PRISM_2FA_2FB_1EC +int refprism_2fa_2fb_1ec_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 4, 5, 40}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0 } + }; +int refprism_2fa_2fb_1ec_0v_splitfaces[][4] = + { + {1,2,3,13}, + {1,2,4,19}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,5,6,46}, + {4,1,5,31}, + {5,6,2,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + { 0, 0, 0, 0 } + }; +int refprism_2fa_2fb_1ec_0v_splitelement[][5] = + { + {1,2,3,4,25}, + {4,1,6,5,37}, + {0,0,0,0,0} + }; + +HPREF_ELEMENT_TYPE refprism_2fa_2fb_1ec_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_NONE, + }; + int refprism_2fa_2fb_1ec_0v_newels[][8] = + { + { 25, 21, 22, 37, 33, 34}, + { 31, 29, 17, 19, 37, 33, 21, 25}, + { 36, 24, 23, 35, 37, 25, 22, 34}, + { 16, 19, 25, 28, 31, 37}, + { 28, 36, 37, 16, 24, 25}, + { 18, 23, 22, 30, 35, 34}, + + { 13, 9, 10, 25, 21, 22 }, + { 7, 2, 9, 13, 19, 17, 21, 25 }, + { 11, 12, 13, 10, 23, 24, 25, 22 }, + { 1, 7, 13, 16, 19, 25 }, + { 12, 1, 13, 24, 16, 25 }, + { 3, 11, 10, 18, 23, 22 }, + + { 46, 43, 42 ,37, 34, 33}, + { 40, 5, 29, 31, 46, 42, 33, 37 }, + { 44, 45, 36, 35, 43, 46, 37, 34 }, + { 40, 4, 46, 31, 28, 37 }, + { 4, 45, 46, 28, 36, 37}, + { 44, 6, 43, 35, 30, 34}, + + }; + HPRef_Struct refprism_2fa_2fb_1ec_0v = + { + HP_PRISM, + refprism_2fa_2fb_1ec_0v_splitedges, + refprism_2fa_2fb_1ec_0v_splitfaces, + refprism_2fa_2fb_1ec_0v_splitelement, + refprism_2fa_2fb_1ec_0v_newelstypes, + refprism_2fa_2fb_1ec_0v_newels + }; + + + +// HP_PRISM_2FA_2FB_3E +int refprism_2fa_2fb_3e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0 } + }; +int refprism_2fa_2fb_3e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,5,6,46}, + {4,1,5,31}, + {5,4,2,32}, + {5,6,2,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + { 0, 0, 0, 0 } + }; +int refprism_2fa_2fb_3e_0v_splitelement[][5] = + { + {1,2,3,4,25}, + {4,1,6,5,37}, + {0,0,0,0,0} + }; + +HPREF_ELEMENT_TYPE refprism_2fa_2fb_3e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + + HP_NONE, + }; + int refprism_2fa_2fb_3e_0v_newels[][8] = + { + { 25, 21, 22, 37, 33, 34}, + { 31, 32, 20, 19, 37, 33, 21, 25}, + { 36, 24, 23, 35, 37, 25, 22, 34}, + { 16, 19, 25, 28, 31, 37}, + { 28, 36, 37, 16, 24, 25}, + { 18, 23, 22, 30, 35, 34}, + { 29, 32, 33, 17, 20, 21}, + + { 13, 9, 10, 25, 21, 22 }, + { 7, 8, 9, 13, 19, 20, 21, 25 }, + { 11, 12, 13, 10, 23, 24, 25, 22 }, + { 1, 7, 13, 16, 19, 25 }, + { 12, 1, 13, 24, 16, 25 }, + { 3, 11, 10, 18, 23, 22 }, + { 8, 2, 9, 20, 17, 21 }, + + { 46, 43, 42 ,37, 34, 33}, + { 40, 41, 32, 31, 46, 42, 33, 37 }, + { 44, 45, 36, 35, 43, 46, 37, 34 }, + { 40, 4, 46, 31, 28, 37 }, + { 4, 45, 46, 28, 36, 37}, + { 44, 6, 43, 35, 30, 34}, + { 5, 41, 42, 29, 32, 33}, + + }; + HPRef_Struct refprism_2fa_2fb_3e_0v = + { + HP_PRISM, + refprism_2fa_2fb_3e_0v_splitedges, + refprism_2fa_2fb_3e_0v_splitfaces, + refprism_2fa_2fb_3e_0v_splitelement, + refprism_2fa_2fb_3e_0v_newelstypes, + refprism_2fa_2fb_3e_0v_newels + }; + + + + +// HP_PRISM_1FA_2E_0V + int refprism_1fa_2e_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {5,4,41}, + {2,1,8}, + {4,5,40}, + {1,2,7}, + {0,0,0}, + + }; + int refprism_1fa_2e_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {2,1,5,20}, + {1,2,4,19}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_1fa_2e_0v_newelstypes[] = + { + HP_HEX, + HP_PRISM, + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_SINGEDGE, + HP_PRISM_1FA_1E_0V, + HP_PRISM_SINGEDGE, + HP_PRISM_1FA_1E_0V, + HP_NONE + }; + int refprism_1fa_2e_0v_newels[][8] = + { + {40,41,20,19,45,42,21,24}, + {24,21,18,45,42,6}, + {12,9,3,24,21,18}, + {9, 12, 7, 8, 21, 24, 19, 20}, + { 17, 21, 20, 5, 42, 41}, + {2, 9, 8, 17, 21, 20}, + {16,19,24,4,40,45}, + {1,7,12,16,19,24} + }; + HPRef_Struct refprism_1fa_2e_0v = + { + HP_PRISM, + refprism_1fa_2e_0v_splitedges, + + refprism_1fa_2e_0v_splitfaces, 0, + refprism_1fa_2e_0v_newelstypes, + refprism_1fa_2e_0v_newels + }; + +// HP_PRISM_2FA_2E_0V + int refprism_2fa_2e_0v_splitedges[][3] = + { + {2,3,9}, + {1,3,12}, + {1,4,16}, + {2,5,17}, + {3,6,18}, + {5,6,42}, + {4,6,45}, + {4,1,28}, + {5,2,29}, + {6,3,30}, + {4,5,40}, + {1,2,7}, + { 5, 4, 41}, + { 2, 1, 8}, + {0,0,0}, + }; + int refprism_2fa_2e_0v_splitfaces[][4] = + { + {2,3,5,21}, + {1,3,4,24}, + {1,2,4,19}, + {4,1,6,36}, + {4,1,5,31}, + {5,6,2,33}, + {5,4,2,32}, + {2,1,5,20}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_2fa_2e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + HP_NONE, + + }; + int refprism_2fa_2e_0v_newels[][8] = + { + { 24, 21, 18, 36, 33, 30}, + { 19, 20, 21, 24, 31, 32, 33, 36}, + { 16, 19, 24, 28, 31, 36}, + { 17, 21, 20, 29, 33, 32}, + + { 12, 9, 3, 24, 21, 18}, + { 7, 8, 9, 12, 19, 20, 21, 24}, + { 1, 7, 12, 16, 19, 24}, + { 2, 9, 8, 17, 21, 20}, + + { 45, 6, 42, 36, 30, 33}, + { 40, 45, 42, 41, 31, 36, 33, 32}, + { 4, 45, 40, 28, 36, 31 }, + { 5, 41, 42, 29, 32, 33 }, + }; + HPRef_Struct refprism_2fa_2e_0v = + { + HP_PRISM, + refprism_2fa_2e_0v_splitedges, + refprism_2fa_2e_0v_splitfaces, 0, + refprism_2fa_2e_0v_newelstypes, + refprism_2fa_2e_0v_newels + }; + + + +// HP_PRISM_3E_0V + int refprism_3e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0}, + }; + int refprism_3e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {2,3,1,14}, + {3,1,2,15}, + {4,5,6,46}, + {5,4,6,47}, + {6,4,5,48}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_3e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX, + HP_HEX, + HP_HEX, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_NONE + }; + int refprism_3e_0v_newels[][8] = + { + { 13, 14, 15, 46, 47, 48}, + { 7, 8, 14, 13, 40, 41, 47, 46}, + { 15, 14, 9, 10, 48, 47, 42, 43}, + { 12, 13, 15, 11, 45, 46, 48, 44}, + { 14, 8, 9, 47, 41, 42 }, + { 11, 15, 10, 44, 48, 43 }, + { 7, 13, 12, 40, 46, 45}, + { 1, 7, 12, 4, 40, 45}, + { 2, 9, 8, 5, 42, 41 }, + { 3, 11, 10, 6, 44, 43 } + }; + HPRef_Struct refprism_3e_0v = + { + HP_PRISM, + refprism_3e_0v_splitedges, + refprism_3e_0v_splitfaces, 0, + refprism_3e_0v_newelstypes, + refprism_3e_0v_newels + }; + + +// HP_PRISM_3E_0V +int refprism_1fa_3e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + + { 0, 0, 0}, + }; +int refprism_1fa_3e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {2,3,1,14}, + {3,1,2,15}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,5,6,46}, + {5,4,6,47}, + {6,4,5,48}, + {0,0,0,0}, + }; + +int refprism_1fa_3e_0v_splitelements[][5] = + { + {1,2,3,4,25}, + {2,1,3,5,26}, + {3,1,2,6,27}, + {0,0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_1fa_3e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX, + HP_HEX, + HP_HEX, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + HP_NONE + }; +int refprism_1fa_3e_0v_newels[][8] = + { + { 25, 26, 27, 46, 47, 48}, + { 19, 20, 26, 25, 40, 41, 47, 46}, + { 27, 26, 21, 22, 48, 47, 42, 43}, + { 23, 24, 25, 27, 44, 45, 46, 48}, + { 19, 25, 24, 40, 46, 45}, + { 26, 20, 21, 47, 41, 42}, + { 23, 27, 22, 44, 48, 43}, + { 16, 19, 24, 4, 40, 45}, + { 17, 21, 20, 5, 42, 41}, + { 18, 23, 22, 6, 44, 43}, + + { 13, 14, 15, 25, 26, 27}, + { 7, 8, 14, 13, 19, 20, 26, 25}, + { 15, 14, 9, 10, 27, 26, 21, 22}, + { 12, 13, 15, 11, 24, 25, 27, 23}, + { 14, 8, 9, 26, 20, 21}, + { 11, 15, 10, 23, 27, 22}, + { 7, 13 , 12, 19, 25, 24}, + { 2, 9, 8, 17, 21, 20}, + { 3, 11, 10, 18, 23, 22}, + { 1, 7, 12, 16, 19, 24}, + }; + HPRef_Struct refprism_1fa_3e_0v = + { + HP_PRISM, + refprism_1fa_3e_0v_splitedges, + refprism_1fa_3e_0v_splitfaces, + refprism_1fa_3e_0v_splitelements, + refprism_1fa_3e_0v_newelstypes, + refprism_1fa_3e_0v_newels + }; + + + +// HP_PRISM_2FA_3E_0V +int refprism_2fa_3e_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0}, + }; +int refprism_2fa_3e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {2,3,1,14}, + {3,1,2,15}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,1,5,31}, + {5,4,2,32}, + {5,6,2,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + {4,5,6,46}, + {5,4,6,47}, + {6,4,5,48}, + {0,0,0,0}, + }; + +int refprism_2fa_3e_0v_splitelements[][5] = + { + {1,2,3,4,25}, + {2,1,3,5,26}, + {3,1,2,6,27}, + {4,1,6,5,37}, + {5,2,4,6,38}, + {6,4,5,3,39}, + {0,0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_2fa_3e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX, + HP_HEX, + HP_HEX, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + + HP_NONE + }; + + int refprism_2fa_3e_0v_newels[][8] = + { + { 25, 26, 27, 37, 38, 39}, + { 19, 20, 26, 25, 31, 32, 38, 37}, + { 27, 26, 21, 22, 39, 38, 33, 34}, + { 23, 24, 25, 27, 35, 36, 37, 39}, + { 19, 25, 24, 31, 37, 36}, + { 26, 20, 21, 38, 32, 33}, + { 23, 27, 22, 35, 39, 34}, + { 16, 19, 24, 28, 31, 36}, + { 17, 21, 20, 29, 33, 32}, + { 18, 23, 22, 30, 35, 34}, + + { 13, 14, 15, 25, 26, 27}, + { 7, 8, 14, 13, 19, 20, 26, 25}, + { 15, 14, 9, 10, 27, 26, 21, 22}, + { 12, 13, 15, 11, 24, 25, 27, 23}, + { 14, 8, 9, 26, 20, 21}, + { 11, 15, 10, 23, 27, 22}, + { 7, 13 , 12, 19, 25, 24}, + { 2, 9, 8, 17, 21, 20}, + { 3, 11, 10, 18, 23, 22}, + { 1, 7, 12, 16, 19, 24}, + + { 48, 47, 46, 39, 38, 37 }, + { 48, 43, 42, 47, 39, 34, 33, 38}, + { 45, 44, 48, 46, 36, 35, 39, 37}, + { 46, 47, 41, 40, 37, 38, 32, 31}, + { 47, 42, 41, 38, 33, 32}, + { 45, 46, 40, 36, 37, 31}, + { 44, 43, 48, 35, 34, 39}, + { 6, 43, 44, 30, 34, 35}, + { 5, 41, 42, 29, 32, 33}, + { 4, 45, 40, 28, 36, 31}, + }; + +HPRef_Struct refprism_2fa_3e_0v = + { + HP_PRISM, + refprism_2fa_3e_0v_splitedges, + refprism_2fa_3e_0v_splitfaces, + refprism_2fa_3e_0v_splitelements, + refprism_2fa_3e_0v_newelstypes, + refprism_2fa_3e_0v_newels + }; + + + +// HP_PRISM_3FB_0V + int refprism_3fb_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0}, + }; + int refprism_3fb_0v_splitfaces[][4] = + { + {1,2,3,13}, + {2,3,1,14}, + {3,1,2,15}, + {4,5,6,46}, + {5,4,6,47}, + {6,4,5,48}, + {0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_3fb_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_NONE + }; + int refprism_3fb_0v_newels[][8] = + { + { 13, 14, 15, 46, 47, 48}, + { 8, 7, 40, 41, 14,13, 46, 47 }, + { 10, 9, 42, 43, 15, 14, 47, 48 }, + { 44, 45, 12, 11, 48, 46, 13, 15}, + { 1, 7, 13, 4, 40, 46 }, + { 4, 45, 46, 1, 12, 13}, + { 2, 9, 14, 5, 42, 47 }, + { 5, 41, 47, 2, 8, 14 }, + { 3, 11, 15, 6, 44, 48}, + { 6, 43, 48, 3, 10, 15}, + + }; + HPRef_Struct refprism_3fb_0v = + { + HP_PRISM, + refprism_3fb_0v_splitedges, + refprism_3fb_0v_splitfaces, 0, + refprism_3fb_0v_newelstypes, + refprism_3fb_0v_newels + }; + + +// HP_PRISM_3FB_0V +int refprism_1fa_3fb_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0}, + }; +int refprism_1fa_3fb_0v_splitfaces[][4] = + { + {1,2,3,13}, + {2,3,1,14}, + {3,1,2,15}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,5,6,46}, + {5,4,6,47}, + {6,4,5,48}, + {0,0,0,0}, + }; + +int refprism_1fa_3fb_0v_splitelements[][5] = + { + {1,2,3,4,25}, + {2,1,3,5,26}, + {3,1,2,6,27}, + {0,0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_1fa_3fb_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_NONE + }; + int refprism_1fa_3fb_0v_newels[][8] = + { + { 25, 26, 27, 46, 47, 48}, + { 19, 40, 41, 20, 25, 46, 47, 26}, + { 22, 21, 42, 43, 27, 26, 47, 48}, + { 24, 23, 44, 45, 25, 27, 48, 46}, + + { 16, 19, 25, 4, 40, 46 }, + { 4, 45, 46, 16, 24, 25 }, + { 17, 21, 26, 5, 42, 47 }, + { 5, 41, 47, 17, 20, 26}, + { 18, 23, 27, 6, 44, 48}, + { 6, 43, 48, 18, 22, 27}, + + { 13, 14, 15, 25, 26, 27}, + { 7, 8, 14, 13, 19, 20, 26, 25}, + { 9, 10, 15, 14, 21, 22, 27, 26}, + { 11, 12, 13, 15, 23, 24, 25, 27}, + + { 2, 9, 14, 17, 21, 26}, + { 8, 2, 14, 20, 17, 26}, + { 1, 7, 13, 16, 19, 25}, + { 12, 1, 13, 24, 16, 25 }, + { 3, 11, 15, 18, 23, 27 }, + { 10, 3, 15, 22, 18, 27}, + + }; + HPRef_Struct refprism_1fa_3fb_0v = + { + HP_PRISM, + refprism_1fa_3fb_0v_splitedges, + refprism_1fa_3fb_0v_splitfaces, + refprism_1fa_3fb_0v_splitelements, + refprism_1fa_3fb_0v_newelstypes, + refprism_1fa_3fb_0v_newels + }; + + + +// HP_PRISM_2FA_3E_0V +int refprism_2fa_3fb_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0}, + }; +int refprism_2fa_3fb_0v_splitfaces[][4] = + { + {1,2,3,13}, + {2,3,1,14}, + {3,1,2,15}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,1,5,31}, + {5,4,2,32}, + {5,6,2,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + {4,5,6,46}, + {5,4,6,47}, + {6,4,5,48}, + {0,0,0,0}, + }; + +int refprism_2fa_3fb_0v_splitelements[][5] = + { + {1,2,3,4,25}, + {2,1,3,5,26}, + {3,1,2,6,27}, + {4,1,6,5,37}, + {5,2,4,6,38}, + {6,4,5,3,39}, + {0,0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_2fa_3fb_0v_newelstypes[] = + { + + HP_PRISM, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_HEX_1FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + + HP_NONE + }; + int refprism_2fa_3fb_0v_newels[][8] = + { + { 25, 26, 27, 37, 38, 39}, + { 19, 31, 32, 20, 25, 37, 38, 26}, + { 33, 34, 22, 21, 38, 39, 27, 26}, + { 35, 36, 24, 23, 39, 37, 25, 27}, + + { 16, 19, 25, 28, 31, 37}, + { 28, 36, 37, 16, 24, 25 }, + { 17, 21, 26, 29, 33, 38 }, + { 29, 32, 38, 17, 20, 26}, + { 18, 23, 27, 30, 35, 39}, + { 30, 34, 39, 18, 22, 27}, + + + { 13, 14, 15, 25, 26, 27}, + { 7, 8, 14, 13, 19, 20, 26, 25}, + { 9, 10, 15, 14, 21, 22, 27, 26}, + { 11, 12, 13, 15, 23, 24, 25, 27}, + + { 2, 9, 14, 17, 21, 26}, + { 8, 2, 14, 20, 17, 26}, + { 1, 7, 13, 16, 19, 25}, + { 12, 1, 13, 24, 16, 25 }, + { 3, 11, 15, 18, 23, 27 }, + { 10, 3, 15, 22, 18, 27}, + + + { 48, 47, 46, 39, 38, 37 }, + { 44, 45, 36, 35, 48, 46, 37, 39}, + { 40, 41, 32, 31, 46, 47, 38, 37}, + { 42, 43, 34, 33, 47, 48, 39, 38}, + + { 6, 43, 48, 30, 34, 39}, + { 44, 6, 48, 35, 30, 39}, + { 4, 45, 46, 28, 36, 37}, + { 40, 4, 46, 31, 28, 37}, + { 5, 41, 47, 29, 32, 38}, + { 42, 5, 47, 33, 29, 38}, + }; + +HPRef_Struct refprism_2fa_3fb_0v = + { + HP_PRISM, + refprism_2fa_3fb_0v_splitedges, + refprism_2fa_3fb_0v_splitfaces, + refprism_2fa_3fb_0v_splitelements, + refprism_2fa_3fb_0v_newelstypes, + refprism_2fa_3fb_0v_newels + }; + + +/* + + +// HP_PRISM_3E_4EH +int refprism_3e_4eh_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0}, + + }; +int refprism_3e_4eh_splitfaces[][4] = + { + {3,1,2,15}, + {6,4,5,48}, + {0,0,0,0}, + }; + +HPREF_ELEMENT_TYPE refprism_2fa_3fb_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX_2EH_0V, + HP_HEX_2EH_0V, + HP_TET_2E, + HP_TET_2E, + HP_PRISM_1E_2EH_0V, + HP_PRISM_1E_2EH_0V, + HP_NONE + }; + int refprism_2fa_3fb_0v_newels[][8] = + { + {15, 7, 8, 48, 40, 41 }, + + }; + +HPRef_Struct refprism_2fa_3fb_0v = + { + HP_PRISM, + refprism_2fa_3fb_0v_splitedges, + refprism_2fa_3fb_0v_splitfaces, + refprism_2fa_3fb_0v_splitelements, + refprism_2fa_3fb_0v_newelstypes, + refprism_2fa_3fb_0v_newels + }; +*/ + +/* +// HP_PRISM_2FA_3E_0V +int refprism_3e_4_0v_splitedges[][3] = + { + { 1, 2, 7}, + { 2, 1, 8}, + { 2, 3, 9}, + { 3, 2, 10}, + { 3, 1, 11}, + { 1, 3, 12}, + { 1, 4, 16}, + { 2, 5, 17}, + { 3, 6, 18}, + { 4, 1, 28}, + { 5, 2, 29}, + { 6, 3, 30}, + { 4, 5, 40}, + { 5, 4, 41}, + { 5, 6, 42}, + { 6, 5, 43}, + { 6, 4, 44}, + { 4, 6, 45}, + { 0, 0, 0}, + }; +int refprism_2fa_3e_0v_splitfaces[][4] = + { + {1,2,3,13}, + {2,3,1,14}, + {3,1,2,15}, + {1,2,4,19}, + {2,1,5,20}, + {2,3,5,21}, + {3,2,6,22}, + {3,1,6,23}, + {1,3,4,24}, + {4,1,5,31}, + {5,4,2,32}, + {5,6,2,33}, + {6,5,3,34}, + {6,4,3,35}, + {4,1,6,36}, + {4,5,6,46}, + {5,4,6,47}, + {6,4,5,48}, + {0,0,0,0}, + }; + +int refprism_2fa_3e_0v_splitelements[][5] = + { + {1,2,3,4,25}, + {2,1,3,5,26}, + {3,1,2,6,27}, + {4,1,6,5,37}, + {5,2,4,6,38}, + {6,4,5,3,39}, + {0,0,0,0,0}, + }; + + HPREF_ELEMENT_TYPE refprism_2fa_3e_0v_newelstypes[] = + { + HP_PRISM, + HP_HEX, + HP_HEX, + HP_HEX, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + + HP_PRISM_1FA_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + HP_PRISM_1FA_1E_0V, + + HP_NONE + }; + + int refprism_2fa_3e_0v_newels[][8] = + { + { 25, 26, 27, 37, 38, 39}, + { 19, 20, 26, 25, 31, 32, 38, 37}, + { 27, 26, 21, 22, 39, 38, 33, 34}, + { 23, 24, 25, 27, 35, 36, 37, 39}, + { 19, 25, 24, 31, 37, 36}, + { 26, 20, 21, 38, 32, 33}, + { 23, 27, 22, 35, 39, 34}, + { 16, 19, 24, 28, 31, 36}, + { 17, 21, 20, 29, 33, 32}, + { 18, 23, 22, 30, 35, 34}, + + { 13, 14, 15, 25, 26, 27}, + { 7, 8, 14, 13, 19, 20, 26, 25}, + { 15, 14, 9, 10, 27, 26, 21, 22}, + { 12, 13, 15, 11, 24, 25, 27, 23}, + { 14, 8, 9, 26, 20, 21}, + { 11, 15, 10, 23, 27, 22}, + { 7, 13 , 12, 19, 25, 24}, + { 2, 9, 8, 17, 21, 20}, + { 3, 11, 10, 18, 23, 22}, + { 1, 7, 12, 16, 19, 24}, + + { 48, 47, 46, 39, 38, 37 }, + { 48, 43, 42, 47, 39, 34, 33, 38}, + { 45, 44, 48, 46, 36, 35, 39, 37}, + { 46, 47, 41, 40, 37, 38, 32, 31}, + { 47, 42, 41, 38, 33, 32}, + { 45, 46, 40, 36, 37, 31}, + { 44, 43, 48, 35, 34, 39}, + { 6, 43, 44, 30, 34, 35}, + { 5, 41, 42, 29, 32, 33}, + { 4, 45, 40, 28, 36, 31}, + }; + +HPRef_Struct refprism_2fa_3e_0v = + { + HP_PRISM, + refprism_2fa_3e_0v_splitedges, + refprism_2fa_3e_0v_splitfaces, + refprism_2fa_3e_0v_splitelements, + refprism_2fa_3e_0v_newelstypes, + refprism_2fa_3e_0v_newels + }; + +*/ +/* + +// HP_PRISM_1FB_1EB_0V ... quad face 1-2-4-5 + int refprism_1fb_1eb_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 3, 8 }, + { 4, 6, 9 }, + { 5, 6, 10 }, + { 2, 1, 11 }, + { 5, 4, 12 }, + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refprism_1fb_1eb_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EB_0V, + HP_PRISM, + HP_NONE, + }; + int refprism_1fb_1eb_0v_newels[][8] = + { + { 1, 4, 12, 11, 7, 9, 10, 8 }, + { 11, 2, 8, 12, 5, 10 }, + { 7, 8, 3, 9, 10, 6 } + }; + HPRef_Struct refprism_1fb_1eb_0v = + { + HP_PRISM, + refprism_1fb_1eb_0v_splitedges, + 0, 0, + refprism_1fb_1eb_0v_newelstypes, + refprism_1fb_1eb_0v_newels + }; + + + + + + + + + + + // HP_PRISM_2F_0E_0V + int refprism_2f_0e_0v_splitedges[][3] = + { + { 1, 3, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 3, 1, 10 }, + + { 4, 6, 12 }, + { 5, 4, 13 }, + { 5, 6, 14 }, + { 6, 4, 15 }, + + { 0, 0, 0 } + }; + + int refprism_2f_0e_0v_splitfaces[][4] = + { + { 2, 1, 3, 11 }, + { 5, 4, 6, 16 }, + { 0, 0, 0, 0 }, + }; + + HPREF_ELEMENT_TYPE refprism_2f_0e_0v_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_HEX_1F_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM, + HP_NONE, + }; + int refprism_2f_0e_0v_newels[][8] = + { + //{ 1, 8, 11, 7, 4, 13, 16, 12 }, + // { 9, 3, 10, 11, 14, 6, 15, 16 }, + { 1, 4, 13, 8, 7, 12, 16, 11 }, + { 9, 14, 6, 3, 11, 16, 15, 10 }, + { 2, 9, 11, 5, 14, 16 }, + // { 8, 2, 11, 13, 5, 16 }, + { 5, 13, 16, 2, 8, 11 }, + { 7, 11, 10, 12, 16, 15 } + }; + HPRef_Struct refprism_2f_0e_0v = + { + HP_PRISM, + refprism_2f_0e_0v_splitedges, + refprism_2f_0e_0v_splitfaces, + 0, + refprism_2f_0e_0v_newelstypes, + refprism_2f_0e_0v_newels + }; + +*/ diff --git a/contrib/Netgen/libsrc/meshing/hpref_pyramid.hpp b/contrib/Netgen/libsrc/meshing/hpref_pyramid.hpp new file mode 100644 index 0000000000000000000000000000000000000000..521daf5081e84bf11891b835a8af358cd2af5c84 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_pyramid.hpp @@ -0,0 +1,118 @@ + + // HP_PYRAMID + int refpyramid_splitedges[][3] = + { + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refpyramid_newelstypes[] = + { + HP_PYRAMID, + HP_NONE, + }; + int refpyramid_newels[][8] = + { + { 1, 2, 3, 4, 5 } + }; + HPRef_Struct refpyramid = + { + HP_PYRAMID, + refpyramid_splitedges, + 0, 0, + refpyramid_newelstypes, + refpyramid_newels + }; + + +// singular point 1 + // HP_PYRAMID_0E_1V + int refpyramid_0e_1v_splitedges[][3] = + { + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refpyramid_0e_1v_newelstypes[] = + { + HP_TET_0E_1V, + HP_TET, + HP_NONE, + }; + int refpyramid_0e_1v_newels[][8] = + { + { 1, 2, 4, 5 }, + { 2, 3, 4, 5 }, + }; + HPRef_Struct refpyramid_0e_1v = + { + HP_PYRAMID, + refpyramid_0e_1v_splitedges, + 0, 0, + refpyramid_0e_1v_newelstypes, + refpyramid_0e_1v_newels + }; + + +// singular edges 1-2 1-4 singular point 1 + // HP_PYRAMID_EDGES + int refpyramid_edges_splitedges[][3] = + { + { 0, 0, 0 } + }; + HPREF_ELEMENT_TYPE refpyramid_edges_newelstypes[] = + { + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_NONE, + }; + int refpyramid_edges_newels[][8] = + { + { 1, 2, 3, 5 }, + { 1, 4, 5, 3 }, + }; + HPRef_Struct refpyramid_edges = + { + HP_PYRAMID, + refpyramid_edges_splitedges, + 0, 0, + refpyramid_edges_newelstypes, + refpyramid_edges_newels + }; + + + +// singular face 1-2-5 singular point 5 + // HP_PYRAMID_1FB_0E_1VA + int refpyramid_1fb_0e_1va_splitedges[][3] = + { + { 1, 4, 6 }, + { 2, 3, 7 }, + { 5, 1, 8 }, + { 5, 2, 9 }, + { 5, 3, 10 }, + { 5, 4, 11 }, + { 0, 0, 0 }, + }; + + HPREF_ELEMENT_TYPE refpyramid_1fb_0e_1va_newelstypes[] = + { + HP_HEX_1F_0E_0V, + HP_PYRAMID_1FB_0E_1VA, + HP_PRISM, + HP_NONE, + }; + int refpyramid_1fb_0e_1va_newels[][8] = + { + { 1, 8, 9, 2, 6, 11, 10, 7 }, + { 8, 9, 10, 11, 5 }, + { 3, 7, 10, 4, 6, 11 } + }; + HPRef_Struct refpyramid_1fb_0e_1va = + { + HP_PYRAMID, + refpyramid_1fb_0e_1va_splitedges, + 0, 0, + refpyramid_1fb_0e_1va_newelstypes, + refpyramid_1fb_0e_1va_newels + }; + + + + diff --git a/contrib/Netgen/libsrc/meshing/hpref_quad.hpp b/contrib/Netgen/libsrc/meshing/hpref_quad.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2a23156d1c66e7bc1efeb637a60de8756e77946f --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_quad.hpp @@ -0,0 +1,2082 @@ +// HP_QUAD +int refquad_splitedges[][3] = +{ + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_newelstypes[] = +{ + HP_QUAD, + HP_NONE, +}; +int refquad_newels[][8] = +{ + { 1, 2, 3, 4 }, +}; +HPRef_Struct refquad = +{ + HP_QUAD, + refquad_splitedges, + 0, 0, + refquad_newelstypes, + refquad_newels +}; + + + + + + + +// HP_QUAD_SINGCORNER +int refquad_singcorner_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_singcorner_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_QUAD, + HP_TRIG, + HP_NONE, +}; +int refquad_singcorner_newels[][8] = +{ + { 1, 5, 6 }, + { 2, 4, 6, 5 }, + { 2, 3, 4 }, +}; +HPRef_Struct refquad_singcorner = +{ + HP_QUAD, + refquad_singcorner_splitedges, + 0, 0, + refquad_singcorner_newelstypes, + refquad_singcorner_newels +}; + + + + + +// HP_DUMMY_QUAD_SINGCORNER +int refdummyquad_singcorner_splitedges[][3] = +{ + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refdummyquad_singcorner_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_TRIG, + HP_NONE, +}; +int refdummyquad_singcorner_newels[][8] = +{ + { 1, 2, 4 }, + { 4, 2, 3 }, +}; +HPRef_Struct refdummyquad_singcorner = +{ + HP_QUAD, + refdummyquad_singcorner_splitedges, + 0, 0, + refdummyquad_singcorner_newelstypes, + refdummyquad_singcorner_newels +}; + + + + + + + +// HP_QUAD_SINGEDGE +int refquad_singedge_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_singedge_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_singedge_newels[][8] = +{ + { 1, 2, 6, 5 }, + { 5, 6, 3, 4 }, +}; +HPRef_Struct refquad_singedge = +{ + HP_QUAD, + refquad_singedge_splitedges, + 0, 0, + refquad_singedge_newelstypes, + refquad_singedge_newels +}; + + + + + + +// HP_QUAD_0E_2VA +int refquad_0e_2va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_0e_2va_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD, + HP_QUAD, + HP_NONE, +}; +int refquad_0e_2va_newels[][8] = +{ + { 1, 5, 6 }, + { 2, 8, 7 }, + { 5, 7, 8, 6 }, + { 6, 8, 3, 4 }, +}; +HPRef_Struct refquad_0e_2va = +{ + HP_QUAD, + refquad_0e_2va_splitedges, + 0, 0, + refquad_0e_2va_newelstypes, + refquad_0e_2va_newels +}; + + + +// HP_QUAD_0E_2VB +int refquad_0e_2vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 3, 4, 7 }, + { 3, 2, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_0e_2vb_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD, + HP_QUAD, + HP_NONE, +}; +int refquad_0e_2vb_newels[][8] = +{ + { 1, 5, 6 }, + { 3, 7, 8 }, + { 5, 2, 4, 6 }, + { 2, 8, 7, 4 }, +}; +HPRef_Struct refquad_0e_2vb = +{ + HP_QUAD, + refquad_0e_2vb_splitedges, + 0, 0, + refquad_0e_2vb_newelstypes, + refquad_0e_2vb_newels +}; + + + + +// HP_QUAD_0E_3V +int refquad_0e_3v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 3, 2, 9 }, + { 3, 4, 10 }, + { 0, 0, 0 } +}; + +int refquad_0e_3v_splitfaces[][4] = +{ + { 2, 3, 1, 14 }, + { 0, 0, 0, 0 }, +}; + +HPREF_ELEMENT_TYPE refquad_0e_3v_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_DUMMY_QUAD_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD, + HP_QUAD, + HP_QUAD, + HP_NONE, +}; +int refquad_0e_3v_newels[][8] = +{ + { 1, 5, 6 }, + { 2, 8, 14, 7 }, + { 3, 10, 9 }, + { 5, 7, 14, 6 }, + { 8, 9, 10, 14 }, + { 6, 14, 10, 4 }, +}; +HPRef_Struct refquad_0e_3v = +{ + HP_QUAD, + refquad_0e_3v_splitedges, + refquad_0e_3v_splitfaces, + 0, + refquad_0e_3v_newelstypes, + refquad_0e_3v_newels +}; + + + + +// HP_QUAD_0E_4V +int refquad_0e_4v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 3, 2, 9 }, + { 3, 4, 10 }, + { 4, 1, 11 }, + { 4, 3, 12 }, + { 0, 0, 0 } +}; + +int refquad_0e_4v_splitfaces[][4] = +{ + { 1, 2, 4, 13 }, + { 2, 3, 1, 14 }, + { 3, 4, 2, 15 }, + { 4, 1, 3, 16 }, + { 0, 0, 0, 0 }, +}; + +HPREF_ELEMENT_TYPE refquad_0e_4v_newelstypes[] = +{ + HP_DUMMY_QUAD_SINGCORNER, + HP_DUMMY_QUAD_SINGCORNER, + HP_DUMMY_QUAD_SINGCORNER, + HP_DUMMY_QUAD_SINGCORNER, + + HP_QUAD, + HP_QUAD, + HP_QUAD, + HP_QUAD, + + HP_QUAD, + HP_NONE, +}; +int refquad_0e_4v_newels[][8] = +{ + { 1, 5, 13, 6 }, + { 2, 8, 14, 7 }, + { 3, 10, 15, 9 }, + { 4, 11, 16, 12 }, + { 5, 7, 14, 13 }, + { 8, 9, 15, 14 }, + { 10, 12, 16, 15 }, + { 11, 6, 13, 16 }, + { 13, 14, 15, 16 } +}; +HPRef_Struct refquad_0e_4v = +{ + HP_QUAD, + refquad_0e_4v_splitedges, + refquad_0e_4v_splitfaces, + 0, + refquad_0e_4v_newelstypes, + refquad_0e_4v_newels +}; + + + + + + + + +// HP_QUAD_1E_1VA +int refquad_1e_1va_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_1va_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGEDGECORNER1, + HP_NONE, +}; +int refquad_1e_1va_newels[][8] = +{ + { 7, 2, 6, 5 }, + { 5, 6, 3, 4 }, + { 1, 7, 5 }, +}; +HPRef_Struct refquad_1e_1va = +{ + HP_QUAD, + refquad_1e_1va_splitedges, + 0, 0, + refquad_1e_1va_newelstypes, + refquad_1e_1va_newels +}; + + + + +// HP_QUAD_1E_1VB +int refquad_1e_1vb_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 2, 1, 7 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_1vb_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGEDGECORNER2, + HP_NONE, +}; +int refquad_1e_1vb_newels[][8] = +{ + { 1, 7, 6, 5 }, + { 5, 6, 3, 4 }, + { 7, 2, 6 }, +}; +HPRef_Struct refquad_1e_1vb = +{ + HP_QUAD, + refquad_1e_1vb_splitedges, + 0, 0, + refquad_1e_1vb_newelstypes, + refquad_1e_1vb_newels +}; + + + +// HP_QUAD_1E_1VC +int refquad_1e_1vc_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 3, 4, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_1vc_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_1e_1vc_newels[][8] = +{ + { 1, 2, 6, 5 }, + { 5, 6, 4 }, + { 4, 6, 7, 8 }, + { 3, 8, 7 } +}; +HPRef_Struct refquad_1e_1vc = +{ + HP_QUAD, + refquad_1e_1vc_splitedges, + 0, 0, + refquad_1e_1vc_newelstypes, + refquad_1e_1vc_newels +}; + + + +// HP_QUAD_1E_1VD +int refquad_1e_1vd_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 4, 1, 7 }, + { 4, 3, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_1vd_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_1e_1vd_newels[][8] = +{ + { 1, 2, 6, 5 }, + { 5, 6, 3 }, + { 5, 3, 8, 7 }, + { 4, 7, 8 } +}; +HPRef_Struct refquad_1e_1vd = +{ + HP_QUAD, + refquad_1e_1vd_splitedges, + 0, 0, + refquad_1e_1vd_newelstypes, + refquad_1e_1vd_newels +}; + + + + + + + +// HP_QUAD_1E_2VA +int refquad_1e_2va_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 2, 1, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_2va_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_NONE, +}; +int refquad_1e_2va_newels[][8] = +{ + { 7, 8, 6, 5 }, + { 5, 6, 3, 4 }, + { 1, 7, 5 }, + { 8, 2, 6 } +}; +HPRef_Struct refquad_1e_2va = +{ + HP_QUAD, + refquad_1e_2va_splitedges, + 0, 0, + refquad_1e_2va_newelstypes, + refquad_1e_2va_newels +}; + + + + +// HP_QUAD_1E_2VB +int refquad_1e_2vb_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 3, 2, 8 }, + { 3, 4, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_2vb_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_1e_2vb_newels[][8] = +{ + { 7, 2, 6, 5 }, + { 1, 7, 5 }, + { 5, 6, 4 }, + { 4, 6, 8, 9 }, + { 3, 9, 8 } +}; +HPRef_Struct refquad_1e_2vb = +{ + HP_QUAD, + refquad_1e_2vb_splitedges, + 0, 0, + refquad_1e_2vb_newelstypes, + refquad_1e_2vb_newels +}; + + + + +// HP_QUAD_1E_2VC +int refquad_1e_2vc_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 4, 1, 8 }, + { 4, 3, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_2vc_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_1e_2vc_newels[][8] = +{ + { 7, 2, 6, 5 }, + { 1, 7, 5 }, + { 5, 6, 3 }, + { 5, 3, 9, 8 }, + { 4, 8, 9 } +}; +HPRef_Struct refquad_1e_2vc = +{ + HP_QUAD, + refquad_1e_2vc_splitedges, + 0, 0, + refquad_1e_2vc_newelstypes, + refquad_1e_2vc_newels +}; + + + + +// HP_QUAD_1E_2VD +int refquad_1e_2vd_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 2, 1, 7 }, + { 3, 2, 8 }, + { 3, 4, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_2vd_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_1e_2vd_newels[][8] = +{ + { 1, 7, 6, 5 }, + { 7, 2, 6 }, + { 5, 6, 4 }, + { 4, 6, 8, 9 }, + { 3, 9, 8 } +}; +HPRef_Struct refquad_1e_2vd = +{ + HP_QUAD, + refquad_1e_2vd_splitedges, + 0, 0, + refquad_1e_2vd_newelstypes, + refquad_1e_2vd_newels +}; + + + + + +// HP_QUAD_1E_2VE +int refquad_1e_2ve_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 2, 1, 7 }, + { 4, 1, 8 }, + { 4, 3, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_2ve_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_1e_2ve_newels[][8] = +{ + { 1, 7, 6, 5 }, + { 7, 2, 6 }, + { 5, 6, 3 }, + { 5, 3, 9, 8 }, + { 4, 8, 9 } +}; +HPRef_Struct refquad_1e_2ve = +{ + HP_QUAD, + refquad_1e_2ve_splitedges, + 0, 0, + refquad_1e_2ve_newelstypes, + refquad_1e_2ve_newels +}; + + + + + + +// HP_QUAD_1E_2VF +int refquad_1e_2vf_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 4, 1, 7 }, + { 4, 3, 8 }, + { 3, 2, 9 }, + { 3, 4, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_2vf_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_1e_2vf_newels[][8] = +{ + { 1, 2, 6, 5 }, + { 5, 6, 9, 7 }, + { 7, 9, 10, 8 }, + { 4, 7, 8 }, + { 3, 10, 9 }, +}; +HPRef_Struct refquad_1e_2vf = +{ + HP_QUAD, + refquad_1e_2vf_splitedges, + 0, 0, + refquad_1e_2vf_newelstypes, + refquad_1e_2vf_newels +}; + + + + + +// HP_QUAD_1E_3VA +int refquad_1e_3va_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 2, 1, 8 }, + { 3, 2, 9 }, + { 3, 4, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_3va_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGCORNER, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG, + HP_NONE, +}; +int refquad_1e_3va_newels[][8] = +{ + { 1, 7, 5 }, + { 8, 2, 6 }, + { 3, 10, 9 }, + { 7, 8, 6, 5 }, + { 4, 6, 9, 10 }, + { 5, 6, 4 } +}; +HPRef_Struct refquad_1e_3va = +{ + HP_QUAD, + refquad_1e_3va_splitedges, + 0, 0, + refquad_1e_3va_newelstypes, + refquad_1e_3va_newels +}; + + + + + +// HP_QUAD_1E_3VB +int refquad_1e_3vb_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 2, 1, 8 }, + { 4, 1, 9 }, + { 4, 3, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_3vb_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGCORNER, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG, + HP_NONE, +}; +int refquad_1e_3vb_newels[][8] = +{ + { 1, 7, 5 }, + { 8, 2, 6 }, + { 4, 9, 10 }, + { 7, 8, 6, 5 }, + { 5, 3, 10, 9 }, + { 5, 6, 3 } +}; +HPRef_Struct refquad_1e_3vb = +{ + HP_QUAD, + refquad_1e_3vb_splitedges, + 0, 0, + refquad_1e_3vb_newelstypes, + refquad_1e_3vb_newels +}; + + + + + +// HP_QUAD_1E_3VC +int refquad_1e_3vc_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 3, 2, 8 }, + { 3, 4, 9 }, + { 4, 3, 10 }, + { 4, 1, 11 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_3vc_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_QUAD, + HP_NONE, +}; +int refquad_1e_3vc_newels[][8] = +{ + { 1, 7, 5 }, + { 3, 9, 8 }, + { 4, 11, 10 }, + { 7, 2, 6, 5 }, + { 5, 6, 8, 11 }, + { 11, 8, 9, 10 } +}; +HPRef_Struct refquad_1e_3vc = +{ + HP_QUAD, + refquad_1e_3vc_splitedges, + 0, 0, + refquad_1e_3vc_newelstypes, + refquad_1e_3vc_newels +}; + + + + +// HP_QUAD_1E_3VD +int refquad_1e_3vd_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 2, 1, 7 }, + { 3, 2, 8 }, + { 3, 4, 9 }, + { 4, 3, 10 }, + { 4, 1, 11 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_3vd_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_QUAD, + HP_NONE, +}; +int refquad_1e_3vd_newels[][8] = +{ + { 7, 2, 6 }, + { 3, 9, 8 }, + { 4, 11, 10 }, + { 1, 7, 6, 5 }, + { 5, 6, 8, 11 }, + { 11, 8, 9, 10 } +}; +HPRef_Struct refquad_1e_3vd = +{ + HP_QUAD, + refquad_1e_3vd_splitedges, + 0, 0, + refquad_1e_3vd_newelstypes, + refquad_1e_3vd_newels +}; + + + + + + +// HP_QUAD_1E_4V +int refquad_1e_4v_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 2, 1, 8 }, + { 4, 1, 9 }, + { 3, 2, 10 }, + { 4, 3, 11 }, + { 3, 4, 12 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_1e_4v_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_QUAD, + HP_NONE, +}; +int refquad_1e_4v_newels[][8] = +{ + { 1, 7, 5 }, + { 8, 2, 6 }, + { 3, 12, 10 }, + { 4, 9, 11 }, + { 7, 8, 6, 5 }, + { 5, 6, 10, 9 }, + { 9, 10, 12, 11 } +}; +HPRef_Struct refquad_1e_4v = +{ + HP_QUAD, + refquad_1e_4v_splitedges, + 0, 0, + refquad_1e_4v_newelstypes, + refquad_1e_4v_newels +}; + +//////////////////////////////////////////////////////////////////////////////// + +// HP_QUAD_2E +int refquad_2e_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 3, 8 }, + { 0, 0, 0 } +}; +int refquad_2e_splitfaces[][4] = +{ + { 1, 2, 4, 9 }, + { 0, 0, 0, 0 }, +}; + + +/* + HPREF_ELEMENT_TYPE refquad_2e_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_2e_newels[][8] = +{ + { 1, 5, 9 }, + { 6, 1, 9 }, + { 5, 2, 7, 9 }, + { 4, 6, 9, 8 }, + { 9, 7, 3, 8 }, +}; +*/ + +// SZ refine to 4 quads +HPREF_ELEMENT_TYPE refquad_2e_newelstypes[] = +{ + HP_QUAD_2E, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_2e_newels[][8] = +{ + { 1, 5, 9, 6 }, + { 5, 2, 7, 9 }, + { 4, 6, 9, 8 }, + { 9, 7, 3, 8 }, +}; + +HPRef_Struct refquad_2e = +{ + HP_QUAD, + refquad_2e_splitedges, + refquad_2e_splitfaces, + 0, + refquad_2e_newelstypes, + refquad_2e_newels +}; + + +// HP_QUAD_2E_1VA +int refquad_2e_1va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 3, 8 }, + { 2, 1, 10 }, + { 0, 0, 0 } +}; +int refquad_2e_1va_splitfaces[][4] = +{ + { 1, 2, 4, 9 }, + { 0, 0, 0, 0 }, +}; + +/* +HPREF_ELEMENT_TYPE refquad_2e_1va_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGEDGECORNER2, + HP_NONE, +}; +int refquad_2e_1va_newels[][8] = +{ + { 1, 5, 9 }, + { 6, 1, 9 }, + { 5, 10, 7, 9 }, + { 4, 6, 9, 8 }, + { 9, 7, 3, 8 }, + { 10, 2, 7 }, +}; +*/ +// SZ Quad_2e refinement +HPREF_ELEMENT_TYPE refquad_2e_1va_newelstypes[] = +{ + HP_QUAD_2E, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGEDGECORNER2, + HP_NONE, +}; +int refquad_2e_1va_newels[][8] = +{ + { 1, 5, 9, 6 }, + { 5, 10, 7, 9 }, + { 4, 6, 9, 8 }, + { 9, 7, 3, 8 }, + { 10, 2, 7 }, +}; + +HPRef_Struct refquad_2e_1va = +{ + HP_QUAD, + refquad_2e_1va_splitedges, + refquad_2e_1va_splitfaces, + 0, + refquad_2e_1va_newelstypes, + refquad_2e_1va_newels +}; + + + +// HP_QUAD_2E_1VB +int refquad_2e_1vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 3, 8 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 0, 0, 0 } +}; +int refquad_2e_1vb_splitfaces[][4] = +{ + { 1, 2, 4, 9 }, + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2e_1vb_newelstypes[] = +{ + // HP_TRIG_SINGEDGECORNER1, + // HP_TRIG_SINGEDGECORNER2, + // SZ QUAD_2E + HP_QUAD_2E, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int refquad_2e_1vb_newels[][8] = +{ + //{ 1, 5, 9 }, + //{ 6, 1, 9 }, + { 1, 5, 9, 6 }, + { 5, 2, 7, 9 }, + { 4, 6, 9, 8 }, + { 7, 8, 9 }, + { 8, 7, 10, 11 }, + { 3, 11, 10 } +}; +HPRef_Struct refquad_2e_1vb = +{ + HP_QUAD, + refquad_2e_1vb_splitedges, + refquad_2e_1vb_splitfaces, + 0, + refquad_2e_1vb_newelstypes, + refquad_2e_1vb_newels +} +; + +// HP_QUAD_2E_1VC +int refquad_2e_1vc_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 1, 8 }, + { 4, 3, 9 }, + { 0, 0, 0 } +}; +int refquad_2e_1vc_splitfaces[][4] = +{ + { 1, 2, 4, 10 }, + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2e_1vc_newelstypes[] = +{ + // HP_TRIG_SINGEDGECORNER1, + // HP_TRIG_SINGEDGECORNER2, + HP_QUAD_2E, + HP_TRIG_SINGEDGECORNER1, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_2e_1vc_newels[][8] = +{ + //{ 1, 5, 10 }, + //{ 6, 1, 10 }, + { 1, 5, 10, 6}, + { 4, 8, 9 }, + { 5, 2, 7, 10 }, + { 8, 6, 10, 9 }, + { 10, 7, 3, 9 }, +}; +HPRef_Struct refquad_2e_1vc = +{ + HP_QUAD, + refquad_2e_1vc_splitedges, + refquad_2e_1vc_splitfaces, + 0, + refquad_2e_1vc_newelstypes, + refquad_2e_1vc_newels +}; + +// HP_QUAD_2E_2VA +int refquad_2e_2va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 3, 8 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 2, 1, 12 }, + { 0, 0, 0 } +}; +int refquad_2e_2va_splitfaces[][4] = +{ + { 1, 2, 4, 9 }, + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2e_2va_newelstypes[] = +{ + //HP_TRIG_SINGEDGECORNER1, + //HP_TRIG_SINGEDGECORNER2, + HP_QUAD_2E, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGEDGECORNER2, + HP_NONE, +}; +int refquad_2e_2va_newels[][8] = +{ + // { 1, 5, 9 }, + // { 6, 1, 9 }, + { 1, 5, 9, 6 }, + { 5, 12, 7, 9 }, + { 4, 6, 9, 8 }, + { 7, 8, 9 }, + { 8, 7, 10, 11 }, + { 3, 11, 10 }, + { 12, 2, 7 } +}; +HPRef_Struct refquad_2e_2va = +{ + HP_QUAD, + refquad_2e_2va_splitedges, + refquad_2e_2va_splitfaces, + 0, + refquad_2e_2va_newelstypes, + refquad_2e_2va_newels +}; + + + + + + +// HP_QUAD_2E_2VB +int refquad_2e_2vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 4, 1, 9 }, + { 4, 3, 10 }, + { 0, 0, 0 } +}; +int refquad_2e_2vb_splitfaces[][4] = +{ + { 1, 2, 4, 11 }, + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2e_2vb_newelstypes[] = +{ + // HP_TRIG_SINGEDGECORNER1, + // HP_TRIG_SINGEDGECORNER2, + HP_QUAD_2E, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_2e_2vb_newels[][8] = +{ + //{ 1, 5, 11 }, + //{ 6, 1, 11 }, + { 1, 5, 11, 6 }, + { 4, 9, 10 }, + { 7, 2, 8 }, + { 5, 7, 8, 11 }, + { 9, 6, 11, 10 }, + { 3, 10, 11, 8 }, +}; +HPRef_Struct refquad_2e_2vb = +{ + HP_QUAD, + refquad_2e_2vb_splitedges, + refquad_2e_2vb_splitfaces, + 0, + refquad_2e_2vb_newelstypes, + refquad_2e_2vb_newels +}; + +// HP_QUAD_2E_2VC +int refquad_2e_2vc_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 3, 8 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 4, 1, 12 }, + { 0, 0, 0 } +}; +int refquad_2e_2vc_splitfaces[][4] = +{ + { 1, 2, 4, 9 }, + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2e_2vc_newelstypes[] = +{ + // HP_TRIG_SINGEDGECORNER1, + // HP_TRIG_SINGEDGECORNER2, + HP_QUAD_2E, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGEDGECORNER1, //SZ (vorher: SINGEDGECORNER2) + HP_NONE, +}; +int refquad_2e_2vc_newels[][8] = +{ + { 1, 5, 9 }, + { 6, 1, 9 }, + { 5, 2, 7, 9 }, + { 12, 6, 9, 8 }, + { 7, 8, 9 }, + { 8, 7, 10, 11 }, + { 3, 11, 10 }, + { 4, 12, 8 } +}; +HPRef_Struct refquad_2e_2vc = +{ + HP_QUAD, + refquad_2e_2vc_splitedges, + refquad_2e_2vc_splitfaces, + 0, + refquad_2e_2vc_newelstypes, + refquad_2e_2vc_newels +}; + +// HP_QUAD_2E_3V +int refquad_2e_3v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 4, 3, 8 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 2, 1, 12 }, + { 4, 1, 13 }, + { 0, 0, 0 } +}; +int refquad_2e_3v_splitfaces[][4] = +{ + { 1, 2, 4, 9 }, + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2e_3v_newelstypes[] = +{ + // HP_TRIG_SINGEDGECORNER1, + // HP_TRIG_SINGEDGECORNER2, + HP_QUAD_2E, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER1, + HP_NONE, +}; +int refquad_2e_3v_newels[][8] = +{ + //{ 1, 5, 9 }, + //{ 6, 1, 9 }, + { 1, 5, 9, 6 }, + { 5, 12, 7, 9 }, + { 13, 6, 9, 8 }, + { 7, 8, 9 }, + { 8, 7, 10, 11 }, + { 3, 11, 10 }, + { 12, 2, 7 }, + { 4, 13, 8 } +}; +HPRef_Struct refquad_2e_3v = +{ + HP_QUAD, + refquad_2e_3v_splitedges, + refquad_2e_3v_splitfaces, + 0, + refquad_2e_3v_newelstypes, + refquad_2e_3v_newels +}; + +// HP_QUAD_2EB_0V +int refquad_2eb_0v_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 0, 0, 0 } +}; +int refquad_2eb_0v_splitfaces[][4] = +{ + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2eb_0v_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_0v_newels[][8] = +{ + { 1, 2, 6, 5 }, + { 3, 4, 8, 7 }, + { 5, 6, 7, 8 } +}; +HPRef_Struct refquad_2eb_0v = +{ + HP_QUAD, + refquad_2eb_0v_splitedges, + refquad_2eb_0v_splitfaces, + 0, + refquad_2eb_0v_newelstypes, + refquad_2eb_0v_newels +}; + + +// HP_QUAD_2EB_1VA +int refquad_2eb_1va_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 1, 2, 9 }, + { 0, 0, 0 } +}; +int refquad_2eb_1va_splitfaces[][4] = +{ + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2eb_1va_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_1va_newels[][8] = +{ + { 9, 2, 6, 5 }, + { 3, 4, 8, 7 }, + { 1, 9, 5 }, + { 5, 6, 7, 8 } +}; +HPRef_Struct refquad_2eb_1va = +{ + HP_QUAD, + refquad_2eb_1va_splitedges, + refquad_2eb_1va_splitfaces, + 0, + refquad_2eb_1va_newelstypes, + refquad_2eb_1va_newels +}; + +// HP_QUAD_2EB_1VB +int refquad_2eb_1vb_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 2, 1, 9 }, + { 0, 0, 0 } +}; +int refquad_2eb_1vb_splitfaces[][4] = +{ + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2eb_1vb_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_1vb_newels[][8] = +{ + { 1, 9, 6, 5 }, + { 3, 4, 8, 7 }, + { 9, 2, 6 }, + { 5, 6, 7, 8 } +}; +HPRef_Struct refquad_2eb_1vb = +{ + HP_QUAD, + refquad_2eb_1vb_splitedges, + refquad_2eb_1vb_splitfaces, + 0, + refquad_2eb_1vb_newelstypes, + refquad_2eb_1vb_newels +}; + +// HP_QUAD_2EB_2VA +int refquad_2eb_2va_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 1, 2, 9 }, + { 2, 1, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_2eb_2va_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_2va_newels[][8] = +{ + { 9, 10, 6, 5 }, + { 3, 4, 8, 7 }, + { 1, 9, 5 }, + { 10, 2, 6 }, + { 5, 6, 7, 8 } +}; +HPRef_Struct refquad_2eb_2va = +{ + HP_QUAD, + refquad_2eb_2va_splitedges, + 0, 0, + refquad_2eb_2va_newelstypes, + refquad_2eb_2va_newels +}; + + + +// HP_QUAD_2EB_2VB +int refquad_2eb_2vb_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 1, 2, 9 }, + { 3, 4, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_2eb_2vb_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER1, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_2vb_newels[][8] = +{ + { 9, 2, 6, 5 }, + { 10, 4, 8, 7 }, + { 1, 9, 5 }, + { 3, 10, 7 }, + { 5, 6, 7, 8 } +}; +HPRef_Struct refquad_2eb_2vb = +{ + HP_QUAD, + refquad_2eb_2vb_splitedges, + 0, 0, + refquad_2eb_2vb_newelstypes, + refquad_2eb_2vb_newels +}; + + + +// HP_QUAD_2EB_2VC +int refquad_2eb_2vc_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 1, 2, 9 }, + { 4, 3, 10 }, + { 0, 0, 0 } +}; +int refquad_2eb_2vc_splitfaces[][4] = +{ + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2eb_2vc_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_2vc_newels[][8] = +{ + { 9, 2, 6, 5 }, + { 3, 10, 8, 7 }, + { 1, 9, 5 }, + { 10, 4, 8 }, + { 5, 6, 7, 8 } +}; +HPRef_Struct refquad_2eb_2vc = +{ + HP_QUAD, + refquad_2eb_2vc_splitedges, + refquad_2eb_2vc_splitfaces, + 0, + refquad_2eb_2vc_newelstypes, + refquad_2eb_2vc_newels +}; + + +// HP_QUAD_2EB_2VD +int refquad_2eb_2vd_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 2, 1, 9 }, + { 4, 3, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_2eb_2vd_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_2vd_newels[][8] = +{ + { 1, 9, 6, 5 }, + { 3, 10, 8, 7 }, + { 9, 2, 6 }, + { 10, 4, 8 }, + { 5, 6, 7, 8 } +}; +HPRef_Struct refquad_2eb_2vd = +{ + HP_QUAD, + refquad_2eb_2vd_splitedges, + 0, 0, + refquad_2eb_2vd_newelstypes, + refquad_2eb_2vd_newels +}; + + +// HP_QUAD_2EB_3VA +int refquad_2eb_3va_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 2, 1, 8 }, + { 3, 2, 9 }, + { 4, 1, 10 }, + { 3, 4, 11 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_2eb_3va_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER1, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_3va_newels[][8] = +{ + { 1, 7, 5 }, + { 8, 2, 6 }, + { 3, 11, 9}, + { 7, 8, 6, 5 }, + { 11, 4, 10, 9 }, + { 5, 6, 9, 10 } +}; +HPRef_Struct refquad_2eb_3va = +{ + HP_QUAD, + refquad_2eb_3va_splitedges, + 0, 0, + refquad_2eb_3va_newelstypes, + refquad_2eb_3va_newels +}; + + +// HP_QUAD_2EB_3VB +int refquad_2eb_3vb_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 1, 2, 7 }, + { 2, 1, 8 }, + { 3, 2, 9 }, + { 4, 1, 10 }, + { 4, 3, 11 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE refquad_2eb_3vb_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_NONE, +}; +int refquad_2eb_3vb_newels[][8] = +{ + { 1, 7, 5 }, + { 8, 2, 6 }, + { 11, 4, 10 }, + { 7, 8, 6, 5 }, + { 3, 11, 10, 9 }, + { 5, 6, 9, 10 } +}; +HPRef_Struct refquad_2eb_3vb = +{ + HP_QUAD, + refquad_2eb_3vb_splitedges, + 0, 0, + refquad_2eb_3vb_newelstypes, + refquad_2eb_3vb_newels +}; + + +// HP_QUAD_2EB_4V +int refquad_2eb_4v_splitedges[][3] = +{ + { 1, 4, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 4, 1, 8 }, + { 1, 2, 9 }, + { 2, 1, 10 }, + { 3, 4, 11 }, + { 4, 3, 12 }, + { 0, 0, 0 } +}; +int refquad_2eb_4v_splitfaces[][4] = +{ + { 0, 0, 0, 0 }, +}; +HPREF_ELEMENT_TYPE refquad_2eb_4v_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_NONE, +}; +int refquad_2eb_4v_newels[][8] = +{ + { 9, 10, 6, 5 }, + { 11, 12, 8, 7 }, + { 5, 6, 7, 8 }, + { 1, 9, 5 }, + { 10, 2, 6 }, + { 3, 11, 7 }, + { 12, 4, 8 }, +}; +HPRef_Struct refquad_2eb_4v = +{ + HP_QUAD, + refquad_2eb_4v_splitedges, + refquad_2eb_4v_splitfaces, + 0, + refquad_2eb_4v_newelstypes, + refquad_2eb_4v_newels +}; + + + +// HP_QUAD_3E +int refquad_3e_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 3, 4, 10 }, + { 4, 3, 12 }, + { 0, 0, 0 } +}; + +int refquad_3e_splitfaces[][4] = +{ + { 1, 2, 4, 13 }, + { 2, 3, 1, 14 }, + { 0, 0, 0, 0 }, +}; + +HPREF_ELEMENT_TYPE refquad_3e_newelstypes[] = +{ + HP_QUAD_2E, + HP_QUAD_2E, +// HP_TRIG_SINGEDGECORNER1, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER1, + + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + + HP_QUAD, + HP_NONE, +}; +int refquad_3e_newels[][8] = +{ +// { 1, 5, 13 }, +// { 6, 1, 13 }, +// { 7, 2, 14 }, +// { 2, 8, 14 }, + { 1, 5, 13, 6 }, + { 2, 8, 14, 7 }, + { 5, 7, 14, 13 }, + { 8, 3, 10, 14 }, + { 4, 6, 13, 12 }, + { 13, 14, 10, 12 } +}; +HPRef_Struct refquad_3e = +{ + HP_QUAD, + refquad_3e_splitedges, + refquad_3e_splitfaces, + 0, + refquad_3e_newelstypes, + refquad_3e_newels +}; + + + + + + + +// HP_QUAD_3E_3VA +int refquad_3e_3va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 3, 4, 10 }, + { 3, 2, 11 }, + { 4, 3, 12 }, + { 0, 0, 0 } +}; + +int refquad_3e_3va_splitfaces[][4] = +{ + { 1, 2, 4, 13 }, + { 2, 3, 1, 14 }, + { 0, 0, 0, 0 }, +}; + +HPREF_ELEMENT_TYPE refquad_3e_3va_newelstypes[] = +{ + HP_QUAD_2E, + HP_QUAD_2E, + +// HP_TRIG_SINGEDGECORNER1, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + + HP_QUAD, + HP_NONE, +}; +int refquad_3e_3va_newels[][8] = +{ +// { 1, 5, 13 }, +// { 6, 1, 13 }, +// { 7, 2, 14 }, +// { 2, 8, 14 }, + { 1, 5, 13, 6 }, + { 2, 8, 14, 7 }, + { 11, 3, 10 }, + { 5, 7, 14, 13 }, + { 8, 11, 10, 14 }, + { 4, 6, 13, 12 }, + { 13, 14, 10, 12 } +}; +HPRef_Struct refquad_3e_3va = +{ + HP_QUAD, + refquad_3e_3va_splitedges, + refquad_3e_3va_splitfaces, + 0, + refquad_3e_3va_newelstypes, + refquad_3e_3va_newels +}; + +// HP_QUAD_3E_3VB +int refquad_3e_3vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 3, 4, 10 }, + { 4, 1, 11 }, + { 4, 3, 12 }, + { 0, 0, 0 } +}; + +int refquad_3e_3vb_splitfaces[][4] = +{ + { 1, 2, 4, 13 }, + { 2, 3, 1, 14 }, + { 0, 0, 0, 0 }, +}; + +HPREF_ELEMENT_TYPE refquad_3e_3vb_newelstypes[] = +{ + HP_QUAD_2E, + HP_QUAD_2E, + +// HP_TRIG_SINGEDGECORNER1, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER1, + + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + + HP_QUAD, + HP_NONE, +}; +int refquad_3e_3vb_newels[][8] = +{ +// { 1, 5, 13 }, +// { 6, 1, 13 }, +// { 7, 2, 14 }, +// { 2, 8, 14 }, + { 1, 5, 13, 6 }, + { 2, 8, 14, 7 }, + { 4, 11, 12 }, + { 5, 7, 14, 13 }, + { 8, 3, 10, 14 }, + { 11, 6, 13, 12 }, + { 13, 14, 10, 12 } +}; +HPRef_Struct refquad_3e_3vb = +{ + HP_QUAD, + refquad_3e_3vb_splitedges, + refquad_3e_3vb_splitfaces, + 0, + refquad_3e_3vb_newelstypes, + refquad_3e_3vb_newels +}; + + + + + + + + + +// HP_QUAD_3E_4V +int refquad_3e_4v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 3, 4, 10 }, + { 3, 2, 11 }, + { 4, 3, 12 }, + { 4, 1, 15 }, + { 0, 0, 0 } +}; + +int refquad_3e_4v_splitfaces[][4] = +{ + { 1, 2, 4, 13 }, + { 2, 3, 1, 14 }, + { 0, 0, 0, 0 }, +}; + +HPREF_ELEMENT_TYPE refquad_3e_4v_newelstypes[] = +{ + HP_QUAD_2E, + HP_QUAD_2E, + +// HP_TRIG_SINGEDGECORNER1, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER2, +// HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER1, + + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + + HP_QUAD, + HP_NONE, +}; +int refquad_3e_4v_newels[][8] = +{ +// { 1, 5, 13 }, +// { 6, 1, 13 }, +// { 7, 2, 14 }, +// { 2, 8, 14 }, + { 1, 5, 13, 6 }, + { 2, 8, 14, 7 }, + { 11, 3, 10 }, + { 4, 15, 12 }, + { 5, 7, 14, 13 }, + { 8, 11, 10, 14 }, + { 15, 6, 13, 12 }, + { 13, 14, 10, 12 } +}; +HPRef_Struct refquad_3e_4v = +{ + HP_QUAD, + refquad_3e_4v_splitedges, + refquad_3e_4v_splitfaces, + 0, + refquad_3e_4v_newelstypes, + refquad_3e_4v_newels +}; + + + + + + + + + +// HP_QUAD_4E +int refquad_4e_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 3, 2, 9 }, + { 3, 4, 10 }, + { 4, 1, 11 }, + { 4, 3, 12 }, + { 0, 0, 0 } +}; + +int refquad_4e_splitfaces[][4] = +{ + { 1, 2, 4, 13 }, + { 2, 3, 1, 14 }, + { 3, 4, 2, 15 }, + { 4, 1, 3, 16 }, + { 0, 0, 0, 0 }, +}; + +HPREF_ELEMENT_TYPE refquad_4e_newelstypes[] = +{ + HP_QUAD_2E, + HP_QUAD_2E, + HP_QUAD_2E, + HP_QUAD_2E, + + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + + HP_QUAD, + HP_NONE, +}; +int refquad_4e_newels[][8] = +{ + { 1, 5, 13, 6 }, + { 2, 8, 14, 7 }, + { 3, 10, 15, 9 }, + { 4, 11, 16, 12 }, + { 5, 7, 14, 13 }, + { 8, 9, 15, 14 }, + { 10, 12, 16, 15 }, + { 11, 6, 13, 16 }, + { 13, 14, 15, 16 } +}; +HPRef_Struct refquad_4e = +{ + HP_QUAD, + refquad_4e_splitedges, + refquad_4e_splitfaces, + 0, + refquad_4e_newelstypes, + refquad_4e_newels +}; diff --git a/contrib/Netgen/libsrc/meshing/hpref_segm.hpp b/contrib/Netgen/libsrc/meshing/hpref_segm.hpp new file mode 100644 index 0000000000000000000000000000000000000000..254458232106e82712d96084678bc4b95fc33b31 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_segm.hpp @@ -0,0 +1,122 @@ + // HP_SEGM + int refsegm_splitedges[][3] = + { + { 0, 0, 0 } + }; + + HPREF_ELEMENT_TYPE refsegm_newelstypes[] = + { + HP_SEGM, + HP_NONE, + }; + int refsegm_newels[][8] = + { + { 1, 2 }, + }; + HPRef_Struct refsegm = + { + HP_SEGM, + refsegm_splitedges, + 0, 0, + refsegm_newelstypes, + refsegm_newels + }; + + // HP_SEGM_SINGCORNERL = 2, + int refsegm_scl_splitedges[][3] = + { + { 1, 2, 3 }, + { 0, 0, 0 } + }; + + HPREF_ELEMENT_TYPE refsegm_scl_newelstypes[] = + { + HP_SEGM_SINGCORNERL, + HP_SEGM, + HP_NONE, + }; + + int refsegm_scl_newels[][8] = + { + { 1, 3 }, + { 3, 2 }, + { 0, 0 }, + }; + HPRef_Struct refsegm_scl = + { + HP_SEGM, + refsegm_scl_splitedges, + 0, 0, + refsegm_scl_newelstypes, + refsegm_scl_newels + }; + + + + // HP_SEGM_SINGCORNERR + int refsegm_scr_splitedges[][3] = + { + { 2, 1, 3 }, + { 0, 0, 0 } + }; + + HPREF_ELEMENT_TYPE refsegm_scr_newelstypes[] = + { + HP_SEGM, + HP_SEGM_SINGCORNERR, + HP_NONE, + }; + int refsegm_scr_newels[][8] = + { + { 1, 3 }, + { 3, 2 }, + { 0, 0 }, + }; + HPRef_Struct refsegm_scr = + { + HP_SEGM, + refsegm_scr_splitedges, + 0, 0, + refsegm_scr_newelstypes, + refsegm_scr_newels + }; + + + + + + + // HP_SEGM_SINGCORNERS = 3, + int refsegm_sc2_splitedges[][3] = + { + { 1, 2, 3 }, + { 2, 1, 4 }, + { 0, 0, 0 } + }; + + HPREF_ELEMENT_TYPE refsegm_sc2_newelstypes[] = + { + HP_SEGM_SINGCORNERL, + HP_SEGM_SINGCORNERR, + HP_SEGM, + HP_NONE, + }; + int refsegm_sc2_newels[][8] = + { + { 1, 3 }, + { 4, 2 }, + { 3, 4 }, + { 0, 0 }, + }; + HPRef_Struct refsegm_sc2 = + { + HP_SEGM, + refsegm_sc2_splitedges, + 0, 0, + refsegm_sc2_newelstypes, + refsegm_sc2_newels + }; + + + + diff --git a/contrib/Netgen/libsrc/meshing/hpref_tet.hpp b/contrib/Netgen/libsrc/meshing/hpref_tet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..df0e2af890aec6de2c30a1821912e8ed79ca0a6b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_tet.hpp @@ -0,0 +1,3128 @@ + + + +// HP_TET +int reftet_splitedges[][3] = +{ + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_newelstypes[] = +{ + HP_TET, + HP_NONE, +}; +int reftet_newels[][8] = +{ + { 1, 2, 3, 4 }, +}; +HPRef_Struct reftet = +{ + HP_TET, + reftet_splitedges, + 0, 0, + reftet_newelstypes, + reftet_newels +}; + + + +/* *********** Tet - Refinement - 0 edges *************** */ + +// HP_TET_0E_1V +int reftet_0e_1v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_0e_1v_newelstypes[] = +{ + HP_TET_0E_1V, + HP_PRISM, + HP_NONE, +}; +int reftet_0e_1v_newels[][8] = +{ + { 1, 5, 6, 7 }, + { 5, 6, 7, 2, 3, 4 } +}; +HPRef_Struct reftet_0e_1v = +{ + HP_TET, + reftet_0e_1v_splitedges, + 0, 0, + reftet_0e_1v_newelstypes, + reftet_0e_1v_newels +}; + + + +// HP_TET_0E_2V +int reftet_0e_2v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_0e_2v_newelstypes[] = +{ + HP_TET_0E_1V, + HP_TET_0E_1V, + HP_PRISM, + HP_PRISM, + HP_NONE, +}; +int reftet_0e_2v_newels[][8] = +{ + { 1, 5, 6, 7 }, + { 2, 10, 9, 8 }, + { 5, 6, 7, 8, 9, 10 }, + { 4, 10, 7, 3, 9, 6 }, +}; +HPRef_Struct reftet_0e_2v = +{ + HP_TET, + reftet_0e_2v_splitedges, + 0, 0, + reftet_0e_2v_newelstypes, + reftet_0e_2v_newels +}; + + + + + +// HP_TET_0E_3V +int reftet_0e_3v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 0, 0, 0 } +}; +int reftet_0e_3v_splitfaces[][4] = + { + { 1, 2, 3, 14 }, + { 2, 3, 1, 15 }, + { 3, 1, 2, 16 }, + { 0, 0, 0, 0 }, + }; +HPREF_ELEMENT_TYPE reftet_0e_3v_newelstypes[] = +{ + HP_PYRAMID_0E_1V, + HP_PYRAMID_0E_1V, + HP_PYRAMID_0E_1V, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_TET, + HP_NONE, +}; +int reftet_0e_3v_newels[][8] = +{ + { 1, 5, 14, 6, 7 }, + { 2, 9, 15, 8, 10 }, + { 3, 11, 16, 12, 13 }, + { 5, 14, 7, 8, 15, 10 }, + { 9, 15, 10, 12, 16, 13 }, + { 6, 7, 14, 11, 13, 16 }, + { 14, 15, 16, 7, 10, 13 }, + { 7, 10, 13, 4 } +}; +HPRef_Struct reftet_0e_3v = +{ + HP_TET, + reftet_0e_3v_splitedges, + reftet_0e_3v_splitfaces, + 0, + reftet_0e_3v_newelstypes, + reftet_0e_3v_newels +}; + + + + + +// HP_TET_0E_4V +int reftet_0e_4v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_0e_4v_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 1, 2, 4, 18 }, + { 1, 3, 4, 19 }, + + { 2, 1, 3, 20 }, + { 2, 1, 4, 21 }, + { 2, 3, 4, 22 }, + + { 3, 1, 2, 23 }, + { 3, 1, 4, 24 }, + { 3, 2, 4, 25 }, + + { 4, 1, 2, 26 }, + { 4, 1, 3, 27 }, + { 4, 2, 3, 28 }, + { 0, 0, 0, 0 }, + }; +int reftet_0e_4v_splitelements[][5] = + { + { 1, 2, 3, 4, 29 }, + { 2, 3, 4, 1, 30 }, + { 3, 4, 1, 2, 31 }, + { 4, 1, 2, 3, 32 }, + { 0 }, + }; +HPREF_ELEMENT_TYPE reftet_0e_4v_newelstypes[] = +{ + HP_HEX_0E_1V, + HP_HEX_0E_1V, + HP_HEX_0E_1V, + HP_HEX_0E_1V, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_TET, + HP_NONE, +}; +int reftet_0e_4v_newels[][8] = +{ + { 1, 5, 17, 6, 7, 18, 29, 19 }, + { 2, 9, 20, 8, 10, 22, 30, 21 }, + { 3, 11, 23, 12, 13, 24, 31, 25 }, + { 4, 15, 26, 14, 16, 28, 32, 27 }, + { 5, 17, 18, 8, 20, 21 }, + { 18, 17, 29, 21, 20, 30 }, + { 6, 19, 17, 11, 24, 23 }, + { 17, 19, 29, 23, 24, 31 }, + { 7, 18, 19, 14, 26, 27 }, + { 19, 18, 29, 27, 26, 32 }, + { 9, 20, 22, 12, 23, 25 }, + { 22, 20, 30, 25, 23, 31 }, + { 10, 22, 21, 15, 28, 26 }, + { 21, 22, 30, 26, 28, 32 }, + { 13, 24, 25, 16, 27, 28 }, + { 25, 24, 31, 28, 27, 32 }, + { 17, 20, 23, 29, 30, 31 }, + { 18, 26, 21, 29, 32, 30 }, + { 19, 24, 27, 29, 31, 32 }, + { 22, 28, 25, 30, 32, 31 }, + { 29, 30, 31, 32 }, +}; +HPRef_Struct reftet_0e_4v = +{ + HP_TET, + reftet_0e_4v_splitedges, + reftet_0e_4v_splitfaces, + reftet_0e_4v_splitelements, + reftet_0e_4v_newelstypes, + reftet_0e_4v_newels +}; + + + + + + + + + + + + + + + + + +/* *********** Tet - Refinement - 1 edge *************** */ + + + +// HP_TET_1E_0V +int reftet_1e_0v_splitedges[][3] = +{ + { 1, 3, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 2, 4, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_1e_0v_newelstypes[] = +{ + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_NONE, +}; +int reftet_1e_0v_newels[][8] = +{ + { 1, 5, 6, 2, 7, 8 }, + { 7, 3, 5, 8, 4, 6 } +}; +HPRef_Struct reftet_1e_0v = +{ + HP_TET, + reftet_1e_0v_splitedges, + 0, 0, + reftet_1e_0v_newelstypes, + reftet_1e_0v_newels +}; + + + + + +// HP_TET_1E_1VA +int reftet_1e_1va_splitedges[][3] = +{ + { 1, 3, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 2, 4, 8 }, + { 1, 2, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_1e_1va_newelstypes[] = +{ + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_NONE, +}; +int reftet_1e_1va_newels[][8] = +{ + { 1, 9, 5, 6 }, + { 9, 5, 6, 2, 7, 8 }, + { 7, 3, 5, 8, 4, 6 } +}; +HPRef_Struct reftet_1e_1va = +{ + HP_TET, + reftet_1e_1va_splitedges, + 0, 0, + reftet_1e_1va_newelstypes, + reftet_1e_1va_newels +}; + + + + + + +// HP_TET_1E_1VB +int reftet_1e_1vb_splitedges[][3] = +{ + { 1, 3, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 2, 4, 8 }, + { 4, 1, 9 }, + { 4, 2, 10 }, + { 4, 3, 11 }, + { 0, 0, 0 } +}; +int reftet_1e_1vb_splitelements[][5] = +{ + { 4, 1, 2, 3, 12 }, + { 0 } +}; + +HPREF_ELEMENT_TYPE reftet_1e_1vb_newelstypes[] = +{ + HP_PRISM_SINGEDGE, + HP_TET_0E_1V, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_NONE, +}; +int reftet_1e_1vb_newels[][8] = +{ + { 1, 5, 6, 2, 7, 8 }, + { 4, 11, 10, 9 }, + { 7, 8, 10, 11, 12 }, + { 3, 7, 11, 12 }, + { 5, 11, 9, 6, 12 }, + { 5, 3, 11, 12 }, + { 6, 9, 10, 8, 12 }, + { 5, 7, 3, 12 }, + { 5, 6, 8, 7, 12 }, + { 9, 11, 10, 12 } +}; +HPRef_Struct reftet_1e_1vb = +{ + HP_TET, + reftet_1e_1vb_splitedges, + 0, + reftet_1e_1vb_splitelements, + reftet_1e_1vb_newelstypes, + reftet_1e_1vb_newels +}; + + + + + + + + +// HP_TET_1E_2VA +int reftet_1e_2va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_1e_2va_newelstypes[] = +{ + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_NONE, +}; +int reftet_1e_2va_newels[][8] = +{ + { 1, 5, 6, 7 }, + { 2, 8, 10, 9 }, + { 5, 6, 7, 8, 9, 10 }, + { 4, 10, 7, 3, 9, 6 }, +}; +HPRef_Struct reftet_1e_2va = +{ + HP_TET, + reftet_1e_2va_splitedges, + 0, 0, + reftet_1e_2va_newelstypes, + reftet_1e_2va_newels +}; + + + + + + + +// HP_TET_1E_2VB +int reftet_1e_2vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 1, 10 }, + { 3, 2, 11 }, + { 3, 4, 12 }, + { 0, 0, 0 } +}; +int reftet_1e_2vb_splitelements[][5] = +{ + { 3, 4, 1, 2, 13 }, + { 0 } +}; + +HPREF_ELEMENT_TYPE reftet_1e_2vb_newelstypes[] = +{ + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_TET_0E_1V, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_NONE, +}; +int reftet_1e_2vb_newels[][8] = +{ + { 1, 5, 6, 7 }, + { 5, 6, 7, 2, 8, 9 }, + { 3, 10, 11, 12 }, + + { 8, 9, 12, 11, 13 }, + { 4, 12, 9, 13 }, + { 6, 10, 12, 7, 13 }, + { 4, 7, 12, 13 }, + { 6, 8, 11, 10, 13 }, + { 4, 9, 7, 13 }, + { 6, 7, 9, 8, 13 }, + { 10, 11, 12, 13 }, +}; +HPRef_Struct reftet_1e_2vb = +{ + HP_TET, + reftet_1e_2vb_splitedges, + 0, + reftet_1e_2vb_splitelements, + reftet_1e_2vb_newelstypes, + reftet_1e_2vb_newels +}; + + + + + + +// HP_TET_1E_2VC +int reftet_1e_2vc_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 4, 1, 10 }, + { 4, 2, 11 }, + { 4, 3, 12 }, + { 0, 0, 0 } +}; +int reftet_1e_2vc_splitelements[][5] = +{ + { 4, 1, 2, 3, 13 }, + { 0 } +}; + +HPREF_ELEMENT_TYPE reftet_1e_2vc_newelstypes[] = +{ + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_TET_0E_1V, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_NONE, +}; +int reftet_1e_2vc_newels[][8] = +{ + { 1, 5, 6, 7 }, + { 5, 6, 7, 2, 8, 9 }, + { 4, 11, 10, 12 }, + { 8, 9, 11, 12, 13 }, + { 3, 8, 12, 13 }, + { 7, 6, 12, 10, 13 }, + { 3, 12, 6, 13 }, + { 9, 7, 10, 11, 13 }, + { 3, 6, 8, 13 }, + { 6, 7, 9, 8, 13 }, + { 10, 12, 11, 13 } +}; +HPRef_Struct reftet_1e_2vc = +{ + HP_TET, + reftet_1e_2vc_splitedges, + 0, + reftet_1e_2vc_splitelements, + reftet_1e_2vc_newelstypes, + reftet_1e_2vc_newels +}; + + + + + + + + +/* + +// HP_TET_1E_2VD +int reftet_1e_2vd_splitedges[][3] = +{ + { 1, 3, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 2, 4, 8 }, + { 3, 1, 9 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 4, 1, 12 }, + { 4, 2, 13 }, + { 4, 3, 14 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_1e_2vd_newelstypes[] = +{ + HP_PRISM_SINGEDGE, + HP_TET_0E_1V, + HP_TET_0E_1V, + HP_PRISM, + HP_HEX, + HP_NONE, +}; +int reftet_1e_2vd_newels[][8] = +{ + { 1, 5, 6, 2, 7, 8 }, + { 4, 13, 12, 14 }, + { 3, 10, 11, 9 }, + { 14, 13, 12, 11, 10, 9 }, + { 6, 12, 13, 8, 5, 9, 10, 7 }, +}; +HPRef_Struct reftet_1e_2vd = +{ + HP_TET, + reftet_1e_2vd_splitedges, + 0, 0, + reftet_1e_2vd_newelstypes, + reftet_1e_2vd_newels +}; + +*/ + + + + +// HP_TET_1E_2VD, // 1 v on edge +int reftet_1e_2vd_splitedges[][3] = +{ + // { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + // { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_1e_2vd_splitfaces[][4] = + { + { 1, 3, 4, 19 }, + { 2, 3, 4, 22 }, + { 3, 1, 4, 24 }, + { 3, 2, 4, 25 }, + { 4, 1, 3, 27 }, + { 4, 2, 3, 28 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_1e_2vd_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_TET_0E_1V, + HP_TET_0E_1V, + HP_PRISM, + HP_HEX, + HP_PYRAMID, + HP_HEX, + HP_PYRAMID, + HP_PRISM, + HP_PRISM, + HP_NONE, + }; +int reftet_1e_2vd_newels[][8] = +{ + { 1, 6, 7, 2, 9, 10 }, + { 3, 11, 12, 13 }, + { 4, 16, 15, 14 }, + { 7, 6, 19, 10, 9, 22 }, + { 7, 19, 27, 14, 10, 22, 28, 15 }, + { 14, 15, 28, 27, 16 }, + { 9, 6, 19, 22, 12, 11, 24, 25 }, + { 12, 11, 24, 25, 13 }, + { 19, 24, 27, 22, 25, 28 }, + { 16, 28, 27, 13, 25, 24 } +}; +HPRef_Struct reftet_1e_2vd = +{ + HP_TET, + reftet_1e_2vd_splitedges, + reftet_1e_2vd_splitfaces, + 0, + reftet_1e_2vd_newelstypes, + reftet_1e_2vd_newels +}; + + + + + + + + + + + + + + + +// HP_TET_1E_3VA +int reftet_1e_3va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 0, 0, 0 } +}; +int reftet_1e_3va_splitelements[][5] = +{ + { 1, 2, 3, 4, 14 }, + { 0 } +}; + +HPREF_ELEMENT_TYPE reftet_1e_3va_newelstypes[] = +{ + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_TET_0E_1V, + + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_PYRAMID, + HP_TET, + HP_NONE, +}; +int reftet_1e_3va_newels[][8] = +{ + { 5, 6, 7, 8, 9, 10 }, + { 1, 5, 6, 7 }, + { 2, 8, 10, 9 }, + { 3, 11, 12, 13 }, + + { 6, 7, 10, 9, 14 }, + { 4, 10, 7, 14 }, + { 9, 10, 13, 12, 14 }, + { 4, 13, 10, 14 }, + { 6, 11, 13, 7, 14 }, + { 4, 7, 13, 14 }, + { 6, 11, 12, 9, 14 }, + { 11, 13, 12, 14 }, +}; + +HPRef_Struct reftet_1e_3va = +{ + HP_TET, + reftet_1e_3va_splitedges, + 0, + reftet_1e_3va_splitelements, + reftet_1e_3va_newelstypes, + reftet_1e_3va_newels +}; + + + + + + + + + + + + + + + + + + + + + + +// HP_TET_1E_3VB, // 1 v on edge +int reftet_1e_3vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + // { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_1e_3vb_splitfaces[][4] = + { + { 1, 3, 4, 19 }, + { 2, 3, 4, 22 }, + { 3, 1, 4, 24 }, + { 3, 2, 4, 25 }, + { 4, 1, 3, 27 }, + { 4, 2, 3, 28 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_1e_3vb_newelstypes[] = + { + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_TET_0E_1V, + HP_TET_0E_1V, + HP_PRISM, + HP_HEX, + HP_PYRAMID, + HP_HEX, + HP_PYRAMID, + HP_PRISM, + HP_PRISM, + HP_NONE, + }; +int reftet_1e_3vb_newels[][8] = +{ + { 1, 5, 6, 7 }, + { 5, 6, 7, 2, 9, 10 }, + { 3, 11, 12, 13 }, + { 4, 16, 15, 14 }, + { 7, 6, 19, 10, 9, 22 }, + { 7, 19, 27, 14, 10, 22, 28, 15 }, + { 14, 15, 28, 27, 16 }, + { 9, 6, 19, 22, 12, 11, 24, 25 }, + { 12, 11, 24, 25, 13 }, + { 19, 24, 27, 22, 25, 28 }, + { 16, 28, 27, 13, 25, 24 } +}; +HPRef_Struct reftet_1e_3vb = +{ + HP_TET, + reftet_1e_3vb_splitedges, + reftet_1e_3vb_splitfaces, + 0, + reftet_1e_3vb_newelstypes, + reftet_1e_3vb_newels +}; + + + + + + +/* +// HP_TET_1E_4V +int reftet_1e_4v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_1e_4v_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 1, 2, 4, 18 }, + { 1, 3, 4, 19 }, + + { 2, 1, 3, 20 }, + { 2, 1, 4, 21 }, + { 2, 3, 4, 22 }, + + { 3, 1, 2, 23 }, + { 3, 1, 4, 24 }, + { 3, 2, 4, 25 }, + + { 4, 1, 2, 26 }, + { 4, 1, 3, 27 }, + { 4, 2, 3, 28 }, + { 0, 0, 0, 0 }, + }; +int reftet_1e_4v_splitelements[][5] = + { + { 1, 2, 3, 4, 29 }, + { 2, 3, 4, 1, 30 }, + { 3, 4, 1, 2, 31 }, + { 4, 1, 2, 3, 32 }, + { 0 }, + }; +HPREF_ELEMENT_TYPE reftet_1e_4v_newelstypes[] = +{ + HP_HEX_1E_1V, + HP_HEX_1E_1V, + HP_HEX_0E_1V, + HP_HEX_0E_1V, + HP_PRISM_SINGEDGE, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_TET, + HP_NONE, +}; +int reftet_1e_4v_newels[][8] = +{ + { 1, 5, 17, 6, 7, 18, 29, 19 }, + // { 2, 9, 20, 8, 10, 22, 30, 21 }, + { 2, 8, 21, 10, 9, 20, 30, 22 }, + { 3, 11, 23, 12, 13, 24, 31, 25 }, + { 4, 15, 26, 14, 16, 28, 32, 27 }, + { 5, 17, 18, 8, 20, 21 }, + { 18, 17, 29, 21, 20, 30 }, + { 6, 19, 17, 11, 24, 23 }, + { 17, 19, 29, 23, 24, 31 }, + { 7, 18, 19, 14, 26, 27 }, + { 19, 18, 29, 27, 26, 32 }, + { 9, 20, 22, 12, 23, 25 }, + { 22, 20, 30, 25, 23, 31 }, + { 10, 22, 21, 15, 28, 26 }, + { 21, 22, 30, 26, 28, 32 }, + { 13, 24, 25, 16, 27, 28 }, + { 25, 24, 31, 28, 27, 32 }, + { 17, 20, 23, 29, 30, 31 }, + { 18, 26, 21, 29, 32, 30 }, + { 19, 24, 27, 29, 31, 32 }, + { 22, 28, 25, 30, 32, 31 }, + + { 29, 30, 31, 32 }, +}; +HPRef_Struct reftet_1e_4v = +{ + HP_TET, + reftet_1e_4v_splitedges, + reftet_1e_4v_splitfaces, + reftet_1e_4v_splitelements, + reftet_1e_4v_newelstypes, + reftet_1e_4v_newels +}; +*/ + + + + +// HP_TET_1E_4V +int reftet_1e_4v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_1e_4v_splitfaces[][4] = + { + { 1, 3, 4, 17 }, + { 2, 3, 4, 18 }, + + { 3, 1, 4, 19 }, + { 3, 2, 4, 20 }, + + { 4, 1, 3, 21 }, + { 4, 2, 3, 22 }, + { 0, 0, 0, 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_1e_4v_newelstypes[] = +{ + HP_TET_1E_1VA, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_HEX, + HP_HEX, + HP_PRISM, + HP_PRISM, + + HP_PYRAMID, + HP_TET_0E_1V, + + HP_PYRAMID, + HP_TET_0E_1V, + + HP_NONE, +}; + +int reftet_1e_4v_newels[][8] = +{ + { 1, 5, 6, 7 }, + { 2, 8, 10, 9 }, + + { 5, 6, 7, 8, 9, 10 }, + { 7, 6, 17, 10, 9, 18 }, + + { 7, 10, 18, 17, 14, 15, 22, 21 }, + { 9, 6, 17, 18, 12, 11, 19, 20 }, + + { 17, 19, 21, 18, 20, 22 }, + { 16, 22, 21, 13, 20, 19 }, + + { 14, 15, 22, 21, 16 }, + { 4, 14, 16, 15 }, + { 12, 11, 19, 20, 13 }, + { 3, 11, 12, 13 }, + + + + { 1, 5, 17, 6, 7, 18, 29, 19 }, + // { 2, 9, 20, 8, 10, 22, 30, 21 }, + { 2, 8, 21, 10, 9, 20, 30, 22 }, + { 3, 11, 23, 12, 13, 24, 31, 25 }, + { 4, 15, 26, 14, 16, 28, 32, 27 }, + { 5, 17, 18, 8, 20, 21 }, + { 18, 17, 29, 21, 20, 30 }, + { 6, 19, 17, 11, 24, 23 }, + { 17, 19, 29, 23, 24, 31 }, + { 7, 18, 19, 14, 26, 27 }, + { 19, 18, 29, 27, 26, 32 }, + { 9, 20, 22, 12, 23, 25 }, + { 22, 20, 30, 25, 23, 31 }, + { 10, 22, 21, 15, 28, 26 }, + { 21, 22, 30, 26, 28, 32 }, + { 13, 24, 25, 16, 27, 28 }, + { 25, 24, 31, 28, 27, 32 }, + { 17, 20, 23, 29, 30, 31 }, + { 18, 26, 21, 29, 32, 30 }, + { 19, 24, 27, 29, 31, 32 }, + { 22, 28, 25, 30, 32, 31 }, + + { 29, 30, 31, 32 }, +}; +HPRef_Struct reftet_1e_4v = +{ + HP_TET, + reftet_1e_4v_splitedges, + reftet_1e_4v_splitfaces, + 0, + reftet_1e_4v_newelstypes, + reftet_1e_4v_newels +}; + + + + + + + + + + + + + +// HP_TET_2EA_0V, // 2 edges connected +int reftet_2ea_0v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 0, 0, 0 } +}; +int reftet_2ea_0v_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_0v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_2ea_0v_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 5, 17, 7, 2, 9, 10 }, + { 6, 7, 17, 3, 13, 12 }, + { 17, 9, 12, 7, 10, 13 }, + { 7, 10, 13, 4 }, +}; +HPRef_Struct reftet_2ea_0v = +{ + HP_TET, + reftet_2ea_0v_splitedges, + reftet_2ea_0v_splitfaces, + 0, + reftet_2ea_0v_newelstypes, + reftet_2ea_0v_newels +}; + + + + + + +// HP_TET_2EA_1VA, // 2 edges connected +int reftet_2ea_1va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 0, 0, 0 } +}; +int reftet_2ea_1va_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_1va_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_2ea_1va_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 5, 17, 7, 8, 9, 10 }, + { 2, 8, 10, 9 }, + { 6, 7, 17, 3, 13, 12 }, + { 17, 9, 12, 7, 10, 13 }, + { 7, 10, 13, 4 }, +}; +HPRef_Struct reftet_2ea_1va = +{ + HP_TET, + reftet_2ea_1va_splitedges, + reftet_2ea_1va_splitfaces, + 0, + reftet_2ea_1va_newelstypes, + reftet_2ea_1va_newels +}; + + + + + + + + +// HP_TET_2EA_1VB, +int reftet_2ea_1vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 0, 0, 0 } +}; +int reftet_2ea_1vb_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_1vb_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_2ea_1vb_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 3, 11, 12, 13 }, + { 5, 17, 7, 2, 9, 10 }, + { 6, 7, 17, 11, 13, 12 }, + { 17, 9, 12, 7, 10, 13 }, + { 7, 10, 13, 4 }, +}; +HPRef_Struct reftet_2ea_1vb = +{ + HP_TET, + reftet_2ea_1vb_splitedges, + reftet_2ea_1vb_splitfaces, + 0, + reftet_2ea_1vb_newelstypes, + reftet_2ea_1vb_newels +}; + + + + + + +// HP_TET_2EA_1VC, // 2 edges connected +int reftet_2ea_1vc_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + // { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_2ea_1vc_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 2, 3, 4, 18 }, + { 3, 4, 2, 19 }, + { 4, 2, 3, 20 }, + { 0, 0, 0, 0 } + }; +int reftet_2ea_1vc_splitelements[][5] = + { + { 1, 2, 3, 4, 21 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_1vc_newelstypes[] = + { + HP_PYRAMID_EDGES, + // HP_TET_1E_1VA, + HP_TET_0E_1V, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_TET, HP_TET, HP_TET, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, + HP_PYRAMID, HP_PYRAMID, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_TET, + // HP_PRISM, + // HP_PRISM, + HP_NONE, + }; +int reftet_2ea_1vc_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + // { 3, 11, 12, 13 }, + { 4, 15, 14, 16 }, + { 5, 17, 7, 2, 9, 10 }, + { 6, 7, 17, 3, 13, 12 }, + + { 9, 10, 18, 21 }, + { 13, 12, 19, 21 }, + { 15, 16, 20, 21 }, + { 18, 20, 19, 21 }, + { 10, 15, 20, 18, 21 }, + { 13, 19, 20, 16, 21 }, + { 9, 18, 19, 12, 21 }, + + { 7, 13, 16, 14, 21 }, + { 7, 14, 15, 10, 21 }, + { 9, 12, 17, 21 }, + { 7, 10, 9, 17, 21 }, + { 7, 17, 12, 13, 21 }, + { 14, 16, 15, 21 }, + // { 17, 9, 12, 7, 10, 13 }, + // { 7, 10, 13, 14, 15, 16 }, +}; +HPRef_Struct reftet_2ea_1vc = +{ + HP_TET, + reftet_2ea_1vc_splitedges, + reftet_2ea_1vc_splitfaces, + reftet_2ea_1vc_splitelements, + reftet_2ea_1vc_newelstypes, + reftet_2ea_1vc_newels +}; + + + + + + + + + + + + +// HP_TET_2EA_2VA, +int reftet_2ea_2va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 0, 0, 0 } +}; +int reftet_2ea_2va_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_2va_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_2ea_2va_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 3, 11, 12, 13 }, + { 2, 8, 10, 9 }, + { 5, 17, 7, 8, 9, 10 }, + { 6, 7, 17, 11, 13, 12 }, + { 17, 9, 12, 7, 10, 13 }, + { 7, 10, 13, 4 }, +}; +HPRef_Struct reftet_2ea_2va = +{ + HP_TET, + reftet_2ea_2va_splitedges, + reftet_2ea_2va_splitfaces, + 0, + reftet_2ea_2va_newelstypes, + reftet_2ea_2va_newels +}; + + + + + + + + + + + +// HP_TET_2EA_2VB, // 2 edges connected +int reftet_2ea_2vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + // { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_2ea_2vb_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 2, 3, 4, 18 }, + { 3, 4, 2, 19 }, + { 4, 2, 3, 20 }, + { 0, 0, 0, 0 } + }; +int reftet_2ea_2vb_splitelements[][5] = + { + { 1, 2, 3, 4, 21 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_2vb_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_TET_0E_1V, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_TET, HP_TET, HP_TET, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, + HP_PYRAMID, HP_PYRAMID, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_TET, + // HP_PRISM, + // HP_PRISM, + HP_NONE, + }; +int reftet_2ea_2vb_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 2, 8, 10, 9 }, + // { 3, 11, 12, 13 }, + { 4, 15, 14, 16 }, + { 5, 17, 7, 8, 9, 10 }, + { 6, 7, 17, 3, 13, 12 }, + + { 9, 10, 18, 21 }, + { 13, 12, 19, 21 }, + { 15, 16, 20, 21 }, + { 18, 20, 19, 21 }, + { 10, 15, 20, 18, 21 }, + { 13, 19, 20, 16, 21 }, + { 9, 18, 19, 12, 21 }, + + { 7, 13, 16, 14, 21 }, + { 7, 14, 15, 10, 21 }, + { 9, 12, 17, 21 }, + { 7, 10, 9, 17, 21 }, + { 7, 17, 12, 13, 21 }, + { 14, 16, 15, 21 }, + // { 17, 9, 12, 7, 10, 13 }, + // { 7, 10, 13, 14, 15, 16 }, +}; +HPRef_Struct reftet_2ea_2vb = +{ + HP_TET, + reftet_2ea_2vb_splitedges, + reftet_2ea_2vb_splitfaces, + reftet_2ea_2vb_splitelements, + reftet_2ea_2vb_newelstypes, + reftet_2ea_2vb_newels +}; + + + + + + + + + + +// HP_TET_2EA_2VC, // 2 edges connected +int reftet_2ea_2vc_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + // { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_2ea_2vc_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 2, 3, 4, 18 }, + { 3, 4, 2, 19 }, + { 4, 2, 3, 20 }, + { 0, 0, 0, 0 } + }; +int reftet_2ea_2vc_splitelements[][5] = + { + { 1, 2, 3, 4, 21 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_2vc_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_TET_0E_1V, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_TET, HP_TET, HP_TET, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, + HP_PYRAMID, HP_PYRAMID, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_TET, + // HP_PRISM, + // HP_PRISM, + HP_NONE, + }; +int reftet_2ea_2vc_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + // { 2, 8, 10, 9 }, + { 3, 11, 12, 13 }, + { 4, 15, 14, 16 }, + { 5, 17, 7, 2, 9, 10 }, + { 6, 7, 17, 11, 13, 12 }, + + { 9, 10, 18, 21 }, + { 13, 12, 19, 21 }, + { 15, 16, 20, 21 }, + { 18, 20, 19, 21 }, + { 10, 15, 20, 18, 21 }, + { 13, 19, 20, 16, 21 }, + { 9, 18, 19, 12, 21 }, + + { 7, 13, 16, 14, 21 }, + { 7, 14, 15, 10, 21 }, + { 9, 12, 17, 21 }, + { 7, 10, 9, 17, 21 }, + { 7, 17, 12, 13, 21 }, + { 14, 16, 15, 21 }, + // { 17, 9, 12, 7, 10, 13 }, + // { 7, 10, 13, 14, 15, 16 }, +}; +HPRef_Struct reftet_2ea_2vc = +{ + HP_TET, + reftet_2ea_2vc_splitedges, + reftet_2ea_2vc_splitfaces, + reftet_2ea_2vc_splitelements, + reftet_2ea_2vc_newelstypes, + reftet_2ea_2vc_newels +}; + + + + + + + + +// HP_TET_2EA_3V, // 2 edges connected +int reftet_2ea_3v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_2ea_3v_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 2, 3, 4, 18 }, + { 3, 4, 2, 19 }, + { 4, 2, 3, 20 }, + { 0, 0, 0, 0 } + }; +int reftet_2ea_3v_splitelements[][5] = + { + { 1, 2, 3, 4, 21 }, + { 0, 0, 0, 0 } + }; +HPREF_ELEMENT_TYPE reftet_2ea_3v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_TET_0E_1V, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_TET, HP_TET, HP_TET, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_PYRAMID, + HP_PYRAMID, HP_PYRAMID, HP_TET, + HP_PYRAMID, HP_PYRAMID, HP_TET, + // HP_PRISM, + // HP_PRISM, + HP_NONE, + }; +int reftet_2ea_3v_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 2, 8, 10, 9 }, + { 3, 11, 12, 13 }, + { 4, 15, 14, 16 }, + { 5, 17, 7, 8, 9, 10 }, + { 6, 7, 17, 11, 13, 12 }, + + { 9, 10, 18, 21 }, + { 13, 12, 19, 21 }, + { 15, 16, 20, 21 }, + { 18, 20, 19, 21 }, + { 10, 15, 20, 18, 21 }, + { 13, 19, 20, 16, 21 }, + { 9, 18, 19, 12, 21 }, + + { 7, 13, 16, 14, 21 }, + { 7, 14, 15, 10, 21 }, + { 9, 12, 17, 21 }, + { 7, 10, 9, 17, 21 }, + { 7, 17, 12, 13, 21 }, + { 14, 16, 15, 21 }, + // { 17, 9, 12, 7, 10, 13 }, + // { 7, 10, 13, 14, 15, 16 }, +}; +HPRef_Struct reftet_2ea_3v = +{ + HP_TET, + reftet_2ea_3v_splitedges, + reftet_2ea_3v_splitfaces, + reftet_2ea_3v_splitelements, + reftet_2ea_3v_newelstypes, + reftet_2ea_3v_newels +}; + + + + + + + +// HP_TET_2EB_0V, // 2 opposite edges +int reftet_2eb_0v_splitedges[][3] = +{ + { 1, 3, 5 }, + { 1, 4, 6 }, + { 2, 3, 7 }, + { 2, 4, 8 }, + { 3, 1, 9 }, + { 3, 2, 10 }, + { 4, 1, 11 }, + { 4, 2, 12 }, + { 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftet_2eb_0v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_HEX, + HP_NONE, + }; +int reftet_2eb_0v_newels[][8] = +{ + { 1, 5, 6, 2, 7, 8 }, + { 3, 9, 10, 4, 11, 12 }, + { 6, 11, 12, 8, 5, 9, 10, 7 }, +}; +HPRef_Struct reftet_2eb_0v = +{ + HP_TET, + reftet_2eb_0v_splitedges, + 0, 0, + reftet_2eb_0v_newelstypes, + reftet_2eb_0v_newels +}; + + +// HP_TET_2EB_1V, // V1 + + +// HP_TET_2EB_1V, // 2 opposite edges, V1 +int reftet_2eb_1v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftet_2eb_1v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + // HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_HEX, + HP_NONE, + }; +int reftet_2eb_1v_newels[][8] = +{ + { 5, 6, 7, 2, 9, 10 }, + { 4, 15, 14, 3, 12, 11 }, + { 1, 5, 6, 7 }, + // { 2, 8, 10, 9 }, + // { 3, 13, 11, 12 }, + // { 4, 16, 15, 14 }, + { 7, 14, 15, 10, 6, 11, 12, 9 } +}; +HPRef_Struct reftet_2eb_1v = +{ + HP_TET, + reftet_2eb_1v_splitedges, + 0, 0, + reftet_2eb_1v_newelstypes, + reftet_2eb_1v_newels +}; + + + +// HP_TET_2EB_2VA, // 2 opposite edges, V1,2 +int reftet_2eb_2va_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftet_2eb_2va_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_HEX, + HP_NONE, + }; +int reftet_2eb_2va_newels[][8] = +{ + { 5, 6, 7, 8, 9, 10 }, + { 4, 15, 14, 3, 12, 11 }, + { 1, 5, 6, 7 }, + { 2, 8, 10, 9 }, + // { 3, 13, 11, 12 }, + // { 4, 16, 15, 14 }, + { 7, 14, 15, 10, 6, 11, 12, 9 } +}; +HPRef_Struct reftet_2eb_2va = +{ + HP_TET, + reftet_2eb_2va_splitedges, + 0, 0, + reftet_2eb_2va_newelstypes, + reftet_2eb_2va_newels +}; + + +// HP_TET_2EB_2VB, // V1,3 +int reftet_2eb_2vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftet_2eb_2vb_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_HEX, + HP_NONE, + }; +int reftet_2eb_2vb_newels[][8] = +{ + { 5, 6, 7, 2, 9, 10 }, + { 4, 15, 14, 13, 12, 11 }, + { 1, 5, 6, 7 }, + // { 2, 8, 10, 9 }, + { 3, 13, 11, 12 }, + // { 4, 16, 15, 14 }, + { 7, 14, 15, 10, 6, 11, 12, 9 } +}; +HPRef_Struct reftet_2eb_2vb = +{ + HP_TET, + reftet_2eb_2vb_splitedges, + 0, 0, + reftet_2eb_2vb_newelstypes, + reftet_2eb_2vb_newels +}; + + + + +// HP_TET_2EB_2VC, // V1,4 +int reftet_2eb_2vc_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftet_2eb_2vc_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_HEX, + HP_NONE, + }; +int reftet_2eb_2vc_newels[][8] = +{ + { 5, 6, 7, 2, 9, 10 }, + { 16, 15, 14, 3, 12, 11 }, + { 1, 5, 6, 7 }, + // { 2, 8, 10, 9 }, + // { 3, 13, 11, 12 }, + { 4, 16, 15, 14 }, + { 7, 14, 15, 10, 6, 11, 12, 9 } +}; +HPRef_Struct reftet_2eb_2vc = +{ + HP_TET, + reftet_2eb_2vc_splitedges, + 0, 0, + reftet_2eb_2vc_newelstypes, + reftet_2eb_2vc_newels +}; + + + + + + +// HP_TET_2EB_3V, // V1,2,3 +int reftet_2eb_3v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftet_2eb_3v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_HEX, + HP_NONE, + }; +int reftet_2eb_3v_newels[][8] = +{ + { 5, 6, 7, 8, 9, 10 }, + { 4, 15, 14, 13, 12, 11 }, + { 1, 5, 6, 7 }, + { 2, 8, 10, 9 }, + { 3, 13, 11, 12 }, + // { 4, 16, 15, 14 }, + { 7, 14, 15, 10, 6, 11, 12, 9 } +}; +HPRef_Struct reftet_2eb_3v = +{ + HP_TET, + reftet_2eb_3v_splitedges, + 0, 0, + reftet_2eb_3v_newelstypes, + reftet_2eb_3v_newels +}; + + + + + + +// HP_TET_2EB_4V, // 2 opposite edges +int reftet_2eb_4v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftet_2eb_4v_newelstypes[] = + { + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_HEX, + HP_NONE, + }; +int reftet_2eb_4v_newels[][8] = +{ + { 5, 6, 7, 8, 9, 10 }, + { 16, 15, 14, 13, 12, 11 }, + { 1, 5, 6, 7 }, + { 2, 8, 10, 9 }, + { 3, 13, 11, 12 }, + { 4, 16, 15, 14 }, + { 7, 14, 15, 10, 6, 11, 12, 9 } +}; +HPRef_Struct reftet_2eb_4v = +{ + HP_TET, + reftet_2eb_4v_splitedges, + 0, 0, + reftet_2eb_4v_newelstypes, + reftet_2eb_4v_newels +}; + + + + + + + + + + + + + + + + + +// HP_TET_3EA_0V, +int reftet_3ea_0v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 4, 2, 12 }, + { 4, 3, 13 }, + { 0, 0, 0 } +}; +int reftet_3ea_0v_splitfaces[][4] = + { + { 1, 2, 3, 14 }, + { 1, 2, 4, 15 }, + { 1, 3, 4, 16 }, + { 2, 3, 4, 17 }, + { 3, 4, 2, 18 }, + { 4, 2, 3, 19 }, + { 0, 0, 0, 0 } + }; +int reftet_3ea_0v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3ea_0v_newelstypes[] = + { + HP_HEX_3E_0V, + HP_HEX_1E_0V, + HP_HEX_1E_0V, + HP_HEX_1E_0V, + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_3ea_0v_newels[][8] = +{ + { 1, 5, 14, 6, 7, 15, 20, 16 }, + { 5, 2, 8, 14, 15, 9, 17, 20 }, + { 3, 6, 14, 10, 11, 16, 20, 18 }, + { 7, 4, 12, 15, 16, 13, 19, 20 }, + { 11, 13, 16, 18, 19, 20 }, + { 15, 12, 9, 20, 19, 17 }, + { 8, 10, 14, 17, 18, 20 }, + { 20, 17, 18, 19 }, +}; +HPRef_Struct reftet_3ea_0v = +{ + HP_TET, + reftet_3ea_0v_splitedges, + reftet_3ea_0v_splitfaces, + reftet_3ea_0v_splitelements, + reftet_3ea_0v_newelstypes, + reftet_3ea_0v_newels +}; + + + + + + + + + + +// HP_TET_3EA_1V, +int reftet_3ea_1v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 4, 2, 12 }, + { 4, 3, 13 }, + { 2, 1, 21 }, + { 3, 1, 22 }, + { 4, 1, 23 }, + { 0, 0, 0 } +}; +int reftet_3ea_1v_splitfaces[][4] = + { + { 1, 2, 3, 14 }, + { 1, 2, 4, 15 }, + { 1, 3, 4, 16 }, + { 2, 3, 4, 17 }, + { 3, 4, 2, 18 }, + { 4, 2, 3, 19 }, + { 0, 0, 0, 0 } + }; +int reftet_3ea_1v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3ea_1v_newelstypes[] = + { + HP_HEX_3E_0V, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_3ea_1v_newels[][8] = +{ + { 1, 5, 14, 6, 7, 15, 20, 16 }, + + { 2, 21, 9, 8 }, + { 5, 14, 15, 21, 8, 9 }, + { 15, 14, 20, 9, 8, 17 }, + // { 3, 22, 10, 11 }, + // { 6, 16, 14, 22, 11, 10 }, + { 6, 16, 14, 3, 11, 10 }, + { 14, 16, 20, 10, 11, 18 }, + // { 4, 23, 13, 12 }, + // { 7, 15, 16, 23, 12, 13 }, + { 7, 15, 16, 4, 12, 13 }, + { 16, 15, 20, 13, 12, 19 }, + + { 11, 13, 16, 18, 19, 20 }, + { 15, 12, 9, 20, 19, 17 }, + { 8, 10, 14, 17, 18, 20 }, + { 20, 17, 18, 19 }, +}; +HPRef_Struct reftet_3ea_1v = +{ + HP_TET, + reftet_3ea_1v_splitedges, + reftet_3ea_1v_splitfaces, + reftet_3ea_1v_splitelements, + reftet_3ea_1v_newelstypes, + reftet_3ea_1v_newels +}; + + + + + + + + + + +// HP_TET_3EA_2V, +int reftet_3ea_2v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 4, 2, 12 }, + { 4, 3, 13 }, + { 2, 1, 21 }, + { 3, 1, 22 }, + { 4, 1, 23 }, + { 0, 0, 0 } +}; +int reftet_3ea_2v_splitfaces[][4] = + { + { 1, 2, 3, 14 }, + { 1, 2, 4, 15 }, + { 1, 3, 4, 16 }, + { 2, 3, 4, 17 }, + { 3, 4, 2, 18 }, + { 4, 2, 3, 19 }, + { 0, 0, 0, 0 } + }; +int reftet_3ea_2v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3ea_2v_newelstypes[] = + { + HP_HEX_3E_0V, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_3ea_2v_newels[][8] = +{ + { 1, 5, 14, 6, 7, 15, 20, 16 }, + + { 2, 21, 9, 8 }, + { 5, 14, 15, 21, 8, 9 }, + { 15, 14, 20, 9, 8, 17 }, + { 3, 22, 10, 11 }, + { 6, 16, 14, 22, 11, 10 }, + { 14, 16, 20, 10, 11, 18 }, + // { 4, 23, 13, 12 }, + { 7, 15, 16, 4, 12, 13 }, + { 16, 15, 20, 13, 12, 19 }, + + { 11, 13, 16, 18, 19, 20 }, + { 15, 12, 9, 20, 19, 17 }, + { 8, 10, 14, 17, 18, 20 }, + { 20, 17, 18, 19 }, +}; +HPRef_Struct reftet_3ea_2v = +{ + HP_TET, + reftet_3ea_2v_splitedges, + reftet_3ea_2v_splitfaces, + reftet_3ea_2v_splitelements, + reftet_3ea_2v_newelstypes, + reftet_3ea_2v_newels +}; + + + + + + + + +// HP_TET_3EA_3V, +int reftet_3ea_3v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 2, 10 }, + { 3, 4, 11 }, + { 4, 2, 12 }, + { 4, 3, 13 }, + { 2, 1, 21 }, + { 3, 1, 22 }, + { 4, 1, 23 }, + { 0, 0, 0 } +}; +int reftet_3ea_3v_splitfaces[][4] = + { + { 1, 2, 3, 14 }, + { 1, 2, 4, 15 }, + { 1, 3, 4, 16 }, + { 2, 3, 4, 17 }, + { 3, 4, 2, 18 }, + { 4, 2, 3, 19 }, + { 0, 0, 0, 0 } + }; +int reftet_3ea_3v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3ea_3v_newelstypes[] = + { + HP_HEX_3E_0V, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + + HP_PRISM, + HP_PRISM, + HP_PRISM, + HP_TET, + HP_NONE, + }; +int reftet_3ea_3v_newels[][8] = +{ + { 1, 5, 14, 6, 7, 15, 20, 16 }, + + { 2, 21, 9, 8 }, + { 5, 14, 15, 21, 8, 9 }, + { 15, 14, 20, 9, 8, 17 }, + { 3, 22, 10, 11 }, + { 6, 16, 14, 22, 11, 10 }, + { 14, 16, 20, 10, 11, 18 }, + { 4, 23, 13, 12 }, + { 7, 15, 16, 23, 12, 13 }, + { 16, 15, 20, 13, 12, 19 }, + + { 11, 13, 16, 18, 19, 20 }, + { 15, 12, 9, 20, 19, 17 }, + { 8, 10, 14, 17, 18, 20 }, + { 20, 17, 18, 19 }, +}; +HPRef_Struct reftet_3ea_3v = +{ + HP_TET, + reftet_3ea_3v_splitedges, + reftet_3ea_3v_splitfaces, + reftet_3ea_3v_splitelements, + reftet_3ea_3v_newelstypes, + reftet_3ea_3v_newels +}; + + + + + + + +// HP_TET_3EV_0V, +int reftet_3eb_0v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + // { 3, 2, 12 }, + { 3, 4, 13 }, + // { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_3eb_0v_splitfaces[][4] = + { + { 1, 2, 4, 17 }, + { 2, 1, 3, 18 }, + { 0, 0, 0, 0 } + }; +int reftet_3eb_0v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3eb_0v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PYRAMID_EDGES, + // HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PYRAMID, + HP_PYRAMID, + HP_TET, + HP_TET, + HP_PYRAMID, + HP_PYRAMID, + HP_PYRAMID, + HP_NONE, + }; +int reftet_3eb_0v_newels[][8] = +{ + { 1, 7, 17, 5, 6 }, + { 2, 9, 18, 8, 10 }, + // { 3, 12, 13, 11 }, + // { 4, 14, 16, 15 }, + { 5, 6, 17, 8, 18, 10 }, + { 7, 17, 6, 4, 15, 16 }, + { 9, 18, 10, 3, 11, 13 }, + + { 10, 15, 16, 13, 20 }, + { 6, 11, 13, 16, 20 }, + { 10, 17, 15, 20 }, + { 6, 18, 11, 20 }, + { 6, 17, 10, 18, 20 }, + { 6, 16, 15, 17, 20 }, + { 18, 10, 13, 11, 20 }, +}; +HPRef_Struct reftet_3eb_0v = +{ + HP_TET, + reftet_3eb_0v_splitedges, + reftet_3eb_0v_splitfaces, + reftet_3eb_0v_splitelements, + reftet_3eb_0v_newelstypes, + reftet_3eb_0v_newels +}; + + + + + + + + + +// HP_TET_3EV_1V, +int reftet_3eb_1v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + // { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_3eb_1v_splitfaces[][4] = + { + { 1, 2, 4, 17 }, + { 2, 1, 3, 18 }, + { 0, 0, 0, 0 } + }; +int reftet_3eb_1v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3eb_1v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PYRAMID, + HP_PYRAMID, + HP_TET, + HP_TET, + HP_PYRAMID, + HP_PYRAMID, + HP_PYRAMID, + HP_NONE, + }; +int reftet_3eb_1v_newels[][8] = +{ + { 1, 7, 17, 5, 6 }, + { 2, 9, 18, 8, 10 }, + { 3, 12, 13, 11 }, + // { 4, 14, 16, 15 }, + { 5, 6, 17, 8, 18, 10 }, + { 7, 17, 6, 4, 15, 16 }, + { 9, 18, 10, 12, 11, 13 }, + + { 10, 15, 16, 13, 20 }, + { 6, 11, 13, 16, 20 }, + { 10, 17, 15, 20 }, + { 6, 18, 11, 20 }, + { 6, 17, 10, 18, 20 }, + { 6, 16, 15, 17, 20 }, + { 18, 10, 13, 11, 20 }, +}; +HPRef_Struct reftet_3eb_1v = +{ + HP_TET, + reftet_3eb_1v_splitedges, + reftet_3eb_1v_splitfaces, + reftet_3eb_1v_splitelements, + reftet_3eb_1v_newelstypes, + reftet_3eb_1v_newels +}; + + + + + + + + +// HP_TET_3EV_2V, +int reftet_3eb_2v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_3eb_2v_splitfaces[][4] = + { + { 1, 2, 4, 17 }, + { 2, 1, 3, 18 }, + { 0, 0, 0, 0 } + }; +int reftet_3eb_2v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3eb_2v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PYRAMID, + HP_PYRAMID, + HP_TET, + HP_TET, + HP_PYRAMID, + HP_PYRAMID, + HP_PYRAMID, + HP_NONE, + }; +int reftet_3eb_2v_newels[][8] = +{ + { 1, 7, 17, 5, 6 }, + { 2, 9, 18, 8, 10 }, + { 3, 12, 13, 11 }, + { 4, 14, 16, 15 }, + { 5, 6, 17, 8, 18, 10 }, + { 7, 17, 6, 14, 15, 16 }, + { 9, 18, 10, 12, 11, 13 }, + + { 10, 15, 16, 13, 20 }, + { 6, 11, 13, 16, 20 }, + { 10, 17, 15, 20 }, + { 6, 18, 11, 20 }, + { 6, 17, 10, 18, 20 }, + { 6, 16, 15, 17, 20 }, + { 18, 10, 13, 11, 20 }, +}; +HPRef_Struct reftet_3eb_2v = +{ + HP_TET, + reftet_3eb_2v_splitedges, + reftet_3eb_2v_splitfaces, + reftet_3eb_2v_splitelements, + reftet_3eb_2v_newelstypes, + reftet_3eb_2v_newels +}; + + + + + + + + + + + + + +// HP_TET_3EC_0V, +int reftet_3ec_0v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + // { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + // { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_3ec_0v_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 2, 1, 4, 18 }, + { 0, 0, 0, 0 } + }; +int reftet_3ec_0v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3ec_0v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PYRAMID_EDGES, + // HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PYRAMID, + HP_PYRAMID, + HP_TET, + HP_TET, + HP_PYRAMID, + HP_PYRAMID, + HP_PYRAMID, + HP_NONE, + }; +int reftet_3ec_0v_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 2, 8, 18, 10, 9 }, + // { 3, 11, 12, 13 }, + // { 4, 15, 14, 16 }, + { 5, 17, 7, 8, 9, 18 }, + { 6, 7, 17, 3, 13, 12 }, + { 10, 9, 18, 4, 16, 14 }, + + { 9, 16, 13, 12, 20 }, + { 7, 13, 16, 14, 20 }, + { 7, 14, 18, 20 }, + { 9, 12, 17, 20 }, + { 17, 7, 18, 9, 20 }, + { 7, 17, 12, 13, 20 }, + { 9, 18, 14, 16, 20 }, +}; +HPRef_Struct reftet_3ec_0v = +{ + HP_TET, + reftet_3ec_0v_splitedges, + reftet_3ec_0v_splitfaces, + reftet_3ec_0v_splitelements, + reftet_3ec_0v_newelstypes, + reftet_3ec_0v_newels +}; + + + + + + + + + +// HP_TET_3EC_1V, +int reftet_3ec_1v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + // { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_3ec_1v_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 2, 1, 4, 18 }, + { 0, 0, 0, 0 } + }; +int reftet_3ec_1v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3ec_1v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + // HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PYRAMID, + HP_PYRAMID, + HP_TET, + HP_TET, + HP_PYRAMID, + HP_PYRAMID, + HP_PYRAMID, + HP_NONE, + }; +int reftet_3ec_1v_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 2, 8, 18, 10, 9 }, + { 3, 11, 12, 13 }, + // { 4, 15, 14, 16 }, + { 5, 17, 7, 8, 9, 18 }, + { 6, 7, 17, 11, 13, 12 }, + { 10, 9, 18, 4, 16, 14 }, + + { 9, 16, 13, 12, 20 }, + { 7, 13, 16, 14, 20 }, + { 7, 14, 18, 20 }, + { 9, 12, 17, 20 }, + { 17, 7, 18, 9, 20 }, + { 7, 17, 12, 13, 20 }, + { 9, 18, 14, 16, 20 }, +}; +HPRef_Struct reftet_3ec_1v = +{ + HP_TET, + reftet_3ec_1v_splitedges, + reftet_3ec_1v_splitfaces, + reftet_3ec_1v_splitelements, + reftet_3ec_1v_newelstypes, + reftet_3ec_1v_newels +}; + + + + + + + + +// HP_TET_3EC_2V, +int reftet_3ec_2v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 2, 3, 9 }, + { 2, 4, 10 }, + { 3, 1, 11 }, + { 3, 2, 12 }, + { 3, 4, 13 }, + { 4, 1, 14 }, + { 4, 2, 15 }, + { 4, 3, 16 }, + { 0, 0, 0 } +}; +int reftet_3ec_2v_splitfaces[][4] = + { + { 1, 2, 3, 17 }, + { 2, 1, 4, 18 }, + { 0, 0, 0, 0 } + }; +int reftet_3ec_2v_splitelements[][5] = + { + { 1, 2, 3, 4, 20 }, + { 0 }, + }; + +HPREF_ELEMENT_TYPE reftet_3ec_2v_newelstypes[] = + { + HP_PYRAMID_EDGES, + HP_PYRAMID_EDGES, + HP_TET_1E_1VA, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE, + + HP_PYRAMID, + HP_PYRAMID, + HP_TET, + HP_TET, + HP_PYRAMID, + HP_PYRAMID, + HP_PYRAMID, + HP_NONE, + }; +int reftet_3ec_2v_newels[][8] = +{ + { 1, 5, 17, 6, 7 }, + { 2, 8, 18, 10, 9 }, + { 3, 11, 12, 13 }, + { 4, 15, 14, 16 }, + { 5, 17, 7, 8, 9, 18 }, + { 6, 7, 17, 11, 13, 12 }, + { 10, 9, 18, 15, 16, 14 }, + + { 9, 16, 13, 12, 20 }, + { 7, 13, 16, 14, 20 }, + { 7, 14, 18, 20 }, + { 9, 12, 17, 20 }, + { 17, 7, 18, 9, 20 }, + { 7, 17, 12, 13, 20 }, + { 9, 18, 14, 16, 20 }, +}; +HPRef_Struct reftet_3ec_2v = +{ + HP_TET, + reftet_3ec_2v_splitedges, + reftet_3ec_2v_splitfaces, + reftet_3ec_2v_splitelements, + reftet_3ec_2v_newelstypes, + reftet_3ec_2v_newels +}; + + + + + + + + + + +/* ************************ 1 singular face ******************** */ + + +// HP_TET_1F_0E_0V +int reftet_1f_0e_0v_splitedges[][3] = +{ + { 2, 1, 5 }, + { 3, 1, 6 }, + { 4, 1, 7 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_1f_0e_0v_newelstypes[] = +{ + HP_PRISM_1FA_0E_0V, + HP_TET, + HP_NONE, +}; +int reftet_1f_0e_0v_newels[][8] = +{ + { 3, 2, 4, 6, 5, 7 }, + { 5, 7, 6, 1 } +}; +HPRef_Struct reftet_1f_0e_0v = +{ + HP_TET, + reftet_1f_0e_0v_splitedges, + 0, 0, + reftet_1f_0e_0v_newelstypes, + reftet_1f_0e_0v_newels +}; + + + + + +// HP_TET_1F_0E_1VA ... singular vertex in face +int reftet_1f_0e_1va_splitedges[][3] = +{ + { 2, 1, 5 }, + { 2, 3, 6 }, + { 2, 4, 7 }, + { 3, 1, 8 }, + { 4, 1, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_1f_0e_1va_newelstypes[] = +{ + HP_HEX_1F_0E_0V, + HP_TET_1F_0E_1VA, + HP_TET, + HP_NONE, +}; +int reftet_1f_0e_1va_newels[][8] = +{ + { 3, 6, 7, 4, 8, 5, 5, 9 }, + { 5, 2, 6, 7 }, + { 5, 9, 8, 1 }, +}; +HPRef_Struct reftet_1f_0e_1va = +{ + HP_TET, + reftet_1f_0e_1va_splitedges, + 0, 0, + reftet_1f_0e_1va_newelstypes, + reftet_1f_0e_1va_newels +}; + + + + + +// HP_TET_1F_0E_1VB ... singular vertex not in face +int reftet_1f_0e_1vb_splitedges[][3] = +{ + { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 1, 8 }, + { 3, 1, 9 }, + { 4, 1, 10 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftet_1f_0e_1vb_newelstypes[] = +{ + HP_PRISM_1FA_0E_0V, + HP_PRISM, + HP_TET_0E_1V, + HP_NONE, +}; +int reftet_1f_0e_1vb_newels[][8] = +{ + { 2, 4, 3, 8, 10, 9 }, + { 8, 10, 9, 5, 7, 6 }, + { 1, 5, 6, 7 }, +}; +HPRef_Struct reftet_1f_0e_1vb = +{ + HP_TET, + reftet_1f_0e_1vb_splitedges, + 0, 0, + reftet_1f_0e_1vb_newelstypes, + reftet_1f_0e_1vb_newels +}; + + + + + + + + +// HP_TET_1F_1EA_0V ... sing edge is 1..2 +int reftet_1f_1ea_0v_splitedges[][3] = +{ + { 1, 3, 5 }, + { 1, 4, 6 }, + { 2, 1, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 1, 10 }, + { 4, 1, 11 }, + { 0, 0, 0 } +}; + +int reftet_1f_1ea_0v_splitfaces[][4] = + { + { 2, 1, 3, 12 }, + { 2, 1, 4, 13 }, + { 0, 0, 0, 0 } + }; + + +HPREF_ELEMENT_TYPE reftet_1f_1ea_0v_newelstypes[] = +{ + HP_HEX_1F_0E_0V, + // HP_PRISM, + HP_PYRAMID_1FB_0E_1VA, + HP_TET_1E_1VA, + HP_PRISM_SINGEDGE, + HP_PRISM, + HP_NONE, +}; +int reftet_1f_1ea_0v_newels[][8] = +{ + { 3, 8, 9, 4, 10, 12, 13, 11 }, + // { 2, 9, 8, 7, 13, 12 }, + { 8, 9, 13, 12, 2 }, + { 2, 7, 13, 12 }, + { 7, 13, 12, 1, 6, 5 }, + { 6, 11, 13, 5, 10, 12 } +}; +HPRef_Struct reftet_1f_1ea_0v = +{ + HP_TET, + reftet_1f_1ea_0v_splitedges, + reftet_1f_1ea_0v_splitfaces, + 0, + reftet_1f_1ea_0v_newelstypes, + reftet_1f_1ea_0v_newels +}; + + + + + + + + +// HP_TET_1F_1EB_0V singular edge in face, edge is 2-3 +int reftet_1f_1eb_0v_splitedges[][3] = +{ + { 2, 1, 5 }, + { 2, 4, 6 }, + { 3, 1, 7 }, + { 3, 4, 8 }, + { 4, 1, 9 }, + { 0, 0, 0 } +}; + + +HPREF_ELEMENT_TYPE reftet_1f_1eb_0v_newelstypes[] = +{ + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FA_0E_0V, + HP_TET, + HP_NONE, +}; +int reftet_1f_1eb_0v_newels[][8] = +{ + // { 2, 5, 6, 3, 7, 8 }, + { 3, 8, 7, 2, 6, 5 }, + { 6, 4, 8, 5, 9, 7 }, + { 5, 9, 7, 1} +}; +HPRef_Struct reftet_1f_1eb_0v = +{ + HP_TET, + reftet_1f_1eb_0v_splitedges, + 0, 0, + reftet_1f_1eb_0v_newelstypes, + reftet_1f_1eb_0v_newels +}; + + + + + + + + + + +/* ************************ 2 singular faces ******************** */ + + +// HP_TET_2F_0E_0V +int reftet_2f_0e_0v_splitedges[][3] = +{ + { 1, 2, 5 }, + { 2, 1, 6 }, + { 3, 1, 7 }, + { 3, 2, 8 }, + { 4, 1, 9 }, + { 4, 2, 10 }, + { 0, 0, 0 } +}; + +int reftet_2f_0e_0v_splitfaces[][4] = + { + { 3, 1, 2, 11 }, + { 4, 1, 2, 12 }, + { 0, 0, 0, 0 } + }; + + +HPREF_ELEMENT_TYPE reftet_2f_0e_0v_newelstypes[] = +{ + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FA_0E_0V, + HP_PRISM_1FB_1EA_0V, + HP_PRISM_1FB_1EA_0V, + HP_TET, + HP_NONE, +}; +int reftet_2f_0e_0v_newels[][8] = +{ + { 2, 10, 8, 6, 12, 11 }, + { 1, 7, 9, 5, 11, 12 }, + // { 3, 11, 8, 4, 12, 10 }, + { 4, 10, 12, 3, 8, 11 }, + { 3, 7, 11, 4, 9, 12 }, + { 5, 6, 11, 12 } +}; +HPRef_Struct reftet_2f_0e_0v = +{ + HP_TET, + reftet_2f_0e_0v_splitedges, + reftet_2f_0e_0v_splitfaces, + 0, + reftet_2f_0e_0v_newelstypes, + reftet_2f_0e_0v_newels +}; + diff --git a/contrib/Netgen/libsrc/meshing/hpref_trig.hpp b/contrib/Netgen/libsrc/meshing/hpref_trig.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3676ad0f33f5fdd5c1f0d9d428ec02f723155aba --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hpref_trig.hpp @@ -0,0 +1,776 @@ + + +// HP_TRIG +int reftrig_splitedges[][3] = +{ + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_newelstypes[] = +{ + HP_TRIG, + HP_NONE, +}; +int reftrig_newels[][8] = +{ + { 1, 2, 3 }, +}; +HPRef_Struct reftrig = +{ + HP_TRIG, + reftrig_splitedges, + 0, 0, + reftrig_newelstypes, + reftrig_newels +}; + + + +// HP_TRIG_SINGCORNER +int reftrig_singcorner_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singcorner_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_QUAD, + HP_NONE, +}; +int reftrig_singcorner_newels[][8] = +{ + { 1, 4, 5 }, + { 2, 3, 5, 4 }, +}; +HPRef_Struct reftrig_singcorner = +{ + HP_TRIG, + reftrig_singcorner_splitedges, + 0, 0, + reftrig_singcorner_newelstypes, + reftrig_singcorner_newels +}; + + +/* +// HP_TRIG_SINGCORNER, trigs only +int reftrig_singcorner_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singcorner_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_TRIG, + HP_TRIG, + HP_NONE, +}; +int reftrig_singcorner_newels[][8] = +{ + { 1, 4, 5 }, + { 4, 2, 5 }, + { 5, 2, 3 }, +}; +HPRef_Struct reftrig_singcorner = +{ + HP_TRIG, + reftrig_singcorner_splitedges, + 0, 0, + reftrig_singcorner_newelstypes, + reftrig_singcorner_newels +}; +*/ + + + + + +// HP_TRIG_SINGCORNER12 +int reftrig_singcorner12_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 1, 6 }, + { 2, 3, 7 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singcorner12_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD, + HP_TRIG, + HP_NONE, +}; +int reftrig_singcorner12_newels[][8] = +{ + { 1, 4, 5 }, + { 2, 7, 6 }, + { 4, 6, 7, 5 }, + { 5, 7, 3 }, +}; +HPRef_Struct reftrig_singcorner12 = +{ + HP_TRIG, + reftrig_singcorner12_splitedges, + 0, 0, + reftrig_singcorner12_newelstypes, + reftrig_singcorner12_newels +}; + + + + +// HP_TRIG_SINGCORNER123_2D +int reftrig_singcorner123_2D_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 1, 6 }, + { 2, 3, 7 }, + { 3, 1, 8 }, + { 3, 2, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singcorner123_2D_newelstypes[] = +{ + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER, + HP_QUAD, + HP_QUAD, + HP_NONE, +}; +int reftrig_singcorner123_2D_newels[][8] = +{ + { 1, 4, 5 }, + { 2, 7, 6 }, + { 3, 8, 9 }, + { 4, 6, 8, 5 }, + { 6, 7, 9, 8 }, +}; +HPRef_Struct reftrig_singcorner123_2D = +{ + HP_TRIG, + reftrig_singcorner123_2D_splitedges, + 0, 0, + reftrig_singcorner123_2D_newelstypes, + reftrig_singcorner123_2D_newels +}; + + + + + + +// HP_TRIG_SINGCORNER123 +int reftrig_singcorner123_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 1, 6 }, + { 2, 3, 7 }, + { 3, 1, 8 }, + { 3, 2, 9 }, + { 0, 0, 0 } +}; + +int reftrig_singcorner123_splitfaces[][4] = +{ + { 1, 2, 3, 10 }, + { 2, 3, 1, 11 }, + { 3, 1, 2, 12 }, + { 0, 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singcorner123_newelstypes[] = +{ + HP_DUMMY_QUAD_SINGCORNER, + HP_DUMMY_QUAD_SINGCORNER, + HP_DUMMY_QUAD_SINGCORNER, + // HP_TRIG_SINGCORNER, + // HP_TRIG, + // HP_TRIG_SINGCORNER, + // HP_TRIG, + // HP_TRIG_SINGCORNER, + // HP_TRIG, + HP_QUAD, + HP_QUAD, + HP_QUAD, + HP_TRIG, + HP_NONE, +}; +int reftrig_singcorner123_newels[][8] = +{ + { 1, 4, 10, 5 }, + { 2, 7, 11, 6 }, + { 3, 8, 12, 9 }, + // { 1, 4, 5 }, + // { 5, 4, 10 }, + // { 2, 7, 6 }, + // { 6, 7, 11 }, + // { 3, 8, 9 }, + // { 8, 12, 9 }, + { 4, 6, 11, 10 }, + { 7, 9, 12, 11 }, + { 8, 5, 10, 12 }, + { 10, 11, 12 }, +}; +HPRef_Struct reftrig_singcorner123 = +{ + HP_TRIG, + reftrig_singcorner123_splitedges, + reftrig_singcorner123_splitfaces, + 0, + reftrig_singcorner123_newelstypes, + reftrig_singcorner123_newels +}; + +// HP_TRIG_SINGEDGE +int reftrig_singedge_splitedges[][3] = +{ + { 2, 3, 4 }, + { 1, 3, 5 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedge_newelstypes[] = +{ + HP_TRIG, + HP_QUAD_SINGEDGE, + HP_NONE, +}; +int reftrig_singedge_newels[][8] = +{ + { 4, 3, 5 }, + { 1, 2, 4, 5 }, +}; +HPRef_Struct reftrig_singedge = +{ + HP_TRIG, + reftrig_singedge_splitedges, + 0, 0, + reftrig_singedge_newelstypes, + reftrig_singedge_newels +}; + + + + + + +// HP_TRIG_SINGEDGECORNER1 +int reftrig_singedgecorner1_splitedges[][3] = +{ + { 1, 2, 6 }, + { 1, 3, 5 }, + { 2, 3, 4 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedgecorner1_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_NONE, +}; +int reftrig_singedgecorner1_newels[][8] = +{ + { 1, 6, 5 }, + { 6, 2, 4, 5 }, + { 5, 4, 3 }, +}; +HPRef_Struct reftrig_singedgecorner1 = +{ + HP_TRIG, + reftrig_singedgecorner1_splitedges, + 0, 0, + reftrig_singedgecorner1_newelstypes, + reftrig_singedgecorner1_newels +}; + + + + + + + + +// HP_TRIG_SINGEDGECORNER2 +int reftrig_singedgecorner2_splitedges[][3] = +{ + { 2, 1, 6 }, + { 1, 3, 5 }, + { 2, 3, 4 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedgecorner2_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_NONE, +}; +int reftrig_singedgecorner2_newels[][8] = +{ + { 6, 2, 4}, + { 1, 6, 4, 5 }, + { 5, 4, 3 }, +}; +HPRef_Struct reftrig_singedgecorner2 = +{ + HP_TRIG, + reftrig_singedgecorner2_splitedges, + 0, 0, + reftrig_singedgecorner2_newelstypes, + reftrig_singedgecorner2_newels +}; + + + + +// HP_TRIG_SINGEDGECORNER12 +int reftrig_singedgecorner12_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 1, 6 }, + { 2, 3, 7 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedgecorner12_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_NONE, +}; +int reftrig_singedgecorner12_newels[][8] = +{ + { 1, 4, 5 }, + { 6, 2, 7 }, + { 4, 6, 7, 5 }, + { 5, 7, 3 }, +}; +HPRef_Struct reftrig_singedgecorner12 = +{ + HP_TRIG, + reftrig_singedgecorner12_splitedges, + 0, 0, + reftrig_singedgecorner12_newelstypes, + reftrig_singedgecorner12_newels +}; + + + + + + + +// HP_TRIG_SINGEDGECORNER3 +int reftrig_singedgecorner3_splitedges[][3] = +{ + { 1, 3, 4 }, + { 3, 1, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedgecorner3_newelstypes[] = +{ + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int reftrig_singedgecorner3_newels[][8] = +{ + { 1, 2, 6, 4 }, + { 4, 6, 7, 5 }, + { 3, 5, 7 }, +}; +HPRef_Struct reftrig_singedgecorner3 = +{ + HP_TRIG, + reftrig_singedgecorner3_splitedges, + 0, 0, + reftrig_singedgecorner3_newelstypes, + reftrig_singedgecorner3_newels +}; + + + + +// HP_TRIG_SINGEDGECORNER13 +int reftrig_singedgecorner13_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 3, 6 }, + { 3, 1, 7 }, + { 3, 2, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedgecorner13_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int reftrig_singedgecorner13_newels[][8] = +{ + { 1, 4, 5 }, + { 4, 2, 6, 5 }, + { 5, 6, 8, 7 }, + { 3, 7, 8 }, +}; +HPRef_Struct reftrig_singedgecorner13 = +{ + HP_TRIG, + reftrig_singedgecorner13_splitedges, + 0, 0, + reftrig_singedgecorner13_newelstypes, + reftrig_singedgecorner13_newels +}; + + + + + +// HP_TRIG_SINGEDGECORNER23 +int reftrig_singedgecorner23_splitedges[][3] = +{ + { 1, 3, 4 }, + { 2, 1, 5 }, + { 2, 3, 6 }, + { 3, 1, 7 }, + { 3, 2, 8 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedgecorner23_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int reftrig_singedgecorner23_newels[][8] = +{ + { 5, 2, 6 }, + { 1, 5, 6, 4 }, + { 4, 6, 8, 7 }, + { 3, 7, 8 }, +}; +HPRef_Struct reftrig_singedgecorner23 = +{ + HP_TRIG, + reftrig_singedgecorner23_splitedges, + 0, 0, + reftrig_singedgecorner23_newelstypes, + reftrig_singedgecorner23_newels +}; + + + +// HP_TRIG_SINGEDGECORNER123 +int reftrig_singedgecorner123_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 1, 6 }, + { 2, 3, 7 }, + { 3, 1, 8 }, + { 3, 2, 9 }, + { 0, 0, 0 } +}; +HPREF_ELEMENT_TYPE reftrig_singedgecorner123_newelstypes[] = +{ + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD, + HP_TRIG_SINGCORNER, + HP_NONE, +}; +int reftrig_singedgecorner123_newels[][8] = +{ + { 1, 4, 5 }, + { 6, 2, 7 }, + { 4, 6, 7, 5 }, + { 5, 7, 9, 8 }, + { 3, 8, 9 }, +}; +HPRef_Struct reftrig_singedgecorner123 = +{ + HP_TRIG, + reftrig_singedgecorner123_splitedges, + 0, 0, + reftrig_singedgecorner123_newelstypes, + reftrig_singedgecorner123_newels +}; + +// HP_TRIG_SINGEDGES +int reftrig_singedges_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 0, 0, 0 } +}; +int reftrig_singedges_splitfaces[][4] = +{ + { 1, 2, 3, 8 }, + { 0, 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftrig_singedges_newelstypes[] = +{ + // HP_QUAD_2E, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG, + HP_NONE, +}; +int reftrig_singedges_newels[][8] = +{ + // { 1, 4, 8, 5 }, + { 1, 4, 8 }, + { 5, 1, 8 }, + { 4, 2, 6, 8 }, + { 3, 5, 8, 7 }, + { 6, 7, 8 }, +}; +HPRef_Struct reftrig_singedges = +{ + HP_TRIG, + reftrig_singedges_splitedges, + reftrig_singedges_splitfaces, + 0, + reftrig_singedges_newelstypes, + reftrig_singedges_newels +}; + + + + + + + + +// HP_TRIG_SINGEDGES2 +int reftrig_singedges2_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 1, 6 }, + { 2, 3, 7 }, + { 3, 2, 8 }, + { 0, 0, 0 } +}; +int reftrig_singedges2_splitfaces[][4] = +{ + { 1, 2, 3, 9 }, + { 0, 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftrig_singedges2_newelstypes[] = +{ + // HP_QUAD_2E, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG, + HP_NONE, +}; +int reftrig_singedges2_newels[][8] = +{ + // { 1, 4, 9, 5 }, + { 1, 4, 9 }, + { 5, 1, 9 }, + { 4, 6, 7, 9 }, + { 3, 5, 9, 8 }, + { 6, 2, 7 }, + { 7, 8, 9 }, +}; +HPRef_Struct reftrig_singedges2 = +{ + HP_TRIG, + reftrig_singedges2_splitedges, + reftrig_singedges2_splitfaces, + 0, + reftrig_singedges2_newelstypes, + reftrig_singedges2_newels +}; + + + + +// HP_TRIG_SINGEDGES3 +int reftrig_singedges3_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 3, 6 }, + { 3, 1, 7 }, + { 3, 2, 8 }, + { 0, 0, 0 } +}; +int reftrig_singedges3_splitfaces[][4] = +{ + { 1, 2, 3, 9 }, + { 0, 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftrig_singedges3_newelstypes[] = +{ + // HP_QUAD_2E, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG, + HP_NONE, +}; +int reftrig_singedges3_newels[][8] = +{ + // { 1, 4, 9, 5 }, + { 1, 4, 9 }, + { 5, 1, 9 }, + { 4, 2, 6, 9 }, + { 7, 5, 9, 8 }, + { 3, 7, 8 }, + { 6, 8, 9 }, +}; +HPRef_Struct reftrig_singedges3 = +{ + HP_TRIG, + reftrig_singedges3_splitedges, + reftrig_singedges3_splitfaces, + 0, + reftrig_singedges3_newelstypes, + reftrig_singedges3_newels +}; + + + + + + +// HP_TRIG_SINGEDGES23 +int reftrig_singedges23_splitedges[][3] = +{ + { 1, 2, 4 }, + { 1, 3, 5 }, + { 2, 1, 6 }, + { 2, 3, 7 }, + { 3, 1, 8 }, + { 3, 2, 9 }, + { 0, 0, 0 } +}; +int reftrig_singedges23_splitfaces[][4] = +{ + { 1, 2, 3, 10 }, + { 0, 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftrig_singedges23_newelstypes[] = +{ + // HP_QUAD_2E, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG, + HP_NONE, +}; +int reftrig_singedges23_newels[][8] = +{ + // { 1, 4, 10, 5 }, + { 1 , 4, 10 }, + { 5, 1, 10 }, + { 4, 6, 7, 10 }, + { 8, 5, 10, 9 }, + { 6, 2, 7 }, + { 3, 8, 9 }, + { 7, 9, 10 }, +}; +HPRef_Struct reftrig_singedges23 = +{ + HP_TRIG, + reftrig_singedges23_splitedges, + reftrig_singedges23_splitfaces, + 0, + reftrig_singedges23_newelstypes, + reftrig_singedges23_newels +}; + + +// HP_TRIG_3SINGEDGES +int reftrig_3singedges_splitedges[][3] = +{ + { 1, 2, 4 }, + { 2, 1, 5 }, + { 2, 3, 6 }, + { 3, 2, 7 }, + { 3, 1, 8 }, + { 1, 3, 9 }, + { 0, 0, 0 } +}; +int reftrig_3singedges_splitfaces[][4] = +{ + { 1, 2, 3, 10 }, + { 2, 3, 1, 11 }, + { 3, 1, 2, 12 }, + { 0, 0, 0, 0 } +}; + +HPREF_ELEMENT_TYPE reftrig_3singedges_newelstypes[] = +{ + HP_TRIG, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_QUAD_SINGEDGE, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_TRIG_SINGEDGECORNER1, + HP_TRIG_SINGEDGECORNER2, + HP_NONE, +}; +int reftrig_3singedges_newels[][8] = +{ + { 10, 11, 12 }, + { 4, 5, 11, 10 }, + { 6, 7, 12, 11 }, + { 8, 9, 10, 12 }, + { 1, 4, 10 }, + { 9, 1, 10 }, + { 2, 6, 11 }, + { 5, 2, 11 }, + { 3, 8, 12 }, + { 7, 3, 12 }, +}; +HPRef_Struct reftrig_3singedges = +{ + HP_TRIG, + reftrig_3singedges_splitedges, + reftrig_3singedges_splitfaces, + 0, + reftrig_3singedges_newelstypes, + reftrig_3singedges_newels +}; diff --git a/contrib/Netgen/libsrc/meshing/hprefinement.cpp b/contrib/Netgen/libsrc/meshing/hprefinement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ba4238baf29e61fc5fe0462d6bed0b37523cf9a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hprefinement.cpp @@ -0,0 +1,1955 @@ +#include <mystdlib.h> +#include "meshing.hpp" +#include "hprefinement.hpp" + +namespace netgen +{ + +#include "hpref_segm.hpp" +#include "hpref_trig.hpp" +#include "hpref_quad.hpp" +#include "hpref_tet.hpp" +#include "hpref_prism.hpp" +#include "hpref_hex.hpp" +#include "hpref_pyramid.hpp" +#include "classifyhpel.hpp" + + + void HPRefElement :: Reset(void) + { + np = 8; + for (int i = 0; i < 8; i++) + { + pnums[i] = -1; + param[i][0] = param[i][1] = param[i][2] = 0; + domin=-1; domout=-1; // he: + } + } + + HPRefElement :: HPRefElement () + { + Reset(); + } + + HPRefElement :: HPRefElement(Element & el) + { + //Reset(); + np = el.GetNV(); + for (int i=0; i<np ; i++) + pnums[i] = el[i]; + + index = el.GetIndex(); + const Point3d * points = + MeshTopology :: GetVertices (el.GetType()); + for(int i=0;i<np;i++) + for(int l=0;l<3;l++) + param[i][l] = points[i].X(l+1); + type = HP_NONE; + domin=-1; domout=-1; // he: needed for segments + } + + + HPRefElement :: HPRefElement(Element2d & el) + { + //Reset(); + np = el.GetNV(); + + for (int i=0; i<np ; i++) + pnums[i] = el[i]; + + index = el.GetIndex(); + const Point3d * points = + MeshTopology :: GetVertices (el.GetType()); + for(int i=0;i<np;i++) + for(int l=0;l<3;l++) + param[i][l] = points[i].X(l+1); + type = HP_NONE; + domin=-1; domout=-1; // he: needed for segments + } + + HPRefElement :: HPRefElement(Segment & el) + { + //Reset(); + np = 2; + for (int i=0; i<np ; i++) + pnums[i] = el[i]; + const Point3d * points = + MeshTopology :: GetVertices (SEGMENT); + for(int i=0;i<np;i++) + for(int l=0;l<3;l++) + param[i][l] = points[i].X(l+1); + + /* + for (int i=0; i<np; i++) + { + param[i][0] = i; + param[i][1] = -1; param[i][2] = -1; + } + */ + + singedge_left = el.singedge_left; + singedge_right = el.singedge_right; + type = HP_NONE; + // he: needed for orientation! + domin = el.domin; + domout = el.domout; + } + + HPRefElement :: HPRefElement(HPRefElement & el) + { + //Reset(); + np = el.np; + for (int i=0; i<np ; i++) + { + pnums[i] = el[i]; + for(int l=0; l<3; l++) param[i][l] = el.param[i][l]; + } + index = el.index; + levelx = el.levelx; + levely = el.levely; + levelz = el.levelz; + type = el.type; + coarse_elnr = el.coarse_elnr; + singedge_left = el.singedge_left; + singedge_right = el.singedge_right; + domin = el.domin; // he: needed for segments + domout=el.domout; + + } + + void HPRefElement :: SetType( HPREF_ELEMENT_TYPE t) + { + type = t; + switch(type) + { + case HP_SEGM: np=2; break; + case HP_TRIG: np=3; break; + case HP_QUAD: np=4; break; + case HP_TET: np=4; break; + case HP_PRISM: np=6; break; + case HP_PYRAMID: np=5; break; + case HP_HEX: np=8; break; + } + for(int k=0;k<8;k++) + { + pnums[k]=0; + for(int l=0;l<3;l++) param[k][l]=0.; + } + } + + + HPRef_Struct * Get_HPRef_Struct (HPREF_ELEMENT_TYPE type) + { + HPRef_Struct * hps = NULL; + + switch (type) + { + case HP_SEGM: + hps = &refsegm; break; + case HP_SEGM_SINGCORNERL: + hps = &refsegm_scl; break; + case HP_SEGM_SINGCORNERR: + hps = &refsegm_scr; break; + case HP_SEGM_SINGCORNERS: + hps = &refsegm_sc2; break; + + case HP_TRIG: + hps = &reftrig; break; + case HP_TRIG_SINGCORNER: + hps = &reftrig_singcorner; break; + case HP_TRIG_SINGCORNER12: + hps = &reftrig_singcorner12; break; + case HP_TRIG_SINGCORNER123: + hps = &reftrig_singcorner123; break; + case HP_TRIG_SINGCORNER123_2D: + hps = &reftrig_singcorner123_2D; break; + case HP_TRIG_SINGEDGE: + hps = &reftrig_singedge; break; + case HP_TRIG_SINGEDGECORNER1: + hps = &reftrig_singedgecorner1; break; + case HP_TRIG_SINGEDGECORNER2: + hps = &reftrig_singedgecorner2; break; + case HP_TRIG_SINGEDGECORNER12: + hps = &reftrig_singedgecorner12; break; + case HP_TRIG_SINGEDGECORNER3: + hps = &reftrig_singedgecorner3; break; + case HP_TRIG_SINGEDGECORNER13: + hps = &reftrig_singedgecorner13; break; + case HP_TRIG_SINGEDGECORNER23: + hps = &reftrig_singedgecorner23; break; + case HP_TRIG_SINGEDGECORNER123: + hps = &reftrig_singedgecorner123; break; + case HP_TRIG_SINGEDGES: + hps = &reftrig_singedges; break; + case HP_TRIG_SINGEDGES2: + hps = &reftrig_singedges2; break; + case HP_TRIG_SINGEDGES3: + hps = &reftrig_singedges3; break; + case HP_TRIG_SINGEDGES23: + hps = &reftrig_singedges23; break; + case HP_TRIG_3SINGEDGES: + hps = &reftrig_3singedges; break; + + + case HP_QUAD: + hps = &refquad; break; + case HP_DUMMY_QUAD_SINGCORNER: + hps = &refdummyquad_singcorner; break; + case HP_QUAD_SINGCORNER: + hps = &refquad_singcorner; break; + case HP_QUAD_SINGEDGE: + hps = &refquad_singedge; break; + + case HP_QUAD_0E_2VA: + hps = &refquad_0e_2va; break; + case HP_QUAD_0E_2VB: + hps = &refquad_0e_2vb; break; + + case HP_QUAD_0E_3V: + hps = &refquad_0e_3v; break; + case HP_QUAD_0E_4V: + hps = &refquad_0e_4v; break; + + case HP_QUAD_1E_1VA: + hps = &refquad_1e_1va; break; + case HP_QUAD_1E_1VB: + hps = &refquad_1e_1vb; break; + case HP_QUAD_1E_1VC: + hps = &refquad_1e_1vc; break; + case HP_QUAD_1E_1VD: + hps = &refquad_1e_1vd; break; + + case HP_QUAD_1E_2VA: + hps = &refquad_1e_2va; break; + case HP_QUAD_1E_2VB: + hps = &refquad_1e_2vb; break; + case HP_QUAD_1E_2VC: + hps = &refquad_1e_2vc; break; + case HP_QUAD_1E_2VD: + hps = &refquad_1e_2vd; break; + case HP_QUAD_1E_2VE: + hps = &refquad_1e_2ve; break; + case HP_QUAD_1E_2VF: + hps = &refquad_1e_2vf; break; + + case HP_QUAD_1E_3VA: + hps = &refquad_1e_3va; break; + case HP_QUAD_1E_3VB: + hps = &refquad_1e_3vb; break; + case HP_QUAD_1E_3VC: + hps = &refquad_1e_3vc; break; + case HP_QUAD_1E_3VD: + hps = &refquad_1e_3vd; break; + case HP_QUAD_1E_4V: + hps = &refquad_1e_4v; break; + + + case HP_QUAD_2E: + hps = &refquad_2e; break; + case HP_QUAD_2E_1VA: + hps = &refquad_2e_1va; break; + case HP_QUAD_2E_1VB: + hps = &refquad_2e_1vb; break; + case HP_QUAD_2E_1VC: + hps = &refquad_2e_1vc; break; + case HP_QUAD_2E_2VA: + hps = &refquad_2e_2va; break; + case HP_QUAD_2E_2VB: + hps = &refquad_2e_2vb; break; + case HP_QUAD_2E_2VC: + hps = &refquad_2e_2vc; break; + case HP_QUAD_2E_3V: + hps = &refquad_2e_3v; break; + + case HP_QUAD_2EB_0V: + hps = &refquad_2eb_0v; break; + + case HP_QUAD_2EB_1VA: + hps = &refquad_2eb_1va; break; + case HP_QUAD_2EB_1VB: + hps = &refquad_2eb_1vb; break; + + + case HP_QUAD_2EB_2VA: + hps = &refquad_2eb_2va; break; + case HP_QUAD_2EB_2VB: + hps = &refquad_2eb_2vb; break; + case HP_QUAD_2EB_2VC: + hps = &refquad_2eb_2vc; break; + case HP_QUAD_2EB_2VD: + hps = &refquad_2eb_2vd; break; + + case HP_QUAD_2EB_3VA: + hps = &refquad_2eb_3va; break; + case HP_QUAD_2EB_3VB: + hps = &refquad_2eb_3vb; break; + + case HP_QUAD_2EB_4V: + hps = &refquad_2eb_4v; break; + + case HP_QUAD_3E: + hps = &refquad_3e; break; + case HP_QUAD_3E_3VA: + hps = &refquad_3e_3va; break; + case HP_QUAD_3E_3VB: + hps = &refquad_3e_3vb; break; + case HP_QUAD_3E_4V: + hps = &refquad_3e_4v; break; + + + case HP_QUAD_4E: + hps = &refquad_4e; break; + + + case HP_TET: + hps = &reftet; break; + case HP_TET_0E_1V: + hps = &reftet_0e_1v; break; + case HP_TET_0E_2V: + hps = &reftet_0e_2v; break; + case HP_TET_0E_3V: + hps = &reftet_0e_3v; break; + case HP_TET_0E_4V: + hps = &reftet_0e_4v; break; + + case HP_TET_1E_0V: + hps = &reftet_1e_0v; break; + case HP_TET_1E_1VA: + hps = &reftet_1e_1va; break; + case HP_TET_1E_1VB: + hps = &reftet_1e_1vb; break; + + case HP_TET_1E_2VA: + hps = &reftet_1e_2va; break; + case HP_TET_1E_2VB: + hps = &reftet_1e_2vb; break; + case HP_TET_1E_2VC: + hps = &reftet_1e_2vc; break; + case HP_TET_1E_2VD: + hps = &reftet_1e_2vd; break; + + case HP_TET_1E_3VA: + hps = &reftet_1e_3va; break; + case HP_TET_1E_3VB: + hps = &reftet_1e_3vb; break; + case HP_TET_1E_4V: + hps = &reftet_1e_4v; break; + + case HP_TET_2EA_0V: + hps = &reftet_2ea_0v; break; + case HP_TET_2EA_1VB: + hps = &reftet_2ea_1vb; break; + case HP_TET_2EA_1VC: + hps = &reftet_2ea_1vc; break; + case HP_TET_2EA_1VA: + hps = &reftet_2ea_1va; break; + case HP_TET_2EA_2VA: + hps = &reftet_2ea_2va; break; + case HP_TET_2EA_2VB: + hps = &reftet_2ea_2vb; break; + case HP_TET_2EA_2VC: + hps = &reftet_2ea_2vc; break; + case HP_TET_2EA_3V: + hps = &reftet_2ea_3v; break; + + case HP_TET_2EB_0V: + hps = &reftet_2eb_0v; break; + case HP_TET_2EB_1V: + hps = &reftet_2eb_1v; break; + case HP_TET_2EB_2VA: + hps = &reftet_2eb_2va; break; + case HP_TET_2EB_2VB: + hps = &reftet_2eb_2vb; break; + case HP_TET_2EB_2VC: + hps = &reftet_2eb_2vc; break; + case HP_TET_2EB_3V: + hps = &reftet_2eb_3v; break; + case HP_TET_2EB_4V: + hps = &reftet_2eb_4v; break; + + + case HP_TET_3EA_0V: + hps = &reftet_3ea_0v; break; + case HP_TET_3EA_1V: + hps = &reftet_3ea_1v; break; + case HP_TET_3EA_2V: + hps = &reftet_3ea_2v; break; + case HP_TET_3EA_3V: + hps = &reftet_3ea_3v; break; + + case HP_TET_3EB_0V: + hps = &reftet_3eb_0v; break; + case HP_TET_3EB_1V: + hps = &reftet_3eb_1v; break; + case HP_TET_3EB_2V: + hps = &reftet_3eb_2v; break; + case HP_TET_3EC_0V: + hps = &reftet_3ec_0v; break; + case HP_TET_3EC_1V: + hps = &reftet_3ec_1v; break; + case HP_TET_3EC_2V: + hps = &reftet_3ec_2v; break; + + + case HP_TET_1F_0E_0V: + hps = &reftet_1f_0e_0v; break; + case HP_TET_1F_0E_1VA: + hps = &reftet_1f_0e_1va; break; + case HP_TET_1F_0E_1VB: + hps = &reftet_1f_0e_1vb; break; + case HP_TET_1F_1EA_0V: + hps = &reftet_1f_1ea_0v; break; + case HP_TET_1F_1EB_0V: + hps = &reftet_1f_1eb_0v; break; + case HP_TET_2F_0E_0V: + hps = &reftet_2f_0e_0v; break; + + + case HP_PRISM: + hps = &refprism; break; + case HP_PRISM_SINGEDGE: + hps = &refprism_singedge; break; + // case HP_PRISM_SINGEDGE_H1: + // hps = &refprism_singedge_h1; break; + // case HP_PRISM_SINGEDGE_H12: + // hps = &refprism_singedge_h12; break; + case HP_PRISM_SINGEDGE_V12: + hps = &refprism_singedge_v12; break; + + + case HP_PRISM_1FA_0E_0V: + hps = &refprism_1fa_0e_0v; break; + case HP_PRISM_2FA_0E_0V: + hps = &refprism_2fa_0e_0v; break; + case HP_PRISM_1FB_0E_0V: + hps = &refprism_1fb_0e_0v; break; + case HP_PRISM_1FB_1EA_0V: + hps = &refprism_1fb_1ea_0v; break; + + case HP_PRISM_1FA_1E_0V: + hps = &refprism_1fa_1e_0v; break; + case HP_PRISM_2FA_1E_0V: + hps = &refprism_2fa_1e_0v; break; + case HP_PRISM_1FA_1FB_0E_0V: + hps = &refprism_1fa_1fb_0e_0v; break; + case HP_PRISM_2FA_1FB_0E_0V: + hps = &refprism_2fa_1fb_0e_0v; break; + case HP_PRISM_1FA_1FB_1EA_0V: + hps = &refprism_1fa_1fb_1ea_0v; break; + case HP_PRISM_1FA_1FB_1EB_0V: + hps = &refprism_1fa_1fb_1eb_0v; break; + case HP_PRISM_2FA_1FB_1EA_0V: + hps = &refprism_2fa_1fb_1ea_0v; break; + case HP_PRISM_1FB_1EC_0V: + hps = &refprism_1fb_1ec_0v; break; + case HP_PRISM_1FA_1FB_1EC_0V: + hps = &refprism_1fa_1fb_1ec_0v; break; + case HP_PRISM_2FA_1FB_1EC_0V: + hps = &refprism_2fa_1fb_1ec_0v; break; + case HP_PRISM_1FB_2EA_0V: + hps = &refprism_1fb_2ea_0v; break; + case HP_PRISM_1FA_1FB_2EA_0V: + hps = &refprism_1fa_1fb_2ea_0v; break; + case HP_PRISM_2FA_1FB_2EA_0V: + hps = &refprism_2fa_1fb_2ea_0v; break; + case HP_PRISM_1FB_2EB_0V: + hps = &refprism_1fb_2eb_0v; break; + case HP_PRISM_1FA_1FB_2EB_0V: + hps = &refprism_1fa_1fb_2eb_0v; break; + case HP_PRISM_1FA_1FB_2EC_0V: + hps = &refprism_1fa_1fb_2ec_0v; break; + case HP_PRISM_2FA_1FB_2EB_0V: + hps = &refprism_2fa_1fb_2eb_0v; break; + case HP_PRISM_1FB_3E_0V: + hps = &refprism_1fb_3e_0v; break; + case HP_PRISM_1FA_1FB_3E_0V: + hps = &refprism_1fa_1fb_3e_0v; break; + case HP_PRISM_2FA_1FB_3E_0V: + hps = &refprism_2fa_1fb_3e_0v; break; + case HP_PRISM_2FB_0E_0V: + hps = &refprism_2fb_0e_0v; break; + case HP_PRISM_1FA_2FB_0E_0V: + hps = &refprism_1fa_2fb_0e_0v; break; + case HP_PRISM_2FA_2FB_0E_0V: + hps = &refprism_2fa_2fb_0e_0v; break; + case HP_PRISM_2FB_1EC_0V: + hps = &refprism_2fb_1ec_0v; break; + case HP_PRISM_1FA_2FB_1EC_0V: + hps = &refprism_1fa_2fb_1ec_0v; break; + case HP_PRISM_2FA_2FB_1EC_0V: + hps = &refprism_2fa_2fb_1ec_0v; break; + case HP_PRISM_1FA_2FB_1EB_0V: + hps = &refprism_1fa_2fb_1eb_0v; break; + case HP_PRISM_2FB_3E_0V: + hps = &refprism_2fb_3e_0v; break; + case HP_PRISM_1FA_2FB_3E_0V: + hps = &refprism_1fa_2fb_3e_0v; break; + case HP_PRISM_2FA_2FB_3E_0V: + hps = &refprism_2fa_2fb_3e_0v; break; + case HP_PRISM_1FA_2E_0V: + hps = &refprism_1fa_2e_0v; break; + case HP_PRISM_2FA_2E_0V: + hps = &refprism_2fa_2e_0v; break; + case HP_PRISM_3E_0V: + hps = &refprism_3e_0v; break; + case HP_PRISM_1FA_3E_0V: + hps = &refprism_1fa_3e_0v; break; + case HP_PRISM_2FA_3E_0V: + hps = &refprism_2fa_3e_0v; break; + case HP_PRISM_3FB_0V: + hps = &refprism_3fb_0v; break; + case HP_PRISM_1FA_3FB_0V: + hps = &refprism_1fa_3fb_0v; break; + case HP_PRISM_2FA_3FB_0V: + hps = &refprism_2fa_3fb_0v; break; + // case HP_PRISM_3E_4EH: + // hps = &refprism_3e_4eh; break; + + + /*case HP_PRISM_1FB_1EB_0V: + hps = &refprism_1fb_1eb_0v; break; + case HP_PRISM_2F_0E_0V: + hps = &refprism_2f_0e_0v; break; + */ + + + case HP_PYRAMID: + hps = &refpyramid; break; + case HP_PYRAMID_0E_1V: + hps = &refpyramid_0e_1v; break; + case HP_PYRAMID_EDGES: + hps = &refpyramid_edges; break; + case HP_PYRAMID_1FB_0E_1VA: + hps = &refpyramid_1fb_0e_1va; break; + + + case HP_HEX: + hps = &refhex; break; + case HP_HEX_0E_1V: + hps = &refhex_0e_1v; break; + case HP_HEX_1E_1V: + hps = &refhex_1e_1v; break; + case HP_HEX_1E_0V: + hps = &refhex_1e_0v; break; + case HP_HEX_3E_0V: + hps = &refhex_3e_0v; break; + + case HP_HEX_1F_0E_0V: + hps = &refhex_1f_0e_0v; break; + case HP_HEX_1FA_1FB_0E_0V: + hps = &refhex_1fa_1fb_0e_0v; break; + } + + /* + if (type != HP_TET_1E_4V && type != HP_TET_1E_2VD) + { + if (hps->geom == HP_TET) + hps = &reftet; + if (hps->geom == HP_TRIG) + hps = &reftrig; + } + */ + + if (!hps) + { + cout << "Attention hps : hp-refinement not implemented for case " << type << endl; + PrintSysError ("hp-refinement not implemented for case ", type); + } + + return hps; + } + + bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoiclt_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint, int & levels, int & act_ref); + + bool ClassifyHPElements (Mesh & mesh, ARRAY<HPRefElement> & elements, int & act_ref, int & levels); + + + void InitHPElements(Mesh & mesh, ARRAY<HPRefElement> & elements) + { + for(ElementIndex i=0;i<mesh.GetNE();i++) + { + HPRefElement hpel(mesh[i]); + hpel.coarse_elnr=i; + + switch (mesh[i].GetType()) + { + case PRISM: + hpel.type = HP_PRISM; + break; + case HEX: + hpel.type = HP_HEX; + break; + case TET: + hpel.type = HP_TET; + break; + case PYRAMID: + hpel.type = HP_PYRAMID; + break; + } + elements.Append(hpel); + } + + for(SurfaceElementIndex i=0;i<mesh.GetNSE();i++) + { + HPRefElement hpel(mesh.SurfaceElement(i)); + hpel.coarse_elnr = i; + switch(mesh.SurfaceElement(i).GetType()) + { + case TRIG: + hpel.type = HP_TRIG; + break; + case QUAD: + hpel.type = HP_QUAD; + break; + } + elements.Append(hpel); + } + + for(int i=1;i<=mesh.GetNSeg();i++) + { + Segment & seg = mesh.LineSegment(i); + HPRefElement hpel(seg); + hpel.coarse_elnr = i-1; + hpel.type = HP_SEGM; + hpel.index = seg.edgenr + 10000*seg.si; + if(seg.edgenr >= 10000) + { + throw NgException("assumption that seg.edgenr < 10000 is wrong"); + } + elements.Append(hpel); + + } + } + + + + /* ******************************* DoRefinement *************************************** */ + void DoRefinement (Mesh & mesh, ARRAY<HPRefElement> & elements, + Refinement * ref, double fac1) + { + elements.SetAllocSize (5 * elements.Size()); + INDEX_2_HASHTABLE<int> newpts(elements.Size()+1); + INDEX_3_HASHTABLE<int> newfacepts(elements.Size()+1); + + // prepare new points + + fac1 = max(0.001,min(0.33,fac1)); + cout << " in HP-REFINEMENT with fac1 " << fac1 << endl; + *testout << " in HP-REFINEMENT with fac1 " << fac1 << endl; + + + int oldelsize = elements.Size(); + + for (int i = 0; i < oldelsize; i++) + { + HPRefElement & el = elements[i]; + HPRef_Struct * hprs = Get_HPRef_Struct (el.type); + + if (!hprs) + { + cout << "Refinementstruct not defined for element " << el.type << endl; + continue; + } + + int j = 0; + while (hprs->splitedges[j][0]) + { + INDEX_2 i2(el.pnums[hprs->splitedges[j][0]-1], + el.pnums[hprs->splitedges[j][1]-1]); + if (!newpts.Used (i2)) + { + Point<3> np; + for( int l=0;l<3;l++) + np(l) = (1-fac1)*mesh.Point(i2.I1())(l) + + fac1 * mesh.Point(i2.I2())(l); + + int npi = mesh.AddPoint (np); + newpts.Set (i2, npi); + } + j++; + } + + j = 0; + if (hprs->splitfaces) + while (hprs->splitfaces[j][0]) + { + INDEX_3 i3(el.pnums[hprs->splitfaces[j][0]-1], + el.pnums[hprs->splitfaces[j][1]-1], + el.pnums[hprs->splitfaces[j][2]-1]); + + if (i3.I2() > i3.I3()) Swap (i3.I2(), i3.I3()); + + if (!newfacepts.Used (i3)) + { + Point<3> np; + for( int l=0;l<3;l++) + np(l) = (1-2*fac1)*mesh.Point(i3.I1())(l) + + fac1*mesh.Point(i3.I2())(l) + fac1*mesh.Point(i3.I3())(l); + int npi = mesh.AddPoint (np); + newfacepts.Set (i3, npi); + } + j++; + } + } + + for (int i = 0; i < oldelsize; i++) + { + HPRefElement el = elements[i]; + HPRef_Struct * hprs = Get_HPRef_Struct (el.type); + int newlevel = el.levelx + 1; + + int oldnp(0); + switch (hprs->geom) + { + case HP_SEGM: oldnp = 2; break; + case HP_TRIG: oldnp = 3; break; + case HP_QUAD: oldnp = 4; break; + case HP_TET: oldnp = 4; break; + case HP_PYRAMID: oldnp = 5; break; + case HP_PRISM: oldnp = 6; break; + case HP_HEX: oldnp = 8; break; + } + + + if (el.type == HP_SEGM || + el.type == HP_TRIG || + el.type == HP_QUAD || + el.type == HP_TET || + el.type == HP_PRISM || + el.type == HP_HEX || + el.type == HP_PYRAMID) + newlevel = el.levelx; + + if (!hprs) continue; + + int newpnums[64]; + double newparam[64][3]; + + int j; + for (j = 0; j < oldnp; j++) + { + newpnums[j] = el.pnums[j]; + for (int l = 0; l < 3; l++) + newparam[j][l] = el.param[j][l]; + } + + // split edges, incl. transferring curvature + j = 0; + while (hprs->splitedges[j][0]) + { + INDEX_2 i2(el.pnums[hprs->splitedges[j][0]-1], + el.pnums[hprs->splitedges[j][1]-1]); + + int npi = newpts.Get(i2); + newpnums[hprs->splitedges[j][2]-1] = npi; + + for (int l = 0; l < 3; l++) + newparam[hprs->splitedges[j][2]-1][l] = + (1-fac1) * el.param[hprs->splitedges[j][0]-1][l] + + fac1 * el.param[hprs->splitedges[j][1]-1][l]; + + j++; + } + + // split faces + j = 0; + if (hprs->splitfaces) + while (hprs->splitfaces[j][0]) + { + INDEX_3 i3(el.pnums[hprs->splitfaces[j][0]-1], + el.pnums[hprs->splitfaces[j][1]-1], + el.pnums[hprs->splitfaces[j][2]-1]); + if (i3.I2() > i3.I3()) + Swap (i3.I2(), i3.I3()); + int npi = newfacepts.Get(i3); + newpnums[hprs->splitfaces[j][3]-1] = npi; + + + for (int l = 0; l < 3; l++) + newparam[hprs->splitfaces[j][3]-1][l] = + (1-2*fac1) * el.param[hprs->splitfaces[j][0]-1][l] + + fac1 * el.param[hprs->splitfaces[j][1]-1][l] + + fac1 * el.param[hprs->splitfaces[j][2]-1][l]; + j++; + } + // split elements + j = 0; + if (hprs->splitelements) + while (hprs->splitelements[j][0]) + { + //int pi1 = el.pnums[hprs->splitelements[j][0]-1]; + Point<3> np; + for( int l=0;l<3;l++) + np(l) = (1-3*fac1)* mesh.Point(el.pnums[hprs->splitelements[j][0]-1])(l) + + fac1* mesh.Point(el.pnums[hprs->splitelements[j][1]-1])(l) + + fac1* mesh.Point(el.pnums[hprs->splitelements[j][2]-1])(l) + + fac1* mesh.Point(el.pnums[hprs->splitelements[j][3]-1])(l); + + int npi = mesh.AddPoint (np); + + newpnums[hprs->splitelements[j][4]-1] = npi; + + + for (int l = 0; l < 3; l++) + newparam[hprs->splitelements[j][4]-1][l] = + (1-3*fac1) * el.param[hprs->splitelements[j][0]-1][l] + + fac1 * el.param[hprs->splitelements[j][1]-1][l] + + fac1 * el.param[hprs->splitelements[j][2]-1][l] + + fac1 * el.param[hprs->splitelements[j][3]-1][l]; + + j++; + } + + j = 0; + + /* + *testout << " newpnums = "; + for (int hi = 0; hi < 64; hi++) + *testout << newpnums[hi] << " "; + *testout << endl; + */ + + while (hprs->neweltypes[j]) + { + HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]); + HPRefElement newel(el); + + newel.type = hprs->neweltypes[j]; + + // newel.index = elements[i].index; + // newel.coarse_elnr = elements[i].coarse_elnr; + newel.levelx = newel.levely = newel.levelz = newlevel; + switch(hprsnew->geom) + { + case HP_SEGM: newel.np=2; break; + case HP_QUAD: newel.np=4; break; + case HP_TRIG: newel.np=3; break; + case HP_HEX: newel.np=8; break; + case HP_PRISM: newel.np=6; break; + case HP_TET: newel.np=4; break; + case HP_PYRAMID: newel.np=5; break; + } + + for (int k = 0; k < newel.np; k++) + newel.pnums[k] = newpnums[hprs->newels[j][k]-1]; + + /* + *testout << " newel pnums " ; + for (int k = 0; k < newel.np; k++) + *testout << newel.pnums[k] << "\t"; + *testout << endl; + */ + + for (int k = 0; k < newel.np; k++) + { + for (int l = 0; l < 3; l++) + { + newel.param[k][l] = newparam[hprs->newels[j][k]-1][l]; + // *testout << newel.param[k][l] << " \t "; + } + // *testout << endl; + } + + if (j == 0) + elements[i] = newel; // overwrite old element + else + elements.Append (newel); + j++; + } + } + } + + + + + + + /* ************************** DoRefineDummies ******************************** */ + + void DoRefineDummies (Mesh & mesh, ARRAY<HPRefElement> & elements, + Refinement * ref) + { + int oldelsize = elements.Size(); + + for (int i = 0; i < oldelsize; i++) + { + HPRefElement el = elements[i]; + + HPRef_Struct * hprs = Get_HPRef_Struct (el.type); + if (!hprs) continue; + + if (el.type != HP_DUMMY_QUAD_SINGCORNER && + el.type != HP_PYRAMID_EDGES && + el.type != HP_PYRAMID_0E_1V && + el.type != HP_HEX_0E_1V && + el.type != HP_HEX_1E_1V && + el.type != HP_HEX_1E_0V && + el.type != HP_HEX_3E_0V + ) continue; + + int newlevel = el.levelx; + + int newpnums[8]; + int j; + for (j = 0; j < 8; j++) + newpnums[j] = el.pnums[j]; + + double newparam[8][3]; + for (j = 0; j < 8; j++) + for (int k = 0; k < 3; k++) + newparam[j][k] = el.param[j][k]; + + j = 0; + while (hprs->neweltypes[j]) + { + HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]); + HPRefElement newel(el); + switch(hprsnew->geom) + { + case HP_SEGM: newel.np=2; break; + case HP_QUAD: newel.np=4; break; + case HP_TRIG: newel.np=3; break; + case HP_HEX: newel.np=8; break; + case HP_PRISM: newel.np=6; break; + case HP_TET: newel.np=4; break; + case HP_PYRAMID: newel.np=5; break; + } + newel.type = hprs->neweltypes[j]; + for (int k = 0; k < 8; k++) + newel.pnums[k] = newpnums[hprs->newels[j][k]-1]; + newel.index = el.index; + newel.coarse_elnr = el.coarse_elnr; + newel.levelx = newel.levely = newel.levelz = newlevel; + + for (int k = 0; k < 8; k++) + for (int l = 0; l < 3; l++) + newel.param[k][l] = newparam[hprs->newels[j][k]-1][l]; + + if (j == 0) + elements[i] = newel; + else + elements.Append (newel); + j++; + } + } + } + + + + + + + + void SubdivideDegeneratedHexes (Mesh & mesh, ARRAY<HPRefElement> & elements, double fac1) + { + int oldne = elements.Size(); + for (int i = 0; i < oldne; i++) + if (Get_HPRef_Struct (elements[i].type)->geom == HP_HEX) + { + bool common = 0; + for (int j = 0; j < 8; j++) + for (int k = 0; k < j; k++) + if (elements[i].pnums[j] == elements[i].pnums[k]) + common = 1; + if (common) + { + + + cout << " Degenerate Hex found " << endl; + *testout << " Degenerate Hex found " << endl; + HPRefElement el = elements[i]; + HPRefElement newel = el; + + Point<3> center(0,0,0); + double newparam[3] = { 0, 0, 0 }; + + for (int j = 0; j < 8; j++) + { + + + center += 0.125 * Vec<3>(mesh[el.pnums[j]]); + // 0.125 originates form 8 points not from fac1; + + for (int l = 0; l < 3; l++) + newparam[l] += 0.125 * el.param[j][l]; + + } + + int npi = mesh.AddPoint (center); + + const ELEMENT_FACE * faces = MeshTopology::GetFaces (HEX); + + for (int j = 0; j < 6; j++) + { + ARRAY<int> pts; + for (int k = 0; k < 4; k++) + { + bool same = 0; + for (int l = 0; l < pts.Size(); l++) + if (el.pnums[pts[l]] == el.pnums[faces[j][k]-1]) + same = 1; + if (!same) + pts.Append (faces[j][k]-1); + + } + + + if (pts.Size() == 3) // TrigFace -> TET + { + + for (int k = 0; k < 3; k++) + { + newel.pnums[k] = el.pnums[pts[2-k]]; + for (int l = 0; l < 3; l++) + newel.param[k][l] = el.param[pts[2-k]][l]; + } + newel.pnums[3] = npi; + for (int l = 0; l < 3; l++) + newel.param[3][l] = newparam[l]; + + newel.type = HP_TET; + newel.np = 4; + } + else + { + for (int k = 0; k < 4; k++) + { + newel.pnums[k] = el.pnums[pts[3-k]]; + for (int l = 0; l < 3; l++) + newel.param[k][l] = el.param[pts[3-k]][l]; + } + + newel.pnums[4] = npi; + for (int l = 0; l < 3; l++) + newel.param[4][l] = newparam[l]; + + newel.type = HP_PYRAMID; + newel.np = 5; + } + + if (j == 0) + elements[i] = newel; + else + elements.Append (newel); + + + } + + /* const ELEMENT_EDGE * edges = MeshTopology::GetEdges (HEX); + + for(int k=0;k<12;k++) + { + int e[2]; + for(int l=0;l<2;l++) e[l] = edges[k][l]-1; + if(el.PNum(e[0]+1)!=el.PNum(e[1]+1)) + { + newel.SetType(HP_SEGM); + for(int l=0;l<2;l++) + { + newel.pnums[0] = el.PNum(e[l]+1); + newel.pnums[1] = npi; + for(int j=0;j<3;j++) + { + // newel.param[0][j] = el.param[e[l]][j]; + // newel.param[1][j] = newparam[j]; + } + + elements.Append(newel); + } + newel.SetType(HP_TRIG); + newel.pnums[0] = el.PNum(e[0]+1); + newel.pnums[1] = el.PNum(e[1]+1); + newel.pnums[2] = npi; + + *testout << "DEGHEX TRIG :: newpnums " << newel.pnums[0] << "\t" << newel.pnums[1] << "\t" << newel.pnums[2] << endl; + cout << "DEGHEX TRIG :: newpnums " << newel.pnums[0] << "\t" << newel.pnums[1] << "\t" << newel.pnums[2] << endl; + for(int j=0;j<3;j++) + { + // newel.param[0][j] = el.param[e[0]][j]; + // newel.param[1][j] = el.param[e[1]][j]; + // newel.param[2][j] = newparam[j]; + } + + elements.Append(newel); + } + + }*/ + } + } + } + + + void CalcStatistics (ARRAY<HPRefElement> & elements) + { + return; +#ifdef ABC + int i, p; + int nsegm = 0, ntrig = 0, nquad = 0; + int nhex = 0, nprism = 0, npyramid = 0, ntet = 0; + int maxlevel = 0; + + for (i = 1; i <= elements.Size(); i++) + { + const HPRefElement & el = elements.Get(i); + maxlevel = max2 (el.level, maxlevel); + switch (Get_HPRef_Struct (el.type)->geom) + { + case HP_SEGM: + + { + nsegm++; + break; + } + case HP_TRIG: + { + ntrig ++; + break; + } + case HP_QUAD: + { + nquad++; + break; + } + case HP_TET: + { + ntet++; + break; + } + + case HP_PRISM: + { + nprism++; + break; + } + + case HP_PYRAMID: + { + npyramid++; + break; + } + + case HP_HEX: + { + nhex++; + break; + } + + default: + { + cerr << "statistics error, unknown element type" << endl; + } + } + } + + cout << "level = " << maxlevel << endl; + cout << "nsegm = " << nsegm << endl; + cout << "ntrig = " << ntrig << ", nquad = " << nquad << endl; + cout << "ntet = " << ntet << ", npyr = " << npyramid + << ", nprism = " << nprism << ", nhex = " << nhex << endl; + + return; + + double memcost = 0, cpucost = 0; + for (p = 1; p <= 20; p++) + { + memcost = (ntet + nprism + nhex) * pow (static_cast<double>(p), 6.0); + cpucost = (ntet + nprism + nhex) * pow (static_cast<double>(p), 9.0); + cout << "costs for p = " << p << ": mem = " << memcost << ", cpu = " << cpucost << endl; + } + + double memcosttet = 0; + double memcostprism = 0; + double memcosthex = 0; + double memcostsctet = 0; + double memcostscprism = 0; + double memcostschex = 0; + double cpucosttet = 0; + double cpucostprism = 0; + double cpucosthex = 0; + + for (i = 1; i <= elements.Size(); i++) + { + const HPRefElement & el = elements.Get(i); + switch (el.type) + { + case HP_TET: + case HP_TET_0E_1V: + case HP_TET_1E_0V: + case HP_TET_1E_1VA: + { + int p1 = maxlevel - el.level + 1; + (*testout) << "p1 = " << p1 << ", P1^6 = " << pow (static_cast<double>(p1), 6.0) + << " (p1-3)^6 = " << pow ( static_cast<double>(max2(p1-3, 0)), 6.0) + << " p1^3 = " << pow ( static_cast<double>(p1), 3.0) + << " (p1-3)^3 = " << pow ( static_cast<double>(p1-3), 3.0) + << " [p1^3-(p1-3)^3]^2 = " << sqr (pow (static_cast<double>(p1),3.0) - pow ( static_cast<double>(p1-3), 3.0)) + << endl; + + p1 /= 2 +1; + memcosttet += pow (static_cast<double>(p1), 6.0); + memcostsctet += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-3, 1)), 6.0); + cpucosttet += pow (static_cast<double>(p1), 9.0); + break; + } + case HP_PRISM: + case HP_PRISM_SINGEDGE: + { + int p1 = maxlevel - el.level + 1; + p1 /= 2 +1; + memcostprism += pow (static_cast<double>(p1), 6.0); + memcostscprism += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-3, 1)), 6.0); + cpucostprism += pow (static_cast<double>(p1), 9.0); + break; + } + case HP_HEX: + { + int p1 = maxlevel - el.level + 1; + int p2 = maxlevel; + p1 /= 2 +1; + p2 /= 2 +1; + memcosthex += pow (static_cast<double>(p1), 4.0) * pow (static_cast<double>(p2), 2.0); + memcostschex += pow (static_cast<double>(p1), 6.0) - pow ( static_cast<double>(max2(p1-2, 0)), 6.0); + cpucosthex += pow (static_cast<double>(p1), 6.0) * pow (static_cast<double>(p2), 3.0); + break; + } + default: + ; + } + } + cout << "TET: hp-memcost = " << memcosttet + << ", scmemcost = " << memcostsctet + << ", cpucost = " << cpucosttet + << endl; + cout << "PRI: hp-memcost = " << memcostprism + << ", scmemcost = " << memcostscprism + << ", cpucost = " << cpucostprism << endl; + cout << "HEX: hp-memcost = " << memcosthex + << ", scmemcost = " << memcostschex + << ", cpucost = " << cpucosthex << endl; +#endif + } + + + + void ReorderPoints (Mesh & mesh, ARRAY<HPRefElement> & hpelements) + { + ARRAY<int, 1> map (mesh.GetNP()); + + for (int i = 1; i <= mesh.GetNP(); i++) + map[i] = i; + + int nwrong(0), nright(0); + for (int k = 0; k < 5; k++) + { + nwrong = nright = 0; + for (int i = 0; i < hpelements.Size(); i++) + { + const HPRefElement & hpel = hpelements[i]; + + if (Get_HPRef_Struct (hpel.type) -> geom == HP_PRISM) + { + int minbot = 0, mintop = 0; + for (int j = 0; j < 3; j++) + { + if (map[hpel.pnums[j]] < map[hpel.pnums[minbot]]) minbot = j; + if (map[hpel.pnums[j+3]] < map[hpel.pnums[mintop+3]]) mintop = j; + } + if (minbot != mintop) + nwrong++; + else + nright++; + + if (minbot != mintop) + { + if (map[hpel.pnums[minbot]] < map[hpel.pnums[mintop+3]]) + swap (map[hpel.pnums[3+minbot]], map[hpel.pnums[3+mintop]]); + else + swap (map[hpel.pnums[minbot]], map[hpel.pnums[mintop]]); + } + } + } + // cout << nwrong << " wrong prisms, " << nright << " right prisms" << endl; + } + + cout << nwrong << " wrong prisms, " << nright << " right prisms" << endl; + + + ARRAY<MeshPoint, 1> hpts(mesh.GetNP()); + + for (int i = 1; i <= mesh.GetNP(); i++) + hpts[map[i]] = mesh.Point(i); + + for (int i = 1; i <= mesh.GetNP(); i++) + mesh.Point(i) = hpts[i]; + + for (int i = 0; i < hpelements.Size(); i++) + { + HPRefElement & hpel = hpelements[i]; + for (int j = 0; j < hpel.np; j++) + hpel.pnums[j] = map[hpel.pnums[j]]; + } + } + + + + /* ***************************** HPRefinement ********************************** */ + + void HPRefinement (Mesh & mesh, Refinement * ref, int levels, double fac1, bool setorders, bool reflevels) + { + PrintMessage (1, "HP Refinement called, levels = ", levels); + + + NgLock mem_lock (mem_mutex,1); + + mesh.coarsemesh = new Mesh; + *mesh.coarsemesh = mesh; + +#ifdef CURVEDELEMS_NEW + const_cast<CurvedElements&> (mesh.coarsemesh->GetCurvedElements() ). + BuildCurvedElements (ref, mesh.GetCurvedElements().GetOrder()); +#endif + + + delete mesh.hpelements; + mesh.hpelements = new ARRAY<HPRefElement>; + + ARRAY<HPRefElement> & hpelements = *mesh.hpelements; + + InitHPElements(mesh,hpelements); + + ARRAY<int> nplevel; + nplevel.Append (mesh.GetNP()); + + int act_ref=1; + bool sing = ClassifyHPElements(mesh,hpelements, act_ref, levels); + + sing = true; // iterate at least once + while(sing) + { + cout << " Start new hp-refinement: step " << act_ref << endl; + + DoRefinement (mesh, hpelements, ref, fac1); + DoRefineDummies (mesh, hpelements, ref); + + nplevel.Append (mesh.GetNP()); + CalcStatistics (hpelements); + + SubdivideDegeneratedHexes (mesh, hpelements,fac1); + + ReorderPoints (mesh, hpelements); + + mesh.ClearSegments(); + mesh.ClearSurfaceElements(); + mesh.ClearVolumeElements(); + + for (int i = 0; i < hpelements.Size(); i++) + { + HPRefElement & hpel = hpelements[i]; + if (Get_HPRef_Struct (hpel.type)) + switch (Get_HPRef_Struct (hpel.type) -> geom) + { + case HP_SEGM: + { + Segment seg; + seg.p1 = hpel.pnums[0]; + seg.p2 = hpel.pnums[1]; + // NOTE: only for less than 10000 elements (HACK) !!! + seg.edgenr = hpel.index % 10000; + seg.si = hpel.index / 10000; + + /* + seg.epgeominfo[0].dist = hpel.param[0][0]; // he: war hpel.param[0][0] + seg.epgeominfo[1].dist = hpel.param[1][0]; // he: war hpel.param[1][0] + */ + + const Segment & coarseseg = mesh.coarsemesh->LineSegment(hpel.coarse_elnr+1); + double d1 = coarseseg.epgeominfo[0].dist; + double d2 = coarseseg.epgeominfo[1].dist; + + // seg.epgeominfo[0].dist = hpel.param[0][0]; // he: war hpel.param[0][0] + // seg.epgeominfo[1].dist = hpel.param[1][0]; // he: war hpel.param[1][0] + + seg.epgeominfo[0].dist = d1 + hpel.param[0][0] * (d2-d1); // JS, June 08 + seg.epgeominfo[1].dist = d1 + hpel.param[1][0] * (d2-d1); + + + seg.epgeominfo[0].edgenr = seg.edgenr; + seg.epgeominfo[1].edgenr = seg.edgenr; + seg.domin = hpel.domin; seg.domout=hpel.domout; // he: needed for segments! + seg.hp_elnr = i; + seg.singedge_left = hpel.singedge_left; + seg.singedge_right = hpel.singedge_right; + mesh.AddSegment (seg); + break; + } + + case HP_TRIG: + case HP_QUAD: + { + Element2d el(hpel.np); + for(int j=0;j<hpel.np;j++) + el.PNum(j+1) = hpel.pnums[j]; + el.hp_elnr = i; + el.SetIndex(hpel.index); + if(setorders) + el.SetOrder(act_ref+1,act_ref+1,0); + mesh.AddSurfaceElement(el); + break; + } + case HP_HEX: + case HP_TET: + case HP_PRISM: + case HP_PYRAMID: + { + Element el(hpel.np); + for(int j=0;j<hpel.np;j++) + el.PNum(j+1) = hpel.pnums[j]; + el.SetIndex(hpel.index); + el.hp_elnr = i; + if(setorders) + el.SetOrder(act_ref+1,act_ref+1,act_ref+1); + mesh.AddVolumeElement(el); + break; + } + + default: + PrintSysError ("hpref, backconversion failed for element ", + int(Get_HPRef_Struct (hpel.type) -> geom)); + } + } + cout << " Start with Update Topology " << endl; + mesh.UpdateTopology(); + cout << " Mesh Update Topology done " << endl; + + act_ref++; + + sing = ClassifyHPElements(mesh,hpelements, act_ref, levels); + } + + cout << " HP-Refinement done with " << --act_ref << " refinement steps." << endl; + + if(act_ref>=1) + { + for(ElementIndex i=0;i<mesh.GetNE(); i++) + { + Element el = mesh[i] ; + HPRefElement & hpel = hpelements[mesh[i].hp_elnr]; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (mesh[i].GetType()); + double dist[3] = {0,0,0}; + int ord_dir[3] = {0,0,0}; + int edge_dir[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + int ned = 4; + + switch (mesh[i].GetType()) + { + case TET: + /* cout << " TET " ; + for(int k=0;k<4;k++) cout << el[k] << "\t" ; + cout << endl; */ + break; + case PRISM: + /* cout << " PRISM " ; + for(int k=0;k<6;k++) cout << el[k] << "\t" ; + cout << endl; */ + for(int l=6;l<9;l++) edge_dir[l] = 2; + ord_dir[2] = 2; + ned = 9; + break; + case HEX: + /* cout << " HEX " ; + for(int k=0;k<8;k++) cout << el[k] << "\t" ; + cout << endl; */ + for(int l=8;l<12; l++) edge_dir[l] = 2; + edge_dir[2] = edge_dir[3] = edge_dir[6] = edge_dir[7] = 1; + ord_dir[1] = 1; + ord_dir[2] = 2; + ned = 12; + break; + case PYRAMID: + /* cout << " PYRAMID " ; + for(int k=0;k<5;k++) cout << el[k] << "\t" ; + cout << endl; */ + for(int l=4;l<8;l++) edge_dir[l] = 2; + edge_dir[2] = edge_dir[3] = 1; + ord_dir[1] = 1; + ord_dir[2] = 2; + ned = 8; + break; + } + + for (int j=0;j<ned;j++) + { + + Vec<3> v(hpel.param[edges[j][0]-1][0]-hpel.param[edges[j][1]-1][0], + hpel.param[edges[j][0]-1][1]-hpel.param[edges[j][1]-1][1], + hpel.param[edges[j][0]-1][2]-hpel.param[edges[j][1]-1][2]); + dist[edge_dir[j]] = max(v.Length(),dist[edge_dir[j]]); + } + + int refi[3]; + for(int j=0;j<3;j++) + refi[j] = int(max(double(floor(log(dist[ord_dir[j]]/sqrt(2.))/log(fac1))),0.)); + + // cout << " ref " << refi[0] << "\t" << refi[1] << "\t" << refi[2] << endl; + // cout << " order " << act_ref +1 - refi[0] << "\t" << act_ref +1 - refi[1] << "\t" << act_ref +1 - refi[2] << endl; + + if(setorders) + mesh[i].SetOrder(act_ref+1-refi[0],act_ref+1-refi[1],act_ref+1-refi[2]); + } + for(SurfaceElementIndex i=0;i<mesh.GetNSE(); i++) + { + Element2d el = mesh[i] ; + HPRefElement & hpel = hpelements[mesh[i].hp_elnr]; + const ELEMENT_EDGE * edges = MeshTopology::GetEdges (mesh[i].GetType()); + double dist[3] = {0,0,0}; + int ord_dir[3] = {0,0,0}; + int edge_dir[4] = {0,0,0,0} ; + int ned = 3; + + if(mesh[i].GetType() == QUAD) + { + /* cout << " QUAD " ; + for(int k=0;k<4;k++) cout << el[k] << "\t" ; + cout << endl; */ + + edge_dir[2] = edge_dir[3] = 1; + ord_dir[1] = 1; + ned = 4; + } + /* else + { + cout << " TRIG " ; + for(int k=0;k<3;k++) cout << el[k] << "\t" ; + cout << endl; + } */ + + for (int j=0;j<ned;j++) + { + Vec<3> v(hpel.param[edges[j][0]-1][0]-hpel.param[edges[j][1]-1][0], + hpel.param[edges[j][0]-1][1]-hpel.param[edges[j][1]-1][1], + hpel.param[edges[j][0]-1][2]-hpel.param[edges[j][1]-1][2]); + dist[edge_dir[j]] = max(v.Length(),dist[edge_dir[j]]); + } + + int refi[3]; + for(int j=0;j<3;j++) + refi[j] = int(max(double(floor(log(dist[ord_dir[j]]/sqrt(2.))/log(fac1))),0.)); + + if(setorders) + mesh[i].SetOrder(act_ref+1-refi[0],act_ref+1-refi[1],act_ref+1-refi[2]); + + // cout << " ref " << refi[0] << "\t" << refi[1] << endl; + // cout << " order " << act_ref +1 - refi[0] << "\t" << act_ref +1 - refi[1] << endl; + } + } + } + +bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, + BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, + INDEX_2_HASHTABLE<int> & surf_edges, ARRAY<int, PointIndex::BASE> & facepoint, int & levels, int & act_ref) +{ + bool sing=0; + if (mesh.GetDimension() == 3) + { + /* + // check, if point has as least 3 different surfs: + + ARRAY<INDEX_3, PointIndex::BASE> surfonpoint(mesh.GetNP()); + surfonpoint = INDEX_3(0,0,0); + + for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) + { + const Element2d & el = mesh[sei]; + int ind = el.GetIndex(); + for (int j = 0; j < el.GetNP(); j++) + { + INDEX_3 & i3 = surfonpoint[el[j]]; + if (ind != i3.I1() && ind != i3.I2() && ind != i3.I3()) + { + i3.I1() = i3.I2(); + i3.I2() = i3.I3(); + i3.I3() = ind; + } + } + } + for (int i = 1; i <= mesh.GetNP(); i++) + if (surfonpoint.Get(i).I1()) + cornerpoint.Set(i); + */ + cornerpoint.Clear(); + + for (int i = 1; i <= mesh.GetNP(); i++) + { + if (mesh.Point(i).Singularity() * levels >= act_ref) + { + cornerpoint.Set(i); + sing = 1; + } + } + cout << endl; + + for (int i = 1; i <= mesh.GetNSeg(); i++) + if (mesh.LineSegment(i).singedge_left * levels >= act_ref) + { + INDEX_2 i2 (mesh.LineSegment(i).p1, + mesh.LineSegment(i).p2); + + /* + // before + edges.Set (i2, 1); + i2.Sort(); + INDEX_2 i2s(i2.I2(), i2.I1()); + edges.Set (i2s, 1); + */ + + edges.Set (i2, 1); + INDEX_2 i2s(i2.I2(), i2.I1()); + edges.Set (i2s, 1); + + + edgepoint.Set (i2.I1()); + edgepoint.Set (i2.I2()); + sing = 1; + } + + // if 2 adjacent edges of an element are singular, the + // commen point must be a singular point + for (int i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + const ELEMENT_EDGE * eledges = MeshTopology::GetEdges (el.GetType()); + int nedges = MeshTopology::GetNEdges (el.GetType()); + for (int j = 0; j < nedges; j++) + for (int k = 0; k < nedges; k++) + if (j != k) + { + INDEX_2 ej(el.PNum(eledges[j][0]), el.PNum(eledges[j][1])); + ej.Sort(); + INDEX_2 ek(el.PNum(eledges[k][0]), el.PNum(eledges[k][1])); + ek.Sort(); + if (edges.Used(ej) && edges.Used(ek)) + { + if (ej.I1() == ek.I1()) cornerpoint.Set (ek.I1()); + if (ej.I1() == ek.I2()) cornerpoint.Set (ek.I2()); + if (ej.I2() == ek.I1()) cornerpoint.Set (ek.I1()); + if (ej.I2() == ek.I2()) cornerpoint.Set (ek.I2()); + } + } + } + + edgepoint.Or (cornerpoint); + (*testout) << "cornerpoint = " << endl << cornerpoint << endl; + (*testout) << "edgepoint = " << endl << edgepoint << endl; + + facepoint = 0; + for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) + { + const Element2d & el = mesh[sei]; + const FaceDescriptor & fd = mesh.GetFaceDescriptor (el.GetIndex()); + + int domnr = 0; + if (fd.domin_singular * levels < act_ref && fd.domout_singular * levels < act_ref) + { domnr=0; continue;} + + if (fd.domin_singular * levels >= act_ref) + { + domnr = fd.DomainIn(); + sing = 1; + } + if (fd.domout_singular * levels >= act_ref) + { + domnr = fd.DomainOut(); + sing = 1; + } + if (fd.domin_singular * levels >= act_ref + && fd.domout_singular * levels >= act_ref) + { + domnr = -1; + sing = 1; + } + + INDEX_3 i3; + if (el.GetNP() == 3) + i3 = INDEX_3::Sort (el[0], el[1], el[2]); + else + { + INDEX_4 i4 (el[0], el[1], el[2], el[3]); + i4.Sort(); + i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3()); + } + faces.Set (i3, domnr); + + for (int j = 0; j < el.GetNP(); j++) + { + face_edges.Set (INDEX_2::Sort (el[j], el[(j+1)%el.GetNP()]), domnr); + + surf_edges.Set (INDEX_2::Sort (el[j], el[(j+1)%el.GetNP()]), fd.SurfNr()+1); + + facepoint[el[j]] = domnr; + } + + } + (*testout) << "singular faces = " << faces << endl; + (*testout) << "singular faces_edges = " << face_edges << endl; + } + else + { + // 2D case + + // check, if point has as least 3 different surfs: + ARRAY<INDEX_3, PointIndex::BASE> surfonpoint(mesh.GetNP()); + + for (int i = 1; i <= mesh.GetNP(); i++) + surfonpoint.Elem(i) = INDEX_3(0,0,0); + + for (int i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + int ind = seg.edgenr; + + + if (seg.singedge_left * levels >= act_ref) + { + INDEX_2 i2 (mesh.LineSegment(i).p1, + mesh.LineSegment(i).p2); + edges.Set(i2,1); + edgepoint.Set(i2.I1()); + edgepoint.Set(i2.I2()); + *testout << " singleft " << endl; + *testout << " mesh.LineSegment(i).domout " << mesh.LineSegment(i).domout << endl; + *testout << " mesh.LineSegment(i).domin " << mesh.LineSegment(i).domin << endl; + edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domin, i2.I1()), 1); + edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domin, i2.I2()), 1); + sing = 1; + + } + + if (seg.singedge_right * levels >= act_ref) + { + INDEX_2 i2 (mesh.LineSegment(i).p2, + mesh.LineSegment(i).p1); + edges.Set (i2, 1); + edgepoint.Set(i2.I1()); + edgepoint.Set(i2.I2()); + + *testout << " singright " << endl; + *testout << " mesh.LineSegment(i).domout " << mesh.LineSegment(i).domout << endl; + *testout << " mesh.LineSegment(i).domin " << mesh.LineSegment(i).domin << endl; + + edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domout, i2.I1()), 1); + edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domout, i2.I2()), 1); + sing = 1; + } + + // (*testout) << "seg = " << ind << ", " << seg.p1 << "-" << seg.p2 << endl; + + + if (seg.singedge_left * levels >= act_ref + || seg.singedge_right* levels >= act_ref) + { + for (int j = 0; j < 2; j++) + { + int pi = (j == 0) ? seg.p1 : seg.p2; + INDEX_3 & i3 = surfonpoint.Elem(pi); + if (ind != i3.I1() && + ind != i3.I2()) + { + i3.I1() = i3.I2(); + i3.I2() = ind; + } + } + } + } + + + for (int i = 1; i <= mesh.GetNP(); i++) + { + // mark points for refinement that are in corners between two anisotropic edges + if (surfonpoint.Get(i).I1()) + { + cornerpoint.Set(i); + edgepoint.Set(i); + } + + // mark points for refinement that are explicity specified in input file + if (mesh.Point(i).Singularity()*levels >= act_ref) + { + cornerpoint.Set(i); + edgepoint.Set(i); + sing = 1; + } + } + + edgepoint.Or (cornerpoint); + + (*testout) << "2d sing edges: " << endl << edges << endl; + (*testout) << "2d cornerpoints: " << endl << cornerpoint << endl + << "2d edgepoints: " << endl << edgepoint << endl; + + facepoint = 0; + } + + if (!sing) + { + cout << "PrepareElements no more to do for actual refinement " << act_ref << endl; + return(sing); + } + return(sing); +} + + + + bool ClassifyHPElements (Mesh & mesh, ARRAY<HPRefElement> & elements, int & act_ref, int & levels) + { + + INDEX_2_HASHTABLE<int> edges(mesh.GetNSeg()+1); + BitArray edgepoint(mesh.GetNP()); + INDEX_2_HASHTABLE<int> edgepoint_dom(mesh.GetNSeg()+1); + + edgepoint.Clear(); + BitArray cornerpoint(mesh.GetNP()); + cornerpoint.Clear(); + + // value = nr > 0 ... refine elements in domain nr + // value = -1 ..... refine elements in any domain + INDEX_3_HASHTABLE<int> faces(mesh.GetNSE()+1); + INDEX_2_HASHTABLE<int> face_edges(mesh.GetNSE()+1); + INDEX_2_HASHTABLE<int> surf_edges(mesh.GetNSE()+1); + ARRAY<int, PointIndex::BASE> facepoint(mesh.GetNP()); + + bool sing = CheckSingularities(mesh, edges, edgepoint_dom, + cornerpoint, edgepoint, faces, face_edges, + surf_edges, facepoint, levels, act_ref); + + if(sing==0) return(sing); + + int cnt_undef = 0, cnt_nonimplement = 0; + ARRAY<int> misses(10000); + misses = 0; + + (*testout) << "edgepoint_dom = " << endl << edgepoint_dom << endl; + + for( int i = 0; i<elements.Size(); i++) + { + // *testout << "classify element " << i << endl; + + HPRefElement & hpel = elements[i]; + HPRef_Struct * hprs = Get_HPRef_Struct (hpel.type); + HPRefElement old_el = elements[i]; + int dd=3; + + + if(act_ref !=1 && (hpel.type == HP_HEX || hpel.type == HP_PRISM || hpel.type == HP_TET + || hpel.type == HP_PYRAMID || hpel.type == HP_QUAD || hpel.type == HP_TRIG || hpel.type == HP_SEGM)) + continue; + + sing = 1; + switch (hprs->geom) + { + case HP_TET: + { + hpel.type = ClassifyTet(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces,face_edges, surf_edges, facepoint); + break; + } + case HP_PRISM: + { + hpel.type = ClassifyPrism(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, + face_edges, surf_edges, facepoint); + + + break; + } + case HP_HEX: + { + hpel.type = hpel.type = ClassifyHex(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, + face_edges, surf_edges, facepoint); + break; + } + case HP_TRIG: + { + int dim = mesh.GetDimension(); + const FaceDescriptor & fd = mesh.GetFaceDescriptor (hpel.GetIndex()); + + hpel.type = ClassifyTrig(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, + faces, face_edges, surf_edges, facepoint, dim, fd); + + dd = 2; + break; + } + case HP_QUAD: + { + int dim = mesh.GetDimension(); + const FaceDescriptor & fd = mesh.GetFaceDescriptor (hpel.GetIndex()); + hpel.type = ClassifyQuad(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, + faces, face_edges, surf_edges, facepoint, dim, fd); + + dd = 2; + break; + } + case HP_SEGM: + { + hpel.type = ClassifySegm(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, + faces, face_edges, surf_edges, facepoint); + dd = 1; + break; + } + case HP_PYRAMID: + { + hpel.type = ClassifyPyramid(hpel, edges, edgepoint_dom, cornerpoint, edgepoint, faces, + face_edges, surf_edges, facepoint); + + cout << " ** Pyramid classified " << hpel.type << endl; + break; + } + default: + { + cout << "illegal element type for hp-prepare elements " << hpel.type << endl; + throw NgException ("hprefinement.cpp: don't know how to set parameters"); + } + } + + if(hpel.type == HP_NONE) + cnt_undef++; + + //else + //cout << "elem " << i << " classified type " << hpel.type << endl; + + + + if (!Get_HPRef_Struct (hpel.type)) + { + (*testout) << "hp-element-type " << hpel.type << " not implemented " << endl; + (*testout) << " elType " << hprs->geom << endl; + (cout) << " elType " << hprs->geom << endl; + cnt_nonimplement++; + misses[hpel.type]++; + } + + + for(int j=0; j<hpel.np; j++) + { + for( int k=0; k<hpel.np; k++) + if(hpel[j] == old_el.pnums[k]) + { + for(int l=0;l<dd;l++) + hpel.param[j][l] = old_el.param[k][l]; + break; + } + } + + } + + + cout << "undefined elements update classification: " << cnt_undef << endl; + cout << "non-implemented in update classification: " << cnt_nonimplement << endl; + + for (int i = 0; i < misses.Size(); i++) + if (misses[i]) + cout << " in update classification missing case " << i << " occured " << misses[i] << " times" << endl; + + return(sing); + } +} + diff --git a/contrib/Netgen/libsrc/meshing/hprefinement.hpp b/contrib/Netgen/libsrc/meshing/hprefinement.hpp new file mode 100644 index 0000000000000000000000000000000000000000..05e4d7278085f4d9ac6dfddb21360823885b9a25 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/hprefinement.hpp @@ -0,0 +1,319 @@ +#ifndef FILE_HPREFINEMENT +#define FILE_HPREFINEMENT + +/**************************************************************************/ +/* File: hprefinement.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 27. Oct. 2000 */ +/**************************************************************************/ + +/* + HP Refinement +*/ + + + + +enum HPREF_ELEMENT_TYPE { + HP_NONE=0, + + HP_SEGM = 1, + HP_SEGM_SINGCORNERL, + HP_SEGM_SINGCORNERR, + HP_SEGM_SINGCORNERS, + + HP_TRIG = 10, + HP_TRIG_SINGCORNER, + HP_TRIG_SINGCORNER12, + HP_TRIG_SINGCORNER123, + HP_TRIG_SINGCORNER123_2D, // not rotational symmetric + HP_TRIG_SINGEDGE = 20, + HP_TRIG_SINGEDGECORNER1, // E = 100, V = 100 + HP_TRIG_SINGEDGECORNER2, // E = 100, V = 010 + HP_TRIG_SINGEDGECORNER12, // E = 100, V = 110 + HP_TRIG_SINGEDGECORNER3, + HP_TRIG_SINGEDGECORNER13, + HP_TRIG_SINGEDGECORNER23, + HP_TRIG_SINGEDGECORNER123, + HP_TRIG_SINGEDGES = 30, + HP_TRIG_SINGEDGES2, + HP_TRIG_SINGEDGES3, + HP_TRIG_SINGEDGES23, + HP_TRIG_3SINGEDGES = 40, + + HP_QUAD = 50, + HP_QUAD_SINGCORNER, + HP_DUMMY_QUAD_SINGCORNER, + HP_QUAD_SINGEDGE, + HP_QUAD_0E_2VA, // V = 1100 + HP_QUAD_0E_2VB, // V = 1010 + HP_QUAD_0E_3V, + HP_QUAD_0E_4V, + + // one edge: marked edge is always edge from vertex 1 to vertex 2 (E = 1000) + HP_QUAD_1E_1VA, // vertex on beginning of edge: V = 1000 + HP_QUAD_1E_1VB, // vertex on end of edge: V = 0100 + HP_QUAD_1E_1VC, // V = 0010 + HP_QUAD_1E_1VD, // V = 0001 + + HP_QUAD_1E_2VA, // V = 1100 + HP_QUAD_1E_2VB, // V = 1010 + HP_QUAD_1E_2VC, // V = 1001 + HP_QUAD_1E_2VD, // V = 0110 + HP_QUAD_1E_2VE, // V = 0101 + HP_QUAD_1E_2VF, // V = 0011 + + HP_QUAD_1E_3VA, // V = 1110 + HP_QUAD_1E_3VB, // V = 1101 + HP_QUAD_1E_3VC, // V = 1011 + HP_QUAD_1E_3VD, // V = 0111 + + HP_QUAD_1E_4V, // V = 1111 + + + HP_QUAD_2E, // E = 1001, V = 1000 + HP_QUAD_2E_1VA, // E = 1001, V = 1100 + HP_QUAD_2E_1VB, // E = 1001, V = 1010 + HP_QUAD_2E_1VC, // E = 1001, V = 1001 + HP_QUAD_2E_2VA, // E = 1001, V = 1110 + HP_QUAD_2E_2VB, // E = 1001, V = 1101 + HP_QUAD_2E_2VC, // E = 1001, V = 1011 + HP_QUAD_2E_3V, // E = 1001, V = 1111 + + HP_QUAD_2EB_0V, // E = 1010, V = 0000 + HP_QUAD_2EB_1VA, // E = 1010, V = 1000 + HP_QUAD_2EB_1VB, // E = 1010, V = 0100 + HP_QUAD_2EB_2VA, // E = 1010, V = 1100 + HP_QUAD_2EB_2VB, // E = 1010, V = 1010 + HP_QUAD_2EB_2VC, // E = 1010, V = 1001 + HP_QUAD_2EB_2VD, // E = 1010, V = 0101 + HP_QUAD_2EB_3VA, // E = 1010, V = 1110 + HP_QUAD_2EB_3VB, // E = 1010, V = 1101 + + HP_QUAD_2EB_4V, + + + HP_QUAD_3E, // E = 1101, V = 1100 + HP_QUAD_3E_3VA, // E = 1101, V = 1110 + HP_QUAD_3E_3VB, // E = 1101, V = 1101 + HP_QUAD_3E_4V, // E = 1101, V = 1111 + + HP_QUAD_4E, + + + HP_TET = 100, // no singular vertex/edge + HP_TET_0E_1V, // V1 + HP_TET_0E_2V, // V1,2 + HP_TET_0E_3V, // V1,2,3 + HP_TET_0E_4V, // V1,2,3,4 + HP_TET_1E_0V = 200, // E1-2 + HP_TET_1E_1VA, // V1 + HP_TET_1E_1VB, // V3 + HP_TET_1E_2VA, // V1,2 + HP_TET_1E_2VB, // V1,3 + HP_TET_1E_2VC, // V1,4 + HP_TET_1E_2VD, // V3,4 + HP_TET_1E_3VA, // V1,2,3 + HP_TET_1E_3VB, // V1,3,4 + HP_TET_1E_4V, // V1,2,3,4 + + + // 2 connected edges, additonally marked Vs + HP_TET_2EA_0V = 220, // E1-2, E1-3 + HP_TET_2EA_1VA, // V2 + HP_TET_2EA_1VB, // V3 + HP_TET_2EA_1VC, // V4 + HP_TET_2EA_2VA, // V2,3 + HP_TET_2EA_2VB, // V2,4 + HP_TET_2EA_2VC, // V3,4 + HP_TET_2EA_3V, // V2,3,4 + + // 2 opposite edges + HP_TET_2EB_0V = 230, // E1-2, E3-4 + HP_TET_2EB_1V, // V1 + HP_TET_2EB_2VA, // V1,2 + HP_TET_2EB_2VB, // V1,3 + HP_TET_2EB_2VC, // V1,4 + HP_TET_2EB_3V, // V1,2,3 + HP_TET_2EB_4V, // V1,2,3,4 + + HP_TET_3EA_0V = 400, // E1-2, E1-3, E1-4, 3 edges connected + HP_TET_3EA_1V, // V2 + HP_TET_3EA_2V, // V2,3 + HP_TET_3EA_3V, // V2,3,4 + + HP_TET_3EB_0V = 420, // E1-2, E1-4, E2-3 3 edges chain + HP_TET_3EB_1V, // + HP_TET_3EB_2V, // + HP_TET_3EC_0V = 430, // 3 edges chain, alter + HP_TET_3EC_1V, // 3 edges chain, alter + HP_TET_3EC_2V, // 3 edges chain, alter + + + HP_TET_1F_0E_0V = 500, // 1 singular face + HP_TET_1F_0E_1VA, // 1 sing vertex in face (V2) + HP_TET_1F_0E_1VB, // 1 sing vertex not in face (V1) + HP_TET_1F_1EA_0V, // 1 sing edge not in face + HP_TET_1F_1EB_0V, // 1 sing edge in face + HP_TET_2F_0E_0V = 600, // 2 singular faces + + HP_PRISM = 1000, + HP_PRISM_SINGEDGE, + HP_PRISM_SINGEDGE_V12, + HP_PRISM_SINGEDGE_H1, + HP_PRISM_SINGEDGE_H12, + + HP_PRISM_1FA_0E_0V, // 1 singular trig face + HP_PRISM_2FA_0E_0V, // 2 singular trig faces + HP_PRISM_1FB_0E_0V, // 1 singular quad face 1-2-4-5 + + HP_PRISM_1FB_1EA_0V, // 1 singular quad face, edge is 1-2 + HP_PRISM_1FA_1E_0V, + HP_PRISM_2FA_1E_0V, + HP_PRISM_1FA_1FB_0E_0V, + HP_PRISM_2FA_1FB_0E_0V, + HP_PRISM_1FA_1FB_1EA_0V, + HP_PRISM_1FA_1FB_1EB_0V, + HP_PRISM_2FA_1FB_1EA_0V, + HP_PRISM_1FB_1EC_0V, + HP_PRISM_1FA_1FB_1EC_0V, + HP_PRISM_2FA_1FB_1EC_0V, + HP_PRISM_1FB_2EA_0V, + HP_PRISM_1FA_1FB_2EA_0V, + HP_PRISM_2FA_1FB_2EA_0V, + HP_PRISM_1FB_2EB_0V, + HP_PRISM_1FA_1FB_2EB_0V, + HP_PRISM_1FA_1FB_2EC_0V, + HP_PRISM_2FA_1FB_2EB_0V, + HP_PRISM_1FB_3E_0V, + HP_PRISM_1FA_1FB_3E_0V, + HP_PRISM_2FA_1FB_3E_0V, + HP_PRISM_2FB_0E_0V, + HP_PRISM_1FA_2FB_0E_0V, + HP_PRISM_2FA_2FB_0E_0V, + HP_PRISM_2FB_1EC_0V, + HP_PRISM_1FA_2FB_1EC_0V, + HP_PRISM_1FA_2FB_1EB_0V, + HP_PRISM_2FA_2FB_1EC_0V, + HP_PRISM_2FB_3E_0V, + HP_PRISM_1FA_2FB_3E_0V, + HP_PRISM_2FA_2FB_3E_0V, + HP_PRISM_1FA_2E_0V, + HP_PRISM_2FA_2E_0V, + HP_PRISM_3E_0V, + HP_PRISM_1FA_3E_0V, + HP_PRISM_2FA_3E_0V, + HP_PRISM_3FB_0V, + HP_PRISM_1FA_3FB_0V, + HP_PRISM_2FA_3FB_0V, + HP_PRISM_3E_4EH, + + + + /* HP_PRISM_1FB_1EA_0V, // 1 singular quad face, edge is 1-4 + HP_PRISM_1FB_1EB_0V, // 1 singular quad face, edge is 2-5 + HP_PRISM_2F_0E_0V, // 2 singular quad faces + */ + + HP_PYRAMID = 2000, + HP_PYRAMID_0E_1V, + HP_PYRAMID_EDGES, + HP_PYRAMID_1FB_0E_1VA, // 1 trig face, top vertex + + HP_HEX = 3000, + HP_HEX_0E_1V, + HP_HEX_1E_1V, + HP_HEX_1E_0V, + HP_HEX_3E_0V, + HP_HEX_1F_0E_0V, + HP_HEX_1FA_1FB_0E_0V, +}; + + + +struct HPRef_Struct { + HPREF_ELEMENT_TYPE geom; + int (*splitedges)[3]; + int (*splitfaces)[4]; + int (*splitelements)[5]; + HPREF_ELEMENT_TYPE * neweltypes; + int (*newels)[8]; +}; + + + + +class HPRefElement +{ +private: + void Reset(void); + +public: + HPRefElement (); + HPRefElement(Element & el); + HPRefElement(Element2d & el); + HPRefElement(Segment & el); + HPRefElement(HPRefElement & el); + + void SetType( HPREF_ELEMENT_TYPE t); + // HPRefElement(HPRefElement & el, HPREF_ELEMENT_TYPE t); + + /* HPRefElement(HPRefElement & el, HPREF_ELEMENT_TYPE t) + { + type = t; + HPRef_Struct * hprs = Get_HPRef_Struct(t); + for (int i=0; i<np ; i++) + { + pnums[i] = el[i]; + for(int l=0; l<np; l++) param[i][l] = el.param[i][l]; + } + switch(hprs->geom) + { + case HP_SEGM: np=2; sing_edge_left=0; sing_edge_right=0; break; + case HP_QUAD: np=4; break; + case HP_TRIG: np=3; break; + case HP_HEX: np=8; break; + case HP_PRISM: np=6; break; + case HP_TET: np=4; break; + case HP_PYRAMID: np=5; break; + } + index = el.index; + levelx = el.levelx; + levely = el.levely; + levelz = el.levelz; + type = el.type; + coarse_elnr = el.coarse_elnr; + singedge_left = el.singedge_left; + singedge_right = el.singedge_left; + } */ + + HPREF_ELEMENT_TYPE type; + PointIndex pnums[8]; + double param[8][3]; + int index; + int levelx; + int levely; + int levelz; + int np; + int coarse_elnr; + int domin, domout; // he: needed for segment!! in 3d there should be surf1, surf2!! + // int coarse_hpelnr; + PointIndex & operator[](int i) { return(pnums[i]);} + PointIndex & PNumMod(int i) { return pnums[(i-1) % np]; }; + PointIndex & PNum(int i) {return pnums[(i-1)]; }; + int GetIndex () const { return index; }; + double singedge_left, singedge_right; + + + // EdgePointGeomInfo epgeominfo[2]; + +}; + + + +extern void HPRefinement (Mesh & mesh, Refinement * ref, int levels, + double fac1=0.125, bool setorders=true, bool ref_level = false); + + +#endif + diff --git a/contrib/Netgen/libsrc/meshing/improve2.cpp b/contrib/Netgen/libsrc/meshing/improve2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4824d4eb31335a0161223dc5d78ae00c170b38f5 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve2.cpp @@ -0,0 +1,831 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +#ifndef SMALLLIB +//#ifndef NOTCL +//#include <visual.hpp> +//#endif +#endif + +namespace netgen +{ + +class Neighbour +{ + int nr[3]; + int orient[3]; + +public: + Neighbour () { nr[0] = nr[1] = nr[2] = -1; orient[0] = orient[1] = orient[2] = 0; } + + void SetNr (int side, int anr) { nr[side-1] = anr; } + int GetNr (int side) { return nr[side-1]; } + + void SetOrientation (int side, int aorient) { orient[side-1] = aorient; } + int GetOrientation (int side) { return orient[side-1]; } +}; + + + + +class trionedge +{ +public: + int tnr; + int sidenr; + + trionedge () { tnr = 0; sidenr = 0; } + trionedge (int atnr, int asidenr) + { tnr = atnr; sidenr = asidenr; } +}; + + + + +void MeshOptimize2d :: EdgeSwapping (Mesh & mesh, int usemetric) +{ + // return; + + if (!faceindex) + { + if (usemetric) + PrintMessage (3, "Edgeswapping, metric"); + else + PrintMessage (3, "Edgeswapping, topological"); + + for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) + { + EdgeSwapping (mesh, usemetric); + + if (multithread.terminate) + throw NgException ("Meshing stopped"); + } + + faceindex = 0; + mesh.CalcSurfacesOfNode(); + return; + } + + + static int timer = NgProfiler::CreateTimer ("EdgeSwapping 2D"); + NgProfiler::RegionTimer reg1 (timer); + + + int i, i2, j, j2; + bool should; + PointIndex pi; + + ARRAY<SurfaceElementIndex> seia; + mesh.GetSurfaceElementsOfFace (faceindex, seia); + + for (i = 0; i < seia.Size(); i++) + if (mesh[seia[i]].GetNP() != 3) + { + GenericImprove (mesh); + return; + } + + int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); + + ARRAY<Neighbour> neighbors(mesh.GetNSE()); + INDEX_2_HASHTABLE<trionedge> other(seia.Size() + 2); + + + ARRAY<char> swapped(mesh.GetNSE()); + ARRAY<int,PointIndex::BASE> pdef(mesh.GetNP()); + ARRAY<double,PointIndex::BASE> pangle(mesh.GetNP()); + + SurfaceElementIndex t1, t2; + int o1, o2; + + PointIndex pi1, pi2, pi3, pi4; + PointGeomInfo gi1, gi2, gi3, gi4; + + + int nswaps = 0; + int e, done; + double d; + Vec3d nv1, nv2; + double horder; + double loch(-1); + static const double minangle[] = { 0, 1.481, 2.565, 3.627, 4.683, 5.736, 7, 9 }; + + pangle = 0; + + for (i = 0; i < seia.Size(); i++) + { + const Element2d & sel = mesh[seia[i]]; + for (j = 0; j < 3; j++) + { + POINTTYPE typ = mesh[sel[j]].Type(); + if (typ == FIXEDPOINT || typ == EDGEPOINT) + { + pangle[sel[j]] += + Angle (mesh[sel[(j+1)%3]] - mesh[sel[j]], + mesh[sel[(j+2)%3]] - mesh[sel[j]]); + } + } + } + + for (pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + { + if (mesh[pi].Type() == INNERPOINT || mesh[pi].Type() == SURFACEPOINT) + pdef[pi] = -6; + else + for (j = 0; j < 8; j++) + if (pangle[pi] >= minangle[j]) + pdef[pi] = -1-j; + } + + for (i = 0; i < seia.Size(); i++) + { + const Element2d & sel = mesh[seia[i]]; + for (j = 0; j < 3; j++) + pdef[sel[j]]++; + } + + for (i = 0; i < seia.Size(); i++) + { + //const Element2d & sel = mesh[seia[i]]; + for (j = 0; j < 3; j++) + { + neighbors[seia[i]].SetNr (j+1, -1); + neighbors[seia[i]].SetOrientation (j+1, 0); + } + } + + /* + ARRAY<Vec3d> normals(mesh.GetNP()); + for (i = 1; i <= mesh.GetNSE(); i++) + { + Element2d & hel = mesh.SurfaceElement(i); + if (hel.GetIndex() == faceindex) + for (k = 1; k <= 3; k++) + { + int pi = hel.PNum(k); + SelectSurfaceOfPoint (mesh.Point(pi), hel.GeomInfoPi(k)); + int surfi = mesh.GetFaceDescriptor(faceindex).SurfNr(); + GetNormalVector (surfi, mesh.Point(pi), normals.Elem(pi)); + normals.Elem(pi) /= normals.Elem(pi).Length(); + } + } + */ + + + for (i = 0; i < seia.Size(); i++) + { + const Element2d & sel = mesh[seia[i]]; + + for (j = 1; j <= 3; j++) + { + pi1 = sel.PNumMod(j+1); + pi2 = sel.PNumMod(j+2); + + loch = mesh.GetH(mesh[pi1]); + + INDEX_2 edge(pi1, pi2); + edge.Sort(); + + if (mesh.IsSegment (pi1, pi2)) + continue; + + /* + if (segments.Used (edge)) + continue; + */ + INDEX_2 ii2 (pi1, pi2); + if (other.Used (ii2)) + { + // INDEX_2 i2s(ii2); + // i2s.Sort(); + + i2 = other.Get(ii2).tnr; + j2 = other.Get(ii2).sidenr; + + neighbors[seia[i]].SetNr (j, i2); + neighbors[seia[i]].SetOrientation (j, j2); + neighbors[i2].SetNr (j2, seia[i]); + neighbors[i2].SetOrientation (j2, j); + } + else + { + other.Set (INDEX_2 (pi2, pi1), trionedge (seia[i], j)); + } + } + } + + for (i = 0; i < seia.Size(); i++) + swapped[seia[i]] = 0; + + + int t = 4; + done = 0; + while (!done && t >= 2) + { + for (i = 0; i < seia.Size(); i++) + { + t1 = seia[i]; + + if (mesh[t1].IsDeleted()) + continue; + + if (mesh[t1].GetIndex() != faceindex) + continue; + + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + for (o1 = 1; o1 <= 3; o1++) + { + t2 = neighbors[t1].GetNr (o1); + o2 = neighbors[t1].GetOrientation (o1); + + if (t2 == -1) continue; + if (swapped[t1] || swapped[t2]) continue; + + + pi1 = mesh[t1].PNumMod(o1+1); + pi2 = mesh[t1].PNumMod(o1+2); + pi3 = mesh[t1].PNumMod(o1); + pi4 = mesh[t2].PNumMod(o2); + + gi1 = mesh[t1].GeomInfoPiMod(o1+1); + gi2 = mesh[t1].GeomInfoPiMod(o1+2); + gi3 = mesh[t1].GeomInfoPiMod(o1); + gi4 = mesh[t2].GeomInfoPiMod(o2); + + bool allowswap = true; + + Vec3d auxvec1,auxvec2; + + auxvec1 = mesh.Point(pi3)-mesh.Point(pi4); + auxvec2 = mesh.Point(pi1)-mesh.Point(pi4); + allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4; + + if(!allowswap) + continue; + + // normal of new + nv1 = Cross (auxvec1, + auxvec2); + + auxvec1 = mesh.Point(pi4)-mesh.Point(pi3); + auxvec2 = mesh.Point(pi2)-mesh.Point(pi3); + allowswap = allowswap && fabs(1.-(auxvec1*auxvec2)/(auxvec1.Length()*auxvec2.Length())) > 1e-4; + + + if(!allowswap) + continue; + + nv2 = Cross (auxvec1, + auxvec2); + + + // normals of original + Vec3d nv3, nv4; + nv3 = Cross (mesh.Point(pi1)-mesh.Point(pi4), + mesh.Point(pi2)-mesh.Point(pi4)); + nv4 = Cross (mesh.Point(pi2)-mesh.Point(pi3), + mesh.Point(pi1)-mesh.Point(pi3)); + + nv3 *= -1; + nv4 *= -1; + nv3.Normalize(); + nv4.Normalize(); + + nv1.Normalize(); + nv2.Normalize(); + + Vec<3> nvp3, nvp4; + SelectSurfaceOfPoint (mesh.Point(pi3), gi3); + GetNormalVector (surfnr, mesh.Point(pi3), gi3, nvp3); + + nvp3.Normalize(); + + SelectSurfaceOfPoint (mesh.Point(pi4), gi4); + GetNormalVector (surfnr, mesh.Point(pi4), gi4, nvp4); + + nvp4.Normalize(); + + + + double critval = cos (M_PI / 6); // 30 degree + allowswap = allowswap && + (nv1 * nvp3 > critval) && + (nv1 * nvp4 > critval) && + (nv2 * nvp3 > critval) && + (nv2 * nvp4 > critval) && + (nvp3 * nv3 > critval) && + (nvp4 * nv4 > critval); + + + horder = Dist (mesh.Point(pi1), mesh.Point(pi2)); + + if ( // nv1 * nv2 >= 0 && + nv1.Length() > 1e-3 * horder * horder && + nv2.Length() > 1e-3 * horder * horder && + allowswap ) + { + if (!usemetric) + { + e = pdef[pi1] + pdef[pi2] - pdef[pi3] - pdef[pi4]; + d = + Dist2 (mesh.Point(pi1), mesh.Point(pi2)) - + Dist2 (mesh.Point(pi3), mesh.Point(pi4)); + + should = e >= t && (e > 2 || d > 0); + } + else + { + should = + CalcTriangleBadness (mesh.Point(pi4), mesh.Point(pi3), mesh.Point(pi1), + metricweight, loch) + + CalcTriangleBadness (mesh.Point(pi3), mesh.Point(pi4), mesh.Point(pi2), + metricweight, loch) < + CalcTriangleBadness (mesh.Point(pi1), mesh.Point(pi2), mesh.Point(pi3), + metricweight, loch) + + CalcTriangleBadness (mesh.Point(pi2), mesh.Point(pi1), mesh.Point(pi4), + metricweight, loch); + + } + + if (allowswap) + { + Element2d sw1 (pi4, pi3, pi1); + Element2d sw2 (pi3, pi4, pi2); + + int legal1 = + mesh.LegalTrig (mesh.SurfaceElement (t1)) + + mesh.LegalTrig (mesh.SurfaceElement (t2)); + int legal2 = + mesh.LegalTrig (sw1) + mesh.LegalTrig (sw2); + + if (legal1 < legal2) should = 1; + if (legal2 < legal1) should = 0; + } + + if (should) + { + // do swapping ! + + // cout << "swap " << endl; + + nswaps ++; + + // testout << "nv1 = " << nv1 << " nv2 = " << nv2 << endl; + + + done = 1; + + mesh[t1].PNum(1) = pi1; + mesh[t1].PNum(2) = pi4; + mesh[t1].PNum(3) = pi3; + + mesh[t2].PNum(1) = pi2; + mesh[t2].PNum(2) = pi3; + mesh[t2].PNum(3) = pi4; + + mesh[t1].GeomInfoPi(1) = gi1; + mesh[t1].GeomInfoPi(2) = gi4; + mesh[t1].GeomInfoPi(3) = gi3; + + mesh[t2].GeomInfoPi(1) = gi2; + mesh[t2].GeomInfoPi(2) = gi3; + mesh[t2].GeomInfoPi(3) = gi4; + + pdef[pi1]--; + pdef[pi2]--; + pdef[pi3]++; + pdef[pi4]++; + + swapped[t1] = 1; + swapped[t2] = 1; + } + } + } + } + t--; + } + + mesh.SetNextTimeStamp(); +} + + + + + + + + +void MeshOptimize2d :: CombineImprove (Mesh & mesh) +{ + if (!faceindex) + { + PrintMessage (3, "Combine improve"); + + for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) + { + CombineImprove (mesh); + + if (multithread.terminate) + throw NgException ("Meshing stopped"); + } + faceindex = 0; + return; + } + + + static int timer = NgProfiler::CreateTimer ("Combineimprove 2D"); + NgProfiler::RegionTimer reg (timer); + + + + int i, j, k, l; + PointIndex pi; + SurfaceElementIndex sei; + + + ARRAY<SurfaceElementIndex> seia; + mesh.GetSurfaceElementsOfFace (faceindex, seia); + + + for (i = 0; i < seia.Size(); i++) + if (mesh[seia[i]].GetNP() != 3) + return; + + + + int surfnr = 0; + if (faceindex) + surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); + + + PointIndex pi1, pi2; + MeshPoint p1, p2, pnew; + double bad1, bad2; + Vec<3> nv; + + int np = mesh.GetNP(); + //int nse = mesh.GetNSE(); + + TABLE<SurfaceElementIndex,PointIndex::BASE> elementsonnode(np); + ARRAY<SurfaceElementIndex> hasonepi, hasbothpi; + + for (i = 0; i < seia.Size(); i++) + { + Element2d & el = mesh[seia[i]]; + for (j = 0; j < el.GetNP(); j++) + { + elementsonnode.Add (el[j], seia[i]); + } + } + + + ARRAY<bool,PointIndex::BASE> fixed(np); + fixed = false; + + SegmentIndex si; + for (si = 0; si < mesh.GetNSeg(); si++) + { + INDEX_2 i2(mesh[si].p1, mesh[si].p2); + fixed[i2.I1()] = true; + fixed[i2.I2()] = true; + } + + for(i = 0; i<mesh.LockedPoints().Size(); i++) + fixed[mesh.LockedPoints()[i]] = true; + + + ARRAY<Vec<3>,PointIndex::BASE> normals(np); + + for (pi = PointIndex::BASE; + pi < np + PointIndex::BASE; pi++) + { + if (elementsonnode[pi].Size()) + { + Element2d & hel = mesh[elementsonnode[pi][0]]; + for (k = 0; k < 3; k++) + if (hel[k] == pi) + { + SelectSurfaceOfPoint (mesh[pi], hel.GeomInfoPi(k+1)); + GetNormalVector (surfnr, mesh[pi], hel.GeomInfoPi(k+1), normals[pi]); + break; + } + if (k == 3) + { + cerr << "Neuer Fehler von Joachim, code 17121" << endl; + } + } + } + + + for (i = 0; i < seia.Size(); i++) + { + + sei = seia[i]; + Element2d & elem = mesh[sei]; + if (elem.IsDeleted()) continue; + + for (j = 0; j < 3; j++) + { + pi1 = elem[j]; + pi2 = elem[(j+1) % 3]; + + if (pi1 < PointIndex::BASE || + pi2 < PointIndex::BASE) + continue; + + /* + INDEX_2 i2(pi1, pi2); + i2.Sort(); + if (segmentht.Used(i2)) + continue; + */ + + bool debugflag = 0; + + if (debugflag) + { + (*testout) << "Combineimprove, face = " << faceindex + << "pi1 = " << pi1 << " pi2 = " << pi2 << endl; + } + + /* + // save version: + if (fixed.Get(pi1) || fixed.Get(pi2)) + continue; + if (pi2 < pi1) swap (pi1, pi2); + */ + + // more general + if (fixed[pi2]) + Swap (pi1, pi2); + + if (fixed[pi2]) + continue; + + double loch = mesh.GetH (mesh[pi1]); + + INDEX_2 si2 (pi1, pi2); + si2.Sort(); + + /* + if (edgetested.Used (si2)) + continue; + edgetested.Set (si2, 1); + */ + + hasonepi.SetSize(0); + hasbothpi.SetSize(0); + + for (k = 0; k < elementsonnode[pi1].Size(); k++) + { + const Element2d & el2 = mesh[elementsonnode[pi1][k]]; + + if (el2.IsDeleted()) continue; + + if (el2[0] == pi2 || el2[1] == pi2 || el2[2] == pi2) + { + hasbothpi.Append (elementsonnode[pi1][k]); + nv = Cross (Vec3d (mesh[el2[0]], mesh[el2[1]]), + Vec3d (mesh[el2[0]], mesh[el2[2]])); + } + else + { + hasonepi.Append (elementsonnode[pi1][k]); + } + } + + + Element2d & hel = mesh[hasbothpi[0]]; + for (k = 0; k < 3; k++) + if (hel[k] == pi1) + { + SelectSurfaceOfPoint (mesh[pi1], + hel.GeomInfoPi(k+1)); + GetNormalVector (surfnr, mesh[pi1], hel.GeomInfoPi(k+1), nv); + break; + } + if (k == 3) + { + cerr << "Neuer Fehler von Joachim, code 32434" << endl; + } + + + // nv = normals.Get(pi1); + + + + for (k = 0; k < elementsonnode[pi2].Size(); k++) + { + const Element2d & el2 = mesh[elementsonnode[pi2][k]]; + if (el2.IsDeleted()) continue; + + if (el2[0] == pi1 || el2[1] == pi1 || el2[2] == pi1) + ; + else + hasonepi.Append (elementsonnode[pi2][k]); + } + + bad1 = 0; + int illegal1 = 0, illegal2 = 0; + for (k = 0; k < hasonepi.Size(); k++) + { + const Element2d & el = mesh[hasonepi[k]]; + bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]], + nv, -1, loch); + illegal1 += 1-mesh.LegalTrig(el); + } + + for (k = 0; k < hasbothpi.Size(); k++) + { + const Element2d & el = mesh[hasbothpi[k]]; + bad1 += CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]], + nv, -1, loch); + illegal1 += 1-mesh.LegalTrig(el); + } + bad1 /= (hasonepi.Size()+hasbothpi.Size()); + + p1 = mesh[pi1]; + p2 = mesh[pi2]; + + pnew = p1; + mesh[pi1] = pnew; + mesh[pi2] = pnew; + + bad2 = 0; + for (k = 0; k < hasonepi.Size(); k++) + { + Element2d & el = mesh[hasonepi[k]]; + double err = + CalcTriangleBadness (mesh[el[0]], mesh[el[1]], mesh[el[2]], + nv, -1, loch); + bad2 += err; + + Vec<3> hnv = Cross (Vec3d (mesh[el[0]], + mesh[el[1]]), + Vec3d (mesh[el[0]], + mesh[el[2]])); + if (hnv * nv < 0) + bad2 += 1e10; + + for (l = 0; l < 3; l++) + if ( (normals[el[l]] * nv) < 0.5) + bad2 += 1e10; + + illegal2 += 1-mesh.LegalTrig(el); + } + bad2 /= hasonepi.Size(); + + mesh[pi1] = p1; + mesh[pi2] = p2; + + + if (debugflag) + { + (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl; + } + + + bool should = (bad2 < bad1 && bad2 < 1e4); + if (bad2 < 1e4) + { + if (illegal1 > illegal2) should = 1; + if (illegal2 > illegal1) should = 0; + } + + + if (should) + { + // (*testout) << "combine !" << endl; + // (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl; + + + mesh[pi1] = pnew; + PointGeomInfo gi; + bool gi_set(false); + + + Element2d *el1p(NULL); + l=0; + while(mesh[elementsonnode[pi1][l]].IsDeleted() && l<elementsonnode.EntrySize(pi1)) l++; + if(l<elementsonnode.EntrySize(pi1)) + el1p = &mesh[elementsonnode[pi1][l]]; + else + cerr << "OOPS!" << endl; + + for (l = 0; l < el1p->GetNP(); l++) + if ((*el1p)[l] == pi1) + { + gi = el1p->GeomInfoPi (l+1); + gi_set = true; + } + + // (*testout) << "Connect point " << pi2 << " to " << pi1 << "\n"; + for (k = 0; k < elementsonnode[pi2].Size(); k++) + { + Element2d & el = mesh[elementsonnode[pi2][k]]; + if(el.IsDeleted()) continue; + elementsonnode.Add (pi1, elementsonnode[pi2][k]); + + bool haspi1 = 0; + for (l = 0; l < el.GetNP(); l++) + if (el[l] == pi1) + haspi1 = 1; + if (haspi1) continue; + + for (l = 0; l < el.GetNP(); l++) + { + if (el[l] == pi2) + { + el[l] = pi1; + el.GeomInfoPi (l+1) = gi; + } + + fixed[el[l]] = true; + } + } + + /* + for (k = 0; k < hasbothpi.Size(); k++) + { + cout << mesh[hasbothpi[k]] << endl; + for (l = 0; l < 3; l++) + cout << mesh[mesh[hasbothpi[k]][l]] << " "; + cout << endl; + } + */ + + for (k = 0; k < hasbothpi.Size(); k++) + { + mesh[hasbothpi[k]].Delete(); + /* + for (l = 0; l < 4; l++) + mesh[hasbothpi[k]][l] = PointIndex::BASE-1; + */ + } + + } + } + } + + // mesh.Compress(); + mesh.SetNextTimeStamp(); +} + + +void MeshOptimize2d :: CheckMeshApproximation (Mesh & mesh) +{ + // Check angles between elements and normals at corners + /* + + int i, j; + int ne = mesh.GetNSE(); + int surfnr; + + Vec3d n, ng; + ARRAY<Vec3d> ngs(3); + + (*mycout) << "Check Surface Approxiamtion" << endl; + (*testout) << "Check Surface Approxiamtion" << endl; + + for (i = 1; i <= ne; i++) + { + const Element2d & el = mesh.SurfaceElement(i); + surfnr = mesh.GetFaceDescriptor (el.GetIndex()).SurfNr(); + Vec3d n = Cross (mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(2)), + mesh.Point (el.PNum(1)) - mesh.Point (el.PNum(3))); + n /= n.Length(); + + for (j = 1; j <= el.GetNP(); j++) + { + SelectSurfaceOfPoint (mesh.Point(el.PNum(j)), el.GeomInfoPi(j)); + GetNormalVector (surfnr, mesh.Point(el.PNum(j)), ng); + ng /= ng.Length(); + ngs.Elem(j) = ng; + + double angle = (180.0 / M_PI) * Angle (n, ng); + if (angle > 60) + { + (*testout) << "el " << i << " node " << el.PNum(j) + << "has angle = " << angle << endl; + } + } + + for (j = 1; j <= 3; j++) + { + double angle = (180.0 / M_PI) * Angle (ngs.Get(j), ngs.Get(j%3+1)); + if (angle > 60) + { + (*testout) << "el " << i << " node-node " + << ngs.Get(j) << " - " << ngs.Get(j%3+1) + << " has angle = " << angle << endl; + } + } + } + */ +} +} diff --git a/contrib/Netgen/libsrc/meshing/improve2.hpp b/contrib/Netgen/libsrc/meshing/improve2.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4f25863d40857b5600af1bd2cb24bac3273785c5 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve2.hpp @@ -0,0 +1,102 @@ +#ifndef FILE_IMPROVE2 +#define FILE_IMPROVE2 + + + +/// +class MeshOptimize2d +{ + int faceindex; + int improveedges; + double metricweight; + int writestatus; + +public: + /// + MeshOptimize2d (); + /// + void ImproveMesh (Mesh & mesh2d); + void ImproveMeshJacobian (Mesh & mesh2d); + void ImproveVolumeMesh (Mesh & mesh); + void ProjectBoundaryPoints(ARRAY<int> & surfaceindex, + const ARRAY<Point<3>* > & from, ARRAY<Point<3>* > & dest); + + void EdgeSwapping (Mesh & mesh, int usemetric); + void CombineImprove (Mesh & mesh); + + void GenericImprove (Mesh & mesh); + + + void SetFaceIndex (int fi) { faceindex = fi; } + void SetImproveEdges (int ie) { improveedges = ie; } + void SetMetricWeight (double mw) { metricweight = mw; } + void SetWriteStatus (int ws) { writestatus = ws; } + + + + /// + virtual void SelectSurfaceOfPoint (const Point<3> & p, + const PointGeomInfo & gi); + /// + virtual void ProjectPoint (INDEX /* surfind */, Point<3> & /* p */) const { }; + + /// project point, use gi as initial value, and compute new gi + virtual int ProjectPointGI (INDEX surfind, Point<3> & p, PointGeomInfo & gi) const + { ProjectPoint (surfind, p); return CalcPointGeomInfo (surfind, gi, p); } + + /// + virtual void ProjectPoint2 (INDEX /* surfind */, INDEX /* surfind2 */, Point<3> & /* p */) const { }; + + /// liefert zu einem 3d-Punkt die geominfo (Dreieck) und liefert 1, wenn erfolgreich, + /// 0, wenn nicht (Punkt ausserhalb von chart) + virtual int CalcPointGeomInfo(PointGeomInfo& gi, const Point<3> & /*p3*/) const + { gi.trignum = 1; return 1;}; + + virtual int CalcPointGeomInfo(int /* surfind */, PointGeomInfo& gi, const Point<3> & p3) const + { return CalcPointGeomInfo (gi, p3); } + + /// + virtual void GetNormalVector(INDEX surfind, const Point<3> & p, PointGeomInfo & gi, Vec<3> & n) const; + virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const; + + void CheckMeshApproximation (Mesh & mesh); + + + /// + friend class Opti2SurfaceMinFunction; + /// + friend class Opti2EdgeMinFunction; + /// + friend double Opti2FunctionValueGrad (const Vector & x, Vector & grad); + /// + friend double Opti2EdgeFunctionValueGrad (const Vector & x, Vector & grad); + + + +}; + + +extern void CalcTriangleBadness (double x2, double x3, double y3, + double metricweight, + double h, double & badness, + double & g1x, double & g1y); + + + + +extern double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double metricweight, + double h); + +extern double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Vec3d & n, + double metricweight, + double h); + +#endif + + diff --git a/contrib/Netgen/libsrc/meshing/improve2gen.cpp b/contrib/Netgen/libsrc/meshing/improve2gen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75ffc80183a18b9981f95c662ac7d5563391ff88 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve2gen.cpp @@ -0,0 +1,455 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +namespace netgen +{ + + class ImprovementRule + { + public: + ARRAY<Element2d> oldels; + ARRAY<Element2d> newels; + ARRAY<INDEX_2> deledges; + ARRAY<int> incelsonnode; + ARRAY<int> reused; + int bonus; + int onp; + }; + + + void MeshOptimize2d :: GenericImprove (Mesh & mesh) + { + if (!faceindex) + { + if (writestatus) + PrintMessage (3, "Generic Improve"); + + for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) + GenericImprove (mesh); + + faceindex = 0; + } + + // int j, k, l, ri; + int np = mesh.GetNP(); + int ne = mesh.GetNSE(); + // SurfaceElementIndex sei; + + +// for (SurfaceElementIndex sei = 0; sei < ne; sei++) +// { +// const Element2d & el = mesh[sei]; +// (*testout) << "element " << sei << ": " <<flush; +// for(int j=0; j<el.GetNP(); j++) +// (*testout) << el[j] << " " << flush; +// (*testout) << "IsDeleted() " << el.IsDeleted()<< endl; +// } + + bool ok; + int olddef, newdef; + + ARRAY<ImprovementRule*> rules; + ARRAY<SurfaceElementIndex> elmap; + ARRAY<int> elrot; + ARRAY<PointIndex> pmap; + ARRAY<PointGeomInfo> pgi; + + int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); + + ImprovementRule * r1; + + // 2 triangles to quad + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3)); + r1->oldels.Append (Element2d (3, 2, 4)); + r1->newels.Append (Element2d (1, 2, 4, 3)); + r1->deledges.Append (INDEX_2 (2,3)); + r1->onp = 4; + r1->bonus = 2; + rules.Append (r1); + + // 2 quad to 1 quad + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (4, 3, 2, 5)); + r1->newels.Append (Element2d (1, 2, 5, 4)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->deledges.Append (INDEX_2 (3, 4)); + r1->onp = 5; + r1->bonus = 0; + rules.Append (r1); + + // swap quads + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (3, 2, 5, 6)); + r1->newels.Append (Element2d (1, 6, 3, 4)); + r1->newels.Append (Element2d (1, 2, 5, 6)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->onp = 6; + r1->bonus = 0; + rules.Append (r1); + + // three quads to 2 + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (2, 5, 6, 3)); + r1->oldels.Append (Element2d (3, 6, 7, 4)); + r1->newels.Append (Element2d (1, 2, 5, 4)); + r1->newels.Append (Element2d (4, 5, 6, 7)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->deledges.Append (INDEX_2 (3, 4)); + r1->deledges.Append (INDEX_2 (3, 6)); + r1->onp = 7; + r1->bonus = -1; + rules.Append (r1); + + // quad + 2 connected trigs to quad + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (2, 5, 3)); + r1->oldels.Append (Element2d (3, 5, 4)); + r1->newels.Append (Element2d (1, 2, 5, 4)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->deledges.Append (INDEX_2 (3, 4)); + r1->deledges.Append (INDEX_2 (3, 5)); + r1->onp = 5; + r1->bonus = 0; + rules.Append (r1); + + // quad + 2 non-connected trigs to quad (a and b) + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (2, 6, 3)); + r1->oldels.Append (Element2d (1, 4, 5)); + r1->newels.Append (Element2d (1, 3, 4, 5)); + r1->newels.Append (Element2d (1, 2, 6, 3)); + r1->deledges.Append (INDEX_2 (1, 4)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->onp = 6; + r1->bonus = 0; + rules.Append (r1); + + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (2, 6, 3)); + r1->oldels.Append (Element2d (1, 4, 5)); + r1->newels.Append (Element2d (1, 2, 4, 5)); + r1->newels.Append (Element2d (4, 2, 6, 3)); + r1->deledges.Append (INDEX_2 (1, 4)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->onp = 6; + r1->bonus = 0; + rules.Append (r1); + + // two quad + trig -> one quad + trig + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (2, 5, 6, 3)); + r1->oldels.Append (Element2d (4, 3, 6)); + r1->newels.Append (Element2d (1, 2, 6, 4)); + r1->newels.Append (Element2d (2, 5, 6)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->deledges.Append (INDEX_2 (3, 4)); + r1->deledges.Append (INDEX_2 (3, 6)); + r1->onp = 6; + r1->bonus = -1; + rules.Append (r1); + + // swap quad + trig (a and b) + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (2, 5, 3)); + r1->newels.Append (Element2d (2, 5, 3, 4)); + r1->newels.Append (Element2d (1, 2, 4)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->onp = 5; + r1->bonus = 0; + rules.Append (r1); + + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (2, 5, 3)); + r1->newels.Append (Element2d (1, 2, 5, 3)); + r1->newels.Append (Element2d (1, 3, 4)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->onp = 5; + r1->bonus = 0; + rules.Append (r1); + + + // 2 quads to quad + 2 trigs + r1 = new ImprovementRule; + r1->oldels.Append (Element2d (1, 2, 3, 4)); + r1->oldels.Append (Element2d (3, 2, 5, 6)); + r1->newels.Append (Element2d (1, 5, 6, 4)); + r1->newels.Append (Element2d (1, 2, 5)); + r1->newels.Append (Element2d (4, 6, 3)); + r1->deledges.Append (INDEX_2 (2, 3)); + r1->onp = 6; + r1->bonus = 0; + // rules.Append (r1); + + + + + ARRAY<int> mapped(rules.Size()); + ARRAY<int> used(rules.Size()); + used = 0; + mapped = 0; + + + + for (int ri = 0; ri < rules.Size(); ri++) + { + ImprovementRule & rule = *rules[ri]; + rule.incelsonnode.SetSize (rule.onp); + rule.reused.SetSize (rule.onp); + + for (int j = 1; j <= rule.onp; j++) + { + rule.incelsonnode.Elem(j) = 0; + rule.reused.Elem(j) = 0; + } + + for (int j = 1; j <= rule.oldels.Size(); j++) + { + const Element2d & el = rule.oldels.Elem(j); + for (int k = 1; k <= el.GetNP(); k++) + rule.incelsonnode.Elem(el.PNum(k))--; + } + + for (int j = 1; j <= rule.newels.Size(); j++) + { + const Element2d & el = rule.newels.Elem(j); + for (int k = 1; k <= el.GetNP(); k++) + { + rule.incelsonnode.Elem(el.PNum(k))++; + rule.reused.Elem(el.PNum(k)) = 1; + } + } + } + + + + + TABLE<int,PointIndex::BASE> elonnode(np); + ARRAY<int,PointIndex::BASE> nelonnode(np); + TABLE<SurfaceElementIndex> nbels(ne); + + nelonnode = -4; + + for (SurfaceElementIndex sei = 0; sei < ne; sei++) + { + const Element2d & el = mesh[sei]; + + if (el.GetIndex() == faceindex && !el.IsDeleted()) + { + for (int j = 0; j < el.GetNP(); j++) + elonnode.Add (el[j], sei); + } + if(!el.IsDeleted()) + { + for (int j = 0; j < el.GetNP(); j++) + nelonnode[el[j]]++; + } + } + + for (SurfaceElementIndex sei = 0; sei < ne; sei++) + { + const Element2d & el = mesh[sei]; + if (el.GetIndex() == faceindex && !el.IsDeleted()) + { + for (int j = 0; j < el.GetNP(); j++) + { + for (int k = 0; k < elonnode[el[j]].Size(); k++) + { + int nbel = elonnode[el[j]] [k]; + bool inuse = false; + for (int l = 0; l < nbels[sei].Size(); l++) + if (nbels[sei][l] == nbel) + inuse = true; + if (!inuse) + nbels.Add (sei, nbel); + } + } + } + } + + + for (int ri = 0; ri < rules.Size(); ri++) + { + const ImprovementRule & rule = *rules[ri]; + + elmap.SetSize (rule.oldels.Size()); + elrot.SetSize (rule.oldels.Size()); + pmap.SetSize (rule.onp); + pgi.SetSize (rule.onp); + + + for (SurfaceElementIndex sei = 0; sei < ne; sei++) + { + if (multithread.terminate) + break; + if (mesh[sei].IsDeleted()) continue; + + elmap[0] = sei; + FlatArray<SurfaceElementIndex> neighbours = nbels[sei]; + + for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++) + { + const Element2d & el0 = mesh[sei]; + const Element2d & rel0 = rule.oldels[0]; + + if (el0.GetIndex() != faceindex) continue; + if (el0.IsDeleted()) continue; + if (el0.GetNP() != rel0.GetNP()) continue; + + + pmap = -1; + + for (int k = 0; k < el0.GetNP(); k++) + { + pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1); + pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1); + } + + ok = 1; + for (int i = 1; i < elmap.Size(); i++) + { + // try to find a mapping for reference-element i + + const Element2d & rel = rule.oldels[i]; + bool possible = 0; + + for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++) + { + const Element2d & el = mesh[neighbours[elmap[i]]]; + if (el.IsDeleted()) continue; + if (el.GetNP() != rel.GetNP()) continue; + + for (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++) + { + possible = 1; + + for (int k = 0; k < rel.GetNP(); k++) + if (pmap.Elem(rel[k]) != -1 && + pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1)) + possible = 0; + + if (possible) + { + for (int k = 0; k < el.GetNP(); k++) + { + pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1); + pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1); + } + break; + } + } + if (possible) break; + } + + if (!possible) + { + ok = 0; + break; + } + + elmap[i] = neighbours[elmap[i]]; + } + + for(int i=0; ok && i<rule.deledges.Size(); i++) + { + ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()), + pmap.Elem(rule.deledges[i].I2())); + } + + + + + if (!ok) continue; + + mapped[ri]++; + + olddef = 0; + for (int j = 1; j <= pmap.Size(); j++) + olddef += sqr (nelonnode[pmap.Get(j)]); + olddef += rule.bonus; + + newdef = 0; + for (int j = 1; j <= pmap.Size(); j++) + if (rule.reused.Get(j)) + newdef += sqr (nelonnode[pmap.Get(j)] + + rule.incelsonnode.Get(j)); + + if (newdef > olddef) + continue; + + // calc metric badness + double bad1 = 0, bad2 = 0; + Vec<3> n; + + SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1)); + GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n); + + for (int j = 1; j <= rule.oldels.Size(); j++) + bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n); + + // check new element: + for (int j = 1; j <= rule.newels.Size(); j++) + { + const Element2d & rnel = rule.newels.Get(j); + Element2d nel(rnel.GetNP()); + for (int k = 1; k <= rnel.GetNP(); k++) + nel.PNum(k) = pmap.Get(rnel.PNum(k)); + + bad2 += nel.CalcJacobianBadness (mesh.Points(), n); + } + + if (bad2 > 1e3) continue; + + if (newdef == olddef && bad2 > bad1) continue; + + + // generate new element: + for (int j = 1; j <= rule.newels.Size(); j++) + { + const Element2d & rnel = rule.newels.Get(j); + Element2d nel(rnel.GetNP()); + nel.SetIndex (faceindex); + for (int k = 1; k <= rnel.GetNP(); k++) + { + nel.PNum(k) = pmap.Get(rnel.PNum(k)); + nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k)); + } + + mesh.AddSurfaceElement(nel); + } + + for (int j = 0; j < rule.oldels.Size(); j++) + mesh.DeleteSurfaceElement ( elmap[j] ); + + for (int j = 1; j <= pmap.Size(); j++) + nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j); + + used[ri]++; + } + } + } + + mesh.Compress(); + + for (int ri = 0; ri < rules.Size(); ri++) + { + PrintMessage (5, "rule ", ri+1, " ", + mapped[ri], "/", used[ri], " mapped/used"); + } + } + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/improve3.cpp b/contrib/Netgen/libsrc/meshing/improve3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2db1e8b49b14cca4304ab58da2193926eae6df2 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve3.cpp @@ -0,0 +1,2820 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +#ifdef SOLIDGEOM +#include <csg.hpp> +#endif +#include <opti.hpp> + +namespace netgen +{ + +/* + Combine two points to one. + Set new point into the center, if both are + inner points. + Connect inner point to boundary point, if one + point is inner point. +*/ + +void MeshOptimize3d :: CombineImprove (Mesh & mesh, + OPTIMIZEGOAL goal) +{ + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + + TABLE<ElementIndex, PointIndex::BASE> elementsonnode(np); + ARRAY<ElementIndex> hasonepi, hasbothpi; + + ARRAY<double> oneperr; + ARRAY<double> elerrs (ne); + + PrintMessage (3, "CombineImprove"); + (*testout) << "Start CombineImprove" << "\n"; + + // mesh.CalcSurfacesOfNode (); + const char * savetask = multithread.task; + multithread.task = "Combine Improve"; + + + double totalbad = 0; + for (ElementIndex ei = 0; ei < ne; ei++) + { + double elerr = CalcBad (mesh.Points(), mesh[ei], 0); + totalbad += elerr; + elerrs[ei] = elerr; + } + + if (goal == OPT_QUALITY) + { + totalbad = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << totalbad << endl; + PrintMessage (5, "Total badness = ", totalbad); + } + + for (ElementIndex ei = 0; ei < ne; ei++) + if (!mesh[ei].IsDeleted()) + for (int j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + INDEX_2_HASHTABLE<int> edgetested (np+1); + + int cnt = 0; + + for (ElementIndex ei = 0; ei < ne; ei++) + { + if (multithread.terminate) + break; + + multithread.percent = 100.0 * (ei+1) / ne; + + if (mesh.ElementType(ei) == FIXEDELEMENT) + continue; + + for (int j = 0; j < 6; j++) + { + Element & elemi = mesh[ei]; + if (elemi.IsDeleted()) continue; + + static const int tetedges[6][2] = + { { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 1, 2 }, { 1, 3 }, { 2, 3 } }; + + PointIndex pi1 = elemi[tetedges[j][0]]; + PointIndex pi2 = elemi[tetedges[j][1]]; + + if (pi2 < pi1) Swap (pi1, pi2); + + INDEX_2 si2 (pi1, pi2); + si2.Sort(); + + if (edgetested.Used (si2)) continue; + edgetested.Set (si2, 1); + + + // hasonepoint.SetSize(0); + // hasbothpoints.SetSize(0); + hasonepi.SetSize(0); + hasbothpi.SetSize(0); + + FlatArray<ElementIndex> row1 = elementsonnode[pi1]; + for (int k = 0; k < row1.Size(); k++) + { + Element & elem = mesh[row1[k]]; + if (elem.IsDeleted()) continue; + + if (elem[0] == pi2 || elem[1] == pi2 || + elem[2] == pi2 || elem[3] == pi2) + { + hasbothpi.Append (row1[k]); + } + else + { + hasonepi.Append (row1[k]); + } + } + + FlatArray<ElementIndex> row2 = elementsonnode[pi2]; + for (int k = 0; k < row2.Size(); k++) + { + Element & elem = mesh[row2[k]]; + if (elem.IsDeleted()) continue; + + if (elem[0] == pi1 || elem[1] == pi1 || + elem[2] == pi1 || elem[3] == pi1) + ; + else + { + hasonepi.Append (row2[k]); + } + } + + double bad1 = 0; + for (int k = 0; k < hasonepi.Size(); k++) + bad1 += elerrs[hasonepi[k]]; + for (int k = 0; k < hasbothpi.Size(); k++) + bad1 += elerrs[hasbothpi[k]]; + + MeshPoint p1 = mesh[pi1]; + MeshPoint p2 = mesh[pi2]; + + + // if (mesh.PointType(pi2) != INNERPOINT) + if (p2.Type() != INNERPOINT) + continue; + + MeshPoint pnew; + // if (mesh.PointType(pi1) != INNERPOINT) + if (p1.Type() != INNERPOINT) + pnew = p1; + else + pnew = Center (p1, p2); + + mesh[pi1] = pnew; + mesh[pi2] = pnew; + + oneperr.SetSize (hasonepi.Size()); + + double bad2 = 0; + for (int k = 0; k < hasonepi.Size(); k++) + { + const Element & elem = mesh[hasonepi[k]]; + double err = CalcTetBadness (mesh[elem[0]], mesh[elem[1]], + mesh[elem[2]], mesh[elem[3]], 0); + bad2 += err; + oneperr[k] = err; + } + + mesh[pi1] = p1; + mesh[pi2] = p2; + + // if (mesh.PointType(pi1) != INNERPOINT) + if (p1.Type() != INNERPOINT) + { + for (int k = 0; k < hasonepi.Size(); k++) + { + Element & elem = mesh[hasonepi[k]]; + int l; + for (l = 0; l < 4; l++) + if (elem[l] == pi2) + { + elem[l] = pi1; + break; + } + + elem.flags.illegal_valid = 0; + if (!mesh.LegalTet(elem)) + bad2 += 1e4; + + if (l < 4) + { + elem.flags.illegal_valid = 0; + elem[l] = pi2; + } + } + } + + if (bad2 / hasonepi.Size() < + bad1 / (hasonepi.Size()+hasbothpi.Size())) + { + mesh[pi1] = pnew; + cnt++; + + FlatArray<ElementIndex> row = elementsonnode[pi2]; + for (int k = 0; k < row.Size(); k++) + { + Element & elem = mesh[row[k]]; + if (elem.IsDeleted()) continue; + + elementsonnode.Add (pi1, row[k]); + for (int l = 0; l < elem.GetNP(); l++) + if (elem[l] == pi2) + elem[l] = pi1; + + elem.flags.illegal_valid = 0; + if (!mesh.LegalTet (elem)) + (*testout) << "illegal tet " << elementsonnode[pi2][k] << endl; + } + + for (int k = 0; k < hasonepi.Size(); k++) + elerrs[hasonepi[k]] = oneperr[k]; + + for (int k = 0; k < hasbothpi.Size(); k++) + { + mesh[hasbothpi[k]].flags.illegal_valid = 0; + mesh[hasbothpi[k]].Delete(); + } + } + } + } + + mesh.Compress(); + mesh.MarkIllegalElements(); + + PrintMessage (5, cnt, " elements combined"); + (*testout) << "CombineImprove done" << "\n"; + + totalbad = 0; + for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + totalbad += CalcBad (mesh.Points(), mesh[ei], 0); + + if (goal == OPT_QUALITY) + { + totalbad = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << totalbad << endl; + + int cntill = 0; + for (ElementIndex ei = 0; ei < ne; ei++) + if (!mesh.LegalTet (mesh[ei])) + cntill++; + + PrintMessage (5, cntill, " illegal tets"); + } + multithread.task = savetask; +} + + + + + +/* + Mesh improvement by edge splitting. + If mesh quality is improved by inserting a node into an inner edge, + the edge is split into two parts. +*/ +void MeshOptimize3d :: SplitImprove (Mesh & mesh, + OPTIMIZEGOAL goal) +{ + int j, k, l; + Point3d p1, p2, pnew; + + ElementIndex ei; + SurfaceElementIndex sei; + PointIndex pi1, pi2; + + double bad1, bad2, badmax, badlimit; + + + int cnt = 0; + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + + TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np); + ARRAY<ElementIndex> hasbothpoints; + + BitArray origpoint(np), boundp(np); + origpoint.Set(); + + ARRAY<double> elerrs(ne); + BitArray illegaltet(ne); + illegaltet.Clear(); + + const char * savetask = multithread.task; + multithread.task = "Split Improve"; + + + PrintMessage (3, "SplitImprove"); + (*testout) << "start SplitImprove" << "\n"; + + ARRAY<INDEX_3> locfaces; + + INDEX_2_HASHTABLE<int> edgetested (np); + + bad1 = 0; + badmax = 0; + for (ei = 0; ei < ne; ei++) + { + elerrs[ei] = CalcBad (mesh.Points(), mesh[ei], 0); + bad1 += elerrs[ei]; + if (elerrs[ei] > badmax) badmax = elerrs[ei]; + } + + PrintMessage (5, "badmax = ", badmax); + badlimit = 0.5 * badmax; + + + boundp.Clear(); + for (sei = 0; sei < mesh.GetNSE(); sei++) + for (j = 0; j < 3; j++) + boundp.Set (mesh[sei][j]); + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + } + + for (ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + + mesh.MarkIllegalElements(); + if (goal == OPT_QUALITY || goal == OPT_LEGAL) + { + int cntill = 0; + for (ei = 0; ei < ne; ei++) + { + // if (!LegalTet (volelements.Get(i))) + if (mesh[ei].flags.illegal) + { + cntill++; + illegaltet.Set (ei+1); + } + } + // (*mycout) << cntill << " illegal tets" << endl; + } + + + for (ei = 0; ei < ne; ei++) + { + if (multithread.terminate) + break; + + multithread.percent = 100.0 * (ei+1) / ne; + + bool ltestmode = 0; + + + if (elerrs[ei] < badlimit && !illegaltet.Test(ei+1)) continue; + + if ((goal == OPT_LEGAL) && + !illegaltet.Test(ei+1) && + CalcBad (mesh.Points(), mesh[ei], 0) < 1e3) + continue; + + + Element & elem = mesh[ei]; + + if (ltestmode) + { + (*testout) << "test el " << ei << endl; + for (j = 0; j < 4; j++) + (*testout) << elem[j] << " "; + (*testout) << endl; + } + + + for (j = 0; j < 6; j++) + { + + static const int tetedges[6][2] = + { { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 1, 2 }, { 1, 3 }, { 2, 3 } }; + + pi1 = elem[tetedges[j][0]]; + pi2 = elem[tetedges[j][1]]; + + if (pi2 < pi1) Swap (pi1, pi2); + if (pi2 > elementsonnode.Size()) continue; + + if (!origpoint.Test(pi1) || !origpoint.Test(pi2)) + continue; + + + INDEX_2 i2(pi1, pi2); + i2.Sort(); + + if (mesh.BoundaryEdge (pi1, pi2)) continue; + + if (edgetested.Used (i2) && !illegaltet.Test(ei+1)) continue; + edgetested.Set (i2, 1); + + hasbothpoints.SetSize (0); + for (k = 1; k <= elementsonnode.EntrySize(pi1); k++) + { + bool has1 = 0, has2 = 0; + + ElementIndex elnr = elementsonnode.Get(pi1, k); + Element & el = mesh[elnr]; + + for (l = 0; l < el.GetNP(); l++) + { + if (el[l] == pi1) has1 = 1; + if (el[l] == pi2) has2 = 1; + } + if (has1 && has2) + { // only once + for (l = 0; l < hasbothpoints.Size(); l++) + if (hasbothpoints[l] == elnr) + has1 = 0; + + if (has1) + hasbothpoints.Append (elnr); + } + } + + bad1 = 0; + for (k = 0; k < hasbothpoints.Size(); k++) + bad1 += CalcBad (mesh.Points(), mesh[hasbothpoints[k]], 0); + + + bool puretet = 1; + for (k = 0; k < hasbothpoints.Size(); k++) + if (mesh[hasbothpoints[k]].GetType() != TET) + puretet = 0; + if (!puretet) continue; + + p1 = mesh[pi1]; + p2 = mesh[pi2]; + + /* + pnew = Center (p1, p2); + + points.Elem(pi1) = pnew; + bad2 = 0; + for (k = 1; k <= hasbothpoints.Size(); k++) + bad2 += CalcBad (points, + volelements.Get(hasbothpoints.Get(k)), 0); + + points.Elem(pi1) = p1; + points.Elem(pi2) = pnew; + + for (k = 1; k <= hasbothpoints.Size(); k++) + bad2 += CalcBad (points, + volelements.Get(hasbothpoints.Get(k)), 0); + points.Elem(pi2) = p2; + */ + + + locfaces.SetSize (0); + for (k = 0; k < hasbothpoints.Size(); k++) + { + const Element & el = mesh[hasbothpoints[k]]; + + for (l = 0; l < 4; l++) + if (el[l] == pi1 || el[l] == pi2) + { + INDEX_3 i3; + Element2d face; + el.GetFace (l+1, face); + for (int kk = 1; kk <= 3; kk++) + i3.I(kk) = face.PNum(kk); + locfaces.Append (i3); + } + } + + PointFunction1 pf (mesh.Points(), locfaces, -1); + OptiParameters par; + par.maxit_linsearch = 50; + par.maxit_bfgs = 20; + + pnew = Center (p1, p2); + Vector px(3); + px.Elem(1) = pnew.X(); + px.Elem(2) = pnew.Y(); + px.Elem(3) = pnew.Z(); + + if (elerrs[ei] > 0.1 * badmax) + BFGS (px, pf, par); + + bad2 = pf.Func (px); + + pnew.X() = px.Get(1); + pnew.Y() = px.Get(2); + pnew.Z() = px.Get(3); + + + int hpinew = mesh.AddPoint (pnew); + // ptyps.Append (INNERPOINT); + + for (k = 0; k < hasbothpoints.Size(); k++) + { + Element & oldel = mesh[hasbothpoints[k]]; + Element newel1 = oldel; + Element newel2 = oldel; + + oldel.flags.illegal_valid = 0; + newel1.flags.illegal_valid = 0; + newel2.flags.illegal_valid = 0; + + for (l = 0; l < 4; l++) + { + if (newel1[l] == pi2) newel1[l] = hpinew; + if (newel2[l] == pi1) newel2[l] = hpinew; + } + + if (!mesh.LegalTet (oldel)) bad1 += 1e6; + if (!mesh.LegalTet (newel1)) bad2 += 1e6; + if (!mesh.LegalTet (newel2)) bad2 += 1e6; + } + + // mesh.PointTypes().DeleteLast(); + mesh.Points().DeleteLast(); + + if (bad2 < bad1) + /* (bad1 > 1e4 && boundp.Test(pi1) && boundp.Test(pi2)) */ + { + cnt++; + + PointIndex pinew = mesh.AddPoint (pnew); + + for (k = 0; k < hasbothpoints.Size(); k++) + { + Element & oldel = mesh[hasbothpoints[k]]; + Element newel = oldel; + + newel.flags.illegal_valid = 0; + oldel.flags.illegal_valid = 0; + + for (l = 0; l < 4; l++) + { + origpoint.Clear (oldel[l]); + + if (oldel[l] == pi2) oldel[l] = pinew; + if (newel[l] == pi1) newel[l] = pinew; + } + mesh.AddVolumeElement (newel); + } + + j = 10; + } + } + } + + + mesh.Compress(); + PrintMessage (5, cnt, " splits performed"); + + (*testout) << "Splitt - Improve done" << "\n"; + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + + int cntill = 0; + ne = mesh.GetNE(); + for (ei = 0; ei < ne; ei++) + { + if (!mesh.LegalTet (mesh[ei])) + cntill++; + } + // cout << cntill << " illegal tets" << endl; + } + + multithread.task = savetask; +} + + + + + +void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal, + const BitArray * working_elements) +{ + int j, k, l; + + ElementIndex ei; + SurfaceElementIndex sei; + + PointIndex pi1(0), pi2(0), pi3(0), pi4(0), pi5(0), pi6(0); + int cnt = 0; + + Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET); + Element el1(TET), el2(TET), el3(TET), el4(TET); + Element el1b(TET), el2b(TET), el3b(TET), el4b(TET); + + double bad1, bad2, bad3; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + //int nse = mesh.GetNSE(); + + // contains at least all elements at node + TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np); + + ARRAY<ElementIndex> hasbothpoints; + + PrintMessage (3, "SwapImprove "); + (*testout) << "\n" << "Start SwapImprove" << endl; + + const char * savetask = multithread.task; + multithread.task = "Swap Improve"; + + // mesh.CalcSurfacesOfNode (); + /* + for (i = 1; i <= GetNE(); i++) + if (volelements.Get(i).PNum(1)) + if (!LegalTet (volelements.Get(i))) + { + cout << "detected illegal tet, 1" << endl; + (*testout) << "detected illegal tet1: " << i << endl; + } + */ + + + INDEX_3_HASHTABLE<int> faces(mesh.GetNOpenElements()/3 + 2); + if (goal == OPT_CONFORM) + { + for (int i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & hel = mesh.OpenElement(i); + INDEX_3 face(hel[0], hel[1], hel[2]); + face.Sort(); + faces.Set (face, 1); + } + } + + // Calculate total badness + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + } + + // find elements on node + for (ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + /* + BitArray illegaltet(GetNE()); + MarkIllegalElements(); + if (goal == OPT_QUALITY || goal == OPT_LEGAL) + { + int cntill = 0; + for (i = 1; i <= GetNE(); i++) + { + // if (!LegalTet (volelements.Get(i))) + if (VolumeElement(i).flags.illegal) + { + cntill++; + illegaltet.Set (i); + } + } + // (*mycout) << cntill << " illegal tets" << endl; + } + */ + + INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5); + + for (ei = 0; ei < ne; ei++) + { + if (multithread.terminate) + break; + + multithread.percent = 100.0 * (ei+1) / ne; + + if ((mesh.ElementType(ei)) == FIXEDELEMENT) + continue; + + if(working_elements && + ei < working_elements->Size() && + !working_elements->Test(ei)) + continue; + + if (mesh[ei].IsDeleted()) + continue; + + if ((goal == OPT_LEGAL) && + mesh.LegalTet (mesh[ei]) && + CalcBad (mesh.Points(), mesh[ei], 0) < 1e3) + continue; + + // int onlybedges = 1; + + for (j = 0; j < 6; j++) + { + // loop over edges + + const Element & elemi = mesh[ei]; + if (elemi.IsDeleted()) continue; + + + // (*testout) << "check element " << elemi << endl; + + int mattyp = elemi.GetIndex(); + + static const int tetedges[6][2] = + { { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 1, 2 }, { 1, 3 }, { 2, 3 } }; + + pi1 = elemi[tetedges[j][0]]; + pi2 = elemi[tetedges[j][1]]; + + + if (pi2 < pi1) Swap (pi1, pi2); + + if (mesh.BoundaryEdge (pi1, pi2)) continue; + + + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + if (edgeused.Used(i2)) continue; + edgeused.Set (i2, 1); + + hasbothpoints.SetSize (0); + for (k = 0; k < elementsonnode[pi1].Size(); k++) + { + bool has1 = 0, has2 = 0; + ElementIndex elnr = elementsonnode[pi1][k]; + const Element & elem = mesh[elnr]; + + if (elem.IsDeleted()) continue; + + for (l = 0; l < elem.GetNP(); l++) + { + if (elem[l] == pi1) has1 = 1; + if (elem[l] == pi2) has2 = 1; + } + + if (has1 && has2) + { // only once + for (l = 0; l < hasbothpoints.Size(); l++) + if (hasbothpoints[l] == elnr) + has1 = 0; + + if (has1) + hasbothpoints.Append (elnr); + } + } + + bool puretet = 1; + for (k = 0; k < hasbothpoints.Size(); k++) + if (mesh[hasbothpoints[k]].GetType () != TET) + puretet = 0; + if (!puretet) + continue; + + int nsuround = hasbothpoints.Size(); + + if ( nsuround == 3 ) + { + Element & elem = mesh[hasbothpoints[0]]; + for (l = 0; l < 4; l++) + if (elem[l] != pi1 && elem[l] != pi2) + { + pi4 = pi3; + pi3 = elem[l]; + } + + el31[0] = pi1; + el31[1] = pi2; + el31[2] = pi3; + el31[3] = pi4; + el31.SetIndex (mattyp); + + if (WrongOrientation (mesh.Points(), el31)) + { + Swap (pi3, pi4); + el31[2] = pi3; + el31[3] = pi4; + } + + pi5 = 0; + for (k = 1; k < 3; k++) + { + const Element & elemk = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (l = 0; l < 4; l++) + if (elemk[l] == pi4) + has1 = 1; + if (has1) + { + for (l = 0; l < 4; l++) + if (elemk[l] != pi1 && elemk[l] != pi2 && elemk[l] != pi4) + pi5 = elemk[l]; + } + } + + if(pi5 == 0) + throw NgException("Illegal state observed in SwapImprove"); + + + + el32[0] = pi1; + el32[1] = pi2; + el32[2] = pi4; + el32[3] = pi5; + el32.SetIndex (mattyp); + + el33[0] = pi1; + el33[1] = pi2; + el33[2] = pi5; + el33[3] = pi3; + el33.SetIndex (mattyp); + + elementsonnode.Add (pi4, hasbothpoints[1]); + elementsonnode.Add (pi3, hasbothpoints[2]); + + bad1 = CalcBad (mesh.Points(), el31, 0) + + CalcBad (mesh.Points(), el32, 0) + + CalcBad (mesh.Points(), el33, 0); + + el31.flags.illegal_valid = 0; + el32.flags.illegal_valid = 0; + el33.flags.illegal_valid = 0; + + if (!mesh.LegalTet(el31) || + !mesh.LegalTet(el32) || + !mesh.LegalTet(el33)) + bad1 += 1e4; + + el21[0] = pi3; + el21[1] = pi4; + el21[2] = pi5; + el21[3] = pi2; + el21.SetIndex (mattyp); + + el22[0] = pi5; + el22[1] = pi4; + el22[2] = pi3; + el22[3] = pi1; + el22.SetIndex (mattyp); + + bad2 = CalcBad (mesh.Points(), el21, 0) + + CalcBad (mesh.Points(), el22, 0); + + el21.flags.illegal_valid = 0; + el22.flags.illegal_valid = 0; + + if (!mesh.LegalTet(el21) || + !mesh.LegalTet(el22)) + bad2 += 1e4; + + + if (goal == OPT_CONFORM && bad2 < 1e4) + { + INDEX_3 face(pi3, pi4, pi5); + face.Sort(); + if (faces.Used(face)) + { + // (*testout) << "3->2 swap, could improve conformity, bad1 = " << bad1 + // << ", bad2 = " << bad2 << endl; + if (bad2 < 1e4) + bad1 = 2 * bad2; + } + /* + else + { + INDEX_2 hi1(pi3, pi4); + hi1.Sort(); + INDEX_2 hi2(pi3, pi5); + hi2.Sort(); + INDEX_2 hi3(pi4, pi5); + hi3.Sort(); + + if (boundaryedges->Used (hi1) || + boundaryedges->Used (hi2) || + boundaryedges->Used (hi3) ) + bad1 = 2 * bad2; + } + */ + } + + if (bad2 < bad1) + { + // (*mycout) << "3->2 " << flush; + // (*testout) << "3->2 conversion" << endl; + cnt++; + + + /* + (*testout) << "3->2 swap, old els = " << endl + << mesh[hasbothpoints[0]] << endl + << mesh[hasbothpoints[1]] << endl + << mesh[hasbothpoints[2]] << endl + << "new els = " << endl + << el21 << endl + << el22 << endl; + */ + + el21.flags.illegal_valid = 0; + el22.flags.illegal_valid = 0; + mesh[hasbothpoints[0]] = el21; + mesh[hasbothpoints[1]] = el22; + for (l = 0; l < 4; l++) + mesh[hasbothpoints[2]][l] = 0; + mesh[hasbothpoints[2]].Delete(); + + for (k = 0; k < 2; k++) + for (l = 0; l < 4; l++) + elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]); + } + } + + + if (nsuround == 4) + { + const Element & elem1 = mesh[hasbothpoints[0]]; + for (l = 0; l < 4; l++) + if (elem1[l] != pi1 && elem1[l] != pi2) + { + pi4 = pi3; + pi3 = elem1[l]; + } + + el1[0] = pi1; el1[1] = pi2; + el1[2] = pi3; el1[3] = pi4; + el1.SetIndex (mattyp); + + if (WrongOrientation (mesh.Points(), el1)) + { + Swap (pi3, pi4); + el1[2] = pi3; + el1[3] = pi4; + } + + pi5 = 0; + for (k = 1; k < 4; k++) + { + const Element & elem = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (l = 0; l < 4; l++) + if (elem[l] == pi4) + has1 = 1; + if (has1) + { + for (l = 0; l < 4; l++) + if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi4) + pi5 = elem[l]; + } + } + + pi6 = 0; + for (k = 1; k < 4; k++) + { + const Element & elem = mesh[hasbothpoints[k]]; + bool has1 = 0; + for (l = 0; l < 4; l++) + if (elem[l] == pi3) + has1 = 1; + if (has1) + { + for (l = 0; l < 4; l++) + if (elem[l] != pi1 && elem[l] != pi2 && elem[l] != pi3) + pi6 = elem[l]; + } + } + + /* + INDEX_2 i22(pi3, pi5); + i22.Sort(); + INDEX_2 i23(pi4, pi6); + i23.Sort(); + */ + + el1[0] = pi1; el1[1] = pi2; + el1[2] = pi3; el1[3] = pi4; + el1.SetIndex (mattyp); + + el2[0] = pi1; el2[1] = pi2; + el2[2] = pi4; el2[3] = pi5; + el2.SetIndex (mattyp); + + el3[0] = pi1; el3[1] = pi2; + el3[2] = pi5; el3[3] = pi6; + el3.SetIndex (mattyp); + + el4[0] = pi1; el4[1] = pi2; + el4[2] = pi6; el4[3] = pi3; + el4.SetIndex (mattyp); + + // elementsonnode.Add (pi4, hasbothpoints.Elem(2)); + // elementsonnode.Add (pi3, hasbothpoints.Elem(3)); + + bad1 = CalcBad (mesh.Points(), el1, 0) + + CalcBad (mesh.Points(), el2, 0) + + CalcBad (mesh.Points(), el3, 0) + + CalcBad (mesh.Points(), el4, 0); + + + el1.flags.illegal_valid = 0; + el2.flags.illegal_valid = 0; + el3.flags.illegal_valid = 0; + el4.flags.illegal_valid = 0; + + + if (goal != OPT_CONFORM) + { + if (!mesh.LegalTet(el1) || + !mesh.LegalTet(el2) || + !mesh.LegalTet(el3) || + !mesh.LegalTet(el4)) + bad1 += 1e4; + } + + el1[0] = pi3; el1[1] = pi5; + el1[2] = pi2; el1[3] = pi4; + el1.SetIndex (mattyp); + + el2[0] = pi3; el2[1] = pi5; + el2[2] = pi4; el2[3] = pi1; + el2.SetIndex (mattyp); + + el3[0] = pi3; el3[1] = pi5; + el3[2] = pi1; el3[3] = pi6; + el3.SetIndex (mattyp); + + el4[0] = pi3; el4[1] = pi5; + el4[2] = pi6; el4[3] = pi2; + el4.SetIndex (mattyp); + + bad2 = CalcBad (mesh.Points(), el1, 0) + + CalcBad (mesh.Points(), el2, 0) + + CalcBad (mesh.Points(), el3, 0) + + CalcBad (mesh.Points(), el4, 0); + + el1.flags.illegal_valid = 0; + el2.flags.illegal_valid = 0; + el3.flags.illegal_valid = 0; + el4.flags.illegal_valid = 0; + + if (goal != OPT_CONFORM) + { + if (!mesh.LegalTet(el1) || + !mesh.LegalTet(el2) || + !mesh.LegalTet(el3) || + !mesh.LegalTet(el4)) + bad2 += 1e4; + } + + + el1b[0] = pi4; el1b[1] = pi6; + el1b[2] = pi3; el1b[3] = pi2; + el1b.SetIndex (mattyp); + + el2b[0] = pi4; el2b[1] = pi6; + el2b[2] = pi2; el2b[3] = pi5; + el2b.SetIndex (mattyp); + + el3b[0] = pi4; el3b[1] = pi6; + el3b[2] = pi5; el3b[3] = pi1; + el3b.SetIndex (mattyp); + + el4b[0] = pi4; el4b[1] = pi6; + el4b[2] = pi1; el4b[3] = pi3; + el4b.SetIndex (mattyp); + + bad3 = CalcBad (mesh.Points(), el1b, 0) + + CalcBad (mesh.Points(), el2b, 0) + + CalcBad (mesh.Points(), el3b, 0) + + CalcBad (mesh.Points(), el4b, 0); + + el1b.flags.illegal_valid = 0; + el2b.flags.illegal_valid = 0; + el3b.flags.illegal_valid = 0; + el4b.flags.illegal_valid = 0; + + if (goal != OPT_CONFORM) + { + if (!mesh.LegalTet(el1b) || + !mesh.LegalTet(el2b) || + !mesh.LegalTet(el3b) || + !mesh.LegalTet(el4b)) + bad3 += 1e4; + } + + + /* + int swap2 = (bad2 < bad1) && (bad2 < bad3); + int swap3 = !swap2 && (bad3 < bad1); + + if ( ((bad2 < 10 * bad1) || + (bad2 < 1e6)) && mesh.BoundaryEdge (pi3, pi5)) + swap2 = 1; + else if ( ((bad3 < 10 * bad1) || + (bad3 < 1e6)) && mesh.BoundaryEdge (pi4, pi6)) + { + swap3 = 1; + swap2 = 0; + } + */ + bool swap2, swap3; + + if (goal != OPT_CONFORM) + { + swap2 = (bad2 < bad1) && (bad2 < bad3); + swap3 = !swap2 && (bad3 < bad1); + } + else + { + if (mesh.BoundaryEdge (pi3, pi5)) bad2 /= 1e6; + if (mesh.BoundaryEdge (pi4, pi6)) bad3 /= 1e6; + + swap2 = (bad2 < bad1) && (bad2 < bad3); + swap3 = !swap2 && (bad3 < bad1); + } + + + if (swap2 || swap3) + { + // (*mycout) << "4->4 " << flush; + cnt++; + // (*testout) << "4->4 conversion" << "\n"; + /* + (*testout) << "bad1 = " << bad1 + << " bad2 = " << bad2 + << " bad3 = " << bad3 << "\n"; + + (*testout) << "Points: " << pi1 << " " << pi2 << " " << pi3 + << " " << pi4 << " " << pi5 << " " << pi6 << "\n"; + (*testout) << "Elements: " + << hasbothpoints.Get(1) << " " + << hasbothpoints.Get(2) << " " + << hasbothpoints.Get(3) << " " + << hasbothpoints.Get(4) << " " << "\n"; + */ + + /* + { + int i1, j1; + for (i1 = 1; i1 <= 4; i1++) + { + for (j1 = 1; j1 <= 4; j1++) + (*testout) << volelements.Get(hasbothpoints.Get(i1)).PNum(j1) + << " "; + (*testout) << "\n"; + } + } + */ + } + + + if (swap2) + { + // (*mycout) << "bad1 = " << bad1 << " bad2 = " << bad2 << "\n"; + + + /* + (*testout) << "4->4 swap A, old els = " << endl + << mesh[hasbothpoints[0]] << endl + << mesh[hasbothpoints[1]] << endl + << mesh[hasbothpoints[2]] << endl + << mesh[hasbothpoints[3]] << endl + << "new els = " << endl + << el1 << endl + << el2 << endl + << el3 << endl + << el4 << endl; + */ + + + + el1.flags.illegal_valid = 0; + el2.flags.illegal_valid = 0; + el3.flags.illegal_valid = 0; + el4.flags.illegal_valid = 0; + + mesh[hasbothpoints[0]] = el1; + mesh[hasbothpoints[1]] = el2; + mesh[hasbothpoints[2]] = el3; + mesh[hasbothpoints[3]] = el4; + + for (k = 0; k < 4; k++) + for (l = 0; l < 4; l++) + elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]); + } + else if (swap3) + { + // (*mycout) << "bad1 = " << bad1 << " bad3 = " << bad3 << "\n"; + el1b.flags.illegal_valid = 0; + el2b.flags.illegal_valid = 0; + el3b.flags.illegal_valid = 0; + el4b.flags.illegal_valid = 0; + + + /* + (*testout) << "4->4 swap A, old els = " << endl + << mesh[hasbothpoints[0]] << endl + << mesh[hasbothpoints[1]] << endl + << mesh[hasbothpoints[2]] << endl + << mesh[hasbothpoints[3]] << endl + << "new els = " << endl + << el1b << endl + << el2b << endl + << el3b << endl + << el4b << endl; + */ + + + mesh[hasbothpoints[0]] = el1b; + mesh[hasbothpoints[1]] = el2b; + mesh[hasbothpoints[2]] = el3b; + mesh[hasbothpoints[3]] = el4b; + + + for (k = 0; k < 4; k++) + for (l = 0; l < 4; l++) + elementsonnode.Add (mesh[hasbothpoints[k]][l], hasbothpoints[k]); + } + } + + if (nsuround >= 5) + { + Element hel(TET); + + ArrayMem<PointIndex, 50> suroundpts(nsuround); + ArrayMem<char, 50> tetused(nsuround); + + Element & elem = mesh[hasbothpoints[0]]; + + for (l = 0; l < 4; l++) + if (elem[l] != pi1 && elem[l] != pi2) + { + pi4 = pi3; + pi3 = elem[l]; + } + + hel[0] = pi1; + hel[1] = pi2; + hel[2] = pi3; + hel[3] = pi4; + hel.SetIndex (mattyp); + + if (WrongOrientation (mesh.Points(), hel)) + { + Swap (pi3, pi4); + hel[2] = pi3; + hel[3] = pi4; + } + + + // suroundpts.SetSize (nsuround); + suroundpts[0] = pi3; + suroundpts[1] = pi4; + + tetused = 0; + tetused[0] = 1; + + for (l = 2; l < nsuround; l++) + { + int oldpi = suroundpts[l-1]; + int newpi = 0; + + for (k = 0; k < nsuround && !newpi; k++) + if (!tetused[k]) + { + const Element & nel = mesh[hasbothpoints[k]]; + + for (int k2 = 0; k2 < 4 && !newpi; k2++) + if (nel[k2] == oldpi) + { + newpi = + nel[0] + nel[1] + nel[2] + nel[3] + - pi1 - pi2 - oldpi; + + tetused[k] = 1; + suroundpts[l] = newpi; + } + } + } + + + bad1 = 0; + for (k = 0; k < nsuround; k++) + { + hel[0] = pi1; + hel[1] = pi2; + hel[2] = suroundpts[k]; + hel[3] = suroundpts[(k+1) % nsuround]; + hel.SetIndex (mattyp); + + bad1 += CalcBad (mesh.Points(), hel, 0); + } + + // (*testout) << "nsuround = " << nsuround << " bad1 = " << bad1 << endl; + + + int bestl = -1; + int confface = -1; + int confedge = -1; + double badopt = bad1; + + for (l = 0; l < nsuround; l++) + { + bad2 = 0; + + for (k = l+1; k <= nsuround + l - 2; k++) + { + hel[0] = suroundpts[l]; + hel[1] = suroundpts[k % nsuround]; + hel[2] = suroundpts[(k+1) % nsuround]; + hel[3] = pi2; + + bad2 += CalcBad (mesh.Points(), hel, 0); + hel.flags.illegal_valid = 0; + if (!mesh.LegalTet(hel)) bad2 += 1e4; + + hel[2] = suroundpts[k % nsuround]; + hel[1] = suroundpts[(k+1) % nsuround]; + hel[3] = pi1; + + bad2 += CalcBad (mesh.Points(), hel, 0); + + hel.flags.illegal_valid = 0; + if (!mesh.LegalTet(hel)) bad2 += 1e4; + } + // (*testout) << "bad2," << l << " = " << bad2 << endl; + + if ( bad2 < badopt ) + { + bestl = l; + badopt = bad2; + } + + + if (goal == OPT_CONFORM) + // (bad2 <= 100 * bad1 || bad2 <= 1e6)) + { + bool nottoobad = + (bad2 <= bad1) || + (bad2 <= 100 * bad1 && bad2 <= 1e18) || + (bad2 <= 1e8); + + for (k = l+1; k <= nsuround + l - 2; k++) + { + INDEX_3 hi3(suroundpts[l], + suroundpts[k % nsuround], + suroundpts[(k+1) % nsuround]); + hi3.Sort(); + if (faces.Used(hi3)) + { + // (*testout) << "could improve face conformity, bad1 = " << bad1 + // << ", bad 2 = " << bad2 << ", nottoobad = " << nottoobad << endl; + if (nottoobad) + confface = l; + } + } + + for (k = l+2; k <= nsuround+l-2; k++) + { + if (mesh.BoundaryEdge (suroundpts[l], + suroundpts[k % nsuround])) + { + /* + *testout << "could improve edge conformity, bad1 = " << bad1 + << ", bad 2 = " << bad2 << ", nottoobad = " << nottoobad << endl; + */ + if (nottoobad) + confedge = l; + } + } + } + } + + if (confedge != -1) + bestl = confedge; + if (confface != -1) + bestl = confface; + + if (bestl != -1) + { + // (*mycout) << nsuround << "->" << 2 * (nsuround-2) << " " << flush; + cnt++; + + for (k = bestl+1; k <= nsuround + bestl - 2; k++) + { + int k1; + + hel[0] = suroundpts[bestl]; + hel[1] = suroundpts[k % nsuround]; + hel[2] = suroundpts[(k+1) % nsuround]; + hel[3] = pi2; + hel.flags.illegal_valid = 0; + + /* + (*testout) << nsuround << "-swap, new el,top = " + << hel << endl; + */ + mesh.AddVolumeElement (hel); + + for (k1 = 0; k1 < 4; k1++) + elementsonnode.Add (hel[k1], mesh.GetNE()-1); + + + hel[2] = suroundpts[k % nsuround]; + hel[1] = suroundpts[(k+1) % nsuround]; + hel[3] = pi1; + + /* + (*testout) << nsuround << "-swap, new el,bot = " + << hel << endl; + */ + + mesh.AddVolumeElement (hel); + + for (k1 = 0; k1 < 4; k1++) + elementsonnode.Add (hel[k1], mesh.GetNE()-1); + } + + for (k = 0; k < nsuround; k++) + { + Element & rel = mesh[hasbothpoints[k]]; + /* + (*testout) << nsuround << "-swap, old el = " + << rel << endl; + */ + rel.Delete(); + for (int k1 = 0; k1 < 4; k1++) + rel[k1] = 0; + + } + } + } + } + + /* + if (onlybedges) + { + (*testout) << "bad tet: " + << volelements.Get(i)[0] + << volelements.Get(i)[1] + << volelements.Get(i)[2] + << volelements.Get(i)[3] << "\n"; + + if (!mesh.LegalTet (volelements.Get(i))) + cerr << "Illegal tet" << "\n"; + } + */ + } + // (*mycout) << endl; + + /* + cout << "edgeused: "; + edgeused.PrintMemInfo(cout); + */ + PrintMessage (5, cnt, " swaps performed"); + + + + + + mesh.Compress (); + + /* + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + // (*testout) << "Total badness = " << bad1 << endl; + } + */ + + /* + for (i = 1; i <= GetNE(); i++) + if (volelements.Get(i)[0]) + if (!mesh.LegalTet (volelements.Get(i))) + { + cout << "detected illegal tet, 2" << endl; + (*testout) << "detected illegal tet1: " << i << endl; + } + */ + + multithread.task = savetask; +} + + + + + + +void MeshOptimize3d :: SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal, + const BitArray * working_elements, + const ARRAY< ARRAY<int,PointIndex::BASE>* > * idmaps) +{ + ARRAY< ARRAY<int,PointIndex::BASE>* > locidmaps; + const ARRAY< ARRAY<int,PointIndex::BASE>* > * used_idmaps; + + if(idmaps) + used_idmaps = idmaps; + else + { + used_idmaps = &locidmaps; + + for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++) + { + if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC) + { + locidmaps.Append(new ARRAY<int,PointIndex::BASE>); + mesh.GetIdentifications().GetMap(i,*locidmaps.Last(),true); + } + } + } + + ElementIndex ei; + SurfaceElementIndex sei; + + PointIndex pi1, pi2, pi3, pi4, pi5, pi6; + PointIndex pi1other, pi2other; + int cnt = 0; + + //double bad1, bad2, bad3, sbad; + double bad1, sbad; + double h; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + + int mattype, othermattype; + + + // contains at least all elements at node + TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np); + TABLE<SurfaceElementIndex,PointIndex::BASE> surfaceelementsonnode(np); + TABLE<int,PointIndex::BASE> surfaceindicesonnode(np); + + ARRAY<ElementIndex> hasbothpoints; + ARRAY<ElementIndex> hasbothpointsother; + + PrintMessage (3, "SwapImproveSurface "); + (*testout) << "\n" << "Start SwapImproveSurface" << endl; + + const char * savetask = multithread.task; + multithread.task = "Swap Improve Surface"; + + + + // find elements on node + for (ei = 0; ei < ne; ei++) + for (int j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + for (sei = 0; sei < nse; sei++) + for(int j=0; j<mesh[sei].GetNP(); j++) + { + surfaceelementsonnode.Add(mesh[sei][j], sei); + if(!surfaceindicesonnode[mesh[sei][j]].Contains(mesh[sei].GetIndex())) + surfaceindicesonnode.Add(mesh[sei][j],mesh[sei].GetIndex()); + } + + bool periodic; + int idnum(-1); + + INDEX_2_HASHTABLE<int> edgeused(2 * ne + 5); + + for (ei = 0; ei < ne; ei++) + { + if (multithread.terminate) + break; + + multithread.percent = 100.0 * (ei+1) / ne; + + if (mesh.ElementType(ei) == FIXEDELEMENT) + continue; + + if(working_elements && + ei < working_elements->Size() && + !working_elements->Test(ei)) + continue; + + if (mesh[ei].IsDeleted()) + continue; + + if ((goal == OPT_LEGAL) && + mesh.LegalTet (mesh[ei]) && + CalcBad (mesh.Points(), mesh[ei], 0) < 1e3) + continue; + + const Element & elemi = mesh[ei]; + //Element elemi = mesh[ei]; + if (elemi.IsDeleted()) continue; + + + mattype = elemi.GetIndex(); + + bool swapped = false; + + for (int j = 0; !swapped && j < 6; j++) + { + // loop over edges + + + static const int tetedges[6][2] = + { { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 1, 2 }, { 1, 3 }, { 2, 3 } }; + + pi1 = elemi[tetedges[j][0]]; + pi2 = elemi[tetedges[j][1]]; + + + if (pi2 < pi1) + Swap (pi1, pi2); + + + bool found = false; + for(int k=0; !found && k<used_idmaps->Size(); k++) + { + if(pi2 < (*used_idmaps)[k]->Size() + PointIndex::BASE) + { + pi1other = (*(*used_idmaps)[k])[pi1]; + pi2other = (*(*used_idmaps)[k])[pi2]; + found = (pi1other != 0 && pi2other != 0 && pi1other != pi1 && pi2other != pi2); + if(found) + idnum = k; + } + } + if(found) + periodic = true; + else + { + periodic = false; + pi1other = pi1; pi2other = pi2; + } + + + + if (!mesh.BoundaryEdge (pi1, pi2) || + mesh.IsSegment(pi1, pi2)) continue; + + othermattype = -1; + + + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + if (edgeused.Used(i2)) continue; + edgeused.Set (i2, 1); + if(periodic) + { + i2.I1() = pi1other; + i2.I2() = pi2other; + i2.Sort(); + edgeused.Set(i2,1); + } + + + hasbothpoints.SetSize (0); + hasbothpointsother.SetSize (0); + for (int k = 0; k < elementsonnode[pi1].Size(); k++) + { + bool has1 = false, has2 = false; + ElementIndex elnr = elementsonnode[pi1][k]; + const Element & elem = mesh[elnr]; + + if (elem.IsDeleted()) continue; + + for (int l = 0; l < elem.GetNP(); l++) + { + if (elem[l] == pi1) has1 = true; + if (elem[l] == pi2) has2 = true; + } + + if (has1 && has2) + { + if(othermattype == -1 && elem.GetIndex() != mattype) + othermattype = elem.GetIndex(); + + if(elem.GetIndex() == mattype) + { + // only once + for (int l = 0; l < hasbothpoints.Size(); l++) + if (hasbothpoints[l] == elnr) + has1 = 0; + + if (has1) + hasbothpoints.Append (elnr); + } + else if(elem.GetIndex() == othermattype) + { + // only once + for (int l = 0; l < hasbothpointsother.Size(); l++) + if (hasbothpointsother[l] == elnr) + has1 = 0; + + if (has1) + hasbothpointsother.Append (elnr); + } + else + { + cout << "problem with domain indices" << endl; + (*testout) << "problem: mattype = " << mattype << ", othermattype = " << othermattype + << " elem " << elem << " mt " << elem.GetIndex() << endl + << " pi1 " << pi1 << " pi2 " << pi2 << endl; + (*testout) << "hasbothpoints:" << endl; + for(int ii=0; ii < hasbothpoints.Size(); ii++) + (*testout) << mesh[hasbothpoints[ii]] << endl; + (*testout) << "hasbothpointsother:" << endl; + for(int ii=0; ii < hasbothpointsother.Size(); ii++) + (*testout) << mesh[hasbothpointsother[ii]] << endl; + } + } + } + + if(hasbothpointsother.Size() > 0 && periodic) + throw NgException("SwapImproveSurface: Assumption about interface/periodicity wrong!"); + + if(periodic) + { + for (int k = 0; k < elementsonnode[pi1other].Size(); k++) + { + bool has1 = false, has2 = false; + ElementIndex elnr = elementsonnode[pi1other][k]; + const Element & elem = mesh[elnr]; + + if (elem.IsDeleted()) continue; + + for (int l = 0; l < elem.GetNP(); l++) + { + if (elem[l] == pi1other) has1 = true; + if (elem[l] == pi2other) has2 = true; + } + + if (has1 && has2) + { + if(othermattype == -1) + othermattype = elem.GetIndex(); + + // only once + for (int l = 0; l < hasbothpointsother.Size(); l++) + if (hasbothpointsother[l] == elnr) + has1 = 0; + + if (has1) + hasbothpointsother.Append (elnr); + } + } + } + + + //for(k=0; k<hasbothpoints.Size(); k++) + // (*testout) << "hasbothpoints["<<k<<"]: " << mesh[hasbothpoints[k]] << endl; + + + SurfaceElementIndex sel1=-1,sel2=-1; + SurfaceElementIndex sel1other=-1,sel2other=-1; + for(int k = 0; k < surfaceelementsonnode[pi1].Size(); k++) + { + bool has1 = false, has2 = false; + SurfaceElementIndex elnr = surfaceelementsonnode[pi1][k]; + const Element2d & elem = mesh[elnr]; + + if (elem.IsDeleted()) continue; + + for (int l = 0; l < elem.GetNP(); l++) + { + if (elem[l] == pi1) has1 = true; + if (elem[l] == pi2) has2 = true; + } + + if(has1 && has2 && elnr != sel2) + { + sel1 = sel2; + sel2 = elnr; + } + } + + if(periodic) + { + for(int k = 0; k < surfaceelementsonnode[pi1other].Size(); k++) + { + bool has1 = false, has2 = false; + SurfaceElementIndex elnr = surfaceelementsonnode[pi1other][k]; + const Element2d & elem = mesh[elnr]; + + if (elem.IsDeleted()) continue; + + for (int l = 0; l < elem.GetNP(); l++) + { + if (elem[l] == pi1other) has1 = true; + if (elem[l] == pi2other) has2 = true; + } + + if(has1 && has2 && elnr != sel2other) + { + sel1other = sel2other; + sel2other = elnr; + } + } + } + else + { + sel1other = sel1; sel2other = sel2; + } + + //(*testout) << "sel1 " << sel1 << " sel2 " << sel2 << " el " << mesh[sel1] << " resp. " << mesh[sel2] << endl; + + PointIndex sp1(0), sp2(0); + PointIndex sp1other, sp2other; + for(int l=0; l<mesh[sel1].GetNP(); l++) + if(mesh[sel1][l] != pi1 && mesh[sel1][l] != pi2) + sp1 = mesh[sel1][l]; + for(int l=0; l<mesh[sel2].GetNP(); l++) + if(mesh[sel2][l] != pi1 && mesh[sel2][l] != pi2) + sp2 = mesh[sel2][l]; + + if(periodic) + { + sp1other = (*(*used_idmaps)[idnum])[sp1]; + sp2other = (*(*used_idmaps)[idnum])[sp2]; + + bool change = false; + for(int l=0; !change && l<mesh[sel1other].GetNP(); l++) + change = (sp2other == mesh[sel1other][l]); + + if(change) + { + SurfaceElementIndex aux = sel1other; + sel1other = sel2other; + sel2other = aux; + } + + } + else + { + sp1other = sp1; sp2other = sp2; + } + + Vec<3> v1 = mesh[sp1]-mesh[pi1], + v2 = mesh[sp2]-mesh[pi1], + v3 = mesh[sp1]-mesh[pi2], + v4 = mesh[sp2]-mesh[pi2]; + double vol = 0.5*(Cross(v1,v2).Length() + Cross(v3,v4).Length()); + h = sqrt(vol); + h = 0; + + sbad = CalcTriangleBadness (mesh[pi1],mesh[pi2],mesh[sp1],0,0) + + CalcTriangleBadness (mesh[pi2],mesh[pi1],mesh[sp2],0,0); + + + + bool puretet = true; + for (int k = 0; puretet && k < hasbothpoints.Size(); k++) + if (mesh[hasbothpoints[k]].GetType () != TET) + puretet = false; + for (int k = 0; puretet && k < hasbothpointsother.Size(); k++) + if (mesh[hasbothpointsother[k]].GetType () != TET) + puretet = false; + if (!puretet) + continue; + + int nsuround = hasbothpoints.Size(); + int nsuroundother = hasbothpointsother.Size(); + + ARRAY < int > outerpoints(nsuround+1); + outerpoints[0] = sp1; + + for(int i=0; i<nsuround; i++) + { + bool done = false; + for(int jj=i; !done && jj<hasbothpoints.Size(); jj++) + { + for(int k=0; !done && k<4; k++) + if(mesh[hasbothpoints[jj]][k] == outerpoints[i]) + { + done = true; + for(int l=0; l<4; l++) + if(mesh[hasbothpoints[jj]][l] != pi1 && + mesh[hasbothpoints[jj]][l] != pi2 && + mesh[hasbothpoints[jj]][l] != outerpoints[i]) + outerpoints[i+1] = mesh[hasbothpoints[jj]][l]; + } + if(done) + { + ElementIndex aux = hasbothpoints[i]; + hasbothpoints[i] = hasbothpoints[jj]; + hasbothpoints[jj] = aux; + } + } + } + if(outerpoints[nsuround] != sp2) + { + cerr << "OJE OJE OJE" << endl; + (*testout) << "OJE OJE OJE" << endl; + (*testout) << "hasbothpoints: " << endl; + for(int ii=0; ii < hasbothpoints.Size(); ii++) + { + (*testout) << mesh[hasbothpoints[ii]] << endl; + for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++) + if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 0) + (*testout) << mesh[hasbothpoints[ii]][jj] << " between " + << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and " + << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl; + } + (*testout) << "outerpoints: " << outerpoints << endl; + (*testout) << "sel1 " << mesh[sel1] << endl + << "sel2 " << mesh[sel2] << endl; + for(int ii=0; ii<3; ii++) + { + if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0) + (*testout) << mesh[sel1][ii] << " between " + << mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and " + << mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl; + if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0) + (*testout) << mesh[sel2][ii] << " between " + << mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and " + << mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl; + } + } + + + ARRAY < int > outerpointsother; + + if(nsuroundother > 0) + { + outerpointsother.SetSize(nsuroundother+1); + outerpointsother[0] = sp2other; + } + + for(int i=0; i<nsuroundother; i++) + { + bool done = false; + for(int jj=i; !done && jj<hasbothpointsother.Size(); jj++) + { + for(int k=0; !done && k<4; k++) + if(mesh[hasbothpointsother[jj]][k] == outerpointsother[i]) + { + done = true; + for(int l=0; l<4; l++) + if(mesh[hasbothpointsother[jj]][l] != pi1other && + mesh[hasbothpointsother[jj]][l] != pi2other && + mesh[hasbothpointsother[jj]][l] != outerpointsother[i]) + outerpointsother[i+1] = mesh[hasbothpointsother[jj]][l]; + } + if(done) + { + ElementIndex aux = hasbothpointsother[i]; + hasbothpointsother[i] = hasbothpointsother[jj]; + hasbothpointsother[jj] = aux; + } + } + } + if(nsuroundother > 0 && outerpointsother[nsuroundother] != sp1other) + { + cerr << "OJE OJE OJE (other)" << endl; + (*testout) << "OJE OJE OJE (other)" << endl; + (*testout) << "pi1 " << pi1 << " pi2 " << pi2 << " sp1 " << sp1 << " sp2 " << sp2 << endl; + (*testout) << "hasbothpoints: " << endl; + for(int ii=0; ii < hasbothpoints.Size(); ii++) + { + (*testout) << mesh[hasbothpoints[ii]] << endl; + for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++) + if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 0) + (*testout) << mesh[hasbothpoints[ii]][jj] << " between " + << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and " + << mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl; + } + (*testout) << "outerpoints: " << outerpoints << endl; + (*testout) << "sel1 " << mesh[sel1] << endl + << "sel2 " << mesh[sel2] << endl; + for(int ii=0; ii<3; ii++) + { + if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0) + (*testout) << mesh[sel1][ii] << " between " + << mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and " + << mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl; + if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0) + (*testout) << mesh[sel2][ii] << " between " + << mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and " + << mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl; + } + + (*testout) << "pi1other " << pi1other << " pi2other " << pi2other << " sp1other " << sp1other << " sp2other " << sp2other << endl; + (*testout) << "hasbothpointsother: " << endl; + for(int ii=0; ii < hasbothpointsother.Size(); ii++) + { + (*testout) << mesh[hasbothpointsother[ii]] << endl; + for(int jj=0; jj<mesh[hasbothpointsother[ii]].GetNP(); jj++) + if(mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] > 0) + (*testout) << mesh[hasbothpointsother[ii]][jj] << " between " + << mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] << " and " + << mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][1] << endl; + } + (*testout) << "outerpoints: " << outerpointsother << endl; + (*testout) << "sel1other " << mesh[sel1other] << endl + << "sel2other " << mesh[sel2other] << endl; + for(int ii=0; ii<3; ii++) + { + if(mesh.mlbetweennodes[mesh[sel1other][ii]][0] > 0) + (*testout) << mesh[sel1other][ii] << " between " + << mesh.mlbetweennodes[mesh[sel1other][ii]][0] << " and " + << mesh.mlbetweennodes[mesh[sel1other][ii]][1] << endl; + if(mesh.mlbetweennodes[mesh[sel2other][ii]][0] > 0) + (*testout) << mesh[sel2other][ii] << " between " + << mesh.mlbetweennodes[mesh[sel2other][ii]][0] << " and " + << mesh.mlbetweennodes[mesh[sel2other][ii]][1] << endl; + } + } + + bad1=0; + for(int i=0; i<hasbothpoints.Size(); i++) + bad1 += CalcBad(mesh.Points(), mesh[hasbothpoints[i]],h); + for(int i=0; i<hasbothpointsother.Size(); i++) + bad1 += CalcBad(mesh.Points(), mesh[hasbothpointsother[i]],h); + bad1 /= double(hasbothpoints.Size() + hasbothpointsother.Size()); + + + int startpoints,startpointsother; + + + if(outerpoints.Size() == 3) + startpoints = 1; + else if(outerpoints.Size() == 4) + startpoints = 2; + else + startpoints = outerpoints.Size(); + + if(outerpointsother.Size() == 3) + startpointsother = 1; + else if(outerpointsother.Size() == 4) + startpointsother = 2; + else + startpointsother = outerpointsother.Size(); + + + ARRAY < ARRAY < Element* > * > newelts(startpoints); + ARRAY < ARRAY < Element* > * > neweltsother(startpointsother); + + double minbad = 1e50, minbadother = 1e50, currbad; + int minpos = -1, minposother = -1; + + //(*testout) << "pi1 " << pi1 << " pi2 " << pi2 << " outerpoints " << outerpoints << endl; + + for(int i=0; i<startpoints; i++) + { + newelts[i] = new ARRAY <Element*>(2*(nsuround-1)); + + for(int jj=0; jj<nsuround-1; jj++) + { + (*newelts[i])[2*jj] = new Element(TET); + (*newelts[i])[2*jj+1] = new Element(TET); + Element & newel1 = *((*newelts[i])[2*jj]); + Element & newel2 = *((*newelts[i])[2*jj+1]); + + newel1[0] = pi1; + newel1[1] = outerpoints[i]; + newel1[2] = outerpoints[(i+jj+1)%outerpoints.Size()]; + newel1[3] = outerpoints[(i+jj+2)%outerpoints.Size()]; + + newel2[0] = pi2; + newel2[1] = outerpoints[i]; + newel2[2] = outerpoints[(i+jj+2)%outerpoints.Size()]; + newel2[3] = outerpoints[(i+jj+1)%outerpoints.Size()]; + + + //(*testout) << "j " << j << " newel1 " << newel1[0] << " "<< newel1[1] << " "<< newel1[2] << " "<< newel1[3] << endl + // << " newel2 " << newel2[0] << " "<< newel2[1] << " "<< newel2[2] << " "<< newel2[3] << endl; + + newel1.SetIndex(mattype); + newel2.SetIndex(mattype); + + } + + bool wrongorientation = true; + for(int jj = 0; wrongorientation && jj<newelts[i]->Size(); jj++) + wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*newelts[i])[jj]); + + currbad = 0; + + for(int jj=0; jj<newelts[i]->Size(); jj++) + { + if(wrongorientation) + Swap((*(*newelts[i])[jj])[2],(*(*newelts[i])[jj])[3]); + + + // not two new faces on same surface + ARRAY<int> face_index; + for(int k = 0; k<surfaceindicesonnode[(*(*newelts[i])[jj])[0]].Size(); k++) + face_index.Append(surfaceindicesonnode[(*(*newelts[i])[jj])[0]][k]); + + for(int k=1; k<4; k++) + { + for(int l=0; l<face_index.Size(); l++) + { + if(face_index[l] != -1 && + !(surfaceindicesonnode[(*(*newelts[i])[jj])[k]].Contains(face_index[l]))) + face_index[l] = -1; + } + + } + + for(int k=0; k<face_index.Size(); k++) + if(face_index[k] != -1) + currbad += 1e12; + + + currbad += CalcBad(mesh.Points(),*(*newelts[i])[jj],h); + + + } + + //currbad /= double(newelts[i]->Size()); + + + + if(currbad < minbad) + { + minbad = currbad; + minpos = i; + } + + } + + if(startpointsother == 0) + minbadother = 0; + + for(int i=0; i<startpointsother; i++) + { + neweltsother[i] = new ARRAY <Element*>(2*(nsuroundother)); + + for(int jj=0; jj<nsuroundother; jj++) + { + (*neweltsother[i])[2*jj] = new Element(TET); + (*neweltsother[i])[2*jj+1] = new Element(TET); + Element & newel1 = *((*neweltsother[i])[2*jj]); + Element & newel2 = *((*neweltsother[i])[2*jj+1]); + + newel1[0] = pi1other; + newel1[1] = outerpointsother[i]; + newel1[2] = outerpointsother[(i+jj+1)%outerpointsother.Size()]; + newel1[3] = outerpointsother[(i+jj+2)%outerpointsother.Size()]; + + newel2[0] = pi2other; + newel2[1] = outerpointsother[i]; + newel2[2] = outerpointsother[(i+jj+2)%outerpointsother.Size()]; + newel2[3] = outerpointsother[(i+jj+1)%outerpointsother.Size()]; + + + //(*testout) << "j " << j << " newel1 " << newel1[0] << " "<< newel1[1] << " "<< newel1[2] << " "<< newel1[3] << endl + // << " newel2 " << newel2[0] << " "<< newel2[1] << " "<< newel2[2] << " "<< newel2[3] << endl; + + newel1.SetIndex(othermattype); + newel2.SetIndex(othermattype); + + } + + bool wrongorientation = true; + for(int jj = 0; wrongorientation && jj<neweltsother[i]->Size(); jj++) + wrongorientation = wrongorientation && WrongOrientation(mesh.Points(), *(*neweltsother[i])[jj]); + + currbad = 0; + + for(int jj=0; jj<neweltsother[i]->Size(); jj++) + { + if(wrongorientation) + Swap((*(*neweltsother[i])[jj])[2],(*(*neweltsother[i])[jj])[3]); + + currbad += CalcBad(mesh.Points(),*(*neweltsother[i])[jj],h); + } + + //currbad /= double(neweltsother[i]->Size()); + + + + if(currbad < minbadother) + { + minbadother = currbad; + minposother = i; + } + + } + + //(*testout) << "minbad " << minbad << " bad1 " << bad1 << endl; + + + double sbadnew = CalcTriangleBadness (mesh[pi1],mesh[sp2],mesh[sp1],0,0) + + CalcTriangleBadness (mesh[pi2],mesh[sp1],mesh[sp2],0,0); + + + int denom = newelts[minpos]->Size(); + if(minposother >= 0) + denom += neweltsother[minposother]->Size(); + + + if((minbad+minbadother)/double(denom) < bad1 && + sbadnew < sbad) + { + cnt++; + + swapped = true; + + + int start1 = -1; + for(int l=0; l<3; l++) + if(mesh[sel1][l] == pi1) + start1 = l; + if(mesh[sel1][(start1+1)%3] == pi2) + { + mesh[sel1][0] = pi1; + mesh[sel1][1] = sp2; + mesh[sel1][2] = sp1; + mesh[sel2][0] = pi2; + mesh[sel2][1] = sp1; + mesh[sel2][2] = sp2; + } + else + { + mesh[sel1][0] = pi2; + mesh[sel1][1] = sp2; + mesh[sel1][2] = sp1; + mesh[sel2][0] = pi1; + mesh[sel2][1] = sp1; + mesh[sel2][2] = sp2; + } + //(*testout) << "changed surface element " << sel1 << " to " << mesh[sel1] << ", " << sel2 << " to " << mesh[sel2] << endl; + + for(int l=0; l<3; l++) + { + surfaceelementsonnode.Add(mesh[sel1][l],sel1); + surfaceelementsonnode.Add(mesh[sel2][l],sel2); + } + + + + if(periodic) + { + start1 = -1; + for(int l=0; l<3; l++) + if(mesh[sel1other][l] == pi1other) + start1 = l; + + + + //(*testout) << "changed surface elements " << mesh[sel1other] << " and " << mesh[sel2other] << endl; + if(mesh[sel1other][(start1+1)%3] == pi2other) + { + mesh[sel1other][0] = pi1other; + mesh[sel1other][1] = sp2other; + mesh[sel1other][2] = sp1other; + mesh[sel2other][0] = pi2other; + mesh[sel2other][1] = sp1other; + mesh[sel2other][2] = sp2other; + //(*testout) << " with rule 1" << endl; + } + else + { + mesh[sel1other][0] = pi2other; + mesh[sel1other][1] = sp2other; + mesh[sel1other][2] = sp1other; + mesh[sel2other][0] = pi1other; + mesh[sel2other][1] = sp1other; + mesh[sel2other][2] = sp2other; + //(*testout) << " with rule 2" << endl; + } + //(*testout) << " to " << mesh[sel1other] << " and " << mesh[sel2other] << endl; + + //(*testout) << " and surface element " << sel1other << " to " << mesh[sel1other] << ", " << sel2other << " to " << mesh[sel2other] << endl; + + for(int l=0; l<3; l++) + { + surfaceelementsonnode.Add(mesh[sel1other][l],sel1other); + surfaceelementsonnode.Add(mesh[sel2other][l],sel2other); + } + } + + + + + for(int i=0; i<hasbothpoints.Size(); i++) + { + mesh[hasbothpoints[i]] = *(*newelts[minpos])[i]; + + for(int l=0; l<4; l++) + elementsonnode.Add((*(*newelts[minpos])[i])[l],hasbothpoints[i]); + } + + for(int i=hasbothpoints.Size(); i<(*newelts[minpos]).Size(); i++) + { + ElementIndex ni = mesh.AddVolumeElement(*(*newelts[minpos])[i]); + + for(int l=0; l<4; l++) + elementsonnode.Add((*(*newelts[minpos])[i])[l],ni); + } + + if(hasbothpointsother.Size() > 0) + { + for(int i=0; i<hasbothpointsother.Size(); i++) + { + mesh[hasbothpointsother[i]] = *(*neweltsother[minposother])[i]; + for(int l=0; l<4; l++) + elementsonnode.Add((*(*neweltsother[minposother])[i])[l],hasbothpointsother[i]); + } + + for(int i=hasbothpointsother.Size(); i<(*neweltsother[minposother]).Size(); i++) + { + ElementIndex ni = mesh.AddVolumeElement(*(*neweltsother[minposother])[i]); + for(int l=0; l<4; l++) + elementsonnode.Add((*(*neweltsother[minposother])[i])[l],ni); + } + } + + + + } + + for(int i=0; i<newelts.Size(); i++) + { + for(int jj=0; jj<newelts[i]->Size(); jj++) + delete (*newelts[i])[jj]; + delete newelts[i]; + } + + for(int i=0; i<neweltsother.Size(); i++) + { + for(int jj=0; jj<neweltsother[i]->Size(); jj++) + delete (*neweltsother[i])[jj]; + delete neweltsother[i]; + } + + } + } + + PrintMessage (5, cnt, " swaps performed"); + + + for(int i=0; i<locidmaps.Size(); i++) + delete locidmaps[i]; + + + mesh.Compress (); + + multithread.task = savetask; +} + + + + + + + + +/* + 2 -> 3 conversion +*/ + + + +void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal) +{ + int j, k, l; + ElementIndex ei, eli1, eli2, elnr; + SurfaceElementIndex sei; + PointIndex pi1(0), pi2(0), pi3(0), pi4(0), pi5(0); + + int cnt = 0; + + Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET); + + double bad1, bad2; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + + if (goal == OPT_CONFORM) return; + + // contains at least all elements at node + TABLE<ElementIndex, PointIndex::BASE> elementsonnode(np); + TABLE<SurfaceElementIndex, PointIndex::BASE> belementsonnode(np); + + PrintMessage (3, "SwapImprove2 "); + (*testout) << "\n" << "Start SwapImprove2" << "\n"; + // TestOk(); + + + + /* + CalcSurfacesOfNode (); + for (i = 1; i <= GetNE(); i++) + if (volelements.Get(i)[0]) + if (!mesh.LegalTet (volelements.Get(i))) + { + cout << "detected illegal tet, 1" << endl; + (*testout) << "detected illegal tet1: " << i << endl; + } + */ + + + // Calculate total badness + + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + // cout << "tot bad = " << bad1 << endl; + + // find elements on node + + for (ei = 0; ei < ne; ei++) + for (j = 0; j < mesh[ei].GetNP(); j++) + elementsonnode.Add (mesh[ei][j], ei); + + for (sei = 0; sei < nse; sei++) + for (j = 0; j < 3; j++) + belementsonnode.Add (mesh[sei][j], sei); + + for (eli1 = 0; eli1 < ne; eli1++) + { + if (multithread.terminate) + break; + + if (mesh.ElementType (eli1) == FIXEDELEMENT) + continue; + + if (mesh[eli1].GetType() != TET) + continue; + + if ((goal == OPT_LEGAL) && + mesh.LegalTet (mesh[eli1]) && + CalcBad (mesh.Points(), mesh[eli1], 0) < 1e3) + continue; + + // cout << "eli = " << eli1 << endl; + // (*testout) << "swapimp2, eli = " << eli1 << "; el = " << mesh[eli1] << endl; + + for (j = 0; j < 4; j++) + { + // loop over faces + + Element & elem = mesh[eli1]; + // if (elem[0] < PointIndex::BASE) continue; + if (elem.IsDeleted()) continue; + + int mattyp = elem.GetIndex(); + + switch (j) + { + case 0: + pi1 = elem.PNum(1); pi2 = elem.PNum(2); + pi3 = elem.PNum(3); pi4 = elem.PNum(4); + break; + case 1: + pi1 = elem.PNum(1); pi2 = elem.PNum(4); + pi3 = elem.PNum(2); pi4 = elem.PNum(3); + break; + case 2: + pi1 = elem.PNum(1); pi2 = elem.PNum(3); + pi3 = elem.PNum(4); pi4 = elem.PNum(2); + break; + case 3: + pi1 = elem.PNum(2); pi2 = elem.PNum(4); + pi3 = elem.PNum(3); pi4 = elem.PNum(1); + break; + } + + + bool bface = 0; + for (k = 0; k < belementsonnode[pi1].Size(); k++) + { + const Element2d & bel = + mesh[belementsonnode[pi1][k]]; + + bool bface1 = 1; + for (l = 0; l < 3; l++) + if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3) + { + bface1 = 0; + break; + } + + if (bface1) + { + bface = 1; + break; + } + } + + if (bface) continue; + + + FlatArray<ElementIndex> row = elementsonnode[pi1]; + for (k = 0; k < row.Size(); k++) + { + eli2 = row[k]; + + // cout << "\rei1 = " << eli1 << ", pi1 = " << pi1 << ", k = " << k << ", ei2 = " << eli2 + // << ", getne = " << mesh.GetNE(); + + if ( eli1 != eli2 ) + { + Element & elem2 = mesh[eli2]; + if (elem2.IsDeleted()) continue; + if (elem2.GetType() != TET) + continue; + + int comnodes=0; + for (l = 1; l <= 4; l++) + if (elem2.PNum(l) == pi1 || elem2.PNum(l) == pi2 || + elem2.PNum(l) == pi3) + { + comnodes++; + } + else + { + pi5 = elem2.PNum(l); + } + + if (comnodes == 3) + { + bad1 = CalcBad (mesh.Points(), elem, 0) + + CalcBad (mesh.Points(), elem2, 0); + + if (!mesh.LegalTet(elem) || + !mesh.LegalTet(elem2)) + bad1 += 1e4; + + + el31.PNum(1) = pi1; + el31.PNum(2) = pi2; + el31.PNum(3) = pi5; + el31.PNum(4) = pi4; + el31.SetIndex (mattyp); + + el32.PNum(1) = pi2; + el32.PNum(2) = pi3; + el32.PNum(3) = pi5; + el32.PNum(4) = pi4; + el32.SetIndex (mattyp); + + el33.PNum(1) = pi3; + el33.PNum(2) = pi1; + el33.PNum(3) = pi5; + el33.PNum(4) = pi4; + el33.SetIndex (mattyp); + + bad2 = CalcBad (mesh.Points(), el31, 0) + + CalcBad (mesh.Points(), el32, 0) + + CalcBad (mesh.Points(), el33, 0); + + + el31.flags.illegal_valid = 0; + el32.flags.illegal_valid = 0; + el33.flags.illegal_valid = 0; + + if (!mesh.LegalTet(el31) || + !mesh.LegalTet(el32) || + !mesh.LegalTet(el33)) + bad2 += 1e4; + + + bool do_swap = (bad2 < bad1); + + if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) && + mesh.BoundaryEdge (pi4, pi5)) + do_swap = 1; + + if (do_swap) + { + // cout << "do swap, eli1 = " << eli1 << "; eli2 = " << eli2 << endl; + // (*mycout) << "2->3 " << flush; + cnt++; + + el31.flags.illegal_valid = 0; + el32.flags.illegal_valid = 0; + el33.flags.illegal_valid = 0; + + mesh[eli1] = el31; + mesh[eli2] = el32; + + ElementIndex neli = + mesh.AddVolumeElement (el33); + + /* + if (!LegalTet(el31) || !LegalTet(el32) || + !LegalTet(el33)) + { + cout << "Swap to illegal tets !!!" << endl; + } + */ + // cout << "neli = " << neli << endl; + for (l = 0; l < 4; l++) + { + elementsonnode.Add (el31[l], eli1); + elementsonnode.Add (el32[l], eli2); + elementsonnode.Add (el33[l], neli); + } + + break; + } + } + } + } + } + } + + + PrintMessage (5, cnt, " swaps performed"); + + + + /* + CalcSurfacesOfNode (); + for (i = 1; i <= GetNE(); i++) + if (volelements.Get(i).PNum(1)) + if (!LegalTet (volelements.Get(i))) + { + cout << "detected illegal tet, 2" << endl; + (*testout) << "detected illegal tet2: " << i << endl; + } + */ + + + bad1 = CalcTotalBad (mesh.Points(), mesh.VolumeElements()); + (*testout) << "Total badness = " << bad1 << endl; + (*testout) << "swapimprove2 done" << "\n"; + // (*mycout) << "Vol = " << CalcVolume (points, volelements) << "\n"; +} + + +/* + void Mesh :: SwapImprove2 (OPTIMIZEGOAL goal) + { + int i, j; + int eli1, eli2; + int mattyp; + + Element el31(4), el32(4), el33(4); + double bad1, bad2; + + + INDEX_3_HASHTABLE<INDEX_2> elsonface (GetNE()); + + (*mycout) << "SwapImprove2 " << endl; + (*testout) << "\n" << "Start SwapImprove2" << "\n"; + + // Calculate total badness + + if (goal == OPT_QUALITY) + { + double bad1 = CalcTotalBad (points, volelements); + (*testout) << "Total badness = " << bad1 << endl; + } + + // find elements on node + + + Element2d face; + for (i = 1; i <= GetNE(); i++) + if ( (i > eltyps.Size()) || (eltyps.Get(i) != FIXEDELEMENT) ) + { + const Element & el = VolumeElement(i); + if (!el.PNum(1)) continue; + + for (j = 1; j <= 4; j++) + { + el.GetFace (j, face); + INDEX_3 i3 (face.PNum(1), face.PNum(2), face.PNum(3)); + i3.Sort(); + + + int bnr, posnr; + if (!elsonface.PositionCreate (i3, bnr, posnr)) + { + INDEX_2 i2; + elsonface.GetData (bnr, posnr, i3, i2); + i2.I2() = i; + elsonface.SetData (bnr, posnr, i3, i2); + } + else + { + INDEX_2 i2 (i, 0); + elsonface.SetData (bnr, posnr, i3, i2); + } + + // if (elsonface.Used (i3)) + // { + // INDEX_2 i2 = elsonface.Get(i3); + // i2.I2() = i; + // elsonface.Set (i3, i2); + // } + // else + // { + // INDEX_2 i2 (i, 0); + // elsonface.Set (i3, i2); + // } + + } + } + + BitArray original(GetNE()); + original.Set(); + + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & sface = SurfaceElement(i); + INDEX_3 i3 (sface.PNum(1), sface.PNum(2), sface.PNum(3)); + i3.Sort(); + INDEX_2 i2(0,0); + elsonface.Set (i3, i2); + } + + + for (i = 1; i <= elsonface.GetNBags(); i++) + for (j = 1; j <= elsonface.GetBagSize(i); j++) + { + INDEX_3 i3; + INDEX_2 i2; + elsonface.GetData (i, j, i3, i2); + + + int eli1 = i2.I1(); + int eli2 = i2.I2(); + + if (eli1 && eli2 && original.Test(eli1) && original.Test(eli2) ) + { + Element & elem = volelements.Elem(eli1); + Element & elem2 = volelements.Elem(eli2); + + int pi1 = i3.I1(); + int pi2 = i3.I2(); + int pi3 = i3.I3(); + + int pi4 = elem.PNum(1) + elem.PNum(2) + elem.PNum(3) + elem.PNum(4) - pi1 - pi2 - pi3; + int pi5 = elem2.PNum(1) + elem2.PNum(2) + elem2.PNum(3) + elem2.PNum(4) - pi1 - pi2 - pi3; + + + + + + + el31.PNum(1) = pi1; + el31.PNum(2) = pi2; + el31.PNum(3) = pi3; + el31.PNum(4) = pi4; + el31.SetIndex (mattyp); + + if (WrongOrientation (points, el31)) + swap (pi1, pi2); + + + bad1 = CalcBad (points, elem, 0) + + CalcBad (points, elem2, 0); + + // if (!LegalTet(elem) || !LegalTet(elem2)) + // bad1 += 1e4; + + + el31.PNum(1) = pi1; + el31.PNum(2) = pi2; + el31.PNum(3) = pi5; + el31.PNum(4) = pi4; + el31.SetIndex (mattyp); + + el32.PNum(1) = pi2; + el32.PNum(2) = pi3; + el32.PNum(3) = pi5; + el32.PNum(4) = pi4; + el32.SetIndex (mattyp); + + el33.PNum(1) = pi3; + el33.PNum(2) = pi1; + el33.PNum(3) = pi5; + el33.PNum(4) = pi4; + el33.SetIndex (mattyp); + + bad2 = CalcBad (points, el31, 0) + + CalcBad (points, el32, 0) + + CalcBad (points, el33, 0); + + // if (!LegalTet(el31) || !LegalTet(el32) || + // !LegalTet(el33)) + // bad2 += 1e4; + + + int swap = (bad2 < bad1); + + INDEX_2 hi2b(pi4, pi5); + hi2b.Sort(); + + if ( ((bad2 < 1e6) || (bad2 < 10 * bad1)) && + boundaryedges->Used (hi2b) ) + swap = 1; + + if (swap) + { + (*mycout) << "2->3 " << flush; + + volelements.Elem(eli1) = el31; + volelements.Elem(eli2) = el32; + volelements.Append (el33); + + original.Clear (eli1); + original.Clear (eli2); + } + } + } + + (*mycout) << endl; + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (points, volelements); + (*testout) << "Total badness = " << bad1 << endl; + } + + // FindOpenElements (); + + (*testout) << "swapimprove2 done" << "\n"; + } + +*/ +} diff --git a/contrib/Netgen/libsrc/meshing/improve3.hpp b/contrib/Netgen/libsrc/meshing/improve3.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e82f37b028f86edd369620f52333b6d3120d5265 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/improve3.hpp @@ -0,0 +1,99 @@ +#ifndef FILE_IMPROVE3 +#define FILE_IMPROVE3 + + + + +/// +class MeshOptimize3d +{ +public: + void CombineImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); + void SplitImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); + void SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY, + const BitArray * working_elements = NULL); + void SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY, + const BitArray * working_elements = NULL, + const ARRAY< ARRAY<int,PointIndex::BASE>* > * idmaps = NULL); + void SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY); +}; + + + +extern double CalcBad (const Mesh::T_POINTS & points, const Element & elem, + double h); + +extern double CalcTotalBad (const Mesh::T_POINTS & points, + const Mesh::T_VOLELEMENTS & elements); + +extern int WrongOrientation (const Mesh::T_POINTS & points, const Element & el); + + +/* Functional depending of inner point inside triangular surface */ + + +class MinFunctionSum : public MinFunction +{ +protected: + ARRAY<MinFunction*> functions; + +public: + + virtual double Func (const Vector & x) const; + virtual void Grad (const Vector & x, Vector & g) const; + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; + virtual double GradStopping (const Vector & x) const; + + void AddFunction(MinFunction & fun); + + const MinFunction & Function(int i) const; + MinFunction & Function(int i); +}; + + + +class PointFunction1 : public MinFunction +{ + Mesh::T_POINTS & points; + const ARRAY<INDEX_3> & faces; + double h; +public: + PointFunction1 (Mesh::T_POINTS & apoints, + const ARRAY<INDEX_3> & afaces, + double ah); + + virtual double Func (const Vector & x) const; + virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double GradStopping (const Vector & x) const; +}; + + +class JacobianPointFunction : public MinFunction +{ +public: + Mesh::T_POINTS & points; + const Mesh::T_VOLELEMENTS & elements; + TABLE<INDEX> elementsonpoint; + PointIndex actpind; + + bool onplane; + Vec<3> nv; + +public: + JacobianPointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements); + + virtual void SetPointIndex (PointIndex aactpind); + virtual double Func (const Vector & x) const; + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; + + inline void SetNV(const Vec<3> & anv) {nv = anv; onplane = true;} + inline void UnSetNV(void) {onplane = false;} +}; + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/localh.cpp b/contrib/Netgen/libsrc/meshing/localh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a9f3d340da7294cc8f709a214ecd6c44661da77 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/localh.cpp @@ -0,0 +1,680 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + +GradingBox :: GradingBox (const double * ax1, const double * ax2) +{ + h2 = 0.5 * (ax2[0] - ax1[0]); + for (int i = 0; i <= 2; i++) + { + /* + x1[i] = ax1[i]; + x2[i] = ax2[i]; + */ + xmid[i] = 0.5 * (ax1[i] + ax2[i]); + } + + /* + (*testout) << "new box: " << xmid[0] << "-" << xmid[1] << "-" << xmid[2] + << " h = " << (x2[0] - x1[0]) << endl; + */ + + for (int i = 0; i < 8; i++) + childs[i] = NULL; + father = NULL; + + flags.cutboundary = 0; + flags.isinner = 0; + flags.oldcell = 0; + flags.pinner = 0; + + // hopt = x2[0] - x1[0]; + hopt = 2 * h2; +} + + + +BlockAllocator GradingBox :: ball(sizeof (GradingBox)); + +void * GradingBox :: operator new(size_t) +{ + return ball.Alloc(); +} + +void GradingBox :: operator delete (void * p) +{ + ball.Free (p); +} + + + + + + + +void GradingBox :: DeleteChilds() +{ + int i; + for (i = 0; i < 8; i++) + if (childs[i]) + { + childs[i]->DeleteChilds(); + delete childs[i]; + childs[i] = NULL; + } +} + + +LocalH :: LocalH (const Point3d & pmin, const Point3d & pmax, double agrading) +{ + double x1[3], x2[3]; + double hmax; + int i; + + boundingbox = Box3d (pmin, pmax); + grading = agrading; + + // a small enlargement, non-regular points + double val = 0.0879; + for (i = 1; i <= 3; i++) + { + + x1[i-1] = (1 + val * i) * pmin.X(i) - val * i * pmax.X(i); + x2[i-1] = 1.1 * pmax.X(i) - 0.1 * pmin.X(i); + } + + hmax = x2[0] - x1[0]; + for (i = 1; i <= 2; i++) + if (x2[i] - x1[i] > hmax) + hmax = x2[i] - x1[i]; + + for (i = 0; i <= 2; i++) + x2[i] = x1[i] + hmax; + + root = new GradingBox (x1, x2); + boxes.Append (root); +} + +LocalH :: ~LocalH () +{ + root->DeleteChilds(); + delete root; +} + +void LocalH :: Delete () +{ + root->DeleteChilds(); +} + +void LocalH :: SetH (const Point3d & p, double h) +{ + /* + (*testout) << "Set h at " << p << " to " << h << endl; + if (h < 1e-8) + { + cout << "do not set h to " << h << endl; + return; + } + */ + + if (fabs (p.X() - root->xmid[0]) > root->h2 || + fabs (p.Y() - root->xmid[1]) > root->h2 || + fabs (p.Z() - root->xmid[2]) > root->h2) + return; + + /* + if (p.X() < root->x1[0] || p.X() > root->x2[0] || + p.Y() < root->x1[1] || p.Y() > root->x2[1] || + p.Z() < root->x1[2] || p.Z() > root->x2[2]) + return; + */ + + + if (GetH(p) <= 1.2 * h) return; + + + GradingBox * box = root; + GradingBox * nbox = root; + GradingBox * ngb; + int childnr; + double x1[3], x2[3]; + + while (nbox) + { + box = nbox; + childnr = 0; + if (p.X() > box->xmid[0]) childnr += 1; + if (p.Y() > box->xmid[1]) childnr += 2; + if (p.Z() > box->xmid[2]) childnr += 4; + nbox = box->childs[childnr]; + }; + + + while (2 * box->h2 > h) + { + childnr = 0; + if (p.X() > box->xmid[0]) childnr += 1; + if (p.Y() > box->xmid[1]) childnr += 2; + if (p.Z() > box->xmid[2]) childnr += 4; + + double h2 = box->h2; + if (childnr & 1) + { + x1[0] = box->xmid[0]; + x2[0] = x1[0]+h2; // box->x2[0]; + } + else + { + x2[0] = box->xmid[0]; + x1[0] = x2[0]-h2; // box->x1[0]; + } + + if (childnr & 2) + { + x1[1] = box->xmid[1]; + x2[1] = x1[1]+h2; // box->x2[1]; + } + else + { + x2[1] = box->xmid[1]; + x1[1] = x2[1]-h2; // box->x1[1]; + } + + if (childnr & 4) + { + x1[2] = box->xmid[2]; + x2[2] = x1[2]+h2; // box->x2[2]; + } + else + { + x2[2] = box->xmid[2]; + x1[2] = x2[2]-h2; // box->x1[2]; + } + + ngb = new GradingBox (x1, x2); + box->childs[childnr] = ngb; + ngb->father = box; + + boxes.Append (ngb); + box = box->childs[childnr]; + } + + box->hopt = h; + + + double hbox = 2 * box->h2; // box->x2[0] - box->x1[0]; + double hnp = h + grading * hbox; + + Point3d np; + int i; + for (i = 1; i <= 3; i++) + { + np = p; + np.X(i) = p.X(i) + hbox; + SetH (np, hnp); + + np.X(i) = p.X(i) - hbox; + SetH (np, hnp); + } + /* + Point3d np; + int i1, i2, i3; + for (i1 = -1; i1 <= 1; i1++) + for (i2 = -1; i2 <= 1; i2++) + for (i3 = -1; i3 <= 1; i3++) + { + np.X() = p.X() + hbox * i1; + np.Y() = p.Y() + hbox * i2; + np.Z() = p.Z() + hbox * i3; + + SetH (np, hnp); + } + */ +} + + + +double LocalH :: GetH (const Point3d & x) const +{ + const GradingBox * box = root; + const GradingBox * nbox; + int childnr; + + while (1) + { + childnr = 0; + if (x.X() > box->xmid[0]) childnr += 1; + if (x.Y() > box->xmid[1]) childnr += 2; + if (x.Z() > box->xmid[2]) childnr += 4; + nbox = box->childs[childnr]; + if (nbox) + box = nbox; + else + { + // (*testout) << "diam = " << (box->x2[0] - box->x1[0]) + // << " h = " << box->hopt << endl; + return box->hopt; + } + } +} + + +/// minimal h in box (pmin, pmax) +double LocalH :: GetMinH (const Point3d & pmin, const Point3d & pmax) const +{ + Point3d pmin2, pmax2; + for (int j = 1; j <= 3; j++) + if (pmin.X(j) < pmax.X(j)) + { pmin2.X(j) = pmin.X(j); pmax2.X(j) = pmax.X(j); } + else + { pmin2.X(j) = pmax.X(j); pmax2.X(j) = pmin.X(j); } + + return GetMinHRec (pmin2, pmax2, root); +} + + +double LocalH :: GetMinHRec (const Point3d & pmin, const Point3d & pmax, + const GradingBox * box) const +{ + double h2 = box->h2; + if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 || + pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2 || + pmax.Z() < box->xmid[2]-h2 || pmin.Z() > box->xmid[2]+h2) + return 1e8; + /* + if (pmax.X() < box->x1[0] || pmin.X() > box->x2[0] || + pmax.Y() < box->x1[1] || pmin.Y() > box->x2[1] || + pmax.Z() < box->x1[2] || pmin.Z() > box->x2[2]) + return 1e8; + */ + + + double hmin = 2 * box->h2; // box->x2[0] - box->x1[0]; + int i; + + for (i = 0; i <= 7; i++) + { + if (box->childs[i]) + { + double hi = GetMinHRec (pmin, pmax, box->childs[i]); + if (hi < hmin) + hmin = hi; + } + } + + return hmin; +} + + +void LocalH :: CutBoundaryRec (const Point3d & pmin, const Point3d & pmax, + GradingBox * box) +{ + double h2 = box->h2; + if (pmax.X() < box->xmid[0]-h2 || pmin.X() > box->xmid[0]+h2 || + pmax.Y() < box->xmid[1]-h2 || pmin.Y() > box->xmid[1]+h2 || + pmax.Z() < box->xmid[2]-h2 || pmin.Z() > box->xmid[2]+h2) + return; + /* + if (pmax.X() < box->x1[0] || pmin.X() > box->x2[0] || + pmax.Y() < box->x1[1] || pmin.Y() > box->x2[1] || + pmax.Z() < box->x1[2] || pmin.Z() > box->x2[2]) + return; + */ + + box->flags.cutboundary = 1; + for (int i = 0; i < 8; i++) + if (box->childs[i]) + CutBoundaryRec (pmin, pmax, box->childs[i]); +} + + + + +void LocalH :: FindInnerBoxes ( // int (*sameside)(const Point3d & p1, const Point3d & p2), + AdFront3 * adfront, + int (*testinner)(const Point3d & p1)) +{ + int i; + + int nf = adfront->GetNF(); + + for (i = 0; i < boxes.Size(); i++) + boxes[i] -> flags.isinner = 0; + + root->flags.isinner = 0; + + Point3d rpmid(root->xmid[0], root->xmid[1], root->xmid[2]); + Vec3d rv(root->h2, root->h2, root->h2); + Point3d rx2 = rpmid + rv; + Point3d rx1 = rpmid - rv; + + + root->flags.pinner = !adfront->SameSide (rpmid, rx2); + + if (testinner) + (*testout) << "inner = " << root->flags.pinner << " =?= " + << testinner(Point3d(root->xmid[0], root->xmid[1], root->xmid[2])) << endl; + + ARRAY<int> faceinds(nf); + ARRAY<Box3d> faceboxes(nf); + + for (i = 1; i <= nf; i++) + { + faceinds.Elem(i) = i; + adfront->GetFaceBoundingBox(i, faceboxes.Elem(i)); + } + + for (i = 0; i < 8; i++) + FindInnerBoxesRec2 (root->childs[i], adfront, faceboxes, faceinds, nf); +} + + +void LocalH :: +FindInnerBoxesRec2 (GradingBox * box, + class AdFront3 * adfront, + ARRAY<Box3d> & faceboxes, + ARRAY<int> & faceinds, int nfinbox) +{ + if (!box) return; + + int i, j; + + GradingBox * father = box -> father; + + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + Vec3d v(box->h2, box->h2, box->h2); + Box3d boxc(c-v, c+v); + + Point3d fc(father->xmid[0], father->xmid[1], father->xmid[2]); + Vec3d fv(father->h2, father->h2, father->h2); + Box3d fboxc(fc-fv, fc+fv); + + Box3d boxcfc(c,fc); + + + static ARRAY<int> faceused; + static ARRAY<int> faceused2; + static ARRAY<int> facenotused; + + faceused.SetSize(0); + facenotused.SetSize(0); + faceused2.SetSize(0); + + for (j = 1; j <= nfinbox; j++) + { + // adfront->GetFaceBoundingBox (faceinds.Get(j), facebox); + const Box3d & facebox = faceboxes.Get(faceinds.Get(j)); + + if (boxc.Intersect (facebox)) + faceused.Append(faceinds.Get(j)); + else + facenotused.Append(faceinds.Get(j)); + + if (boxcfc.Intersect (facebox)) + faceused2.Append (faceinds.Get(j)); + } + + for (j = 1; j <= faceused.Size(); j++) + faceinds.Elem(j) = faceused.Get(j); + for (j = 1; j <= facenotused.Size(); j++) + faceinds.Elem(j+faceused.Size()) = facenotused.Get(j); + + + if (!father->flags.cutboundary) + { + box->flags.isinner = father->flags.isinner; + box->flags.pinner = father->flags.pinner; + } + else + { + Point3d cf(father->xmid[0], father->xmid[1], father->xmid[2]); + + if (father->flags.isinner) + box->flags.pinner = 1; + else + { + if (adfront->SameSide (c, cf, &faceused2)) + box->flags.pinner = father->flags.pinner; + else + box->flags.pinner = 1 - father->flags.pinner; + } + + if (box->flags.cutboundary) + box->flags.isinner = 0; + else + box->flags.isinner = box->flags.pinner; + } + + int nf = faceused.Size(); + for (i = 0; i < 8; i++) + FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds, nf); +} + + + + + + + + + + + + +/* +void LocalH :: FindInnerBoxes ( // int (*sameside)(const Point3d & p1, const Point3d & p2), + AdFront3 * adfront, + int (*testinner)(const Point3d & p1)) +{ + int i; + for (i = 1; i <= boxes.Size(); i++) + boxes.Elem(i)->flags.isinner = 0; + + root->flags.isinner = 0; + + Point3d rpmid(root->xmid[0], root->xmid[1], root->xmid[2]); + Point3d rx2 = rpmid + Vec3d (root->h2, root->h2, root->h2); + + root->flags.pinner = !adfront->SameSide (rpmid, rx2); + + if (testinner) + (*testout) << "inner = " << root->flags.pinner << " =?= " + << testinner(Point3d(root->xmid[0], root->xmid[1], root->xmid[2])) << endl; + + + for (i = 2; i <= boxes.Size(); i++) + { + GradingBox * box = boxes.Elem(i); + GradingBox * father = box -> father; + + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + Vec3d v(box->h2, box->h2, box->h2); + Point3d x1 = c-v; + Point3d x2 = c+v; + + + if (!father->flags.cutboundary) + { + box->flags.isinner = father->flags.isinner; + box->flags.pinner = father->flags.pinner; + } + else + { + Point3d cf(father->xmid[0], father->xmid[1], father->xmid[2]); + + if (father->flags.isinner) + box->flags.pinner = 1; + else + { + if (adfront->SameSide (c, cf)) + box->flags.pinner = father->flags.pinner; + else + box->flags.pinner = 1 - father->flags.pinner; + } + + if (box->flags.cutboundary) + box->flags.isinner = 0; + else + box->flags.isinner = box->flags.pinner; + } + } + // FindInnerBoxesRec (inner, root); +} +*/ + + +void LocalH :: FindInnerBoxesRec ( int (*inner)(const Point3d & p), + GradingBox * box) +{ + int i; + if (box->flags.cutboundary) + { + for (i = 0; i < 8; i++) + if (box->childs[i]) + FindInnerBoxesRec (inner, box->childs[i]); + } + else + { + if (inner (Point3d (box->xmid[0], box->xmid[1], box->xmid[2]))) + SetInnerBoxesRec (box); + } +} + + +void LocalH :: SetInnerBoxesRec (GradingBox * box) +{ + box->flags.isinner = 1; + for (int i = 0; i < 8; i++) + if (box->childs[i]) + ClearFlagsRec (box->childs[i]); +} + +void LocalH :: ClearFlagsRec (GradingBox * box) +{ + box->flags.cutboundary = 0; + box->flags.isinner = 0; + for (int i = 0; i < 8; i++) + if (box->childs[i]) + ClearFlagsRec (box->childs[i]); +} + + +void LocalH :: WidenRefinement () +{ + int nb = boxes.Size(); + int i; + // (*testout) << "old boxes: " << nb << endl; + for (i = 1; i <= nb; i++) + { + GradingBox * box = boxes.Get(i); + // double h = box->x2[0] - box->x1[0]; + double h = box->hopt; + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + // (*testout) << " i = " << i + // << " c = " << c << " h = " << h << endl; + + for (int i1 = -1; i1 <= 1; i1++) + for (int i2 = -1; i2 <= 1; i2++) + for (int i3 = -1; i3 <= 1; i3++) + SetH (Point3d (c.X() + i1 * h, + c.Y() + i2 * h, + c.Z() + i3 * h), 1.001 * h); + } +} + +void LocalH :: GetInnerPoints (ARRAY<Point3d> & points) +{ + int i, nb = boxes.Size(); + + for (i = 1; i <= nb; i++) + { + GradingBox * box = boxes.Get(i); + /* + if (box->flags.pinner) + points.Append (box->randomip); + */ + // if (box->flags.pinner) + if (box->flags.isinner) + { + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + points.Append (c); + /* + cout << "add point " << c << "; h = " << box->hopt + << "; max-min = " << (box->x2[0]-box->x1[0]) << endl; + */ + } + } +} + + + +void LocalH :: GetOuterPoints (ARRAY<Point3d> & points) +{ + int i, nb = boxes.Size(); + + for (i = 1; i <= nb; i++) + { + GradingBox * box = boxes.Get(i); + if (!box->flags.isinner && + !box->flags.cutboundary) + { + Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); + points.Append (c); + } + } +} + + + +void LocalH :: Convexify () +{ + ConvexifyRec (root); +} + +void LocalH :: ConvexifyRec (GradingBox * box) +{ + Point3d center(box->xmid[0], box->xmid[1], box->xmid[2]); + Point3d hp; + + double size = 2 * box->h2; // box->x2[0] - box->x1[0]; + double dx = 0.6 * size; + + double maxh = box->hopt; + int i; + + + + for (i = 1; i <= 6; i++) + { + hp = center; + switch (i) + { + case 1: hp.X() += dx; break; + case 2: hp.X() -= dx; break; + case 3: hp.Y() += dx; break; + case 4: hp.Y() -= dx; break; + case 5: hp.Z() += dx; break; + case 6: hp.Z() -= dx; break; + } + + double hh = GetH (hp); + if (hh > maxh) maxh = hh; + } + + if (maxh < 0.95 * box->hopt) + SetH (center, maxh); + + for (i = 0; i < 8; i++) + if (box->childs[i]) + ConvexifyRec (box->childs[i]); +} + +void LocalH :: PrintMemInfo (ostream & ost) const +{ + ost << "LocalH: " << boxes.Size() << " boxes of " << sizeof(GradingBox) + << " bytes = " << boxes.Size()*sizeof(GradingBox) << " bytes" << endl; +} +} diff --git a/contrib/Netgen/libsrc/meshing/localh.hpp b/contrib/Netgen/libsrc/meshing/localh.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7531bc7faf8b71107857cd19606e6cb7764e71b8 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/localh.hpp @@ -0,0 +1,145 @@ +#ifndef LOCALH +#define LOCALH + +/**************************************************************************/ +/* File: localh.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 29. Jan. 97 */ +/**************************************************************************/ + + + + +/// box for grading +class GradingBox +{ + /* + /// xmin + float x1[3]; + /// xmax + float x2[3]; + */ + /// xmid + float xmid[3]; + /// half edgelength + float h2; + /// + GradingBox * childs[8]; + /// + GradingBox * father; + /// + double hopt; + /// + struct + { + unsigned int cutboundary:1; + unsigned int isinner:1; + unsigned int oldcell:1; + unsigned int pinner:1; + } flags; +public: + /// + GradingBox (const double * ax1, const double * ax2); + /// + void DeleteChilds(); + /// + friend class LocalH; + + + static BlockAllocator ball; + void * operator new(size_t); + void operator delete (void *); +}; + + + +/** + Control of 3D mesh grading + */ +class LocalH +{ + /// + GradingBox * root; + /// + double grading; + /// + ARRAY<GradingBox*> boxes; + /// + Box3d boundingbox; +public: + /// + LocalH (const Point3d & pmin, const Point3d & pmax, double grading); + /// + ~LocalH(); + /// + void Delete(); + /// + void SetGrading (double agrading) { grading = agrading; } + /// + void SetH (const Point3d & x, double h); + /// + double GetH (const Point3d & x) const; + /// minimal h in box (pmin, pmax) + double GetMinH (const Point3d & pmin, const Point3d & pmax) const; + + /// mark boxes intersecting with boundary-box + void CutBoundary (const Point3d & pmin, const Point3d & pmax) + { CutBoundaryRec (pmin, pmax, root); } + + /// find inner boxes + void FindInnerBoxes ( // int (*sameside)(const Point3d & p1, const Point3d & p2), + class AdFront3 * adfront, + int (*testinner)(const Point3d & p1)); + + /// clears all flags + void ClearFlags () + { ClearFlagsRec(root); } + + /// widen refinement zone + void WidenRefinement (); + + /// get points in inner elements + void GetInnerPoints (ARRAY<Point3d> & points); + + /// get points in outer closure + void GetOuterPoints (ARRAY<Point3d> & points); + + /// + void Convexify (); + /// + int GetNBoxes () { return boxes.Size(); } + const Box3d & GetBoundingBox () const + { return boundingbox; } + /// + void PrintMemInfo (ostream & ost) const; +private: + /// + double GetMinHRec (const Point3d & pmin, const Point3d & pmax, + const GradingBox * box) const; + /// + void CutBoundaryRec (const Point3d & pmin, const Point3d & pmax, + GradingBox * box); + + /// + void FindInnerBoxesRec ( int (*inner)(const Point3d & p), + GradingBox * box); + + /// + void FindInnerBoxesRec2 (GradingBox * box, + class AdFront3 * adfront, + ARRAY<Box3d> & faceboxes, + ARRAY<int> & finds, int nfinbox); + + + /// + void SetInnerBoxesRec (GradingBox * box); + + /// + void ClearFlagsRec (GradingBox * box); + + /// + void ConvexifyRec (GradingBox * box); +}; + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/meshclass.cpp b/contrib/Netgen/libsrc/meshing/meshclass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dbec43e959bc56cb5fc3052aaa3129231b6d58a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshclass.cpp @@ -0,0 +1,5582 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +#ifdef PARALLEL +#include <parallel.hpp> +#endif + +namespace netgen +{ + + Mesh :: Mesh () + { + volelements.SetName ("vol elements"); + surfelements.SetName ("surf elements"); + points.SetName ("meshpoints"); + + boundaryedges = NULL; + surfelementht = NULL; + segmentht = NULL; + + lochfunc = NULL; + mglevels = 1; + elementsearchtree = NULL; + elementsearchtreets = NextTimeStamp(); + majortimestamp = timestamp = NextTimeStamp(); + hglob = 1e10; + hmin = 0; + numvertices = -1; + dimension = 3; + + topology = new MeshTopology (*this); + curvedelems = new CurvedElements (*this); + clusters = new AnisotropicClusters (*this); + ident = new Identifications (*this); + + hpelements = NULL; + coarsemesh = NULL; + + ps_startelement = 0; + + geomtype = NO_GEOM; + + bcnames.SetSize(0); +#ifdef PARALLEL + paralleltop = new ParallelMeshTopology (*this); +#endif + } + + + Mesh :: ~Mesh() + { + delete lochfunc; + delete boundaryedges; + delete surfelementht; + delete segmentht; + delete curvedelems; + delete clusters; + delete topology; + delete ident; + delete elementsearchtree; + + delete coarsemesh; + delete hpelements; + + for (int i = 0; i < materials.Size(); i++) + delete [] materials[i]; + + for(int i = 0; i < userdata_int.Size(); i++) + delete userdata_int[i]; + for(int i = 0; i < userdata_double.Size(); i++) + delete userdata_double[i]; + + for (int i = 0; i < bcnames.Size(); i++ ) + if ( bcnames[i] ) delete bcnames[i]; + +#ifdef PARALLEL + delete paralleltop; +#endif + } + + + Mesh & Mesh :: operator= (const Mesh & mesh2) + { + points = mesh2.points; + // eltyps = mesh2.eltyps; + segments = mesh2.segments; + surfelements = mesh2.surfelements; + volelements = mesh2.volelements; + lockedpoints = mesh2.lockedpoints; + facedecoding = mesh2.facedecoding; + dimension = mesh2.dimension; + + bcnames.SetSize( mesh2.bcnames.Size() ); + for ( int i = 0; i < mesh2.bcnames.Size(); i++ ) + if ( mesh2.bcnames[i] ) bcnames[i] = new string ( *mesh2.bcnames[i] ); + else bcnames[i] = 0; + + return *this; + } + + + void Mesh :: DeleteMesh() + { + points.SetSize(0); + segments.SetSize(0); + surfelements.SetSize(0); + volelements.SetSize(0); + lockedpoints.SetSize(0); + surfacesonnode.SetSize(0); + + delete boundaryedges; + boundaryedges = NULL; + + openelements.SetSize(0); + facedecoding.SetSize(0); + + delete ident; + ident = new Identifications (*this); + delete topology; + topology = new MeshTopology (*this); + delete curvedelems; + curvedelems = new CurvedElements (*this); + delete clusters; + clusters = new AnisotropicClusters (*this); + + for ( int i = 0; i < bcnames.Size(); i++ ) + if ( bcnames[i] ) delete bcnames[i]; + +#ifdef PARALLEL + delete paralleltop; + paralleltop = new ParallelMeshTopology (*this); +#endif + + + timestamp = NextTimeStamp(); + } + + + + PointIndex Mesh :: AddPoint (const Point3d & p, int layer) + { + NgLock lock(mutex); + lock.Lock(); + + timestamp = NextTimeStamp(); + + PointIndex pi = points.Size() + PointIndex::BASE; + points.Append ( MeshPoint (p, layer, INNERPOINT) ); + +#ifdef PARALLEL + points.Last().SetGhost(0); +#endif + + lock.UnLock(); + + return pi; + } + + PointIndex Mesh :: AddPoint (const Point3d & p, int layer, POINTTYPE type) + { + NgLock lock(mutex); + lock.Lock(); + + timestamp = NextTimeStamp(); + + PointIndex pi = points.Size() + PointIndex::BASE; + points.Append ( MeshPoint (p, layer, type) ); + +#ifdef PARALLEL + points.Last().SetGhost(0); +#endif + + lock.UnLock(); + + return pi; + } + + +#ifdef PARALLEL + PointIndex Mesh :: AddPoint (const Point3d & p, bool isghost, int layer) + { + NgLock lock(mutex); + lock.Lock(); + + timestamp = NextTimeStamp(); + + PointIndex pi = points.Size() + PointIndex::BASE; + points.Append ( MeshPoint (p, layer, INNERPOINT) ); + + points.Last().SetGhost(isghost); + + lock.UnLock(); + + return pi; + } + + PointIndex Mesh :: AddPoint (const Point3d & p, bool isghost, int layer, POINTTYPE type) + { + NgLock lock(mutex); + lock.Lock(); + + timestamp = NextTimeStamp(); + + PointIndex pi = points.Size() + PointIndex::BASE; + points.Append ( MeshPoint (p, layer, type) ); + + points.Last().SetGhost(isghost); + + lock.UnLock(); + + return pi; + } + +#endif + + + + SegmentIndex Mesh :: AddSegment (const Segment & s) + { + NgLock lock(mutex); + lock.Lock(); + timestamp = NextTimeStamp(); + + int maxn = max2 (s.p1, s.p2); + maxn += 1-PointIndex::BASE; + + /* + if (maxn > ptyps.Size()) + { + int maxo = ptyps.Size(); + ptyps.SetSize (maxn); + for (int i = maxo; i < maxn; i++) + ptyps[i] = INNERPOINT; + } + + if (ptyps[s.p1] > EDGEPOINT) ptyps[s.p1] = EDGEPOINT; + if (ptyps[s.p2] > EDGEPOINT) ptyps[s.p2] = EDGEPOINT; + */ + + if (maxn <= points.Size()) + { + if (points[s.p1].Type() > EDGEPOINT) + points[s.p1].SetType (EDGEPOINT); + if (points[s.p2].Type() > EDGEPOINT) + points[s.p2].SetType (EDGEPOINT); + } + /* + else + { + cerr << "edge points nrs > points.Size" << endl; + } + */ + + SegmentIndex si = segments.Size(); + segments.Append (s); + + lock.UnLock(); + return si; + } + + SurfaceElementIndex Mesh :: AddSurfaceElement (const Element2d & el) + { + NgLock lock(mutex); + lock.Lock(); + timestamp = NextTimeStamp(); + + int maxn = el[0]; + for (int i = 1; i < el.GetNP(); i++) + if (el[i] > maxn) maxn = el[i]; + + maxn += 1-PointIndex::BASE; + + /* + if (maxn > ptyps.Size()) + { + int maxo = ptyps.Size(); + ptyps.SetSize (maxn); + for (i = maxo+PointIndex::BASE; + i < maxn+PointIndex::BASE; i++) + ptyps[i] = INNERPOINT; + + } + */ + if (maxn <= points.Size()) + { + for (int i = 0; i < el.GetNP(); i++) + if (points[el[i]].Type() > SURFACEPOINT) + points[el[i]].SetType(SURFACEPOINT); + } + /* + else + { + cerr << "surf points nrs > points.Size" << endl; + } + */ + + SurfaceElementIndex si = surfelements.Size(); + surfelements.Append (el); + + if (el.index > facedecoding.Size()) + cerr << "has no facedecoding: fd.size = " << facedecoding.Size() << ", ind = " << el.index << endl; + + surfelements.Last().next = facedecoding[el.index-1].firstelement; + facedecoding[el.index-1].firstelement = si; + +#ifdef PARALLEL + surfelements.Last().SetGhost ( el.IsGhost() ); +#endif + + lock.UnLock(); + return si; + } + + + ElementIndex Mesh :: AddVolumeElement (const Element & el) + { + NgLock lock(mutex); + lock.Lock(); + + int maxn = el[0]; + for (int i = 1; i < el.GetNP(); i++) + if (el[i] > maxn) maxn = el[i]; + + maxn += 1-PointIndex::BASE; + + /* + if (maxn > ptyps.Size()) + { + int maxo = ptyps.Size(); + ptyps.SetSize (maxn); + for (i = maxo+PointIndex::BASE; + i < maxn+PointIndex::BASE; i++) + ptyps[i] = INNERPOINT; + } + */ + /* + if (maxn > points.Size()) + { + cerr << "add vol element before point" << endl; + } + */ + + int ve = volelements.Size(); + + volelements.Append (el); + volelements.Last().flags.illegal_valid = 0; + +#ifdef PARALLEL + volelements.Last().SetGhost ( el.IsGhost() ); +#endif + + // while (volelements.Size() > eltyps.Size()) + // eltyps.Append (FREEELEMENT); + + timestamp = NextTimeStamp(); + + lock.UnLock(); + return ve; + } + + + + + + + void Mesh :: Save (const string & filename) const + { + + ofstream outfile(filename.c_str()); + + Save(outfile); + } + + + + void Mesh :: Save (ostream & outfile) const + { + int i, j; + + double scale = 1; // globflags.GetNumFlag ("scale", 1); + int inverttets = 0; // globflags.GetDefineFlag ("inverttets"); + int invertsurf = 0; // globflags.GetDefineFlag ("invertsurfacemesh"); + + + + outfile << "mesh3d" << "\n"; + + outfile << "dimension\n" << GetDimension() << "\n"; + + outfile << "geomtype\n" << int(geomtype) << "\n"; + + + outfile << "\n"; + outfile << "# surfnr bcnr domin domout np p1 p2 p3" + << "\n"; + + + switch (geomtype) + { + case GEOM_STL: + outfile << "surfaceelementsgi" << "\n"; + break; + case GEOM_OCC: case GEOM_ACIS: + outfile << "surfaceelementsuv" << "\n"; + break; + default: + outfile << "surfaceelements" << "\n"; + } + + outfile << GetNSE() << "\n"; + + SurfaceElementIndex sei; + for (sei = 0; sei < GetNSE(); sei++) + { + if ((*this)[sei].GetIndex()) + { + outfile.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).SurfNr()+1; + outfile.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); + outfile.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainIn(); + outfile.width(8); + outfile << GetFaceDescriptor((*this)[sei].GetIndex ()).DomainOut(); + } + else + outfile << " 0 0 0"; + + Element2d sel = (*this)[sei]; + if (invertsurf) + sel.Invert(); + + outfile.width(8); + outfile << sel.GetNP(); + + for (j = 0; j < sel.GetNP(); j++) + { + outfile.width(8); + outfile << sel[j]; + } + + + switch (geomtype) + { + case GEOM_STL: + for (j = 1; j <= sel.GetNP(); j++) + { + outfile.width(7); + outfile << " " << sel.GeomInfoPi(j).trignum; + } + break; + case GEOM_OCC: case GEOM_ACIS: + for (j = 1; j <= sel.GetNP(); j++) + { + outfile.width(7); + outfile << " " << sel.GeomInfoPi(j).u; + outfile << " " << sel.GeomInfoPi(j).v; + } + break; + default: + outfile << "\n"; + } + + + outfile << endl; + } + + outfile << "\n" << "\n"; + outfile << "# matnr np p1 p2 p3 p4" << "\n"; + outfile << "volumeelements" << "\n"; + outfile << GetNE() << "\n"; + + for (ElementIndex ei = 0; ei < GetNE(); ei++) + { + outfile.width(8); + outfile << (*this)[ei].GetIndex(); + outfile.width(8); + outfile << (*this)[ei].GetNP(); + + Element el = (*this)[ei]; + if (inverttets) + el.Invert(); + + /* + for (j = 0; j < el.GetNP(); j++) + for (int k = 0; k < el.GetNP()-1; k++) + if (el[k] > el[k+1]) swap (el[k], el[k+1]); + */ + + for (j = 0; j < el.GetNP(); j++) + { + outfile.width(8); + outfile << el[j]; + } + outfile << "\n"; + } + + + outfile << "\n" << "\n"; +// outfile << " surf1 surf2 p1 p2" << "\n"; + outfile << "# surfid 0 p1 p2 trignum1 trignum2 domin/surfnr1 domout/surfnr2 ednr1 dist1 ednr2 dist2 \n"; + outfile << "edgesegmentsgi2" << "\n"; + outfile << GetNSeg() << "\n"; + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + outfile.width(8); + outfile << seg.si; // 2D: bc number, 3D: wievielte Kante + outfile.width(8); + outfile << 0; + outfile.width(8); + outfile << seg.p1; + outfile.width(8); + outfile << seg.p2; + outfile << " "; + outfile.width(8); + outfile << seg.geominfo[0].trignum; // stl dreiecke + outfile << " "; + outfile.width(8); + outfile << seg.geominfo[1].trignum; // << endl; // stl dreieck + + if (dimension == 3) + { + outfile << " "; + outfile.width(8); + outfile << seg.surfnr1+1; + outfile << " "; + outfile.width(8); + outfile << seg.surfnr2+1; + } + else + { + outfile << " "; + outfile.width(8); + outfile << seg.domin; + outfile << " "; + outfile.width(8); + outfile << seg.domout; + } + + outfile << " "; + outfile.width(8); + outfile << seg.edgenr; + outfile << " "; + outfile.width(12); + outfile.precision(16); + outfile << seg.epgeominfo[0].dist; // splineparameter (2D) + outfile << " "; + outfile.width(8); + outfile.precision(16); + outfile << seg.epgeominfo[1].edgenr; // geometry dependent + outfile << " "; + outfile.width(12); + outfile << seg.epgeominfo[1].dist; + + outfile << "\n"; + } + + + outfile << "\n" << "\n"; + outfile << "# X Y Z" << "\n"; + outfile << "points" << "\n"; + outfile << GetNP() << "\n"; + outfile.precision(16); + outfile.setf (ios::fixed, ios::floatfield); + outfile.setf (ios::showpoint); + + PointIndex pi; + for (pi = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; pi++) + { + outfile.width(22); + outfile << (*this)[pi](0)/scale << " "; + outfile.width(22); + outfile << (*this)[pi](1)/scale << " "; + outfile.width(22); + outfile << (*this)[pi](2)/scale << "\n"; + } + + if (ident -> GetMaxNr() > 0) + { + outfile << "identifications\n"; + ARRAY<INDEX_2> identpairs; + int cnt = 0; + for (i = 1; i <= ident -> GetMaxNr(); i++) + { + ident -> GetPairs (i, identpairs); + cnt += identpairs.Size(); + } + outfile << cnt << "\n"; + for (i = 1; i <= ident -> GetMaxNr(); i++) + { + ident -> GetPairs (i, identpairs); + for (j = 1; j <= identpairs.Size(); j++) + { + outfile.width (8); + outfile << identpairs.Get(j).I1(); + outfile.width (8); + outfile << identpairs.Get(j).I2(); + outfile.width (8); + outfile << i << "\n"; + } + } + + outfile << "identificationtypes\n"; + outfile << ident -> GetMaxNr() << "\n"; + for (i = 1; i <= ident -> GetMaxNr(); i++) + { + int type = ident -> GetType(i); + outfile << " " << type; + } + outfile << "\n"; + } + + int cntmat = 0; + for (i = 1; i <= materials.Size(); i++) + if (materials.Get(i) && strlen (materials.Get(i))) + cntmat++; + + if (cntmat) + { + outfile << "materials" << endl; + outfile << cntmat << endl; + for (i = 1; i <= materials.Size(); i++) + if (materials.Get(i) && strlen (materials.Get(i))) + outfile << i << " " << materials.Get(i) << endl; + } + + + int cntbcnames = 0; + for ( int ii = 0; ii < bcnames.Size(); ii++ ) + if ( bcnames[ii] ) cntbcnames++; + + if ( cntbcnames ) + { + outfile << "\n\nbcnames" << endl << bcnames.Size() << endl; + for ( i = 0; i < bcnames.Size(); i++ ) + outfile << i+1 << "\t" << GetBCName(i) << endl; + outfile << endl << endl; + } + + /* + if ( GetDimension() == 2 ) + { + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != "" ) + { + bcprops.Append(seg.si); + cntbcnames++; + } + } + } + else + { + for (sei = 0; sei < GetNSE(); sei++) + { + if ((*this)[sei].GetIndex()) + { + int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); + string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName(); + if ( !bcprops.Contains(bcp) && + name != "" ) + { + bcprops.Append(bcp); + cntbcnames++; + } + } + } + } + + bcprops.SetSize(0); + if ( cntbcnames ) + { + outfile << "\nbcnames" << endl << cntbcnames << endl; + if ( GetDimension() == 2 ) + { + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + if ( ! bcprops.Contains(seg.si) && seg.GetBCName() != "" ) + { + bcprops.Append(seg.si); + outfile << seg.si << "\t" << seg.GetBCName() << endl; + } + } + } + else + { + for (sei = 0; sei < GetNSE(); sei++) + { + if ((*this)[sei].GetIndex()) + { + int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); + string name = GetFaceDescriptor((*this)[sei].GetIndex ()).BCName(); + if ( !bcprops.Contains(bcp) && + name != "" ) + { + bcprops.Append(bcp); + outfile << bcp << "\t" << name << endl; + } + } + } + } + outfile << endl << endl; + } + */ + + int cnt_sing = 0; + for (PointIndex pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++) + if ((*this)[pi].Singularity()>=1.) cnt_sing++; + + if (cnt_sing) + { + outfile << "singular_points" << endl << cnt_sing << endl; + for (PointIndex pi = PointIndex::BASE; pi < GetNP()+PointIndex::BASE; pi++) + if ((*this)[pi].Singularity()>=1.) + outfile << int(pi) << "\t" << (*this)[pi].Singularity() << endl; + } + + cnt_sing = 0; + for (SegmentIndex si = 0; si < GetNSeg(); si++) + if ( segments[si].singedge_left ) cnt_sing++; + if (cnt_sing) + { + outfile << "singular_edge_left" << endl << cnt_sing << endl; + for (SegmentIndex si = 0; si < GetNSeg(); si++) + if ( segments[si].singedge_left ) + outfile << int(si) << "\t" << segments[si].singedge_left << endl; + } + + cnt_sing = 0; + for (SegmentIndex si = 0; si < GetNSeg(); si++) + if ( segments[si].singedge_right ) cnt_sing++; + if (cnt_sing) + { + outfile << "singular_edge_right" << endl << cnt_sing << endl; + for (SegmentIndex si = 0; si < GetNSeg(); si++) + if ( segments[si].singedge_right ) + outfile << int(si) << "\t" << segments[si].singedge_right << endl; + } + + + cnt_sing = 0; + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular) + cnt_sing++; + + if (cnt_sing) + { + outfile << "singular_face_inside" << endl << cnt_sing << endl; + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular) + outfile << int(sei) << "\t" << + GetFaceDescriptor ((*this)[sei].GetIndex()).domin_singular << endl; + } + + cnt_sing = 0; + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular) cnt_sing++; + if (cnt_sing) + { + outfile << "singular_face_outside" << endl << cnt_sing << endl; + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + if ( GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular) + outfile << int(sei) << "\t" + << GetFaceDescriptor ((*this)[sei].GetIndex()).domout_singular << endl; + } + + + } + + + + void Mesh :: Load (const string & filename) + { + + ifstream infile(filename.c_str()); + if (!infile.good()) + throw NgException ("mesh file not found"); + + Load(infile); + } + + + + + void Mesh :: Load (istream & infile) + { + + char str[100]; + int i, n; + + double scale = 1; // globflags.GetNumFlag ("scale", 1); + int inverttets = 0; // globflags.GetDefineFlag ("inverttets"); + int invertsurf = 0; // globflags.GetDefineFlag ("invertsurfacemesh"); + + + facedecoding.SetSize(0); + + bool endmesh = false; + + while (infile.good() && !endmesh) + { + infile >> str; + + if (strcmp (str, "dimension") == 0) + { + infile >> dimension; + } + + if (strcmp (str, "geomtype") == 0) + { + int hi; + infile >> hi; + geomtype = GEOM_TYPE(hi); + } + + + if (strcmp (str, "surfaceelements") == 0) + { + infile >> n; + PrintMessage (3, n, " surface elements"); + for (i = 1; i <= n; i++) + { + int j; + int surfnr, bcp, domin, domout, nep, faceind = 0; + + infile >> surfnr >> bcp >> domin >> domout; + surfnr--; + + for (j = 1; j <= facedecoding.Size(); j++) + if (GetFaceDescriptor(j).SurfNr() == surfnr && + GetFaceDescriptor(j).BCProperty() == bcp && + GetFaceDescriptor(j).DomainIn() == domin && + GetFaceDescriptor(j).DomainOut() == domout) + faceind = j; + + if (!faceind) + { + faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0)); + GetFaceDescriptor(faceind).SetBCProperty (bcp); + } + + infile >> nep; + if (!nep) nep = 3; + + Element2d tri(nep); + tri.SetIndex(faceind); + + for (j = 1; j <= nep; j++) + infile >> tri.PNum(j); + + if (invertsurf) + tri.Invert(); + + AddSurfaceElement (tri); + } + } + + if (strcmp (str, "surfaceelementsgi") == 0) + { + infile >> n; + PrintMessage (3, n, " surface elements"); + for (i = 1; i <= n; i++) + { + int j; + int surfnr, bcp, domin, domout, nep, faceind = 0; + infile >> surfnr >> bcp >> domin >> domout; + surfnr--; + + for (j = 1; j <= facedecoding.Size(); j++) + if (GetFaceDescriptor(j).SurfNr() == surfnr && + GetFaceDescriptor(j).BCProperty() == bcp && + GetFaceDescriptor(j).DomainIn() == domin && + GetFaceDescriptor(j).DomainOut() == domout) + faceind = j; + + if (!faceind) + { + faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0)); + GetFaceDescriptor(faceind).SetBCProperty (bcp); + } + + infile >> nep; + if (!nep) nep = 3; + + Element2d tri(nep); + tri.SetIndex(faceind); + + for (j = 1; j <= nep; j++) + infile >> tri.PNum(j); + + for (j = 1; j <= nep; j++) + infile >> tri.GeomInfoPi(j).trignum; + + if (invertsurf) + tri.Invert(); + + AddSurfaceElement (tri); + } + } + + if (strcmp (str, "surfaceelementsuv") == 0) + { + infile >> n; + PrintMessage (3, n, " surface elements"); + for (i = 1; i <= n; i++) + { + int j; + int surfnr, bcp, domin, domout, nep, faceind = 0; + infile >> surfnr >> bcp >> domin >> domout; + surfnr--; + + for (j = 1; j <= facedecoding.Size(); j++) + if (GetFaceDescriptor(j).SurfNr() == surfnr && + GetFaceDescriptor(j).BCProperty() == bcp && + GetFaceDescriptor(j).DomainIn() == domin && + GetFaceDescriptor(j).DomainOut() == domout) + faceind = j; + + if (!faceind) + { + faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0)); + GetFaceDescriptor(faceind).SetBCProperty (bcp); + } + + infile >> nep; + if (!nep) nep = 3; + + Element2d tri(nep); + tri.SetIndex(faceind); + + for (j = 1; j <= nep; j++) + infile >> tri.PNum(j); + + for (j = 1; j <= nep; j++) + infile >> tri.GeomInfoPi(j).u >> tri.GeomInfoPi(j).v; + + if (invertsurf) + tri.Invert(); + + AddSurfaceElement (tri); + } + } + + + if (strcmp (str, "volumeelements") == 0) + { + infile >> n; + PrintMessage (3, n, " volume elements"); + for (i = 1; i <= n; i++) + { + Element el; + int hi, nep; + infile >> hi; + if (hi == 0) hi = 1; + el.SetIndex(hi); + infile >> nep; + el.SetNP(nep); + + for (int j = 0; j < nep; j++) + infile >> (int&)(el[j]); + + if (inverttets) + el.Invert(); + + AddVolumeElement (el); + } + } + + + if (strcmp (str, "edgesegments") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + Segment seg; + int hi; + infile >> seg.si >> hi >> seg.p1 >> seg.p2; + AddSegment (seg); + } + } + + + + if (strcmp (str, "edgesegmentsgi") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + Segment seg; + int hi; + infile >> seg.si >> hi >> seg.p1 >> seg.p2 + >> seg.geominfo[0].trignum + >> seg.geominfo[1].trignum; + AddSegment (seg); + } + } + + if (strcmp (str, "edgesegmentsgi2") == 0) + { + int a; + infile >> a; + n=a; + + PrintMessage (3, n, " curve elements"); + + for (i = 1; i <= n; i++) + { + Segment seg; + int hi; + infile >> seg.si >> hi >> seg.p1 >> seg.p2 + >> seg.geominfo[0].trignum + >> seg.geominfo[1].trignum + >> seg.surfnr1 >> seg.surfnr2 + >> seg.edgenr + >> seg.epgeominfo[0].dist + >> seg.epgeominfo[1].edgenr + >> seg.epgeominfo[1].dist; + + seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr; + + seg.domin = seg.surfnr1; + seg.domout = seg.surfnr2; + + seg.surfnr1--; + seg.surfnr2--; + + AddSegment (seg); + } + } + + if (strcmp (str, "points") == 0) + { + infile >> n; + PrintMessage (3, n, " points"); + for (i = 1; i <= n; i++) + { + Point3d p; + infile >> p.X() >> p.Y() >> p.Z(); + p.X() *= scale; + p.Y() *= scale; + p.Z() *= scale; + AddPoint (p); + } + } + + if (strcmp (str, "identifications") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + PointIndex pi1, pi2; + int ind; + infile >> pi1 >> pi2 >> ind; + ident -> Add (pi1, pi2, ind); + } + } + + if (strcmp (str, "identificationtypes") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + int type; + infile >> type; + ident -> SetType(i,Identifications::ID_TYPE(type)); + } + } + + if (strcmp (str, "materials") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + int nr; + string mat; + infile >> nr >> mat; + SetMaterial (nr, mat.c_str()); + } + } + + if ( strcmp (str, "bcnames" ) == 0 ) + { + infile >> n; + ARRAY<int,0> bcnrs(n); + + SetNBCNames(n); + for ( i = 1; i <= n; i++ ) + { + string nextbcname; + infile >> bcnrs[i-1] >> nextbcname; + bcnames[bcnrs[i-1]-1] = new string(nextbcname); + } + + if ( GetDimension() == 2 ) + { + for (i = 1; i <= GetNSeg(); i++) + { + Segment & seg = LineSegment (i); + if ( seg.si <= n ) + seg.SetBCName (bcnames[seg.si-1]); + else + seg.SetBCName(0); + } + } + else + { + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + { + if ((*this)[sei].GetIndex()) + { + int bcp = GetFaceDescriptor((*this)[sei].GetIndex ()).BCProperty(); + if ( bcp <= n ) + GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(bcnames[bcp-1]); + else + GetFaceDescriptor((*this)[sei].GetIndex ()).SetBCName(0); + + } + } + + } + + + } + + if (strcmp (str, "singular_points") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + PointIndex pi; + double s; + infile >> pi; + infile >> s; + (*this)[pi].Singularity (s); + } + } + + if (strcmp (str, "singular_edge_left") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + SegmentIndex si; + double s; + infile >> si; + infile >> s; + (*this)[si].singedge_left = s; + } + } + if (strcmp (str, "singular_edge_right") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + SegmentIndex si; + double s; + infile >> si; + infile >> s; + (*this)[si].singedge_right = s; + } + } + + if (strcmp (str, "singular_face_inside") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + SurfaceElementIndex sei; + double s; + infile >> sei; + infile >> s; + GetFaceDescriptor((*this)[sei].GetIndex()).domin_singular = s; + } + } + + if (strcmp (str, "singular_face_outside") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + SurfaceElementIndex sei; + double s; + infile >> sei; + infile >> s; + GetFaceDescriptor((*this)[sei].GetIndex()).domout_singular = s; + } + } + + if (strcmp (str, "endmesh") == 0) + endmesh = true; + + + + strcpy (str, ""); + } + + CalcSurfacesOfNode (); + // BuildConnectedNodes (); + topology -> Update(); + clusters -> Update(); + + SetNextMajorTimeStamp(); + // PrintMemInfo (cout); + + +#ifdef PARALLEL + if ( ntasks > 1 ) + { + // for parallel processing + Distribute (); + return; + } +#endif + + } + + + + + + void Mesh :: Merge (const string & filename, const int surfindex_offset) + { + ifstream infile(filename.c_str()); + if (!infile.good()) + throw NgException ("mesh file not found"); + + Merge(infile,surfindex_offset); + + } + + + + void Mesh :: Merge (istream & infile, const int surfindex_offset) + { + char str[100]; + int i, n; + + + int inverttets = 0; // globflags.GetDefineFlag ("inverttets"); + + int oldnp = GetNP(); + int oldne = GetNSeg(); + int oldnd = GetNDomains(); + + for(SurfaceElementIndex si = 0; si < GetNSE(); si++) + for(int j=1; j<=(*this)[si].GetNP(); j++) (*this)[si].GeomInfoPi(j).trignum = -1; + + int max_surfnr = 0; + for (i = 1; i <= GetNFD(); i++) + max_surfnr = max2 (max_surfnr, GetFaceDescriptor(i).SurfNr()); + max_surfnr++; + + if(max_surfnr < surfindex_offset) max_surfnr = surfindex_offset; + + + bool endmesh = false; + + while (infile.good() && !endmesh) + { + infile >> str; + + if (strcmp (str, "surfaceelementsgi") == 0) + { + infile >> n; + PrintMessage (3, n, " surface elements"); + for (i = 1; i <= n; i++) + { + int j; + int surfnr, bcp, domin, domout, nep, faceind = 0; + infile >> surfnr >> bcp >> domin >> domout; + + surfnr--; + + if(domin > 0) domin += oldnd; + if(domout > 0) domout += oldnd; + surfnr += max_surfnr; + + + for (j = 1; j <= facedecoding.Size(); j++) + if (GetFaceDescriptor(j).SurfNr() == surfnr && + GetFaceDescriptor(j).BCProperty() == bcp && + GetFaceDescriptor(j).DomainIn() == domin && + GetFaceDescriptor(j).DomainOut() == domout) + faceind = j; + + if (!faceind) + { + faceind = AddFaceDescriptor (FaceDescriptor(surfnr, domin, domout, 0)); + if(GetDimension() == 2) bcp++; + GetFaceDescriptor(faceind).SetBCProperty (bcp); + } + + infile >> nep; + if (!nep) nep = 3; + + Element2d tri(nep); + tri.SetIndex(faceind); + + for (j = 1; j <= nep; j++) + { + infile >> tri.PNum(j); + tri.PNum(j) = tri.PNum(j) + oldnp; + } + + for (j = 1; j <= nep; j++) + { + infile >> tri.GeomInfoPi(j).trignum; + tri.GeomInfoPi(j).trignum = -1; + } + + AddSurfaceElement (tri); + } + } + + + if (strcmp (str, "edgesegments") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + Segment seg; + int hi; + infile >> seg.si >> hi >> seg.p1 >> seg.p2; + seg.p1 = seg.p1 + oldnp; + seg.p2 = seg.p2 + oldnp; + AddSegment (seg); + } + } + + + + if (strcmp (str, "edgesegmentsgi") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + Segment seg; + int hi; + infile >> seg.si >> hi >> seg.p1 >> seg.p2 + >> seg.geominfo[0].trignum + >> seg.geominfo[1].trignum; + seg.p1 = seg.p1 + oldnp; + seg.p2 = seg.p2 + oldnp; + AddSegment (seg); + } + } + if (strcmp (str, "edgesegmentsgi2") == 0) + { + infile >> n; + PrintMessage (3, n, " curve elements"); + + for (i = 1; i <= n; i++) + { + Segment seg; + int hi; + infile >> seg.si >> hi >> seg.p1 >> seg.p2 + >> seg.geominfo[0].trignum + >> seg.geominfo[1].trignum + >> seg.surfnr1 >> seg.surfnr2 + >> seg.edgenr + >> seg.epgeominfo[0].dist + >> seg.epgeominfo[1].edgenr + >> seg.epgeominfo[1].dist; + seg.epgeominfo[0].edgenr = seg.epgeominfo[1].edgenr; + + seg.surfnr1--; + seg.surfnr2--; + + if(seg.surfnr1 >= 0) seg.surfnr1 = seg.surfnr1 + max_surfnr; + if(seg.surfnr2 >= 0) seg.surfnr2 = seg.surfnr2 + max_surfnr; + seg.p1 = seg.p1 +oldnp; + seg.p2 = seg.p2 +oldnp; + seg.edgenr = seg.edgenr + oldne; + seg.epgeominfo[1].edgenr = seg.epgeominfo[1].edgenr + oldne; + + AddSegment (seg); + } + } + + if (strcmp (str, "volumeelements") == 0) + { + infile >> n; + PrintMessage (3, n, " volume elements"); + for (i = 1; i <= n; i++) + { + Element el; + int hi, nep; + infile >> hi; + if (hi == 0) hi = 1; + el.SetIndex(hi+oldnd); + infile >> nep; + el.SetNP(nep); + + for (int j = 0; j < nep; j++) + { + infile >> (int&)(el[j]); + el[j] = el[j]+oldnp; + } + + if (inverttets) + el.Invert(); + + AddVolumeElement (el); + } + } + + + if (strcmp (str, "points") == 0) + { + infile >> n; + PrintMessage (3, n, " points"); + for (i = 1; i <= n; i++) + { + Point3d p; + infile >> p.X() >> p.Y() >> p.Z(); + AddPoint (p); + } + } + + + if (strcmp (str, "endmesh") == 0) + { + endmesh = true; + } + + + if (strcmp (str, "materials") == 0) + { + infile >> n; + for (i = 1; i <= n; i++) + { + int nr; + string mat; + infile >> nr >> mat; + SetMaterial (nr+oldnd, mat.c_str()); + } + } + + + strcpy (str, ""); + } + + CalcSurfacesOfNode (); + + topology -> Update(); + clusters -> Update(); + + SetNextMajorTimeStamp(); + } + + + + + + + + + + + bool Mesh :: TestOk () const + { + for (ElementIndex ei = 0; ei < volelements.Size(); ei++) + { + for (int j = 0; j < 4; j++) + if ( (*this)[ei][j] <= PointIndex::BASE-1) + { + (*testout) << "El " << ei << " has 0 nodes: "; + for (int k = 0; k < 4; k++) + (*testout) << (*this)[ei][k]; + break; + } + } + CheckMesh3D (*this); + return 1; + } + + void Mesh :: SetAllocSize(int nnodes, int nsegs, int nsel, int nel) + { + points.SetAllocSize(nnodes); + segments.SetAllocSize(nsegs); + surfelements.SetAllocSize(nsel); + volelements.SetAllocSize(nel); + } + + + void Mesh :: BuildBoundaryEdges(void) + { + delete boundaryedges; + + boundaryedges = new INDEX_2_CLOSED_HASHTABLE<int> + (3 * (GetNSE() + GetNOpenElements()) + GetNSeg() + 1); + + + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + + int si = sel.GetIndex(); + + for (int j = 0; j < sel.GetNP(); j++) + { + INDEX_2 i2; + i2.I1() = sel.PNumMod(j+1); + i2.I2() = sel.PNumMod(j+2); + i2.Sort(); + if (sel.GetNP() <= 4) + boundaryedges->Set (i2, 1); + } + } + + + for (int i = 0; i < openelements.Size(); i++) + { + const Element2d & sel = openelements[i]; + for (int j = 0; j < sel.GetNP(); j++) + { + INDEX_2 i2; + i2.I1() = sel.PNumMod(j+1); + i2.I2() = sel.PNumMod(j+2); + i2.Sort(); + boundaryedges->Set (i2, 1); + + points[sel[j]].SetType(FIXEDPOINT); + } + } + + for (int i = 0; i < GetNSeg(); i++) + { + const Segment & seg = segments[i]; + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + + boundaryedges -> Set (i2, 2); + //segmentht -> Set (i2, i); + } + + + } + + void Mesh :: CalcSurfacesOfNode () + { + int i, j, k; + SurfaceElementIndex sei; + + surfacesonnode.SetSize (GetNP()); + + delete boundaryedges; + boundaryedges = NULL; + + delete surfelementht; + delete segmentht; + + /* + surfelementht = new INDEX_3_HASHTABLE<int> (GetNSE()/4 + 1); + segmentht = new INDEX_2_HASHTABLE<int> (GetNSeg() + 1); + */ + + surfelementht = new INDEX_3_CLOSED_HASHTABLE<int> (3*GetNSE() + 1); + segmentht = new INDEX_2_CLOSED_HASHTABLE<int> (3*GetNSeg() + 1); + + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + + int si = sel.GetIndex(); + + for (j = 0; j < sel.GetNP(); j++) + { + PointIndex pi = sel[j]; + bool found = 0; + for (k = 0; k < surfacesonnode[pi].Size(); k++) + if (surfacesonnode[pi][k] == si) + { + found = 1; + break; + } + + if (!found) + surfacesonnode.Add (pi, si); + + } + } + /* + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + + INDEX_3 i3; + i3.I1() = sel.PNum(1); + i3.I2() = sel.PNum(2); + i3.I3() = sel.PNum(3); + i3.Sort(); + surfelementht -> PrepareSet (i3); + } + + surfelementht -> AllocateElements(); + */ + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + + INDEX_3 i3; + i3.I1() = sel.PNum(1); + i3.I2() = sel.PNum(2); + i3.I3() = sel.PNum(3); + i3.Sort(); + surfelementht -> Set (i3, sei); // war das wichtig ??? sel.GetIndex()); + } + + int np = GetNP(); + + if (dimension == 3) + { + for (PointIndex pi = PointIndex::BASE; + pi < np+PointIndex::BASE; pi++) + points[pi].SetType (INNERPOINT); + + if (GetNFD() == 0) + { + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + for (j = 0; j < sel.GetNP(); j++) + { + PointIndex pi = SurfaceElement(sei)[j]; + points[pi].SetType(FIXEDPOINT); + } + } + } + else + { + for (sei = 0; sei < GetNSE(); sei++) + { + const Element2d & sel = surfelements[sei]; + if (sel.IsDeleted()) continue; + for (j = 0; j < sel.GetNP(); j++) + { + PointIndex pi = sel[j]; + int ns = surfacesonnode[pi].Size(); + if (ns == 1) + points[pi].SetType(SURFACEPOINT); + if (ns == 2) + points[pi].SetType(EDGEPOINT); + if (ns >= 3) + points[pi].SetType(FIXEDPOINT); + } + } + } + + for (i = 0; i < segments.Size(); i++) + { + const Segment & seg = segments[i]; + for (j = 1; j <= 2; j++) + { + PointIndex hi = (j == 1) ? seg.p1 : seg.p2; + + if (points[hi].Type() == INNERPOINT || + points[hi].Type() == SURFACEPOINT) + points[hi].SetType(EDGEPOINT); + } + } + + + for (i = 0; i < lockedpoints.Size(); i++) + points[lockedpoints[i]].SetType(FIXEDPOINT); + } + + + /* + for (i = 0; i < openelements.Size(); i++) + { + const Element2d & sel = openelements[i]; + for (j = 0; j < sel.GetNP(); j++) + { + INDEX_2 i2; + i2.I1() = sel.PNumMod(j+1); + i2.I2() = sel.PNumMod(j+2); + i2.Sort(); + boundaryedges->Set (i2, 1); + + points[sel[j]].SetType(FIXEDPOINT); + } + } + */ + + // eltyps.SetSize (GetNE()); + // eltyps = FREEELEMENT; + + for (i = 0; i < GetNSeg(); i++) + { + const Segment & seg = segments[i]; + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + + //boundaryedges -> Set (i2, 2); + segmentht -> Set (i2, i); + } + } + + + void Mesh :: FixPoints (const BitArray & fixpoints) + { + if (fixpoints.Size() != GetNP()) + { + cerr << "Mesh::FixPoints: sizes don't fit" << endl; + return; + } + int np = GetNP(); + for (int i = 1; i <= np; i++) + if (fixpoints.Test(i)) + { + points.Elem(i).SetType (FIXEDPOINT); + } + } + + + void Mesh :: FindOpenElements (int dom) + { + static int timer = NgProfiler::CreateTimer ("Mesh::FindOpenElements"); + static int timera = NgProfiler::CreateTimer ("Mesh::FindOpenElements A"); + static int timerb = NgProfiler::CreateTimer ("Mesh::FindOpenElements B"); + static int timerc = NgProfiler::CreateTimer ("Mesh::FindOpenElements C"); + static int timerd = NgProfiler::CreateTimer ("Mesh::FindOpenElements D"); + static int timere = NgProfiler::CreateTimer ("Mesh::FindOpenElements E"); + + NgProfiler::RegionTimer reg (timer); + + int np = GetNP(); + int ne = GetNE(); + int nse = GetNSE(); + + ARRAY<int,PointIndex::BASE> numonpoint(np); + + numonpoint = 0; + + NgProfiler::StartTimer (timera); + for (ElementIndex ei = 0; ei < ne; ei++) + { + const Element & el = (*this)[ei]; + if (dom == 0 || dom == el.GetIndex()) + { + if (el.GetNP() == 4) + { + INDEX_4 i4(el[0], el[1], el[2], el[3]); + i4.Sort(); + numonpoint[i4.I1()]++; + numonpoint[i4.I2()]++; + } + else + for (int j = 0; j < el.GetNP(); j++) + numonpoint[el[j]]++; + } + } + + TABLE<ElementIndex,PointIndex::BASE> elsonpoint(numonpoint); + for (ElementIndex ei = 0; ei < ne; ei++) + { + const Element & el = (*this)[ei]; + if (dom == 0 || dom == el.GetIndex()) + { + if (el.GetNP() == 4) + { + INDEX_4 i4(el[0], el[1], el[2], el[3]); + i4.Sort(); + elsonpoint.Add (i4.I1(), ei); + elsonpoint.Add (i4.I2(), ei); + } + else + for (int j = 0; j < el.GetNP(); j++) + elsonpoint.Add (el[j], ei); + } + } + NgProfiler::StopTimer (timera); + + + + + NgProfiler::StartTimer (timerb); + + + + ARRAY<char, 1> hasface(GetNFD()); + + int i; + for (i = 1; i <= GetNFD(); i++) + { + int domin = GetFaceDescriptor(i).DomainIn(); + int domout = GetFaceDescriptor(i).DomainOut(); + hasface[i] = + dom == 0 && (domin != 0 || domout != 0) || + dom != 0 && (domin == dom || domout == dom); + } + + numonpoint = 0; + for (SurfaceElementIndex sii = 0; sii < nse; sii++) + { + int ind = surfelements[sii].GetIndex(); + /* + if ( + GetFaceDescriptor(ind).DomainIn() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) + || + GetFaceDescriptor(ind).DomainOut() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) + ) + */ + if (hasface[ind]) + { + /* + Element2d hel = surfelements[i]; + hel.NormalizeNumbering(); + numonpoint[hel[0]]++; + */ + const Element2d & hel = surfelements[sii]; + int mini = 0; + for (int j = 1; j < hel.GetNP(); j++) + if (hel[j] < hel[mini]) + mini = j; + numonpoint[hel[mini]]++; + } + } + + TABLE<SurfaceElementIndex,PointIndex::BASE> selsonpoint(numonpoint); + for (SurfaceElementIndex sii = 0; sii < nse; sii++) + { + int ind = surfelements[sii].GetIndex(); + + /* + if ( + GetFaceDescriptor(ind).DomainIn() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) + || + GetFaceDescriptor(ind).DomainOut() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) + ) + */ + if (hasface[ind]) + { + /* + Element2d hel = surfelements[i]; + hel.NormalizeNumbering(); + selsonpoint.Add (hel[0], i); + */ + const Element2d & hel = surfelements[sii]; + int mini = 0; + for (int j = 1; j < hel.GetNP(); j++) + if (hel[j] < hel[mini]) + mini = j; + selsonpoint.Add (hel[mini], sii); + } + } + + + NgProfiler::StopTimer (timerb); + + int ii, j, k, l; + PointIndex pi; + SurfaceElementIndex sei; + Element2d hel; + + NgProfiler::RegionTimer regc (timerc); + + + INDEX_3_CLOSED_HASHTABLE<INDEX_2> faceht(100); + openelements.SetSize(0); + + for (pi = PointIndex::BASE; pi < np+PointIndex::BASE; pi++) + if (selsonpoint[pi].Size()+elsonpoint[pi].Size()) + { + faceht.SetSize (2 * selsonpoint[pi].Size() + 4 * elsonpoint[pi].Size()); + + FlatArray<SurfaceElementIndex> row = selsonpoint[pi]; + for (ii = 0; ii < row.Size(); ii++) + { + hel = SurfaceElement(row[ii]); + int ind = hel.GetIndex(); + + if (GetFaceDescriptor(ind).DomainIn() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainIn()) ) + { + hel.NormalizeNumbering(); + if (hel.PNum(1) == pi) + { + INDEX_3 i3(hel[0], hel[1], hel[2]); + INDEX_2 i2 (GetFaceDescriptor(ind).DomainIn(), + (hel.GetNP() == 3) + ? PointIndex (PointIndex::BASE-1) + : hel.PNum(4)); + faceht.Set (i3, i2); + } + } + if (GetFaceDescriptor(ind).DomainOut() && + (dom == 0 || dom == GetFaceDescriptor(ind).DomainOut()) ) + { + hel.Invert(); + hel.NormalizeNumbering(); + if (hel.PNum(1) == pi) + { + INDEX_3 i3(hel[0], hel[1], hel[2]); + INDEX_2 i2 (GetFaceDescriptor(ind).DomainOut(), + (hel.GetNP() == 3) + ? PointIndex (PointIndex::BASE-1) + : hel.PNum(4)); + faceht.Set (i3, i2); + } + } + } + + + FlatArray<ElementIndex> rowel = elsonpoint[pi]; + for (ii = 0; ii < rowel.Size(); ii++) + { + const Element & el = VolumeElement(rowel[ii]); + + if (dom == 0 || el.GetIndex() == dom) + { + for (j = 1; j <= el.GetNFaces(); j++) + { + el.GetFace (j, hel); + hel.Invert(); + hel.NormalizeNumbering(); + + if (hel[0] == pi) + { + INDEX_3 i3(hel[0], hel[1], hel[2]); + + if (faceht.Used (i3)) + { + INDEX_2 i2 = faceht.Get(i3); + if (i2.I1() == el.GetIndex()) + { + i2.I1() = PointIndex::BASE-1; + faceht.Set (i3, i2); + } + else + { + if (i2.I1() == 0) + { + PrintSysError ("more elements on face"); + (*testout) << "more elements on face!!!" << endl; + (*testout) << "el = " << el << endl; + (*testout) << "hel = " << hel << endl; + (*testout) << "face = " << i3 << endl; + (*testout) << "points = " << endl; + for (int jj = 1; jj <= 3; jj++) + (*testout) << "p = " << Point(i3.I(jj)) << endl; + } + } + } + else + { + hel.Invert(); + hel.NormalizeNumbering(); + INDEX_3 i3(hel[0], hel[1], hel[2]); + INDEX_2 i2(el.GetIndex(), + (hel.GetNP() == 3) + ? PointIndex (PointIndex::BASE-1) + : hel[3]); + faceht.Set (i3, i2); + } + } + } + } + } + for (i = 0; i < faceht.Size(); i++) + if (faceht.UsedPos (i)) + { + INDEX_3 i3; + INDEX_2 i2; + faceht.GetData (i, i3, i2); + if (i2.I1() != PointIndex::BASE-1) + { + Element2d tri; + tri.SetType ( (i2.I2() == PointIndex::BASE-1) ? TRIG : QUAD); + for (l = 0; l < 3; l++) + tri[l] = i3.I(l+1); + tri.PNum(4) = i2.I2(); + tri.SetIndex (i2.I1()); + + // tri.Invert(); + + openelements.Append (tri); + } + } + } + + int cnt3 = 0; + for (i = 0; i < openelements.Size(); i++) + if (openelements[i].GetNP() == 3) + cnt3++; + + int cnt4 = openelements.Size() - cnt3; + + + MyStr treequad; + if (cnt4) + treequad = MyStr(" (") + MyStr(cnt3) + MyStr (" + ") + + MyStr(cnt4) + MyStr(")"); + + PrintMessage (5, openelements.Size(), treequad, " open elements"); + + BuildBoundaryEdges(); + + + NgProfiler::RegionTimer regd (timerd); + + for (i = 1; i <= openelements.Size(); i++) + { + const Element2d & sel = openelements.Get(i); + + if (boundaryedges) + for (j = 1; j <= sel.GetNP(); j++) + { + INDEX_2 i2; + i2.I1() = sel.PNumMod(j); + i2.I2() = sel.PNumMod(j+1); + i2.Sort(); + boundaryedges->Set (i2, 1); + } + + for (j = 1; j <= 3; j++) + { + int pi = sel.PNum(j); + if (pi < points.Size()+PointIndex::BASE) + points[pi].SetType (FIXEDPOINT); + } + } + + + NgProfiler::RegionTimer rege (timere); + + /* + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment(i); + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + + if (!boundaryedges->Used (i2)) + cerr << "WARNING: no boundedge, but seg edge: " << i2 << endl; + + boundaryedges -> Set (i2, 2); + segmentht -> Set (i2, i-1); + } + */ + } + + bool Mesh :: HasOpenQuads () const + { + int no = GetNOpenElements(); + for (int i = 0; i < no; i++) + if (openelements[i].GetNP() == 4) + return true; + return false; + } + + + + + + void Mesh :: FindOpenSegments (int surfnr) + { + int i, j, k; + + // new version, general elemetns + // hash index: pnum1-2 + // hash data : surfnr, surfel-nr (pos) or segment nr(neg) + INDEX_2_HASHTABLE<INDEX_2> faceht(4 * GetNSE()+GetNSeg()+1); + + PrintMessage (5, "Test Opensegments"); + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + + if (surfnr == 0 || seg.si == surfnr) + { + INDEX_2 key(seg.p1, seg.p2); + INDEX_2 data(seg.si, -i); + + if (faceht.Used (key)) + { + cerr << "ERROR: Segment " << seg << " already used" << endl; + (*testout) << "ERROR: Segment " << seg << " already used" << endl; + } + + faceht.Set (key, data); + } + } + + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + + if (surfnr == 0 || seg.si == surfnr) + { + INDEX_2 key(seg.p2, seg.p1); + if (!faceht.Used(key)) + { + cerr << "ERROR: Segment " << seg << " brother not used" << endl; + (*testout) << "ERROR: Segment " << seg << " brother not used" << endl; + } + } + } + + + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & el = SurfaceElement(i); + if (el.IsDeleted()) continue; + + if (surfnr == 0 || el.GetIndex() == surfnr) + { + for (j = 1; j <= el.GetNP(); j++) + { + INDEX_2 seg (el.PNumMod(j), el.PNumMod(j+1)); + INDEX_2 data; + + if (seg.I1() <= 0 || seg.I2() <= 0) + cerr << "seg = " << seg << endl; + + if (faceht.Used(seg)) + { + data = faceht.Get(seg); + if (data.I1() == el.GetIndex()) + { + data.I1() = 0; + faceht.Set (seg, data); + } + else + { + PrintSysError ("hash table si not fitting for segment: ", + seg.I1(), "-", seg.I2(), " other = ", + data.I2()); + } + } + else + { + Swap (seg.I1(), seg.I2()); + data.I1() = el.GetIndex(); + data.I2() = i; + + faceht.Set (seg, data); + } + } + } + } + + (*testout) << "open segments: " << endl; + opensegments.SetSize(0); + for (i = 1; i <= faceht.GetNBags(); i++) + for (j = 1; j <= faceht.GetBagSize(i); j++) + { + INDEX_2 i2; + INDEX_2 data; + faceht.GetData (i, j, i2, data); + if (data.I1()) // surfnr + { + Segment seg; + seg.p1 = i2.I1(); + seg.p2 = i2.I2(); + seg.si = data.I1(); + + // find geomdata: + if (data.I2() > 0) + { + // segment due to triangle + const Element2d & el = SurfaceElement (data.I2()); + for (k = 1; k <= el.GetNP(); k++) + { + if (seg.p1 == el.PNum(k)) + seg.geominfo[0] = el.GeomInfoPi(k); + if (seg.p2 == el.PNum(k)) + seg.geominfo[1] = el.GeomInfoPi(k); + } + + (*testout) << "trig seg: "; + } + else + { + // segment due to line + const Segment & lseg = LineSegment (-data.I2()); + seg.geominfo[0] = lseg.geominfo[0]; + seg.geominfo[1] = lseg.geominfo[1]; + + (*testout) << "line seg: "; + } + + (*testout) << seg.p1 << " - " << seg.p2 + << " len = " << Dist (Point(seg.p1), Point(seg.p2)) + << endl; + + opensegments.Append (seg); + if (seg.geominfo[0].trignum <= 0 || seg.geominfo[1].trignum <= 0) + { + (*testout) << "Problem with open segment: " << seg << endl; + } + + } + } + + PrintMessage (3, opensegments.Size(), " open segments found"); + (*testout) << opensegments.Size() << " open segments found" << endl; + + /* + ptyps.SetSize (GetNP()); + for (i = 1; i <= ptyps.Size(); i++) + ptyps.Elem(i) = SURFACEPOINT; + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + ptyps.Elem(seg.p1) = EDGEPOINT; + ptyps.Elem(seg.p2) = EDGEPOINT; + } + for (i = 1; i <= GetNOpenSegments(); i++) + { + const Segment & seg = GetOpenSegment (i); + ptyps.Elem(seg.p1) = EDGEPOINT; + ptyps.Elem(seg.p2) = EDGEPOINT; + } + */ + for (i = 1; i <= points.Size(); i++) + points.Elem(i).SetType(SURFACEPOINT); + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment (i); + points[seg.p1].SetType(EDGEPOINT); + points[seg.p2].SetType(EDGEPOINT); + } + for (i = 1; i <= GetNOpenSegments(); i++) + { + const Segment & seg = GetOpenSegment (i); + points[seg.p1].SetType (EDGEPOINT); + points[seg.p2].SetType (EDGEPOINT); + } + + + + /* + + for (i = 1; i <= openelements.Size(); i++) + { + const Element2d & sel = openelements.Get(i); + + if (boundaryedges) + for (j = 1; j <= sel.GetNP(); j++) + { + INDEX_2 i2; + i2.I1() = sel.PNumMod(j); + i2.I2() = sel.PNumMod(j+1); + i2.Sort(); + boundaryedges->Set (i2, 1); + } + + for (j = 1; j <= 3; j++) + { + int pi = sel.PNum(j); + if (pi <= ptyps.Size()) + ptyps.Elem(pi) = FIXEDPOINT; + } + } + */ + } + + + void Mesh :: RemoveOneLayerSurfaceElements () + { + int i, j; + int np = GetNP(); + + FindOpenSegments(); + BitArray frontpoints(np); + + frontpoints.Clear(); + for (i = 1; i <= GetNOpenSegments(); i++) + { + const Segment & seg = GetOpenSegment(i); + frontpoints.Set (seg.p1); + frontpoints.Set (seg.p2); + } + + for (i = 1; i <= GetNSE(); i++) + { + Element2d & sel = surfelements.Elem(i); + int remove = 0; + for (j = 1; j <= sel.GetNP(); j++) + if (frontpoints.Test(sel.PNum(j))) + remove = 1; + if (remove) + sel.PNum(1) = 0; + } + + for (i = surfelements.Size(); i >= 1; i--) + { + if (surfelements.Elem(i).PNum(1) == 0) + { + surfelements.Elem(i) = surfelements.Last(); + surfelements.DeleteLast(); + } + } + + for (int i = 0; i < facedecoding.Size(); i++) + facedecoding[i].firstelement = -1; + for (int i = surfelements.Size()-1; i >= 0; i--) + { + int ind = surfelements[i].GetIndex(); + surfelements[i].next = facedecoding[ind-1].firstelement; + facedecoding[ind-1].firstelement = i; + } + + + timestamp = NextTimeStamp(); + // Compress(); + } + + + + + + void Mesh :: FreeOpenElementsEnvironment (int layers) + { + int i, j, k; + PointIndex pi; + const int large = 9999; + ARRAY<int,PointIndex::BASE> dist(GetNP()); + + dist = large; + + for (int i = 1; i <= GetNOpenElements(); i++) + { + const Element2d & face = OpenElement(i); + for (j = 0; j < face.GetNP(); j++) + dist[face[j]] = 1; + } + + for (k = 1; k <= layers; k++) + for (i = 1; i <= GetNE(); i++) + { + const Element & el = VolumeElement(i); + if (el[0] == -1 || el.IsDeleted()) continue; + + int elmin = large; + for (j = 0; j < el.GetNP(); j++) + if (dist[el[j]] < elmin) + elmin = dist[el[j]]; + + if (elmin < large) + { + for (j = 0; j < el.GetNP(); j++) + if (dist[el[j]] > elmin+1) + dist[el[j]] = elmin+1; + } + } + + int cntfree = 0; + for (i = 1; i <= GetNE(); i++) + { + Element & el = VolumeElement(i); + if (el[0] == -1 || el.IsDeleted()) continue; + + int elmin = large; + for (j = 0; j < el.GetNP(); j++) + if (dist[el[j]] < elmin) + elmin = dist[el[j]]; + + el.flags.fixed = elmin > layers; + // eltyps.Elem(i) = (elmin <= layers) ? + // FREEELEMENT : FIXEDELEMENT; + if (elmin <= layers) + cntfree++; + } + + PrintMessage (5, "free: ", cntfree, ", fixed: ", GetNE()-cntfree); + (*testout) << "free: " << cntfree << ", fixed: " << GetNE()-cntfree << endl; + + for (pi = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; pi++) + { + if (dist[pi] > layers+1) + points[pi].SetType(FIXEDPOINT); + } + } + + + + void Mesh :: SetLocalH (const Point3d & pmin, const Point3d & pmax, double grading) + { + Point3d c = Center (pmin, pmax); + double d = max3 (pmax.X()-pmin.X(), + pmax.Y()-pmin.Y(), + pmax.Z()-pmin.Z()); + d /= 2; + Point3d pmin2 = c - Vec3d (d, d, d); + Point3d pmax2 = c + Vec3d (d, d, d); + + + delete lochfunc; + lochfunc = new LocalH (pmin2, pmax2, grading); + } + + void Mesh :: RestrictLocalH (const Point3d & p, double hloc) + { + if(hloc < hmin) + hloc = hmin; + + //cout << "restrict h in " << p << " to " << hloc << endl; + if (!lochfunc) + { + PrintWarning("RestrictLocalH called, creating mesh-size tree"); + + Point3d boxmin, boxmax; + GetBox (boxmin, boxmax); + SetLocalH (boxmin, boxmax, 0.8); + } + + lochfunc -> SetH (p, hloc); + } + + void Mesh :: RestrictLocalHLine (const Point3d & p1, + const Point3d & p2, + double hloc) + { + if(hloc < hmin) + hloc = hmin; + + // cout << "restrict h along " << p1 << " - " << p2 << " to " << hloc << endl; + int i; + int steps = int (Dist (p1, p2) / hloc) + 2; + Vec3d v(p1, p2); + + for (i = 0; i <= steps; i++) + { + Point3d p = p1 + (double(i)/double(steps) * v); + RestrictLocalH (p, hloc); + } + } + + + void Mesh :: SetMinimalH (double h) + { + hmin = h; + } + + + void Mesh :: SetGlobalH (double h) + { + hglob = h; + } + + double Mesh :: MaxHDomain (int dom) const + { + if (maxhdomain.Size()) + return maxhdomain.Get(dom); + else + return 1e10; + } + + void Mesh :: SetMaxHDomain (const ARRAY<double> & mhd) + { + maxhdomain.SetSize(mhd.Size()); + for (int i = 1; i <= mhd.Size(); i++) + maxhdomain.Elem(i) = mhd.Get(i); + } + + + double Mesh :: GetH (const Point3d & p) const + { + double hmin = hglob; + if (lochfunc) + { + double hl = lochfunc->GetH (p); + if (hl < hglob) + hmin = hl; + } + return hmin; + } + + double Mesh :: GetMinH (const Point3d & pmin, const Point3d & pmax) + { + double hmin = hglob; + if (lochfunc) + { + double hl = lochfunc->GetMinH (pmin, pmax); + if (hl < hmin) + hmin = hl; + } + return hmin; + } + + + + + + double Mesh :: AverageH (int surfnr) const + { + int i, j, n; + double hi, hsum; + double maxh = 0, minh = 1e10; + + hsum = 0; + n = 0; + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & el = SurfaceElement(i); + if (surfnr == 0 || el.GetIndex() == surfnr) + { + for (j = 1; j <= 3; j++) + { + hi = Dist (Point (el.PNumMod(j)), + Point (el.PNumMod(j+1))); + + hsum += hi; + + if (hi > maxh) maxh = hi; + if (hi < minh) minh = hi; + n++; + } + } + } + + PrintMessage (5, "minh = ", minh, " avh = ", (hsum/n), " maxh = ", maxh); + return (hsum / n); + } + + + + void Mesh :: CalcLocalH () + { + if (!lochfunc) + { + Point3d pmin, pmax; + GetBox (pmin, pmax); + SetLocalH (pmin, pmax, mparam.grading); + } + + PrintMessage (3, + "CalcLocalH: ", + GetNP(), " Points ", + GetNE(), " Elements ", + GetNSE(), " Surface Elements"); + + + int i; + for (i = 0; i < GetNSE(); i++) + { + const Element2d & el = surfelements[i]; + int j; + + if (el.GetNP() == 3) + { + double hel = -1; + for (j = 1; j <= 3; j++) + { + const Point3d & p1 = points[el.PNumMod(j)]; + const Point3d & p2 = points[el.PNumMod(j+1)]; + + /* + INDEX_2 i21(el.PNumMod(j), el.PNumMod(j+1)); + INDEX_2 i22(el.PNumMod(j+1), el.PNumMod(j)); + if (! identifiedpoints->Used (i21) && + ! identifiedpoints->Used (i22) ) + */ + if (!ident -> UsedSymmetric (el.PNumMod(j), + el.PNumMod(j+1))) + { + double hedge = Dist (p1, p2); + if (hedge > hel) + hel = hedge; + // lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); + // (*testout) << "trigseth, p1,2 = " << el.PNumMod(j) << ", " << el.PNumMod(j+1) + // << " h = " << (2 * Dist(p1, p2)) << endl; + } + } + + if (hel > 0) + { + const Point3d & p1 = points[el.PNum(1)]; + const Point3d & p2 = points[el.PNum(2)]; + const Point3d & p3 = points[el.PNum(3)]; + lochfunc->SetH (Center (p1, p2, p3), hel); + } + } + else + { + { + const Point3d & p1 = points[el.PNum(1)]; + const Point3d & p2 = points[el.PNum(2)]; + lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); + } + { + const Point3d & p1 = points[el.PNum(3)]; + const Point3d & p2 = points[el.PNum(4)]; + lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); + } + } + } + + for (i = 0; i < GetNSeg(); i++) + { + const Segment & seg = segments[i]; + const Point3d & p1 = points[seg.p1]; + const Point3d & p2 = points[seg.p2]; + /* + INDEX_2 i21(seg.p1, seg.p2); + INDEX_2 i22(seg.p2, seg.p1); + if (identifiedpoints) + if (!identifiedpoints->Used (i21) && !identifiedpoints->Used (i22)) + */ + if (!ident -> UsedSymmetric (seg.p1, seg.p2)) + { + lochfunc->SetH (Center (p1, p2), Dist (p1, p2)); + } + } + /* + cerr << "do vol" << endl; + for (i = 1; i <= GetNE(); i++) + { + const Element & el = VolumeElement(i); + if (el.GetType() == TET) + { + int j, k; + for (j = 2; j <= 4; j++) + for (k = 1; k < j; k++) + { + const Point3d & p1 = Point (el.PNum(j)); + const Point3d & p2 = Point (el.PNum(k)); + lochfunc->SetH (Center (p1, p2), 2 * Dist (p1, p2)); + (*testout) << "set vol h to " << (2 * Dist (p1, p2)) << endl; + + } + } + } + */ + + /* + const char * meshsizefilename = + globflags.GetStringFlag ("meshsize", NULL); + if (meshsizefilename) + { + ifstream msf(meshsizefilename); + if (msf) + { + int nmsp; + msf >> nmsp; + for (i = 1; i <= nmsp; i++) + { + Point3d pi; + double hi; + msf >> pi.X() >> pi.Y() >> pi.Z(); + msf >> hi; + lochfunc->SetH (pi, hi); + } + } + } + */ + // lochfunc -> Convexify(); + // lochfunc -> PrintMemInfo (cout); + } + + + void Mesh :: CalcLocalHFromPointDistances(void) + { + PrintMessage (3, "Calculating local h from point distances"); + + if (!lochfunc) + { + Point3d pmin, pmax; + GetBox (pmin, pmax); + + SetLocalH (pmin, pmax, mparam.grading); + } + + PointIndex i,j; + double hl; + + + for (i = PointIndex::BASE; + i < GetNP()+PointIndex::BASE; i++) + { + for(j=i+1; j<GetNP()+PointIndex::BASE; j++) + { + const Point3d & p1 = points[i]; + const Point3d & p2 = points[j]; + hl = Dist(p1,p2); + RestrictLocalH(p1,hl); + RestrictLocalH(p2,hl); + //cout << "restricted h at " << p1 << " and " << p2 << " to " << hl << endl; + } + } + + + } + + + void Mesh :: CalcLocalHFromSurfaceCurvature (double elperr) + { + PrintMessage (3, "Calculating local h from surface curvature"); + + if (!lochfunc) + { + Point3d pmin, pmax; + GetBox (pmin, pmax); + + SetLocalH (pmin, pmax, mparam.grading); + } + + + INDEX_2_HASHTABLE<int> edges(3 * GetNP() + 2); + INDEX_2_HASHTABLE<int> bedges(GetNSeg() + 2); + int i, j; + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment(i); + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + bedges.Set (i2, 1); + } + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & sel = SurfaceElement(i); + if (!sel.PNum(1)) + continue; + for (j = 1; j <= 3; j++) + { + INDEX_2 i2(sel.PNumMod(j), sel.PNumMod(j+1)); + i2.Sort(); + if (bedges.Used(i2)) continue; + + if (edges.Used(i2)) + { + int other = edges.Get(i2); + + const Element2d & elother = SurfaceElement(other); + + int pi3 = 1; + while ( (sel.PNum(pi3) == i2.I1()) || + (sel.PNum(pi3) == i2.I2())) + pi3++; + pi3 = sel.PNum(pi3); + + int pi4 = 1; + while ( (elother.PNum(pi4) == i2.I1()) || + (elother.PNum(pi4) == i2.I2())) + pi4++; + pi4 = elother.PNum(pi4); + + double rad = ComputeCylinderRadius (Point (i2.I1()), + Point (i2.I2()), + Point (pi3), + Point (pi4)); + + RestrictLocalHLine (Point(i2.I1()), Point(i2.I2()), rad/elperr); + + + /* + (*testout) << "pi1,2, 3, 4 = " << i2.I1() << ", " << i2.I2() << ", " << pi3 << ", " << pi4 + << " p1 = " << Point(i2.I1()) + << ", p2 = " << Point(i2.I2()) + // << ", p3 = " << Point(pi3) + // << ", p4 = " << Point(pi4) + << ", rad = " << rad << endl; + */ + } + else + edges.Set (i2, i); + } + } + + + // Restrict h due to line segments + + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment(i); + const Point3d & p1 = Point(seg.p1); + const Point3d & p2 = Point(seg.p2); + RestrictLocalH (Center (p1, p2), Dist (p1, p2)); + } + + + + /* + + + int i, j; + int np = GetNP(); + int nseg = GetNSeg(); + int nse = GetNSE(); + + ARRAY<Vec3d> normals(np); + BitArray linepoint(np); + + linepoint.Clear(); + for (i = 1; i <= nseg; i++) + { + linepoint.Set (LineSegment(i).p1); + linepoint.Set (LineSegment(i).p2); + } + + for (i = 1; i <= np; i++) + normals.Elem(i) = Vec3d(0,0,0); + + for (i = 1; i <= nse; i++) + { + Element2d & el = SurfaceElement(i); + Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))), + Vec3d (Point (el.PNum(1)), Point(el.PNum(3)))); + for (j = 1; j <= 3; j++) + normals.Elem(el.PNum(j)) += nf; + } + + for (i = 1; i <= np; i++) + normals.Elem(i) /= (1e-12 + normals.Elem(i).Length()); + + for (i = 1; i <= nse; i++) + { + Element2d & el = SurfaceElement(i); + Vec3d nf = Cross (Vec3d (Point (el.PNum(1)), Point(el.PNum(2))), + Vec3d (Point (el.PNum(1)), Point(el.PNum(3)))); + nf /= nf.Length(); + Point3d c = Center (Point(el.PNum(1)), + Point(el.PNum(2)), + Point(el.PNum(3))); + + for (j = 1; j <= 3; j++) + { + if (!linepoint.Test (el.PNum(j))) + { + double dist = Dist (c, Point(el.PNum(j))); + double dn = (nf - normals.Get(el.PNum(j))).Length(); + + RestrictLocalH (Point(el.PNum(j)), dist / (dn+1e-12) /elperr); + } + } + } + */ + } + + + void Mesh :: RestrictLocalH (resthtype rht, int nr, double loch) + { + int i; + switch (rht) + { + case RESTRICTH_FACE: + { + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & sel = SurfaceElement(i); + if (sel.GetIndex() == nr) + RestrictLocalH (RESTRICTH_SURFACEELEMENT, i, loch); + } + break; + } + case RESTRICTH_EDGE: + { + for (i = 1; i <= GetNSeg(); i++) + { + const Segment & seg = LineSegment(i); + if (seg.edgenr == nr) + RestrictLocalH (RESTRICTH_SEGMENT, i, loch); + } + break; + } + case RESTRICTH_POINT: + { + RestrictLocalH (Point (nr), loch); + break; + } + + case RESTRICTH_SURFACEELEMENT: + { + const Element2d & sel = SurfaceElement(nr); + Point3d p = Center (Point(sel.PNum(1)), + Point(sel.PNum(2)), + Point(sel.PNum(3))); + RestrictLocalH (p, loch); + break; + } + case RESTRICTH_SEGMENT: + { + const Segment & seg = LineSegment(nr); + RestrictLocalHLine (Point (seg.p1), Point(seg.p2), loch); + break; + } + } + } + + + void Mesh :: LoadLocalMeshSize (const char * meshsizefilename) + { + if (!meshsizefilename) return; + + ifstream msf(meshsizefilename); + + if (!msf) return; + + PrintMessage (3, "Load local mesh-size"); + int nmsp, nmsl; + msf >> nmsp; + for (int i = 0; i < nmsp; i++) + { + Point3d pi; + double hi; + msf >> pi.X() >> pi.Y() >> pi.Z(); + msf >> hi; + if (!msf.good()) + throw NgException ("problem in mesh-size file\n"); + RestrictLocalH (pi, hi); + } + msf >> nmsl; + for (int i = 0; i < nmsl; i++) + { + Point3d p1, p2; + double hi; + msf >> p1.X() >> p1.Y() >> p1.Z(); + msf >> p2.X() >> p2.Y() >> p2.Z(); + msf >> hi; + if (!msf.good()) + throw NgException ("problem in mesh-size file\n"); + RestrictLocalHLine (p1, p2, hi); + } + } + + + + void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, int dom) const + { + if (points.Size() == 0) + { + pmin = pmax = Point3d(0,0,0); + return; + } + + if (dom <= 0) + { + pmin = Point3d (1e10, 1e10, 1e10); + pmax = Point3d (-1e10, -1e10, -1e10); + + for (PointIndex pi = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; pi++) + { + pmin.SetToMin ( (*this) [pi] ); + pmax.SetToMax ( (*this) [pi] ); + } + } + else + { + int j, nse = GetNSE(); + SurfaceElementIndex sei; + + pmin = Point3d (1e10, 1e10, 1e10); + pmax = Point3d (-1e10, -1e10, -1e10); + for (sei = 0; sei < nse; sei++) + { + const Element2d & el = (*this)[sei]; + if (el.IsDeleted() ) continue; + + if (dom == -1 || el.GetIndex() == dom) + { + for (j = 0; j < 3; j++) + { + pmin.SetToMin ( (*this) [el[j]] ); + pmax.SetToMax ( (*this) [el[j]] ); + } + } + } + } + + if (pmin.X() > 0.5e10) + { + pmin = pmax = Point3d(0,0,0); + } + } + + + + + void Mesh :: GetBox (Point3d & pmin, Point3d & pmax, POINTTYPE ptyp) const + { + if (points.Size() == 0) + { + pmin = pmax = Point3d(0,0,0); + return; + } + + pmin = Point3d (1e10, 1e10, 1e10); + pmax = Point3d (-1e10, -1e10, -1e10); + + for (PointIndex pi = PointIndex::BASE; + pi < GetNP()+PointIndex::BASE; pi++) + if (points[pi].Type() <= ptyp) + { + pmin.SetToMin ( (*this) [pi] ); + pmax.SetToMax ( (*this) [pi] ); + } + } + + + + + double Mesh :: ElementError (int eli) const + { + const Element & el = volelements.Get(eli); + return CalcTetBadness (points.Get(el[0]), points.Get(el[1]), + points.Get(el[2]), points.Get(el[3]), -1); + } + + void Mesh :: AddLockedPoint (PointIndex pi) + { + lockedpoints.Append (pi); + } + + void Mesh :: ClearLockedPoints () + { + lockedpoints.SetSize (0); + } + + + + void Mesh :: Compress () + { + int i, j; + ARRAY<int,PointIndex::BASE> op2np(GetNP()); + ARRAY<MeshPoint> hpoints; + BitArrayChar<PointIndex::BASE> pused(GetNP()); + + /* + (*testout) << "volels: " << endl; + for (i = 1; i <= volelements.Size(); i++) + { + for (j = 1; j <= volelements.Get(i).GetNP(); j++) + (*testout) << volelements.Get(i).PNum(j) << " "; + (*testout) << endl; + } + (*testout) << "np: " << GetNP() << endl; + */ + + for (i = 0; i < volelements.Size(); i++) + if (volelements[i][0] <= PointIndex::BASE-1 || + volelements[i].IsDeleted()) + { + volelements.Delete(i); + i--; + } + + + for (i = 0; i < surfelements.Size(); i++) + if (surfelements[i].IsDeleted()) + { + surfelements.Delete(i); + i--; + } + + for (i = 0; i < segments.Size(); i++) + if (segments[i].p1 <= PointIndex::BASE-1) + { + segments.Delete(i); + i--; + } + + pused.Clear(); + for (i = 0; i < volelements.Size(); i++) + { + const Element & el = volelements[i]; + for (j = 0; j < el.GetNP(); j++) + pused.Set (el[j]); + } + + for (i = 0; i < surfelements.Size(); i++) + { + const Element2d & el = surfelements[i]; + for (j = 0; j < el.GetNP(); j++) + pused.Set (el[j]); + } + + for (i = 0; i < segments.Size(); i++) + { + const Segment & seg = segments[i]; + pused.Set (seg.p1); + pused.Set (seg.p2); + } + + for (i = 0; i < openelements.Size(); i++) + { + const Element2d & el = openelements[i]; + for (j = 0; j < el.GetNP(); j++) + pused.Set(el[j]); + } + + for (i = 0; i < lockedpoints.Size(); i++) + pused.Set (lockedpoints[i]); + + + /* + // compress points doesnt work for identified points ! + if (identifiedpoints) + { + for (i = 1; i <= identifiedpoints->GetNBags(); i++) + if (identifiedpoints->GetBagSize(i)) + { + pused.Set (); + break; + } + } + */ + // pused.Set(); + + + int npi = PointIndex::BASE-1; + + for (i = PointIndex::BASE; + i < points.Size()+PointIndex::BASE; i++) + if (pused.Test(i)) + { + npi++; + op2np[i] = npi; + hpoints.Append (points[i]); + } + else + op2np[i] = -1; + + + + points.SetSize(0); + for (i = 0; i < hpoints.Size(); i++) + points.Append (hpoints[i]); + + + for (i = 1; i <= volelements.Size(); i++) + { + Element & el = VolumeElement(i); + for (j = 0; j < el.GetNP(); j++) + el[j] = op2np[el[j]]; + } + + for (i = 1; i <= surfelements.Size(); i++) + { + Element2d & el = SurfaceElement(i); + for (j = 0; j < el.GetNP(); j++) + el[j] = op2np[el[j]]; + } + + for (i = 0; i < segments.Size(); i++) + { + Segment & seg = segments[i]; + seg.p1 = op2np[seg.p1]; + seg.p2 = op2np[seg.p2]; + } + + for (i = 1; i <= openelements.Size(); i++) + { + Element2d & el = openelements.Elem(i); + for (j = 0; j < el.GetNP(); j++) + el[j] = op2np[el[j]]; + } + + + for (i = 0; i < lockedpoints.Size(); i++) + lockedpoints[i] = op2np[lockedpoints[i]]; + + for (int i = 0; i < facedecoding.Size(); i++) + facedecoding[i].firstelement = -1; + for (int i = surfelements.Size()-1; i >= 0; i--) + { + int ind = surfelements[i].GetIndex(); + surfelements[i].next = facedecoding[ind-1].firstelement; + facedecoding[ind-1].firstelement = i; + } + + + CalcSurfacesOfNode(); + + + // FindOpenElements(); + timestamp = NextTimeStamp(); + + /* + (*testout) << "compress, done" << endl + << "np = " << points.Size() + << "ne = " << volelements.Size() << ", type.size = " << eltyps.Size() + << "volelements = " << volelements << endl; + */ + } + + + int Mesh :: CheckConsistentBoundary () const + { + int nf = GetNOpenElements(); + INDEX_2_HASHTABLE<int> edges(nf+2); + INDEX_2 i2, i2s, edge; + int err = 0; + + for (int i = 1; i <= nf; i++) + { + const Element2d & sel = OpenElement(i); + + for (int j = 1; j <= sel.GetNP(); j++) + { + i2.I1() = sel.PNumMod(j); + i2.I2() = sel.PNumMod(j+1); + + int sign = (i2.I2() > i2.I1()) ? 1 : -1; + i2.Sort(); + if (!edges.Used (i2)) + edges.Set (i2, 0); + edges.Set (i2, edges.Get(i2) + sign); + } + } + + for (int i = 1; i <= edges.GetNBags(); i++) + for (int j = 1; j <= edges.GetBagSize(i); j++) + { + int cnt = 0; + edges.GetData (i, j, i2, cnt); + if (cnt) + { + PrintError ("Edge ", i2.I1() , " - ", i2.I2(), " multiple times in surface mesh"); + + (*testout) << "Edge " << i2 << " multiple times in surface mesh" << endl; + i2s = i2; + i2s.Sort(); + for (int k = 1; k <= nf; k++) + { + const Element2d & sel = OpenElement(k); + for (int l = 1; l <= sel.GetNP(); l++) + { + edge.I1() = sel.PNumMod(l); + edge.I2() = sel.PNumMod(l+1); + edge.Sort(); + + if (edge == i2s) + (*testout) << "edge of element " << sel << endl; + } + } + + + err = 2; + } + } + + return err; + } + + + + int Mesh :: CheckOverlappingBoundary () + { + int i, j, k; + + Point3d pmin, pmax; + GetBox (pmin, pmax); + Box3dTree setree(pmin, pmax); + ARRAY<int> inters; + + bool overlap = 0; + bool incons_layers = 0; + + + for (i = 1; i <= GetNSE(); i++) + SurfaceElement(i).badel = 0; + + + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & tri = SurfaceElement(i); + + Point3d tpmin (Point(tri[0])); + Point3d tpmax (tpmin); + + for (k = 1; k < tri.GetNP(); k++) + { + tpmin.SetToMin (Point (tri[k])); + tpmax.SetToMax (Point (tri[k])); + } + Vec3d diag(tpmin, tpmax); + + tpmax = tpmax + 0.1 * diag; + tpmin = tpmin - 0.1 * diag; + + setree.Insert (tpmin, tpmax, i); + } + + for (i = 1; i <= GetNSE(); i++) + { + const Element2d & tri = SurfaceElement(i); + + Point3d tpmin (Point(tri[0])); + Point3d tpmax (tpmin); + + for (k = 1; k < tri.GetNP(); k++) + { + tpmin.SetToMin (Point (tri[k])); + tpmax.SetToMax (Point (tri[k])); + } + + setree.GetIntersecting (tpmin, tpmax, inters); + + for (j = 1; j <= inters.Size(); j++) + { + const Element2d & tri2 = SurfaceElement(inters.Get(j)); + + if ( (*this)[tri[0]].GetLayer() != (*this)[tri2[0]].GetLayer()) + continue; + + if ( (*this)[tri[0]].GetLayer() != (*this)[tri[1]].GetLayer() || + (*this)[tri[0]].GetLayer() != (*this)[tri[2]].GetLayer()) + { + incons_layers = 1; + cout << "inconsistent layers in triangle" << endl; + } + + + const netgen::Point<3> *trip1[3], *trip2[3]; + for (k = 1; k <= 3; k++) + { + trip1[k-1] = &Point (tri.PNum(k)); + trip2[k-1] = &Point (tri2.PNum(k)); + } + + if (IntersectTriangleTriangle (&trip1[0], &trip2[0])) + { + overlap = 1; + PrintWarning ("Intersecting elements " + ,i, " and ", inters.Get(j)); + + (*testout) << "Intersecting: " << endl; + (*testout) << "openelement " << i << " with open element " << inters.Get(j) << endl; + + cout << "el1 = " << tri << endl; + cout << "el2 = " << tri2 << endl; + cout << "layer1 = " << (*this)[tri[0]].GetLayer() << endl; + cout << "layer2 = " << (*this)[tri2[0]].GetLayer() << endl; + + + for (k = 1; k <= 3; k++) + (*testout) << tri.PNum(k) << " "; + (*testout) << endl; + for (k = 1; k <= 3; k++) + (*testout) << tri2.PNum(k) << " "; + (*testout) << endl; + + for (k = 0; k <= 2; k++) + (*testout) << *trip1[k] << " "; + (*testout) << endl; + for (k = 0; k <= 2; k++) + (*testout) << *trip2[k] << " "; + (*testout) << endl; + + (*testout) << "Face1 = " << GetFaceDescriptor(tri.GetIndex()) << endl; + (*testout) << "Face1 = " << GetFaceDescriptor(tri2.GetIndex()) << endl; + + /* + INDEX_3 i3(tri.PNum(1), tri.PNum(2), tri.PNum(3)); + i3.Sort(); + for (k = 1; k <= GetNSE(); k++) + { + const Element2d & el2 = SurfaceElement(k); + INDEX_3 i3b(el2.PNum(1), el2.PNum(2), el2.PNum(3)); + i3b.Sort(); + if (i3 == i3b) + { + SurfaceElement(k).badel = 1; + } + } + */ + SurfaceElement(i).badel = 1; + SurfaceElement(inters.Get(j)).badel = 1; + } + } + } + + // bug 'fix' + if (incons_layers) overlap = 0; + + return overlap; + } + + + int Mesh :: CheckVolumeMesh () const + { + PrintMessage (3, "Checking volume mesh"); + + int ne = GetNE(); + DenseMatrix dtrans(3,3); + int i, j; + + PrintMessage (5, "elements: ", ne); + for (i = 1; i <= ne; i++) + { + Element & el = (Element&) VolumeElement(i); + el.flags.badel = 0; + int nip = el.GetNIP(); + for (j = 1; j <= nip; j++) + { + el.GetTransformation (j, Points(), dtrans); + double det = dtrans.Det(); + if (det > 0) + { + PrintError ("Element ", i , " has wrong orientation"); + el.flags.badel = 1; + } + } + } + + return 0; + } + + + bool Mesh :: LegalTrig (const Element2d & el) const + { + return 1; + if ( /* hp */ 1) // needed for old, simple hp-refinement + { + // trigs with 2 or more segments are illegal + int i; + int nseg = 0; + + if (!segmentht) + { + cerr << "no segmentht allocated" << endl; + return 0; + } + + // Point3d cp(0.5, 0.5, 0.5); + for (i = 1; i <= 3; i++) + { + INDEX_2 i2(el.PNumMod (i), el.PNumMod (i+1)); + i2.Sort(); + if (segmentht -> Used (i2)) + nseg++; + } + if (nseg >= 2) + return 0; + } + return 1; + } + + + + + /// + bool Mesh :: LegalTet2 (Element & el) const + { + // static int timer1 = NgProfiler::CreateTimer ("Legaltet2"); + + + // Test, whether 4 points have a common surface plus + // at least 4 edges at the boundary + + if(!boundaryedges) + const_cast<Mesh *>(this)->BuildBoundaryEdges(); + + + // non-tets are always legal + if (el.GetType() != TET) + { + el.SetLegal (1); + return 1; + } + + POINTTYPE pointtype[4]; + for(int i = 0; i < 4; i++) + pointtype[i] = (*this)[el[i]].Type(); + + + + // element has at least 2 inner points ---> legal + int cnti = 0; + for (int j = 0; j < 4; j++) + if ( pointtype[j] == INNERPOINT) + { + cnti++; + if (cnti >= 2) + { + el.SetLegal (1); + return 1; + } + } + + + + // which faces are boundary faces ? + int bface[4]; + for (int i = 0; i < 4; i++) + { + bface[i] = surfelementht->Used (INDEX_3::Sort(el[gftetfacesa[i][0]], + el[gftetfacesa[i][1]], + el[gftetfacesa[i][2]])); + } + + int bedge[4][4]; + int segedge[4][4]; + static const int pi3map[4][4] = { { -1, 2, 1, 1 }, + { 2, -1, 0, 0 }, + { 1, 0, -1, 0 }, + { 1, 0, 0, -1 } }; + + static const int pi4map[4][4] = { { -1, 3, 3, 2 }, + { 3, -1, 3, 2 }, + { 3, 3, -1, 1 }, + { 2, 2, 1, -1 } }; + + + for (int i = 0; i < 4; i++) + for (int j = 0; j < i; j++) + { + bool sege = false, be = false; + + int pos = boundaryedges -> Position(INDEX_2::Sort(el[i], el[j])); + if (pos) + { + be = true; + if (boundaryedges -> GetData(pos) == 2) + sege = true; + } + + segedge[j][i] = segedge[i][j] = sege; + bedge[j][i] = bedge[i][j] = be; + } + + // two boundary faces and no edge is illegal + for (int i = 0; i < 3; i++) + for (int j = i+1; j < 4; j++) + { + if (bface[i] && bface[j]) + if (!segedge[pi3map[i][j]][pi4map[i][j]]) + { + // 2 boundary faces withoud edge in between + el.SetLegal (0); + return 0; + } + } + + // three boundary edges meeting in a Surface point + for (int i = 0; i < 4; i++) + { + bool alledges = 1; + if ( pointtype[i] == SURFACEPOINT) + { + bool alledges = 1; + for (int j = 0; j < 4; j++) + if (j != i && !bedge[i][j]) + { + alledges = 0; + break; + } + if (alledges) + { + // cout << "tet illegal due to unmarked node" << endl; + el.SetLegal (0); + return 0; + } + } + } + + + + for (int fnr = 0; fnr < 4; fnr++) + if (!bface[fnr]) + for (int i = 0; i < 4; i++) + if (i != fnr) + { + int pi1 = pi3map[i][fnr]; + int pi2 = pi4map[i][fnr]; + + if ( pointtype[i] == SURFACEPOINT) + { + // two connected edges on surface, but no face + if (bedge[i][pi1] && bedge[i][pi2]) + { + el.SetLegal (0); + return 0; + } + } + + if ( pointtype[i] == EDGEPOINT) + { + // connected surface edge and edge edge, but no face + if (bedge[i][pi1] && segedge[i][pi2] || + bedge[i][pi2] && segedge[i][pi1]) + { + el.SetLegal (0); + return 0; + } + } + + } + + + el.SetLegal (1); + return 1; + + } + + + + int Mesh :: GetNDomains() const + { + int ndom = 0; + + for (int k = 0; k < facedecoding.Size(); k++) + { + if (facedecoding[k].DomainIn() > ndom) + ndom = facedecoding[k].DomainIn(); + if (facedecoding[k].DomainOut() > ndom) + ndom = facedecoding[k].DomainOut(); + } + + return ndom; + } + + + + void Mesh :: SurfaceMeshOrientation () + { + int i, j; + int nse = GetNSE(); + + BitArray used(nse); + used.Clear(); + INDEX_2_HASHTABLE<int> edges(nse+1); + + bool haschanged = 0; + + + const Element2d & tri = SurfaceElement(1); + for (j = 1; j <= 3; j++) + { + INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1)); + edges.Set (i2, 1); + } + used.Set(1); + + bool unused; + do + { + bool changed; + do + { + changed = 0; + for (i = 1; i <= nse; i++) + if (!used.Test(i)) + { + Element2d & el = surfelements.Elem(i); + int found = 0, foundrev = 0; + for (j = 1; j <= 3; j++) + { + INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1)); + if (edges.Used(i2)) + foundrev = 1; + swap (i2.I1(), i2.I2()); + if (edges.Used(i2)) + found = 1; + } + + if (found || foundrev) + { + if (foundrev) + swap (el.PNum(2), el.PNum(3)); + + changed = 1; + for (j = 1; j <= 3; j++) + { + INDEX_2 i2(el.PNumMod(j), el.PNumMod(j+1)); + edges.Set (i2, 1); + } + used.Set (i); + } + } + if (changed) + haschanged = 1; + } + while (changed); + + + unused = 0; + for (i = 1; i <= nse; i++) + if (!used.Test(i)) + { + unused = 1; + const Element2d & tri = SurfaceElement(i); + for (j = 1; j <= 3; j++) + { + INDEX_2 i2(tri.PNumMod(j), tri.PNumMod(j+1)); + edges.Set (i2, 1); + } + used.Set(i); + break; + } + } + while (unused); + + if (haschanged) + timestamp = NextTimeStamp(); + } + + + void Mesh :: Split2Tets() + { + PrintMessage (1, "Split To Tets"); + bool has_prisms = 0; + + int oldne = GetNE(); + for (int i = 1; i <= oldne; i++) + { + Element el = VolumeElement(i); + + if (el.GetType() == PRISM) + { + // prism, to 3 tets + + // make minimal node to node 1 + int minpi=0; + PointIndex minpnum; + minpnum = GetNP() + 1; + + for (int j = 1; j <= 6; j++) + { + if (el.PNum(j) < minpnum) + { + minpnum = el.PNum(j); + minpi = j; + } + } + + if (minpi >= 4) + { + for (int j = 1; j <= 3; j++) + swap (el.PNum(j), el.PNum(j+3)); + minpi -= 3; + } + + while (minpi > 1) + { + int hi = 0; + for (int j = 0; j <= 3; j+= 3) + { + hi = el.PNum(1+j); + el.PNum(1+j) = el.PNum(2+j); + el.PNum(2+j) = el.PNum(3+j); + el.PNum(3+j) = hi; + } + minpi--; + } + + /* + version 1: edge from pi2 to pi6, + version 2: edge from pi3 to pi5, + */ + + static const int ntets[2][12] = + { { 1, 4, 5, 6, 1, 2, 3, 6, 1, 2, 5, 6 }, + { 1, 4, 5, 6, 1, 2, 3, 5, 3, 1, 5, 6 } }; + + const int * min2pi; + + if (min2 (el.PNum(2), el.PNum(6)) < + min2 (el.PNum(3), el.PNum(5))) + { + min2pi = &ntets[0][0]; + // (*testout) << "version 1 "; + } + else + { + min2pi = &ntets[1][0]; + // (*testout) << "version 2 "; + } + + + int firsttet = 1; + for (int j = 1; j <= 3; j++) + { + Element nel(TET); + for (int k = 1; k <= 4; k++) + nel.PNum(k) = el.PNum(min2pi[4 * j + k - 5]); + nel.SetIndex (el.GetIndex()); + + int legal = 1; + for (int k = 1; k <= 3; k++) + for (int l = k+1; l <= 4; l++) + if (nel.PNum(k) == nel.PNum(l)) + legal = 0; + + // (*testout) << nel << " "; + if (legal) + { + if (firsttet) + { + VolumeElement(i) = nel; + firsttet = 0; + } + else + { + AddVolumeElement(nel); + } + } + } + if (firsttet) cout << "no legal"; + (*testout) << endl; + } + + + + else if (el.GetType() == HEX) + { + // hex to A) 2 prisms or B) to 5 tets + + // make minimal node to node 1 + int minpi=0; + PointIndex minpnum; + minpnum = GetNP() + 1; + + for (int j = 1; j <= 8; j++) + { + if (el.PNum(j) < minpnum) + { + minpnum = el.PNum(j); + minpi = j; + } + } + + if (minpi >= 5) + { + for (int j = 1; j <= 4; j++) + swap (el.PNum(j), el.PNum(j+4)); + minpi -= 4; + } + + while (minpi > 1) + { + int hi = 0; + for (int j = 0; j <= 4; j+= 4) + { + hi = el.PNum(1+j); + el.PNum(1+j) = el.PNum(2+j); + el.PNum(2+j) = el.PNum(3+j); + el.PNum(3+j) = el.PNum(4+j); + el.PNum(4+j) = hi; + } + minpi--; + } + + + + static const int to_prisms[3][12] = + { { 0, 1, 2, 4, 5, 6, 0, 2, 3, 4, 6, 7 }, + { 0, 1, 5, 3, 2, 6, 0, 5, 4, 3, 6, 7 }, + { 0, 7, 4, 1, 6, 5, 0, 3, 7, 1, 2, 6 }, + }; + + const int * min2pi = 0; + if (min2 (el[4], el[6]) < min2 (el[5], el[7])) + min2pi = &to_prisms[0][0]; + else if (min2 (el[3], el[6]) < min2 (el[2], el[7])) + min2pi = &to_prisms[1][0]; + else if (min2 (el[1], el[6]) < min2 (el[2], el[5])) + min2pi = &to_prisms[2][0]; + + if (min2pi) + { + has_prisms = 1; + for (int j = 0; j < 2; j++) + { + Element nel(PRISM); + for (int k = 0; k < 6; k++) + nel[k] = el[min2pi[6*j + k]]; + nel.SetIndex (el.GetIndex()); + + if (j == 0) + VolumeElement(i) = nel; + else + AddVolumeElement(nel); + } + } + else + { + // split to 5 tets + + static const int to_tets[20] = + { + 1, 2, 0, 5, + 3, 0, 2, 7, + 4, 5, 7, 0, + 6, 7, 5, 2, + 0, 2, 7, 5 + }; + + for (int j = 0; j < 5; j++) + { + Element nel(TET); + for (int k = 0; k < 4; k++) + nel[k] = el[to_tets[4*j + k]]; + nel.SetIndex (el.GetIndex()); + + if (j == 0) + VolumeElement(i) = nel; + else + AddVolumeElement(nel); + } + + } + } + + + + + + else if (el.GetType() == PYRAMID) + { + // pyramid, to 2 tets + + // cout << "pyramid: " << el << endl; + + static const int ntets[2][8] = + { { 1, 2, 3, 5, 1, 3, 4, 5 }, + { 1, 2, 4, 5, 4, 2, 3, 5 }}; + + const int * min2pi; + + if (min2 (el[0], el[2]) < min2 (el[1], el[3])) + min2pi = &ntets[0][0]; + else + min2pi = &ntets[1][0]; + + bool firsttet = 1; + for (int j = 0; j < 2; j++) + { + Element nel(TET); + for (int k = 0; k < 4; k++) + nel[k] = el[min2pi[4*j + k]-1]; + nel.SetIndex (el.GetIndex()); + + // cout << "pyramid-tet: " << nel << endl; + + bool legal = 1; + for (int k = 0; k < 3; k++) + for (int l = k+1; l < 4; l++) + if (nel[k] == nel[l]) + legal = 0; + + if (legal) + { + (*testout) << nel << " "; + if (firsttet) + VolumeElement(i) = nel; + else + AddVolumeElement(nel); + + firsttet = 0; + } + } + if (firsttet) cout << "no legal"; + (*testout) << endl; + } + } + + + int oldnse = GetNSE(); + for (int i = 1; i <= oldnse; i++) + { + Element2d el = SurfaceElement(i); + if (el.GetNP() == 4) + { + (*testout) << "split el: " << el << " to "; + + static const int ntris[2][6] = + { { 1, 2, 3, 1, 3, 4 }, + { 1, 2, 4, 4, 2, 3 }}; + + const int * min2pi; + + if (min2 (el.PNum(1), el.PNum(3)) < + min2 (el.PNum(2), el.PNum(4))) + min2pi = &ntris[0][0]; + else + min2pi = &ntris[1][0]; + + for (int j = 0; j <6; j++) + (*testout) << min2pi[j] << " "; + + + int firsttri = 1; + for (int j = 1; j <= 2; j++) + { + Element2d nel(3); + for (int k = 1; k <= 3; k++) + nel.PNum(k) = el.PNum(min2pi[3 * j + k - 4]); + nel.SetIndex (el.GetIndex()); + + int legal = 1; + for (int k = 1; k <= 2; k++) + for (int l = k+1; l <= 3; l++) + if (nel.PNum(k) == nel.PNum(l)) + legal = 0; + + if (legal) + { + (*testout) << nel << " "; + if (firsttri) + { + SurfaceElement(i) = nel; + firsttri = 0; + } + else + { + AddSurfaceElement(nel); + } + } + } + (*testout) << endl; + + } + } + + + if (has_prisms) + + Split2Tets(); + + else + { + for (int i = 1; i <= GetNE(); i++) + { + Element & el = VolumeElement(i); + const Point3d & p1 = Point (el.PNum(1)); + const Point3d & p2 = Point (el.PNum(2)); + const Point3d & p3 = Point (el.PNum(3)); + const Point3d & p4 = Point (el.PNum(4)); + + double vol = (Vec3d (p1, p2) * + Cross (Vec3d (p1, p3), Vec3d(p1, p4))); + if (vol > 0) + swap (el.PNum(3), el.PNum(4)); + } + + + + UpdateTopology(); + timestamp = NextTimeStamp(); + } + } + + void Mesh :: BuildElementSearchTree () + { + if (elementsearchtreets == GetTimeStamp()) + return; + + NgLock lock(mutex); + lock.Lock(); + + PrintMessage (4, "Rebuild element searchtree"); + + if (elementsearchtree) + delete elementsearchtree; + elementsearchtree = NULL; + + Box3d box; + int i, j; + int ne = GetNE(); + if (!ne) + { + lock.UnLock(); + return; + } + + box.SetPoint (Point (VolumeElement(1).PNum(1))); + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + for (j = 1; j <= el.GetNP(); j++) + box.AddPoint (Point (el.PNum(j))); + } + + box.Increase (1.01 * box.CalcDiam()); + elementsearchtree = new Box3dTree (box.PMin(), box.PMax()); + + + + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + box.SetPoint (Point (el.PNum(1))); + for (j = 1; j <= el.GetNP(); j++) + box.AddPoint (Point (el.PNum(j))); + + elementsearchtree -> Insert (box.PMin(), box.PMax(), i); + } + + elementsearchtreets = GetTimeStamp(); + + lock.UnLock(); + } + + + + bool Mesh :: PointContainedIn2DElement(const Point3d & p, + double lami[3], + const int element, + bool consider3D) const + { + static Vec3d col1, col2, col3; + static Vec3d rhs, sol; + const double eps = 1e-6; + + static ARRAY<Element2d> loctrigs; + + + //SZ + if(SurfaceElement(element).GetType()==QUAD) + { + const Element2d & el = SurfaceElement(element); + + const Point3d & p1 = Point(el.PNum(1)); + const Point3d & p2 = Point(el.PNum(2)); + const Point3d & p3 = Point(el.PNum(3)); + const Point3d & p4 = Point(el.PNum(4)); + + // Coefficients of Bilinear Mapping from Ref-Elem to global Elem + // X = a + b x + c y + d x y + Vec3d a = p1; + Vec3d b = p2 - a; + Vec3d c = p4 - a; + Vec3d d = p3 - a - b - c; + + double dxb = d.X()*b.Y()-d.Y()*b.X(); + double dxc = d.X()*c.Y()-d.Y()*c.X(); + double dxa = d.X()*a.Y()-d.Y()*a.X(); + double dxp = d.X()*p.Y()-d.Y()*p.X(); + + double c0,c1,c2,rt; + lami[2]=0.; + double eps = 1.E-12; + + if(fabs(d.X()) <= eps && fabs(d.Y())<= eps) + { + //Solve Linear System + lami[0]=(c.Y()*(p.X()-a.X())-c.X()*(p.Y()-a.Y()))/ + (b.X()*c.Y() -b.Y()*c.X()); + lami[1]=(-b.Y()*(p.X()-a.X())+b.X()*(p.Y()-a.Y()))/ + (b.X()*c.Y() -b.Y()*c.X()); + } + else + if(fabs(dxb) <= eps) + { + lami[1] = (dxp-dxa)/dxc; + if(fabs(b.X()-d.X()*lami[1])>=eps) + lami[0] = (p.X()-a.X() - c.X()*lami[1])/(b.X()+d.X()*lami[1]); + else + lami[0] = (p.Y()-a.Y() - c.Y()*lami[1])/(b.Y()+d.Y()*lami[1]); + } + else + if(fabs(dxc) <= eps) + { + lami[0] = (dxp-dxa)/dxb; + if(fabs(c.X()-d.X()*lami[0])>=eps) + lami[1] = (p.X()-a.X() - b.X()*lami[0])/(c.X()+d.X()*lami[0]); + else + lami[1] = (p.Y()-a.Y() - b.Y()*lami[0])/(c.Y()+d.Y()*lami[0]); + } + else //Solve quadratic equation + { + if(fabs(d.X()) >= eps) + { + c2 = d.X()*dxc; + c1 = d.X()*dxc - c.X()*dxb - d.X()*(dxp-dxa); + c0 = -b.X()*(dxp -dxa) - (a.X()-p.X())*dxb; + } + else + { + c2 = d.Y()*dxc; + c1 = d.Y()*dxc - c.Y()*dxb - d.Y()*(dxp-dxa); + c0 = -b.Y()*(dxp -dxa) - (a.Y()-p.Y())*dxb; + } + + double rt = c1*c1 - 4*c2*c0; + if (rt < 0.) return false; + lami[1] = (-c1 + sqrt(rt))/2/c2; + if(lami[1]<=1. && lami[1]>=0.) + { + lami[0] = (dxp - dxa -dxc*lami[1])/dxb; + if(lami[0]<=1. && lami[0]>=0.) + return true; + } + + lami[1] = (-c1 - sqrt(rt))/2/c2; + lami[0] = (dxp - dxa -dxc*lami[1])/dxb; + } + + if( lami[0] <= 1.+eps && lami[0] >= -eps && lami[1]<=1.+eps && lami[1]>=-eps) + { + if(consider3D) + { + Vec3d n = Cross(b,c); + lami[2] = 0; + for(int i=1; i<=3; i++) + lami[2] +=(p.X(i)-a.X(i)-lami[0]*b.X(i)-lami[1]*c.X(i)) * n.X(i); + if(lami[2] >= -eps && lami[2] <= eps) + return true; + } + else + return true; + } + + return false; + + } + else + { + // SurfaceElement(element).GetTets (loctets); + loctrigs.SetSize(1); + loctrigs.Elem(1) = SurfaceElement(element); + + + + for (int j = 1; j <= loctrigs.Size(); j++) + { + const Element2d & el = loctrigs.Get(j); + + + const Point3d & p1 = Point(el.PNum(1)); + const Point3d & p2 = Point(el.PNum(2)); + const Point3d & p3 = Point(el.PNum(3)); + /* + Box3d box; + box.SetPoint (p1); + box.AddPoint (p2); + box.AddPoint (p3); + box.AddPoint (p4); + if (!box.IsIn (p)) + continue; + */ + col1 = p2-p1; + col2 = p3-p1; + col3 = Cross(col1,col2); + //col3 = Vec3d(0, 0, 1); + rhs = p - p1; + + int retval = SolveLinearSystem (col1, col2, col3, rhs, sol); + + //(*testout) << "retval " << retval << endl; + + //(*testout) << "col1 " << col1 << " col2 " << col2 << " col3 " << col3 << " rhs " << rhs << endl; + //(*testout) << "sol " << sol << endl; + + if (sol.X() >= -eps && sol.Y() >= -eps && + sol.X() + sol.Y() <= 1+eps) + { + if(!consider3D || (sol.Z() >= -eps && sol.Z() <= eps)) + { + lami[0] = sol.X(); + lami[1] = sol.Y(); + lami[2] = sol.Z(); + + return true; + } + } + } + } + + return false; + + } + + + + + bool Mesh :: PointContainedIn3DElement(const Point3d & p, + double lami[3], + const int element) const + { + //bool oldresult = PointContainedIn3DElementOld(p,lami,element); + //(*testout) << "old result: " << oldresult + // << " lam " << lami[0] << " " << lami[1] << " " << lami[2] << endl; + + //if(!curvedelems->IsElementCurved(element-1)) + // return PointContainedIn3DElementOld(p,lami,element); + + + const double eps = 1.e-4; + const Element & el = VolumeElement(element); + + netgen::Point<3> lam; + + if (el.GetType() == TET) + { + lam = 0.25; + } + else if (el.GetType() == PRISM) + { + lam(0) = 0.33; lam(1) = 0.33; lam(2) = 0.5; + } + else if (el.GetType() == PYRAMID) + { + lam(0) = 0.4; lam(1) = 0.4; lam(2) = 0.2; + } + else if (el.GetType() == HEX) + { + lam = 0.5; + } + + + Vec<3> deltalam,rhs; + netgen::Point<3> x; + Mat<3,3> Jac,Jact; + + double delta=1; + + bool retval; + + int i = 0; + + const int maxits = 30; + + while(delta > 1e-16 && i<maxits) + { + curvedelems->CalcElementTransformation(lam,element-1,x,Jac); + + rhs = p-x; + Jac.Solve(rhs,deltalam); + + lam += deltalam; + + delta = deltalam.Length2(); + + i++; + //(*testout) << "pcie i " << i << " delta " << delta << " p " << p << " x " << x << " lam " << lam << endl; + //<< "Jac " << Jac << endl; + } + + if(i==maxits) + return false; + + + for(i=0; i<3; i++) + lami[i] = lam(i); + + + + if (el.GetType() == TET) + { + retval = (lam(0) > -eps && + lam(1) > -eps && + lam(2) > -eps && + lam(0) + lam(1) + lam(2) < 1+eps); + } + else if (el.GetType() == PRISM) + { + retval = (lam(0) > -eps && + lam(1) > -eps && + lam(2) > -eps && + lam(2) < 1+eps && + lam(0) + lam(1) < 1+eps); + } + else if (el.GetType() == PYRAMID) + { + retval = (lam(0) > -eps && + lam(1) > -eps && + lam(2) > -eps && + lam(0) + lam(2) < 1+eps && + lam(1) + lam(2) < 1+eps); + } + else if (el.GetType() == HEX) + { + retval = (lam(0) > -eps && lam(0) < 1+eps && + lam(1) > -eps && lam(1) < 1+eps && + lam(2) > -eps && lam(2) < 1+eps); + } + else + throw NgException("Da haun i wos vagessn"); + + return retval; + } + + + + bool Mesh :: PointContainedIn3DElementOld(const Point3d & p, + double lami[3], + const int element) const + { + + static Vec3d col1, col2, col3; + static Vec3d rhs, sol; + const double eps = 1.e-4; + + static ARRAY<Element> loctets; + + VolumeElement(element).GetTets (loctets); + + for (int j = 1; j <= loctets.Size(); j++) + { + const Element & el = loctets.Get(j); + + const Point3d & p1 = Point(el.PNum(1)); + const Point3d & p2 = Point(el.PNum(2)); + const Point3d & p3 = Point(el.PNum(3)); + const Point3d & p4 = Point(el.PNum(4)); + + Box3d box; + box.SetPoint (p1); + box.AddPoint (p2); + box.AddPoint (p3); + box.AddPoint (p4); + if (!box.IsIn (p)) + continue; + + col1 = p2-p1; + col2 = p3-p1; + col3 = p4-p1; + rhs = p - p1; + + SolveLinearSystem (col1, col2, col3, rhs, sol); + + if (sol.X() >= -eps && sol.Y() >= -eps && sol.Z() >= -eps && + sol.X() + sol.Y() + sol.Z() <= 1+eps) + { + ARRAY<Element> loctetsloc; + ARRAY<netgen::Point<3> > pointsloc; + + VolumeElement(element).GetTetsLocal (loctetsloc); + VolumeElement(element).GetNodesLocalNew (pointsloc); + + const Element & le = loctetsloc.Get(j); + + + Point3d pp = + pointsloc.Get(le.PNum(1)) + + sol.X() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(2))) + + sol.Y() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(3))) + + sol.Z() * Vec3d (pointsloc.Get(le.PNum(1)), pointsloc.Get(le.PNum(4))) ; + + lami[0] = pp.X(); + lami[1] = pp.Y(); + lami[2] = pp.Z(); + return true; + } + } + return false; + } + + + int Mesh :: GetElementOfPoint (const Point3d & p, + double lami[3], + bool build_searchtree, + const int index, + const bool allowindex) const + { + if(index != -1) + { + ARRAY<int> dummy(1); + dummy[0] = index; + return GetElementOfPoint(p,lami,&dummy,build_searchtree,allowindex); + } + else + return GetElementOfPoint(p,lami,NULL,build_searchtree,allowindex); + } + + + + + int Mesh :: GetElementOfPoint (const Point3d & p, + double lami[3], + const ARRAY<int> * const indices, + bool build_searchtree, + const bool allowindex) const + { + if (dimension == 2) + { + int i, j; + int ne; + + + if(ps_startelement != 0 && ps_startelement <= GetNSE() && PointContainedIn2DElement(p,lami,ps_startelement)) + return ps_startelement; + + ARRAY<int> locels; + if (0) + { + elementsearchtree->GetIntersecting (p, p, locels); + ne = locels.Size(); + } + else + ne = GetNSE(); + + for (i = 1; i <= ne; i++) + { + int ii; + + if (0) + ii = locels.Get(i); + else + ii = i; + + if(ii == ps_startelement) continue; + + if(indices != NULL && indices->Size() > 0) + { + bool contained = indices->Contains(SurfaceElement(ii).GetIndex()); + if((allowindex && !contained) || (!allowindex && contained)) continue; + } + + if(PointContainedIn2DElement(p,lami,ii)) return ii; + + } + return 0; + } + else + + { + int i, j; + int ne; + + if(ps_startelement != 0 && PointContainedIn3DElement(p,lami,ps_startelement)) + return ps_startelement; + + ARRAY<int> locels; + if (elementsearchtree || build_searchtree) + { + // update if necessary: + const_cast<Mesh&>(*this).BuildElementSearchTree (); + elementsearchtree->GetIntersecting (p, p, locels); + ne = locels.Size(); + } + else + ne = GetNE(); + + for (i = 1; i <= ne; i++) + { + int ii; + + if (elementsearchtree) + ii = locels.Get(i); + else + ii = i; + + if(ii == ps_startelement) continue; + + if(indices != NULL && indices->Size() > 0) + { + bool contained = indices->Contains(VolumeElement(ii).GetIndex()); + if((allowindex && !contained) || (!allowindex && contained)) continue; + } + + + if(PointContainedIn3DElement(p,lami,ii)) + { + ps_startelement = ii; + return ii; + } + } + + // Not found, try uncurved variant: + for (i = 1; i <= ne; i++) + { + int ii; + + if (elementsearchtree) + ii = locels.Get(i); + else + ii = i; + + if(indices != NULL && indices->Size() > 0) + { + bool contained = indices->Contains(VolumeElement(ii).GetIndex()); + if((allowindex && !contained) || (!allowindex && contained)) continue; + } + + + if(PointContainedIn3DElementOld(p,lami,ii)) + { + ps_startelement = ii; + (*testout) << "WARNING: found element of point " << p <<" only for uncurved mesh" << endl; + return ii; + } + } + + + return 0; + } + } + + + + int Mesh :: GetSurfaceElementOfPoint (const Point3d & p, + double lami[3], + bool build_searchtree, + const int index, + const bool allowindex) const + { + if(index != -1) + { + ARRAY<int> dummy(1); + dummy[0] = index; + return GetSurfaceElementOfPoint(p,lami,&dummy,build_searchtree,allowindex); + } + else + return GetSurfaceElementOfPoint(p,lami,NULL,build_searchtree,allowindex); + } + + + + + int Mesh :: GetSurfaceElementOfPoint (const Point3d & p, + double lami[3], + const ARRAY<int> * const indices, + bool build_searchtree, + const bool allowindex) const + { + if (dimension == 2) + { + throw NgException("GetSurfaceElementOfPoint not yet implemented for 2D meshes"); + } + else + { + double vlam[3]; + int velement = GetElementOfPoint(p,vlam,NULL,build_searchtree,allowindex); + + //(*testout) << "p " << p << endl; + //(*testout) << "velement " << velement << endl; + + ARRAY<int> faces; + topology->GetElementFaces(velement,faces); + + //(*testout) << "faces " << faces << endl; + + for(int i=0; i<faces.Size(); i++) + faces[i] = topology->GetFace2SurfaceElement(faces[i]); + + //(*testout) << "surfel " << faces << endl; + + for(int i=0; i<faces.Size(); i++) + { + if(faces[i] == 0) + continue; + + if(indices && indices->Size() != 0) + { + if(indices->Contains(SurfaceElement(faces[i]).GetIndex()) && + PointContainedIn2DElement(p,lami,faces[i],true)) + return faces[i]; + } + else + { + if(PointContainedIn2DElement(p,lami,faces[i],true)) + { + //(*testout) << "found point " << p << " in sel " << faces[i] + // << ", lam " << lami[0] << ", " << lami[1] << ", " << lami[2] << endl; + return faces[i]; + } + } + } + + } + + return 0; + } + + + void Mesh::GetIntersectingVolEls(const Point3d& p1, const Point3d& p2, + ARRAY<int> & locels) const + { + elementsearchtree->GetIntersecting (p1, p2, locels); + } + + void Mesh :: SplitIntoParts() + { + int i, j, dom; + int ne = GetNE(); + int np = GetNP(); + int nse = GetNSE(); + + BitArray surfused(nse); + BitArray pused (np); + + surfused.Clear(); + + dom = 0; + + while (1) + { + int cntd = 1; + + dom++; + + pused.Clear(); + + int found = 0; + for (i = 1; i <= nse; i++) + if (!surfused.Test(i)) + { + SurfaceElement(i).SetIndex (dom); + for (j = 1; j <= 3; j++) + pused.Set (SurfaceElement(i).PNum(j)); + found = 1; + cntd = 1; + surfused.Set(i); + break; + } + + if (!found) + break; + + int change; + do + { + change = 0; + for (i = 1; i <= nse; i++) + { + int is = 0, isnot = 0; + for (j = 1; j <= 3; j++) + if (pused.Test(SurfaceElement(i).PNum(j))) + is = 1; + else + isnot = 1; + + if (is && isnot) + { + change = 1; + for (j = 1; j <= 3; j++) + pused.Set (SurfaceElement(i).PNum(j)); + } + + if (is) + { + if (!surfused.Test(i)) + { + surfused.Set(i); + SurfaceElement(i).SetIndex (dom); + cntd++; + } + } + } + + + for (i = 1; i <= ne; i++) + { + int is = 0, isnot = 0; + for (j = 1; j <= 4; j++) + if (pused.Test(VolumeElement(i).PNum(j))) + is = 1; + else + isnot = 1; + + if (is && isnot) + { + change = 1; + for (j = 1; j <= 4; j++) + pused.Set (VolumeElement(i).PNum(j)); + } + + if (is) + { + VolumeElement(i).SetIndex (dom); + } + } + } + while (change); + + PrintMessage (3, "domain ", dom, " has ", cntd, " surfaceelements"); + } + + /* + facedecoding.SetSize (dom); + for (i = 1; i <= dom; i++) + { + facedecoding.Elem(i).surfnr = 0; + facedecoding.Elem(i).domin = i; + facedecoding.Elem(i).domout = 0; + } + */ + ClearFaceDescriptors(); + for (i = 1; i <= dom; i++) + AddFaceDescriptor (FaceDescriptor (0, i, 0, 0)); + CalcSurfacesOfNode(); + timestamp = NextTimeStamp(); + } + + void Mesh :: SplitSeparatedFaces () + { + PrintMessage (3, "SplitSeparateFaces"); + int fdi; + int np = GetNP(); + + BitArray usedp(np); + ARRAY<SurfaceElementIndex> els_of_face; + + fdi = 1; + while (fdi <= GetNFD()) + { + GetSurfaceElementsOfFace (fdi, els_of_face); + + if (els_of_face.Size() == 0) continue; + + SurfaceElementIndex firstel = els_of_face[0]; + + usedp.Clear(); + for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++) + usedp.Set (SurfaceElement(firstel).PNum(j)); + + bool changed; + do + { + changed = false; + + for (int i = 0; i < els_of_face.Size(); i++) + { + const Element2d & el = SurfaceElement(els_of_face[i]); + + bool has = 0; + bool hasno = 0; + for (int j = 0; j < el.GetNP(); j++) + { + if (usedp.Test(el[j])) + has = true; + else + hasno = true; + } + + if (has && hasno) + changed = true; + + if (has) + for (int j = 0; j < el.GetNP(); j++) + usedp.Set (el[j]); + } + } + while (changed); + + int nface = 0; + for (int i = 0; i < els_of_face.Size(); i++) + { + Element2d & el = SurfaceElement(els_of_face[i]); + + int hasno = 0; + for (int j = 1; j <= el.GetNP(); j++) + if (!usedp.Test(el.PNum(j))) + hasno = 1; + + if (hasno) + { + if (!nface) + { + FaceDescriptor nfd = GetFaceDescriptor(fdi); + nface = AddFaceDescriptor (nfd); + } + + el.SetIndex (nface); + } + } + + // reconnect list + if (nface) + { + facedecoding[nface-1].firstelement = -1; + facedecoding[fdi-1].firstelement = -1; + + for (int i = 0; i < els_of_face.Size(); i++) + { + int ind = SurfaceElement(els_of_face[i]).GetIndex(); + SurfaceElement(els_of_face[i]).next = facedecoding[ind-1].firstelement; + facedecoding[ind-1].firstelement = els_of_face[i]; + } + } + + fdi++; + } + + + /* + fdi = 1; + while (fdi <= GetNFD()) + { + int firstel = 0; + for (int i = 1; i <= GetNSE(); i++) + if (SurfaceElement(i).GetIndex() == fdi) + { + firstel = i; + break; + } + if (!firstel) continue; + + usedp.Clear(); + for (int j = 1; j <= SurfaceElement(firstel).GetNP(); j++) + usedp.Set (SurfaceElement(firstel).PNum(j)); + + int changed; + do + { + changed = 0; + for (int i = 1; i <= GetNSE(); i++) + { + const Element2d & el = SurfaceElement(i); + if (el.GetIndex() != fdi) + continue; + + int has = 0; + int hasno = 0; + for (int j = 1; j <= el.GetNP(); j++) + { + if (usedp.Test(el.PNum(j))) + has = 1; + else + hasno = 1; + } + if (has && hasno) + changed = 1; + + if (has) + for (int j = 1; j <= el.GetNP(); j++) + usedp.Set (el.PNum(j)); + } + } + while (changed); + + int nface = 0; + for (int i = 1; i <= GetNSE(); i++) + { + Element2d & el = SurfaceElement(i); + if (el.GetIndex() != fdi) + continue; + + int hasno = 0; + for (int j = 1; j <= el.GetNP(); j++) + { + if (!usedp.Test(el.PNum(j))) + hasno = 1; + } + + if (hasno) + { + if (!nface) + { + FaceDescriptor nfd = GetFaceDescriptor(fdi); + nface = AddFaceDescriptor (nfd); + } + + el.SetIndex (nface); + } + } + fdi++; + } + */ + } + + + void Mesh :: GetSurfaceElementsOfFace (int facenr, ARRAY<SurfaceElementIndex> & sei) const + { + static int timer = NgProfiler::CreateTimer ("GetSurfaceElementsOfFace"); + NgProfiler::RegionTimer reg (timer); + + /* + sei.SetSize (0); + for (SurfaceElementIndex i = 0; i < GetNSE(); i++) + if ( (*this)[i].GetIndex () == facenr && (*this)[i][0] >= PointIndex::BASE && + !(*this)[i].IsDeleted() ) + sei.Append (i); + + int size1 = sei.Size(); + */ + + sei.SetSize(0); + + SurfaceElementIndex si = facedecoding[facenr-1].firstelement; + while (si != -1) + { + if ( (*this)[si].GetIndex () == facenr && (*this)[si][0] >= PointIndex::BASE && + !(*this)[si].IsDeleted() ) + { + sei.Append (si); + } + + si = (*this)[si].next; + } + + /* + // *testout << "with list = " << endl << sei << endl; + + if (size1 != sei.Size()) + { + cout << "size mismatch" << endl; + exit(1); + } + */ + } + + + + + void Mesh :: CalcMinMaxAngle (double badellimit, double * retvalues) + { + int i, j; + int lpi1, lpi2, lpi3, lpi4; + double phimax = 0, phimin = 10; + double facephimax = 0, facephimin = 10; + int illegaltets = 0, negativetets = 0, badtets = 0; + + for (i = 1; i <= GetNE(); i++) + { + int badel = 0; + + Element & el = VolumeElement(i); + + if (el.GetType() != TET) + { + VolumeElement(i).flags.badel = 0; + continue; + } + + if (el.Volume(Points()) < 0) + { + badel = 1; + negativetets++; + } + + + if (!LegalTet (el)) + { + badel = 1; + illegaltets++; + (*testout) << "illegal tet: " << i << " "; + for (j = 1; j <= el.GetNP(); j++) + (*testout) << el.PNum(j) << " "; + (*testout) << endl; + } + + + // angles between faces + for (lpi1 = 1; lpi1 <= 3; lpi1++) + for (lpi2 = lpi1+1; lpi2 <= 4; lpi2++) + { + lpi3 = 1; + while (lpi3 == lpi1 || lpi3 == lpi2) + lpi3++; + lpi4 = 10 - lpi1 - lpi2 - lpi3; + + const Point3d & p1 = Point (el.PNum(lpi1)); + const Point3d & p2 = Point (el.PNum(lpi2)); + const Point3d & p3 = Point (el.PNum(lpi3)); + const Point3d & p4 = Point (el.PNum(lpi4)); + + Vec3d n(p1, p2); + n /= n.Length(); + Vec3d v1(p1, p3); + Vec3d v2(p1, p4); + + v1 -= (n * v1) * n; + v2 -= (n * v2) * n; + + double cosphi = (v1 * v2) / (v1.Length() * v2.Length()); + double phi = acos (cosphi); + if (phi > phimax) phimax = phi; + if (phi < phimin) phimin = phi; + + if ((180/M_PI) * phi > badellimit) + badel = 1; + } + + + // angles in faces + for (j = 1; j <= 4; j++) + { + Element2d face; + el.GetFace (j, face); + for (lpi1 = 1; lpi1 <= 3; lpi1++) + { + lpi2 = lpi1 % 3 + 1; + lpi3 = lpi2 % 3 + 1; + + const Point3d & p1 = Point (el.PNum(lpi1)); + const Point3d & p2 = Point (el.PNum(lpi2)); + const Point3d & p3 = Point (el.PNum(lpi3)); + + Vec3d v1(p1, p2); + Vec3d v2(p1, p3); + double cosphi = (v1 * v2) / (v1.Length() * v2.Length()); + double phi = acos (cosphi); + if (phi > facephimax) facephimax = phi; + if (phi < facephimin) facephimin = phi; + + if ((180/M_PI) * phi > badellimit) + badel = 1; + + } + } + + + VolumeElement(i).flags.badel = badel; + if (badel) badtets++; + } + + if (!GetNE()) + { + phimin = phimax = facephimin = facephimax = 0; + } + + if (!retvalues) + { + PrintMessage (1, ""); + PrintMessage (1, "between planes: phimin = ", (180/M_PI) * phimin, + " phimax = ", (180/M_PI) *phimax); + PrintMessage (1, "inside planes: phimin = ", (180/M_PI) * facephimin, + " phimax = ", (180/M_PI) * facephimax); + PrintMessage (1, ""); + } + else + { + retvalues[0] = (180/M_PI) * facephimin; + retvalues[1] = (180/M_PI) * facephimax; + retvalues[2] = (180/M_PI) * phimin; + retvalues[3] = (180/M_PI) * phimax; + } + PrintMessage (3, "negative tets: ", negativetets); + PrintMessage (3, "illegal tets: ", illegaltets); + PrintMessage (3, "bad tets: ", badtets); + } + + + int Mesh :: MarkIllegalElements () + { + int cnt = 0; + int i; + + for (i = 1; i <= GetNE(); i++) + { + LegalTet (VolumeElement(i)); + + /* + Element & el = VolumeElement(i); + int leg1 = LegalTet (el); + el.flags.illegal_valid = 0; + int leg2 = LegalTet (el); + + if (leg1 != leg2) + { + cerr << "legal differs!!" << endl; + (*testout) << "legal differs" << endl; + (*testout) << "elnr = " << i << ", el = " << el + << " leg1 = " << leg1 << ", leg2 = " << leg2 << endl; + } + + // el.flags.illegal = !LegalTet (el); + */ + cnt += VolumeElement(i).Illegal(); + } + return cnt; + } + +// #ifdef NONE +// void Mesh :: AddIdentification (int pi1, int pi2, int identnr) +// { +// INDEX_2 pair(pi1, pi2); +// // pair.Sort(); +// identifiedpoints->Set (pair, identnr); +// if (identnr > maxidentnr) +// maxidentnr = identnr; +// timestamp = NextTimeStamp(); +// } + +// int Mesh :: GetIdentification (int pi1, int pi2) const +// { +// INDEX_2 pair(pi1, pi2); +// if (identifiedpoints->Used (pair)) +// return identifiedpoints->Get(pair); +// else +// return 0; +// } + +// int Mesh :: GetIdentificationSym (int pi1, int pi2) const +// { +// INDEX_2 pair(pi1, pi2); +// if (identifiedpoints->Used (pair)) +// return identifiedpoints->Get(pair); + +// pair = INDEX_2 (pi2, pi1); +// if (identifiedpoints->Used (pair)) +// return identifiedpoints->Get(pair); + +// return 0; +// } + + +// void Mesh :: GetIdentificationMap (int identnr, ARRAY<int> & identmap) const +// { +// int i, j; + +// identmap.SetSize (GetNP()); +// for (i = 1; i <= identmap.Size(); i++) +// identmap.Elem(i) = 0; + +// for (i = 1; i <= identifiedpoints->GetNBags(); i++) +// for (j = 1; j <= identifiedpoints->GetBagSize(i); j++) +// { +// INDEX_2 i2; +// int nr; +// identifiedpoints->GetData (i, j, i2, nr); + +// if (nr == identnr) +// { +// identmap.Elem(i2.I1()) = i2.I2(); +// } +// } +// } + + +// void Mesh :: GetIdentificationPairs (int identnr, ARRAY<INDEX_2> & identpairs) const +// { +// int i, j; + +// identpairs.SetSize(0); + +// for (i = 1; i <= identifiedpoints->GetNBags(); i++) +// for (j = 1; j <= identifiedpoints->GetBagSize(i); j++) +// { +// INDEX_2 i2; +// int nr; +// identifiedpoints->GetData (i, j, i2, nr); + +// if (identnr == 0 || nr == identnr) +// identpairs.Append (i2); +// } +// } +// #endif + + + + void Mesh :: InitPointCurve(double red, double green, double blue) const + { + pointcurves_startpoint.Append(pointcurves.Size()); + pointcurves_red.Append(red); + pointcurves_green.Append(green); + pointcurves_blue.Append(blue); + } + void Mesh :: AddPointCurvePoint(const Point3d & pt) const + { + pointcurves.Append(pt); + } + int Mesh :: GetNumPointCurves(void) const + { + return pointcurves_startpoint.Size(); + } + int Mesh :: GetNumPointsOfPointCurve(int curve) const + { + if(curve == pointcurves_startpoint.Size()-1) + return (pointcurves.Size() - pointcurves_startpoint.Last()); + else + return (pointcurves_startpoint[curve+1]-pointcurves_startpoint[curve]); + } + + Point3d & Mesh :: GetPointCurvePoint(int curve, int n) const + { + return pointcurves[pointcurves_startpoint[curve]+n]; + } + + void Mesh :: GetPointCurveColor(int curve, double & red, double & green, double & blue) const + { + red = pointcurves_red[curve]; + green = pointcurves_green[curve]; + blue = pointcurves_blue[curve]; + } + + + void Mesh :: ComputeNVertices () + { + int i, j, nv; + int ne = GetNE(); + int nse = GetNSE(); + + numvertices = 0; + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + nv = el.GetNV(); + for (j = 0; j < nv; j++) + if (el[j] > numvertices) + numvertices = el[j]; + } + for (i = 1; i <= nse; i++) + { + const Element2d & el = SurfaceElement(i); + nv = el.GetNV(); + for (j = 1; j <= nv; j++) + if (el.PNum(j) > numvertices) + numvertices = el.PNum(j); + } + + numvertices += 1- PointIndex::BASE; + } + + int Mesh :: GetNV () const + { + if (numvertices < 0) + return GetNP(); + else + return numvertices; + } + + void Mesh :: SetNP (int np) + { + points.SetSize(np); + // ptyps.SetSize(np); + + int mlold = mlbetweennodes.Size(); + mlbetweennodes.SetSize(np); + if (np > mlold) + for (int i = mlold+PointIndex::BASE; + i < np+PointIndex::BASE; i++) + { + mlbetweennodes[i].I1() = PointIndex::BASE-1; + mlbetweennodes[i].I2() = PointIndex::BASE-1; + } + + GetIdentifications().SetMaxPointNr (np + PointIndex::BASE-1); + } + + + /* + void Mesh :: BuildConnectedNodes () + { + if (PureTetMesh()) + { + connectedtonode.SetSize(0); + return; + } + + + int i, j, k; + int np = GetNP(); + int ne = GetNE(); + TABLE<int> conto(np); + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + + if (el.GetType() == PRISM) + { + for (j = 1; j <= 6; j++) + { + int n1 = el.PNum (j); + int n2 = el.PNum ((j+2)%6+1); + // if (n1 != n2) + { + int found = 0; + for (k = 1; k <= conto.EntrySize(n1); k++) + if (conto.Get(n1, k) == n2) + { + found = 1; + break; + } + if (!found) + conto.Add (n1, n2); + } + } + } + else if (el.GetType() == PYRAMID) + { + for (j = 1; j <= 4; j++) + { + int n1, n2; + switch (j) + { + case 1: n1 = 1; n2 = 4; break; + case 2: n1 = 4; n2 = 1; break; + case 3: n1 = 2; n2 = 3; break; + case 4: n1 = 3; n2 = 2; break; + } + + int found = 0; + for (k = 1; k <= conto.EntrySize(n1); k++) + if (conto.Get(n1, k) == n2) + { + found = 1; + break; + } + if (!found) + conto.Add (n1, n2); + } + } + } + + connectedtonode.SetSize(np); + for (i = 1; i <= np; i++) + connectedtonode.Elem(i) = 0; + + for (i = 1; i <= np; i++) + if (connectedtonode.Elem(i) == 0) + { + connectedtonode.Elem(i) = i; + ConnectToNodeRec (i, i, conto); + } + + + + } + + void Mesh :: ConnectToNodeRec (int node, int tonode, + const TABLE<int> & conto) + { + int i, n2; + // (*testout) << "connect " << node << " to " << tonode << endl; + for (i = 1; i <= conto.EntrySize(node); i++) + { + n2 = conto.Get(node, i); + if (!connectedtonode.Get(n2)) + { + connectedtonode.Elem(n2) = tonode; + ConnectToNodeRec (n2, tonode, conto); + } + } + } + */ + + + bool Mesh :: PureTrigMesh (int faceindex) const + { + if (!faceindex) + return !mparam.quad; + + int i; + for (i = 1; i <= GetNSE(); i++) + if (SurfaceElement(i).GetIndex() == faceindex && + SurfaceElement(i).GetNP() != 3) + return 0; + return 1; + } + + bool Mesh :: PureTetMesh () const + { + for (ElementIndex ei = 0; ei < GetNE(); ei++) + if (VolumeElement(ei).GetNP() != 4) + return 0; + return 1; + } + + void Mesh :: UpdateTopology() + { + topology->Update(); + clusters->Update(); + } + + + void Mesh :: SetMaterial (int domnr, const char * mat) + { + if (domnr > materials.Size()) + { + int olds = materials.Size(); + materials.SetSize (domnr); + for (int i = olds; i < domnr; i++) + materials[i] = 0; + } + materials.Elem(domnr) = new char[strlen(mat)+1]; + strcpy (materials.Elem(domnr), mat); + } + + const char * Mesh :: GetMaterial (int domnr) const + { + if (domnr <= materials.Size()) + return materials.Get(domnr); + return 0; + } + + void Mesh ::SetNBCNames ( int nbcn ) + { + if ( bcnames.Size() ) + for ( int i = 0; i < bcnames.Size(); i++) + if ( bcnames[i] ) delete bcnames[i]; + bcnames.SetSize(nbcn); + bcnames = 0; + } + + void Mesh ::SetBCName ( int bcnr, const string & abcname ) + { + if ( bcnames[bcnr] ) delete bcnames[bcnr]; + if ( abcname != "default" ) + bcnames[bcnr] = new string ( abcname ); + else + bcnames[bcnr] = 0; + } + + string Mesh ::GetBCName ( int bcnr ) const + { + if ( !bcnames.Size() ) + return "default"; + if ( bcnames[bcnr] ) + return *bcnames[bcnr]; + else + return "default"; + } + + void Mesh :: SetUserData(const char * id, ARRAY<int> & data) + { + if(userdata_int.Used(id)) + delete userdata_int.Get(id); + + ARRAY<int> * newdata = new ARRAY<int>(data); + + userdata_int.Set(id,newdata); + } + bool Mesh :: GetUserData(const char * id, ARRAY<int> & data, int shift) const + { + if(userdata_int.Used(id)) + { + if(data.Size() < (*userdata_int.Get(id)).Size()+shift) + data.SetSize((*userdata_int.Get(id)).Size()+shift); + for(int i=0; i<(*userdata_int.Get(id)).Size(); i++) + data[i+shift] = (*userdata_int.Get(id))[i]; + return true; + } + else + { + data.SetSize(0); + return false; + } + } + void Mesh :: SetUserData(const char * id, ARRAY<double> & data) + { + if(userdata_double.Used(id)) + delete userdata_double.Get(id); + + ARRAY<double> * newdata = new ARRAY<double>(data); + + userdata_double.Set(id,newdata); + } + bool Mesh :: GetUserData(const char * id, ARRAY<double> & data, int shift) const + { + if(userdata_double.Used(id)) + { + if(data.Size() < (*userdata_double.Get(id)).Size()+shift) + data.SetSize((*userdata_double.Get(id)).Size()+shift); + for(int i=0; i<(*userdata_double.Get(id)).Size(); i++) + data[i+shift] = (*userdata_double.Get(id))[i]; + return true; + } + else + { + data.SetSize(0); + return false; + } + } + + + + void Mesh :: PrintMemInfo (ostream & ost) const + { + ost << "Mesh Mem:" << endl; + + ost << GetNP() << " Points, of size " + << sizeof (Point3d) << " + " << sizeof(POINTTYPE) << " = " + << GetNP() * (sizeof (Point3d) + sizeof(POINTTYPE)) << endl; + + ost << GetNSE() << " Surface elements, of size " + << sizeof (Element2d) << " = " + << GetNSE() * sizeof(Element2d) << endl; + + ost << GetNE() << " Volume elements, of size " + << sizeof (Element) << " = " + << GetNE() * sizeof(Element) << endl; + + ost << "surfs on node:"; + surfacesonnode.PrintMemInfo (cout); + + ost << "boundaryedges: "; + if (boundaryedges) + boundaryedges->PrintMemInfo (cout); + + ost << "surfelementht: "; + if (surfelementht) + surfelementht->PrintMemInfo (cout); + } +} diff --git a/contrib/Netgen/libsrc/meshing/meshclass.hpp b/contrib/Netgen/libsrc/meshing/meshclass.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4dab869d3427a49f8470ef101a85c1583f39ae89 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshclass.hpp @@ -0,0 +1,777 @@ +#ifndef MESHCLASS +#define MESHCLASS + +/**************************************************************************/ +/* File: meshclass.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 20. Nov. 99 */ +/**************************************************************************/ + +/* + The mesh class +*/ + + + +enum resthtype { RESTRICTH_FACE, RESTRICTH_EDGE, + RESTRICTH_SURFACEELEMENT, RESTRICTH_POINT, RESTRICTH_SEGMENT }; + +class HPRefElement; + + +/// 2d/3d mesh +class Mesh +{ +public: + typedef MoveableArray<MeshPoint,PointIndex::BASE> T_POINTS; + typedef MoveableArray<Element> T_VOLELEMENTS; + typedef MoveableArray<Element2d> T_SURFELEMENTS; + + // typedef ARRAY<MeshPoint,PointIndex::BASE> T_POINTS; + // typedef ARRAY<Element> T_VOLELEMENTS; + // typedef ARRAY<Element2d> T_SURFELEMENTS; + + +private: + /// point coordinates + T_POINTS points; + + /// type of element, set in calcsurfacesofnode + // ARRAY<ELEMENTTYPE> eltyps; + + /// line-segments at edges + ARRAY<Segment> segments; + /// surface elements, 2d-inner elements + T_SURFELEMENTS surfelements; + /// volume elements + T_VOLELEMENTS volelements; + /// points will be fixed forever + ARRAY<PointIndex> lockedpoints; + + + /// surface indices at boundary nodes + TABLE<int,PointIndex::BASE> surfacesonnode; + /// boundary edges (1..normal bedge, 2..segment) + INDEX_2_CLOSED_HASHTABLE<int> * boundaryedges; + /// + INDEX_2_CLOSED_HASHTABLE<int> * segmentht; + /// + INDEX_3_CLOSED_HASHTABLE<int> * surfelementht; + + /// faces of rest-solid + ARRAY<Element2d> openelements; + /// open segmenets for surface meshing + ARRAY<Segment> opensegments; + + + + /** + Representation of local mesh-size h + */ + LocalH * lochfunc; + /// + double hglob; + /// + double hmin; + /// + ARRAY<double> maxhdomain; + + /** + the face-index of the surface element maps into + this table. + */ + ARRAY<FaceDescriptor> facedecoding; + + /// sub-domain materials + ARRAY<char*> materials; + + ARRAY<string*, 0> bcnames; + + /// Periodic surface, close surface, etc. identifications + Identifications * ident; + + + /// number of vertices (if < 0, use np) + int numvertices; + + /// geometric search tree for interval intersection search + Box3dTree * elementsearchtree; + /// time stamp for tree + int elementsearchtreets; + + /// element -> face, element -> edge etc ... + class MeshTopology * topology; + /// methods for high order elements + class CurvedElements * curvedelems; + + /// nodes identified by close points + class AnisotropicClusters * clusters; + + /// space dimension (2 or 3) + int dimension; + + /// changed by every minor modification (addpoint, ...) + int timestamp; + /// changed after finishing global algorithm (improve, ...) + int majortimestamp; + + /// mesh access semaphors. + NgMutex mutex; + /// mesh access semaphors. + NgMutex majormutex; + + SYMBOLTABLE< ARRAY<int>* > userdata_int; + SYMBOLTABLE< ARRAY<double>* > userdata_double; + + + mutable ARRAY< Point3d > pointcurves; + mutable ARRAY<int> pointcurves_startpoint; + mutable ARRAY<double> pointcurves_red,pointcurves_green,pointcurves_blue; + + + /// start element for point search (GetElementOfPoint) + mutable int ps_startelement; + + +#ifdef PARALLEL + /// connection to parallel meshes + class ParallelMeshTopology * paralleltop; + +#endif + + +private: + void BuildBoundaryEdges(void); + +public: + bool PointContainedIn2DElement(const Point3d & p, + double lami[3], + const int element, + bool consider3D = false) const; + bool PointContainedIn3DElement(const Point3d & p, + double lami[3], + const int element) const; + bool PointContainedIn3DElementOld(const Point3d & p, + double lami[3], + const int element) const; + +public: + + // store coarse mesh before hp-refinement + ARRAY<HPRefElement> * hpelements; + Mesh * coarsemesh; + + + /// number of refinement levels + int mglevels; + /// refinement hierarchy + ARRAY<INDEX_2,PointIndex::BASE> mlbetweennodes; + /// parent element of volume element + ARRAY<int> mlparentelement; + /// parent element of surface element + ARRAY<int> mlparentsurfaceelement; + + + + /// + Mesh(); + /// + ~Mesh(); + + Mesh & operator= (const Mesh & mesh2); + + /// + void DeleteMesh(); + + /// + void ClearSurfaceElements() + { + surfelements.SetSize(0); + timestamp = NextTimeStamp(); + } + + /// + void ClearVolumeElements() + { + volelements.SetSize(0); + // eltyps.SetSize(0); + timestamp = NextTimeStamp(); + } + + /// + void ClearSegments() + { + segments.SetSize(0); + timestamp = NextTimeStamp(); + } + + /// + bool TestOk () const; + + void SetAllocSize(int nnodes, int nsegs, int nsel, int nel); + + + PointIndex AddPoint (const Point3d & p, int layer = 1); + PointIndex AddPoint (const Point3d & p, int layer, POINTTYPE type); +#ifdef PARALLEL + PointIndex AddPoint (const Point3d & p, bool aisghost, int layer = 1); + PointIndex AddPoint (const Point3d & p, bool aisghost, int layer, POINTTYPE type); +#endif + int GetNP () const { return points.Size(); } + + MeshPoint & Point(int i) { return points.Elem(i); } + MeshPoint & Point(PointIndex pi) { return points[pi]; } + const MeshPoint & Point(int i) const { return points.Get(i); } + const MeshPoint & Point(PointIndex pi) const { return points[pi]; } + + const MeshPoint & operator[] (PointIndex pi) const { return points[pi]; } + MeshPoint & operator[] (PointIndex pi) { return points[pi]; } + + const T_POINTS & Points() const { return points; } + T_POINTS & Points() { return points; } + + + SegmentIndex AddSegment (const Segment & s); + void DeleteSegment (int segnr) + { + segments.Elem(segnr).p1 = PointIndex::BASE-1; + segments.Elem(segnr).p2 = PointIndex::BASE-1; + } + void FullDeleteSegment (int segnr) + { + segments.Delete(segnr-PointIndex::BASE); + } + + int GetNSeg () const { return segments.Size(); } + Segment & LineSegment(int i) { return segments.Elem(i); } + const Segment & LineSegment(int i) const { return segments.Get(i); } + + Segment & LineSegment(SegmentIndex si) { return segments[si]; } + const Segment & LineSegment(SegmentIndex si) const { return segments[si]; } + const Segment & operator[] (SegmentIndex si) const { return segments[si]; } + Segment & operator[] (SegmentIndex si) { return segments[si]; } + + + + + SurfaceElementIndex AddSurfaceElement (const Element2d & el); + void DeleteSurfaceElement (int eli) + { + surfelements.Elem(eli).Delete(); + surfelements.Elem(eli).PNum(1) = -1; + surfelements.Elem(eli).PNum(2) = -1; + surfelements.Elem(eli).PNum(3) = -1; + timestamp = NextTimeStamp(); + } + + void DeleteSurfaceElement (SurfaceElementIndex eli) + { + DeleteSurfaceElement (int(eli)+1); + } + + int GetNSE () const { return surfelements.Size(); } + Element2d & SurfaceElement(int i) { return surfelements.Elem(i); } + const Element2d & SurfaceElement(int i) const { return surfelements.Get(i); } + + Element2d & SurfaceElement(SurfaceElementIndex i) + { return surfelements[i]; } + const Element2d & SurfaceElement(SurfaceElementIndex i) const + { return surfelements[i]; } + + const Element2d & operator[] (SurfaceElementIndex ei) const + { return surfelements[ei]; } + Element2d & operator[] (SurfaceElementIndex ei) + { return surfelements[ei]; } + + + void GetSurfaceElementsOfFace (int facenr, ARRAY<SurfaceElementIndex> & sei) const; + + ElementIndex AddVolumeElement (const Element & el); + + int GetNE () const { return volelements.Size(); } + + Element & VolumeElement(int i) { return volelements.Elem(i); } + const Element & VolumeElement(int i) const { return volelements.Get(i); } + Element & VolumeElement(ElementIndex i) { return volelements[i]; } + const Element & VolumeElement(ElementIndex i) const { return volelements[i]; } + + const Element & operator[] (ElementIndex ei) const + { return volelements[ei]; } + Element & operator[] (ElementIndex ei) + { return volelements[ei]; } + + + + + // ELEMENTTYPE ElementType (int i) const { return eltyps.Get(i); } + + + // ELEMENTTYPE ElementType (int i) const + // { return (volelements.Get(i).fixed) ? FIXEDELEMENT : FREEELEMENT; } + + ELEMENTTYPE ElementType (ElementIndex i) const + { return (volelements[i].flags.fixed) ? FIXEDELEMENT : FREEELEMENT; } + + /* + ELEMENTTYPE ElementType (int i) const { return eltyps.Get(i); } + ELEMENTTYPE ElementType (ElementIndex i) const { return eltyps[i]; } + */ + + const T_VOLELEMENTS & VolumeElements() const { return volelements; } + T_VOLELEMENTS & VolumeElements() { return volelements; } + + + /// + double ElementError (int eli) const; + + /// + void AddLockedPoint (PointIndex pi); + /// + void ClearLockedPoints (); + + const ARRAY<PointIndex> & LockedPoints() const + { return lockedpoints; } + + /// Returns number of domains + int GetNDomains() const; + + + /// + int GetDimension() const + { return dimension; } + void SetDimension(int dim) + { dimension = dim; } + + /// sets internal tables + void CalcSurfacesOfNode (); + + /// additional (temporarily) fix points + void FixPoints (const BitArray & fixpoints); + + /** + finds elements without neighbour and + boundary elements without inner element. + Results are stored in openelements. + if dom == 0, all sub-domains, else subdomain dom */ + void FindOpenElements (int dom = 0); + + + /** + finds segments without surface element, + and surface elements without neighbours. + store in opensegmentsy + */ + void FindOpenSegments (int surfnr = 0); + /** + remove one layer of surface elements + */ + void RemoveOneLayerSurfaceElements (); + + + int GetNOpenSegments () { return opensegments.Size(); } + const Segment & GetOpenSegment (int nr) { return opensegments.Get(nr); } + + /** + Checks overlap of boundary + return == 1, iff overlap + */ + int CheckOverlappingBoundary (); + /** + Checks consistent boundary + return == 0, everything ok + */ + int CheckConsistentBoundary () const; + + /* + checks element orientation + */ + int CheckVolumeMesh () const; + + + /** + finds average h of surface surfnr if surfnr > 0, + else of all surfaces. + */ + double AverageH (int surfnr = 0) const; + /// Calculates localh + void CalcLocalH (); + /// + void SetLocalH (const Point3d & pmin, const Point3d & pmax, double grading); + /// + void RestrictLocalH (const Point3d & p, double hloc); + /// + void RestrictLocalHLine (const Point3d & p1, const Point3d & p2, + double hloc); + /// number of elements per radius + void CalcLocalHFromSurfaceCurvature(double elperr); + /// + void CalcLocalHFromPointDistances(void); + /// + void RestrictLocalH (resthtype rht, int nr, double loch); + /// + void LoadLocalMeshSize (const char * meshsizefilename); + /// + void SetGlobalH (double h); + /// + void SetMinimalH (double h); + /// + double MaxHDomain (int dom) const; + /// + void SetMaxHDomain (const ARRAY<double> & mhd); + /// + double GetH (const Point3d & p) const; + /// + double GetMinH (const Point3d & pmin, const Point3d & pmax); + /// + LocalH & LocalHFunction () { return * lochfunc; } + /// + bool LocalHFunctionGenerated(void) const { return (lochfunc != NULL); } + + /// Find bounding box + void GetBox (Point3d & pmin, Point3d & pmax, int dom = -1) const; + + /// Find bounding box of points of typ ptyp or less + void GetBox (Point3d & pmin, Point3d & pmax, POINTTYPE ptyp ) const; + + /// + int GetNOpenElements() const + { return openelements.Size(); } + /// + const Element2d & OpenElement(int i) const + { return openelements.Get(i); } + + + /// are also quads open elements + bool HasOpenQuads () const; + + /// split into connected pieces + void SplitIntoParts (); + + /// + void SplitSeparatedFaces (); + + /// Refines mesh and projects points to true surface + // void Refine (int levels, const CSGeometry * geom); + + + bool BoundaryEdge (PointIndex pi1, PointIndex pi2) const + { + if(!boundaryedges) + const_cast<Mesh *>(this)->BuildBoundaryEdges(); + + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + return boundaryedges->Used (i2); + } + + bool IsSegment (PointIndex pi1, PointIndex pi2) const + { + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + return segmentht->Used (i2); + } + + SegmentIndex SegmentNr (PointIndex pi1, PointIndex pi2) const + { + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + return segmentht->Get (i2); + } + + + /** + Remove unused points. etc. + */ + void Compress (); + + /// + void Save (ostream & outfile) const; + /// + void Load (istream & infile); + /// + void Merge (istream & infile, const int surfindex_offset = 0); + /// + void Save (const string & filename) const; + /// + void Load (const string & filename); + /// + void Merge (const string & filename, const int surfindex_offset = 0); + + + /// + void ImproveMesh (OPTIMIZEGOAL goal = OPT_QUALITY); + + /// + void ImproveMeshJacobian (OPTIMIZEGOAL goal = OPT_QUALITY, const BitArray * usepoint = NULL); + /// + void ImproveMeshJacobianOnSurface (const BitArray & usepoint, + const ARRAY< Vec<3>* > & nv, + OPTIMIZEGOAL goal = OPT_QUALITY, + const ARRAY< ARRAY<int,PointIndex::BASE>* > * idmaps = NULL); + /* +#ifdef SOLIDGEOM + /// old + void ImproveMesh (const CSGeometry & surfaces, + OPTIMIZEGOAL goal = OPT_QUALITY); +#endif + */ + + /** + free nodes in environment of openelements + for optimiztion + */ + void FreeOpenElementsEnvironment (int layers); + + /// + bool LegalTet (Element & el) const + { + if (el.IllegalValid()) + return !el.Illegal(); + return LegalTet2 (el); + } + /// + bool LegalTet2 (Element & el) const; + + + /// + bool LegalTrig (const Element2d & el) const; + /** + if values non-null, return values in 4-double array: + triangle angles min/max, tetangles min/max + if null, output results on cout + */ + void CalcMinMaxAngle (double badellimit, double * retvalues = NULL); + + /* + Marks elements which are dangerous to refine + return: number of illegal elements + */ + int MarkIllegalElements (); + + /// orient surface mesh, for one sub-domain only + void SurfaceMeshOrientation (); + + /// convert mixed element mesh to tet-mesh + void Split2Tets(); + + + /// build box-search tree + void BuildElementSearchTree (); + + void SetPointSearchStartElement(const int el) const {ps_startelement = el;} + + /// gives element of point, barycentric coordinates + int GetElementOfPoint (const Point3d & p, + double * lami, + bool build_searchtree = 0, + const int index = -1, + const bool allowindex = true) const; + int GetElementOfPoint (const Point3d & p, + double * lami, + const ARRAY<int> * const indices, + bool build_searchtree = 0, + const bool allowindex = true) const; + int GetSurfaceElementOfPoint (const Point3d & p, + double * lami, + bool build_searchtree = 0, + const int index = -1, + const bool allowindex = true) const; + int GetSurfaceElementOfPoint (const Point3d & p, + double * lami, + const ARRAY<int> * const indices, + bool build_searchtree = 0, + const bool allowindex = true) const; + + /// give list of vol elements which are int the box(p1,p2) + void GetIntersectingVolEls(const Point3d& p1, const Point3d& p2, + ARRAY<int> & locels) const; + + /// + int AddFaceDescriptor(const FaceDescriptor& fd) + { return facedecoding.Append(fd); } + + + /// + void SetMaterial (int domnr, const char * mat); + /// + const char * GetMaterial (int domnr) const; + + void SetNBCNames ( int nbcn ); + + void SetBCName ( int bcnr, const string & abcname ); + + string GetBCName ( int bcnr ) const; + + string * GetBCNamePtr ( int bcnr ) + { return bcnames[bcnr]; } + + /// + void ClearFaceDescriptors() + { facedecoding.SetSize(0); } + + /// + int GetNFD () const + { return facedecoding.Size(); } + + const FaceDescriptor & GetFaceDescriptor (int i) const + { return facedecoding.Get(i); } + + /// + FaceDescriptor & GetFaceDescriptor (int i) + { return facedecoding.Elem(i); } + +// #ifdef NONE +// /* +// Identify points pi1 and pi2, due to +// identification nr identnr +// */ +// void AddIdentification (int pi1, int pi2, int identnr); + +// int GetIdentification (int pi1, int pi2) const; +// int GetIdentificationSym (int pi1, int pi2) const; +// /// +// INDEX_2_HASHTABLE<int> & GetIdentifiedPoints () +// { +// return *identifiedpoints; +// } + +// /// +// void GetIdentificationMap (int identnr, ARRAY<int> & identmap) const; +// /// +// void GetIdentificationPairs (int identnr, ARRAY<INDEX_2> & identpairs) const; +// /// +// int GetMaxIdentificationNr () const +// { +// return maxidentnr; +// } +// #endif + + /// return periodic, close surface etc. identifications + Identifications & GetIdentifications () { return *ident; } + /// return periodic, close surface etc. identifications + const Identifications & GetIdentifications () const { return *ident; } + + + void InitPointCurve(double red = 1, double green = 0, double blue = 0) const; + void AddPointCurvePoint(const Point3d & pt) const; + int GetNumPointCurves(void) const; + int GetNumPointsOfPointCurve(int curve) const; + Point3d & GetPointCurvePoint(int curve, int n) const; + void GetPointCurveColor(int curve, double & red, double & green, double & blue) const; + + + + + /// find number of vertices + void ComputeNVertices (); + /// number of vertices (no edge-midpoints) + int GetNV () const; + /// remove edge points + void SetNP (int np); + + + + + /* + /// build connected nodes along prism stack + void BuildConnectedNodes (); + void ConnectToNodeRec (int node, int tonode, + const TABLE<int> & conto); + */ + + bool PureTrigMesh (int faceindex = 0) const; + bool PureTetMesh () const; + + + const class MeshTopology & GetTopology () const + { return *topology; } + + void UpdateTopology(); + + class CurvedElements & GetCurvedElements () const + { return *curvedelems; } + + const class AnisotropicClusters & GetClusters () const + { return *clusters; } + + int GetTimeStamp() const { return timestamp; } + void SetNextTimeStamp() + { timestamp = NextTimeStamp(); } + + int GetMajorTimeStamp() const { return majortimestamp; } + void SetNextMajorTimeStamp() + { majortimestamp = timestamp = NextTimeStamp(); } + + + /// return mutex + NgMutex & Mutex () { return mutex; } + NgMutex & MajorMutex () { return majormutex; } + + + /// + void SetUserData(const char * id, ARRAY<int> & data); + /// + bool GetUserData(const char * id, ARRAY<int> & data, int shift = 0) const; + /// + void SetUserData(const char * id, ARRAY<double> & data); + /// + bool GetUserData(const char * id, ARRAY<double> & data, int shift = 0) const; + + /// + friend void OptimizeRestart (Mesh & mesh3d); + /// + void PrintMemInfo (ostream & ost) const; + /// + friend class Meshing3; + + + enum GEOM_TYPE { NO_GEOM = 0, GEOM_2D = 1, GEOM_CSG = 10, GEOM_STL = 11, GEOM_OCC = 12, GEOM_ACIS = 13 }; + GEOM_TYPE geomtype; + + + +#ifdef PARALLEL + /// returns parallel topology + class ParallelMeshTopology & GetParallelTopology () const + { return *paralleltop; } + + + /// distributes the master-mesh to local meshes + void Distribute (); + + /// loads a mesh sent from master processor + void ReceiveParallelMesh (); + + /// find connection to parallel meshes +// void FindExchangePoints () ; + +// void FindExchangeEdges (); +// void FindExchangeFaces (); + + /// use metis to decompose master mesh + void ParallelMetis (); // ARRAY<int> & neloc ); + void PartHybridMesh (); // ARRAY<int> & neloc ); + void PartDualHybridMesh (); // ARRAY<int> & neloc ); + void PartDualHybridMesh2D (); // ( ARRAY<int> & neloc ); + + /// send mesh to parallel machine, keep global mesh at master + void SendMesh ( ) const; // Mesh * mastermesh, ARRAY<int> & neloc) const; + + void UpdateOverlap (); + +#endif + + +}; + +inline ostream& operator<<(ostream& ost, const Mesh& mesh) +{ + ost << "mesh: " << endl; + mesh.Save(ost); + return ost; +} + + +#endif + + diff --git a/contrib/Netgen/libsrc/meshing/meshfunc.cpp b/contrib/Netgen/libsrc/meshing/meshfunc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06fb451dd4c999e1447e2ee1fcd02a0b59aed086 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshfunc.cpp @@ -0,0 +1,725 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + extern const char * tetrules[]; + // extern const char * tetrules2[]; + extern const char * prismrules2[]; + extern const char * pyramidrules[]; + extern const char * pyramidrules2[]; + + + extern double teterrpow; + MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d) + { + int i, oldne; + PointIndex pi; + + int meshed; + int cntsteps; + + + ARRAY<INDEX_2> connectednodes; + + mesh3d.Compress(); + + // mesh3d.PrintMemInfo (cout); + + if (mp.checkoverlappingboundary) + if (mesh3d.CheckOverlappingBoundary()) + throw NgException ("Stop meshing since boundary mesh is overlapping"); + + int nonconsist = 0; + for (int k = 1; k <= mesh3d.GetNDomains(); k++) + { + PrintMessage (3, "Check subdomain ", k, " / ", mesh3d.GetNDomains()); + + mesh3d.FindOpenElements(k); + + /* + bool res = mesh3d.CheckOverlappingBoundary(); + if (res) + { + PrintError ("Surface is overlapping !!"); + nonconsist = 1; + } + */ + + bool res = (mesh3d.CheckConsistentBoundary() != 0); + if (res) + { + PrintError ("Surface mesh not consistent"); + nonconsist = 1; + } + } + + if (nonconsist) + { + PrintError ("Stop meshing since surface mesh not consistent"); + throw NgException ("Stop meshing since surface mesh not consistent"); + } + + double globmaxh = mp.maxh; + + for (int k = 1; k <= mesh3d.GetNDomains(); k++) + { + if (multithread.terminate) + break; + + PrintMessage (2, ""); + PrintMessage (1, "Meshing subdomain ", k, " of ", mesh3d.GetNDomains()); + (*testout) << "Meshing subdomain " << k << endl; + + mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k)); + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(k); + + if (!mesh3d.GetNOpenElements()) + continue; + + + + Box<3> domain_bbox( Box<3>::EMPTY_BOX ); + /* + Point<3> (1e10, 1e10, 1e10), + Point<3> (-1e10, -1e10, -1e10)); + */ + + for (SurfaceElementIndex sei = 0; sei < mesh3d.GetNSE(); sei++) + { + const Element2d & el = mesh3d[sei]; + if (el.IsDeleted() ) continue; + + if (mesh3d.GetFaceDescriptor(el.GetIndex()).DomainIn() == k || + mesh3d.GetFaceDescriptor(el.GetIndex()).DomainOut() == k) + + for (int j = 0; j < el.GetNP(); j++) + domain_bbox.Add (mesh3d[el[j]]); + } + domain_bbox.Increase (0.01 * domain_bbox.Diam()); + + + for (int qstep = 1; qstep <= 3; qstep++) + { + if (mesh3d.HasOpenQuads()) + { + string rulefile = ngdir; + + const char ** rulep = NULL; + switch (qstep) + { + case 1: + rulefile += "/rules/prisms2.rls"; + rulep = prismrules2; + break; + case 2: // connect pyramid to triangle + rulefile += "/rules/pyramids2.rls"; + rulep = pyramidrules2; + break; + case 3: // connect to vis-a-vis point + rulefile += "/rules/pyramids.rls"; + rulep = pyramidrules; + break; + } + + // Meshing3 meshing(rulefile); + Meshing3 meshing(rulep); + + MeshingParameters mpquad = mp; + + mpquad.giveuptol = 15; + mpquad.baseelnp = 4; + mpquad.starshapeclass = 1000; + mpquad.check_impossible = qstep == 1; // for prisms only (air domain in trafo) + + + for (pi = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; pi++) + meshing.AddPoint (mesh3d[pi], pi); + + mesh3d.GetIdentifications().GetPairs (0, connectednodes); + for (i = 1; i <= connectednodes.Size(); i++) + meshing.AddConnectedPair (connectednodes.Get(i)); + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + { + Element2d hel = mesh3d.OpenElement(i); + meshing.AddBoundaryElement (hel); + } + + oldne = mesh3d.GetNE(); + + meshing.GenerateMesh (mesh3d, mpquad); + + for (i = oldne + 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (k); + + (*testout) + << "mesh has " << mesh3d.GetNE() << " prism/pyramid�elements" << endl; + + mesh3d.FindOpenElements(k); + } + } + + + if (mesh3d.HasOpenQuads()) + { + PrintSysError ("mesh has still open quads"); + throw NgException ("Stop meshing since too many attempts"); + // return MESHING3_GIVEUP; + } + + + if (mp.delaunay && mesh3d.GetNOpenElements()) + { + Meshing3 meshing((const char**)NULL); + + mesh3d.FindOpenElements(k); + + + for (pi = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; pi++) + meshing.AddPoint (mesh3d[pi], pi); + + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + meshing.AddBoundaryElement (mesh3d.OpenElement(i)); + + oldne = mesh3d.GetNE(); + + meshing.Delaunay (mesh3d, k, mp); + + for (i = oldne + 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (k); + + PrintMessage (3, mesh3d.GetNP(), " points, ", + mesh3d.GetNE(), " elements"); + } + + + cntsteps = 0; + if (mesh3d.GetNOpenElements()) + do + { + if (multithread.terminate) + break; + + mesh3d.FindOpenElements(k); + PrintMessage (5, mesh3d.GetNOpenElements(), " open faces"); + cntsteps++; + + if (cntsteps > mp.maxoutersteps) + throw NgException ("Stop meshing since too many attempts"); + + string rulefile = ngdir + "/tetra.rls"; + PrintMessage (1, "start tetmeshing"); + + // Meshing3 meshing(rulefile); + Meshing3 meshing(tetrules); + + ARRAY<int, PointIndex::BASE> glob2loc(mesh3d.GetNP()); + glob2loc = -1; + + for (pi = PointIndex::BASE; + pi < mesh3d.GetNP()+PointIndex::BASE; pi++) + + if (domain_bbox.IsIn (mesh3d[pi])) + glob2loc[pi] = + meshing.AddPoint (mesh3d[pi], pi); + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + { + Element2d hel = mesh3d.OpenElement(i); + for (int j = 0; j < hel.GetNP(); j++) + hel[j] = glob2loc[hel[j]]; + meshing.AddBoundaryElement (hel); + // meshing.AddBoundaryElement (mesh3d.OpenElement(i)); + } + + oldne = mesh3d.GetNE(); + + mp.giveuptol = 15 + 10 * cntsteps; + mp.sloppy = 5; + meshing.GenerateMesh (mesh3d, mp); + + for (ElementIndex ei = oldne; ei < mesh3d.GetNE(); ei++) + mesh3d[ei].SetIndex (k); + + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(k); + + teterrpow = 2; + if (mesh3d.GetNOpenElements() != 0) + { + meshed = 0; + PrintMessage (5, mesh3d.GetNOpenElements(), " open faces found"); + + // mesh3d.Save ("tmp.vol"); + + + MeshOptimize3d optmesh; + + const char * optstr = "mcmstmcmstmcmstmcm"; + size_t j; + for (j = 1; j <= strlen(optstr); j++) + { + mesh3d.CalcSurfacesOfNode(); + mesh3d.FreeOpenElementsEnvironment(2); + mesh3d.CalcSurfacesOfNode(); + + switch (optstr[j-1]) + { + case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; + case 'd': optmesh.SplitImprove(mesh3d, OPT_REST); break; + case 's': optmesh.SwapImprove(mesh3d, OPT_REST); break; + case 't': optmesh.SwapImprove2(mesh3d, OPT_REST); break; + case 'm': mesh3d.ImproveMesh(OPT_REST); break; + } + + } + + mesh3d.FindOpenElements(k); + PrintMessage (3, "Call remove problem"); + RemoveProblem (mesh3d, k); + mesh3d.FindOpenElements(k); + } + else + { + meshed = 1; + PrintMessage (1, "Success !"); + } + } + while (!meshed); + + PrintMessage (1, mesh3d.GetNP(), " points, ", + mesh3d.GetNE(), " elements"); + } + + mp.maxh = globmaxh; + + MeshQuality3d (mesh3d); + + return MESHING3_OK; + } + + + + + /* + + + MESHING3_RESULT MeshVolumeOld (MeshingParameters & mp, Mesh& mesh3d) + { + int i, k, oldne; + + + int meshed; + int cntsteps; + + + PlotStatistics3d * pstat; + if (globflags.GetNumFlag("silentflag", 1) <= 2) + pstat = new XPlotStatistics3d; + else + pstat = new TerminalPlotStatistics3d; + + cntsteps = 0; + do + { + cntsteps++; + if (cntsteps > mp.maxoutersteps) + { + return MESHING3_OUTERSTEPSEXCEEDED; + } + + + int noldp = mesh3d.GetNP(); + + + if ( (cntsteps == 1) && globflags.GetDefineFlag ("delaunay")) + { + cntsteps ++; + + mesh3d.CalcSurfacesOfNode(); + + + for (k = 1; k <= mesh3d.GetNDomains(); k++) + { + Meshing3 meshing(NULL, pstat); + + mesh3d.FindOpenElements(k); + + for (i = 1; i <= noldp; i++) + meshing.AddPoint (mesh3d.Point(i), i); + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + { + if (mesh3d.OpenElement(i).GetIndex() == k) + meshing.AddBoundaryElement (mesh3d.OpenElement(i)); + } + + oldne = mesh3d.GetNE(); + if (globflags.GetDefineFlag ("blockfill")) + { + if (!globflags.GetDefineFlag ("localh")) + meshing.BlockFill + (mesh3d, mp.h * globflags.GetNumFlag ("relblockfillh", 1)); + else + meshing.BlockFillLocalH (mesh3d); + } + + MeshingParameters mpd; + meshing.Delaunay (mesh3d, mpd); + + for (i = oldne + 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (k); + } + } + + noldp = mesh3d.GetNP(); + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(); + for (k = 1; k <= mesh3d.GetNDomains(); k++) + { + Meshing3 meshing(globflags.GetStringFlag ("rules3d", NULL), pstat); + + Point3d pmin, pmax; + mesh3d.GetBox (pmin, pmax, k); + + rot.SetCenter (Center (pmin, pmax)); + + for (i = 1; i <= noldp; i++) + meshing.AddPoint (mesh3d.Point(i), i); + + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + { + if (mesh3d.OpenElement(i).GetIndex() == k) + meshing.AddBoundaryElement (mesh3d.OpenElement(i)); + } + + oldne = mesh3d.GetNE(); + + + if ( (cntsteps == 1) && globflags.GetDefineFlag ("blockfill")) + { + if (!globflags.GetDefineFlag ("localh")) + { + meshing.BlockFill + (mesh3d, + mp.h * globflags.GetNumFlag ("relblockfillh", 1)); + } + else + { + meshing.BlockFillLocalH (mesh3d); + } + } + + + mp.giveuptol = int(globflags.GetNumFlag ("giveuptol", 15)); + + meshing.GenerateMesh (mesh3d, mp); + + for (i = oldne + 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (k); + } + + + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(); + + teterrpow = 2; + if (mesh3d.GetNOpenElements() != 0) + { + meshed = 0; + (*mycout) << "Open elements found, old" << endl; + const char * optstr = "mcmcmcmcm"; + int j; + for (j = 1; j <= strlen(optstr); j++) + switch (optstr[j-1]) + { + case 'c': mesh3d.CombineImprove(); break; + case 'd': mesh3d.SplitImprove(); break; + case 's': mesh3d.SwapImprove(); break; + case 'm': mesh3d.ImproveMesh(2); break; + } + + (*mycout) << "Call remove" << endl; + RemoveProblem (mesh3d); + (*mycout) << "Problem removed" << endl; + } + else + meshed = 1; + } + while (!meshed); + + MeshQuality3d (mesh3d); + + return MESHING3_OK; + } + + */ + + + + + /* + MESHING3_RESULT MeshMixedVolume(MeshingParameters & mp, Mesh& mesh3d) + { + int i, j; + MESHING3_RESULT res; + Point3d pmin, pmax; + + mp.giveuptol = 10; + mp.baseelnp = 4; + mp.starshapeclass = 100; + + // TerminalPlotStatistics3d pstat; + + Meshing3 meshing1("pyramids.rls"); + for (i = 1; i <= mesh3d.GetNP(); i++) + meshing1.AddPoint (mesh3d.Point(i), i); + + mesh3d.FindOpenElements(); + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + if (mesh3d.OpenElement(i).GetIndex() == 1) + meshing1.AddBoundaryElement (mesh3d.OpenElement(i)); + + res = meshing1.GenerateMesh (mesh3d, mp); + + mesh3d.GetBox (pmin, pmax); + PrintMessage (1, "Mesh pyramids, res = ", res); + if (res) + exit (1); + + + for (i = 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (1); + + // do delaunay + + mp.baseelnp = 0; + mp.starshapeclass = 5; + + Meshing3 meshing2(NULL); + for (i = 1; i <= mesh3d.GetNP(); i++) + meshing2.AddPoint (mesh3d.Point(i), i); + + mesh3d.FindOpenElements(); + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + if (mesh3d.OpenElement(i).GetIndex() == 1) + meshing2.AddBoundaryElement (mesh3d.OpenElement(i)); + + MeshingParameters mpd; + meshing2.Delaunay (mesh3d, mpd); + + for (i = 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (1); + + + mp.baseelnp = 0; + mp.giveuptol = 10; + + for (int trials = 1; trials <= 50; trials++) + { + if (multithread.terminate) + return MESHING3_TERMINATE; + + Meshing3 meshing3("tetra.rls"); + for (i = 1; i <= mesh3d.GetNP(); i++) + meshing3.AddPoint (mesh3d.Point(i), i); + + mesh3d.FindOpenElements(); + for (i = 1; i <= mesh3d.GetNOpenElements(); i++) + if (mesh3d.OpenElement(i).GetIndex() == 1) + meshing3.AddBoundaryElement (mesh3d.OpenElement(i)); + + if (trials > 1) + CheckSurfaceMesh2 (mesh3d); + res = meshing3.GenerateMesh (mesh3d, mp); + + for (i = 1; i <= mesh3d.GetNE(); i++) + mesh3d.VolumeElement(i).SetIndex (1); + + if (res == 0) break; + + + + for (i = 1; i <= mesh3d.GetNE(); i++) + { + const Element & el = mesh3d.VolumeElement(i); + if (el.GetNP() != 4) + { + for (j = 1; j <= el.GetNP(); j++) + mesh3d.AddLockedPoint (el.PNum(j)); + } + } + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(); + + MeshOptimize3d optmesh; + + teterrpow = 2; + const char * optstr = "mcmcmcmcm"; + for (j = 1; j <= strlen(optstr); j++) + switch (optstr[j-1]) + { + case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; + case 'd': optmesh.SplitImprove(mesh3d); break; + case 's': optmesh.SwapImprove(mesh3d); break; + case 'm': mesh3d.ImproveMesh(); break; + } + + RemoveProblem (mesh3d); + } + + + PrintMessage (1, "Meshing tets, res = ", res); + if (res) + { + mesh3d.FindOpenElements(); + PrintSysError (1, "Open elemetns: ", mesh3d.GetNOpenElements()); + exit (1); + } + + + + for (i = 1; i <= mesh3d.GetNE(); i++) + { + const Element & el = mesh3d.VolumeElement(i); + if (el.GetNP() != 4) + { + for (j = 1; j <= el.GetNP(); j++) + mesh3d.AddLockedPoint (el.PNum(j)); + } + } + + mesh3d.CalcSurfacesOfNode(); + mesh3d.FindOpenElements(); + + MeshOptimize3d optmesh; + + teterrpow = 2; + const char * optstr = "mcmcmcmcm"; + for (j = 1; j <= strlen(optstr); j++) + switch (optstr[j-1]) + { + case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; + case 'd': optmesh.SplitImprove(mesh3d); break; + case 's': optmesh.SwapImprove(mesh3d); break; + case 'm': mesh3d.ImproveMesh(); break; + } + + + return MESHING3_OK; + } +*/ + + + + + + + MESHING3_RESULT OptimizeVolume (MeshingParameters & mp, + Mesh & mesh3d) + // const CSGeometry * geometry) + { + int i; + + PrintMessage (1, "Volume Optimization"); + + /* + if (!mesh3d.PureTetMesh()) + return MESHING3_OK; + */ + + // (*mycout) << "optstring = " << mp.optimize3d << endl; + /* + const char * optstr = globflags.GetStringFlag ("optimize3d", "cmh"); + int optsteps = int (globflags.GetNumFlag ("optsteps3d", 2)); + */ + + mesh3d.CalcSurfacesOfNode(); + for (i = 1; i <= mp.optsteps3d; i++) + { + if (multithread.terminate) + break; + + MeshOptimize3d optmesh; + + teterrpow = mp.opterrpow; + for (size_t j = 1; j <= strlen(mp.optimize3d); j++) + { + if (multithread.terminate) + break; + + switch (mp.optimize3d[j-1]) + { + case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; + case 'd': optmesh.SplitImprove(mesh3d); break; + case 's': optmesh.SwapImprove(mesh3d); break; + // case 'u': optmesh.SwapImproveSurface(mesh3d); break; + case 't': optmesh.SwapImprove2(mesh3d); break; +#ifdef SOLIDGEOM + case 'm': mesh3d.ImproveMesh(*geometry); break; + case 'M': mesh3d.ImproveMesh(*geometry); break; +#else + case 'm': mesh3d.ImproveMesh(); break; + case 'M': mesh3d.ImproveMesh(); break; +#endif + case 'j': mesh3d.ImproveMeshJacobian(); break; + } + } + mesh3d.mglevels = 1; + MeshQuality3d (mesh3d); + } + + return MESHING3_OK; + } + + + + + void RemoveIllegalElements (Mesh & mesh3d) + { + int it = 10; + int nillegal, oldn; + + PrintMessage (1, "Remove Illegal Elements"); + // return, if non-pure tet-mesh + /* + if (!mesh3d.PureTetMesh()) + return; + */ + mesh3d.CalcSurfacesOfNode(); + + nillegal = mesh3d.MarkIllegalElements(); + + MeshOptimize3d optmesh; + while (nillegal && (it--) > 0) + { + if (multithread.terminate) + break; + + PrintMessage (5, nillegal, " illegal tets"); + optmesh.SplitImprove (mesh3d, OPT_LEGAL); + + mesh3d.MarkIllegalElements(); // test + optmesh.SwapImprove (mesh3d, OPT_LEGAL); + mesh3d.MarkIllegalElements(); // test + optmesh.SwapImprove2 (mesh3d, OPT_LEGAL); + + oldn = nillegal; + nillegal = mesh3d.MarkIllegalElements(); + + if (oldn != nillegal) + it = 10; + } + PrintMessage (5, nillegal, " illegal tets"); + } +} diff --git a/contrib/Netgen/libsrc/meshing/meshfunc.hpp b/contrib/Netgen/libsrc/meshing/meshfunc.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ab2d661050842ae9abb673d9c39091ca4e1aa78e --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshfunc.hpp @@ -0,0 +1,41 @@ +#ifndef FILE_MESHFUNC +#define FILE_MESHFUNC + +/**************************************************************************/ +/* File: meshfunc.hh */ +/* Author: Johannes Gerstmayr */ +/* Date: 26. Jan. 98 */ +/**************************************************************************/ + + +/* + Functions for mesh-generations strategies + */ + +class Mesh; +// class CSGeometry; + +/// Build tet-mesh +MESHING3_RESULT MeshVolume(MeshingParameters & mp, Mesh& mesh3d); + +/// Build mixed-element mesh +MESHING3_RESULT MeshMixedVolume(MeshingParameters & mp, Mesh& mesh3d); + +/// Optimize tet-mesh +MESHING3_RESULT OptimizeVolume(MeshingParameters & mp, Mesh& mesh3d); +// const CSGeometry * geometry = NULL); + +void RemoveIllegalElements (Mesh & mesh3d); + + +enum MESHING_STEP { + MESHCONST_ANALYSE = 1, + MESHCONST_MESHEDGES = 2, + MESHCONST_MESHSURFACE = 3, + MESHCONST_OPTSURFACE = 4, + MESHCONST_MESHVOLUME = 5, + MESHCONST_OPTVOLUME = 6 +}; + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/meshfunc2d.cpp b/contrib/Netgen/libsrc/meshing/meshfunc2d.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac4fbe8e928691ea24301a0e36f306379ca31dc8 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshfunc2d.cpp @@ -0,0 +1,61 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + void Optimize2d (Mesh & mesh, MeshingParameters & mp) + { + int i; + + //double h = mp.maxh; + + mesh.CalcSurfacesOfNode(); + + const char * optstr = mp.optimize2d; + int optsteps = mp.optsteps2d; + + // cout << "optstr = " << optstr << endl; + + for (i = 1; i <= optsteps; i++) + for (size_t j = 1; j <= strlen(optstr); j++) + { + if (multithread.terminate) break; + switch (optstr[j-1]) + { + case 's': + { // topological swap + MeshOptimize2d meshopt; + meshopt.SetMetricWeight (0); + meshopt.EdgeSwapping (mesh, 0); + break; + } + case 'S': + { // metric swap + MeshOptimize2d meshopt; + meshopt.SetMetricWeight (0); + meshopt.EdgeSwapping (mesh, 1); + break; + } + case 'm': + { + MeshOptimize2d meshopt; + meshopt.SetMetricWeight (1); + meshopt.ImproveMesh(mesh); + break; + } + + case 'c': + { + MeshOptimize2d meshopt; + meshopt.SetMetricWeight (0.2); + meshopt.CombineImprove(mesh); + break; + } + default: + cerr << "Optimization code " << optstr[j-1] << " not defined" << endl; + } + } + } + +} diff --git a/contrib/Netgen/libsrc/meshing/meshing.hpp b/contrib/Netgen/libsrc/meshing/meshing.hpp new file mode 100644 index 0000000000000000000000000000000000000000..10b77f9e18d7129da0403919eea59d2e9520e7cb --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing.hpp @@ -0,0 +1,86 @@ +#ifndef FILE_MESHING +#define FILE_MESHING + + + +#define CURVEDELEMS_NEW + + +#include "../include/myadt.hpp" +#include "../include/gprim.hpp" +#include "../include/linalg.hpp" +#include "../include/opti.hpp" + + + + +namespace netgen +{ + + extern int printmessage_importance; + + class CSGeometry; + + +#include "msghandler.hpp" + +#include "meshtype.hpp" +#include "localh.hpp" +#include "meshclass.hpp" +#include "global.hpp" + + +#include "meshtool.hpp" +#include "ruler2.hpp" +#include "adfront2.hpp" +#include "meshing2.hpp" +#include "improve2.hpp" + + +#include "geomsearch.hpp" +#include "adfront3.hpp" +#include "ruler3.hpp" + +#ifndef SMALLLIB +#define _INCLUDE_MORE +#endif +#ifdef LINUX +#define _INCLUDE_MORE +#endif + +#ifdef _INCLUDE_MORE +#include "meshing3.hpp" +#include "improve3.hpp" +#endif +#include "findip.hpp" +#include "findip2.hpp" + +#include "topology.hpp" + +#ifdef CURVEDELEMS_NEW +#include "curvedelems_new.hpp" +#else +#include "curvedelems.hpp" +#endif +#include "clusters.hpp" + +#ifdef _INCLUDE_MORE +#include "meshfunc.hpp" +#endif +#include "bisect.hpp" +#include "hprefinement.hpp" +#include "boundarylayer.hpp" +#include "specials.hpp" + +#include "validate.hpp" + +#ifdef PARALLEL +#include "../parallel/paralleltop.hpp" +// #include "../parallel/parallelmesh.hpp" +#endif + + + +} + +#endif diff --git a/contrib/Netgen/libsrc/meshing/meshing2.cpp b/contrib/Netgen/libsrc/meshing/meshing2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7793ecbbfa383846485c3d8161a21ef39197909a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing2.cpp @@ -0,0 +1,1890 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + static void glrender (int wait); + + + // global variable for visualization + + static ARRAY<Point3d> locpoints; + static ARRAY<int> legalpoints; + static ARRAY<Point2d> plainpoints; + static ARRAY<int> plainzones; + static ARRAY<INDEX_2> loclines; + static int geomtrig; + //static const char * rname; + static int cntelem, trials, nfaces; + static int oldnl; + static int qualclass; + + + Meshing2 :: Meshing2 (const Box<3> & aboundingbox) + { + boundingbox = aboundingbox; + + LoadRules (NULL); + // LoadRules ("rules/quad.rls"); + // LoadRules ("rules/triangle.rls"); + + adfront = new AdFront2(boundingbox); + starttime = GetTime(); + + maxarea = -1; + } + + + Meshing2 :: ~Meshing2 () + { + delete adfront; + for (int i = 0; i < rules.Size(); i++) + delete rules[i]; + } + + void Meshing2 :: AddPoint (const Point3d & p, PointIndex globind, + MultiPointGeomInfo * mgi, + bool pointonsurface) + { + //(*testout) << "add point " << globind << endl; + adfront ->AddPoint (p, globind, mgi, pointonsurface); + } + + void Meshing2 :: AddBoundaryElement (int i1, int i2, + const PointGeomInfo & gi1, const PointGeomInfo & gi2) + { + // (*testout) << "add line " << i1 << " - " << i2 << endl; + if (!gi1.trignum || !gi2.trignum) + { + PrintSysError ("addboundaryelement: illegal geominfo"); + } + adfront -> AddLine (i1-1, i2-1, gi1, gi2); + } + + + + void Meshing2 :: StartMesh () + { + foundmap.SetSize (rules.Size()); + canuse.SetSize (rules.Size()); + ruleused.SetSize (rules.Size()); + + foundmap = 0; + canuse = 0; + ruleused = 0; + + cntelem = 0; + trials = 0; + } + + void Meshing2 :: EndMesh () + { + for (int i = 0; i < ruleused.Size(); i++) + (*testout) << setw(4) << ruleused[i] + << " times used rule " << rules[i] -> Name() << endl; + } + + void Meshing2 :: SetStartTime (double astarttime) + { + starttime = astarttime; + } + + + void Meshing2 :: SetMaxArea (double amaxarea) + { + maxarea = amaxarea; + } + + + double Meshing2 :: CalcLocalH (const Point3d & /* p */, double gh) const + { + return gh; + } + + // should be class variables !!(?) + static Vec3d ex, ey; + static Point3d globp1; + + void Meshing2 :: DefineTransformation (const Point3d & p1, const Point3d & p2, + const PointGeomInfo * geominfo1, + const PointGeomInfo * geominfo2) + { + globp1 = p1; + ex = p2 - p1; + ex /= ex.Length(); + ey.X() = -ex.Y(); + ey.Y() = ex.X(); + ey.Z() = 0; + } + + void Meshing2 :: TransformToPlain (const Point3d & locpoint, + const MultiPointGeomInfo & geominf, + Point2d & plainpoint, double h, int & zone) + { + Vec3d p1p (globp1, locpoint); + + // p1p = locpoint - globp1; + p1p /= h; + plainpoint.X() = p1p * ex; + plainpoint.Y() = p1p * ey; + zone = 0; + } + + int Meshing2 :: TransformFromPlain (Point2d & plainpoint, + Point3d & locpoint, + PointGeomInfo & gi, + double h) + { + Vec3d p1p; + gi.trignum = 1; + + p1p = plainpoint.X() * ex + plainpoint.Y() * ey; + p1p *= h; + locpoint = globp1 + p1p; + return 0; + } + + + int Meshing2 :: BelongsToActiveChart (const Point3d & p, + const PointGeomInfo & gi) + { + return 1; + } + + + int Meshing2 :: ComputePointGeomInfo (const Point3d & p, PointGeomInfo & gi) + { + gi.trignum = 1; + return 0; + } + + + int Meshing2 :: ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, + PointGeomInfo & pgi) + { + pgi = mpgi.GetPGI(1); + return 0; + } + + + + int Meshing2 :: + IsLineVertexOnChart (const Point3d & p1, const Point3d & p2, + int endpoint, const PointGeomInfo & geominfo) + { + return 1; + } + + void Meshing2 :: + GetChartBoundary (ARRAY<Point2d> & points, + ARRAY<Point3d> & points3d, + ARRAY<INDEX_2> & lines, double h) const + { + points.SetSize (0); + points3d.SetSize (0); + lines.SetSize (0); + } + + double Meshing2 :: Area () const + { + return -1; + } + + + + + + MESHING2_RESULT Meshing2 :: GenerateMesh (Mesh & mesh, double gh, int facenr) + { + ARRAY<int> pindex, lindex; + ARRAY<int> delpoints, dellines; + + ARRAY<PointGeomInfo> upgeominfo; // unique info + ARRAY<MultiPointGeomInfo> mpgeominfo; // multiple info + + ARRAY<Element2d> locelements; + + int z1, z2, oldnp(-1); + SurfaceElementIndex sei; + bool found; + int rulenr(-1); + int globind; + Point<3> p1, p2; + + const PointGeomInfo * blgeominfo1; + const PointGeomInfo * blgeominfo2; + + bool morerisc; + bool debugflag; + + double h, his, hshould; + + + // test for 3d overlaps + Box3dTree surfeltree (boundingbox.PMin(), + boundingbox.PMax()); + + ARRAY<int> intersecttrias; + ARRAY<Point3d> critpoints; + + // test for doubled edges + //INDEX_2_HASHTABLE<int> doubleedge(300000); + + + testmode = 0; + + StartMesh(); + + ARRAY<Point2d> chartboundpoints; + ARRAY<Point3d> chartboundpoints3d; + ARRAY<INDEX_2> chartboundlines; + + // illegal points: points with more then 50 elements per node + int maxlegalpoint(-1), maxlegalline(-1); + ARRAY<int,PointIndex::BASE> trigsonnode; + ARRAY<int,PointIndex::BASE> illegalpoint; + + trigsonnode.SetSize (mesh.GetNP()); + illegalpoint.SetSize (mesh.GetNP()); + + trigsonnode = 0; + illegalpoint = 0; + + + double totalarea = Area (); + double meshedarea = 0; + + // search tree for surface elements: + for (sei = 0; sei < mesh.GetNSE(); sei++) + { + const Element2d & sel = mesh[sei]; + + if (sel.IsDeleted()) continue; + + if (sel.GetIndex() == facenr) + { + Box<3> box; + box.Set ( mesh[sel[0]] ); + box.Add ( mesh[sel[1]] ); + box.Add ( mesh[sel[2]] ); + surfeltree.Insert (box, sei); + } + + double trigarea = Cross ( mesh[sel[1]]-mesh[sel[0]], + mesh[sel[2]]-mesh[sel[0]] ).Length() / 2; + + + if (sel.GetNP() == 4) + trigarea += Cross (Vec3d (mesh.Point (sel.PNum(1)), + mesh.Point (sel.PNum(3))), + Vec3d (mesh.Point (sel.PNum(1)), + mesh.Point (sel.PNum(4)))).Length() / 2;; + meshedarea += trigarea; + } + + + const char * savetask = multithread.task; + multithread.task = "Surface meshing"; + + adfront ->SetStartFront (); + + + int plotnexttrial = 999; + + double meshedarea_before = meshedarea; + + while (!adfront ->Empty() && !multithread.terminate) + { + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + // known for STL meshing + if (totalarea > 0) + multithread.percent = 100 * meshedarea / totalarea; + /* + else + multithread.percent = 0; + */ + + locpoints.SetSize(0); + loclines.SetSize(0); + pindex.SetSize(0); + lindex.SetSize(0); + delpoints.SetSize(0); + dellines.SetSize(0); + locelements.SetSize(0); + + + + // plot statistics + if (trials > plotnexttrial) + { + PrintMessage (5, + "faces = ", nfaces, + " trials = ", trials, + " elements = ", mesh.GetNSE(), + " els/sec = ", + (mesh.GetNSE() / (GetTime() - starttime + 0.0001))); + plotnexttrial += 1000; + } + + + // unique-pgi, multi-pgi + upgeominfo.SetSize(0); + mpgeominfo.SetSize(0); + + + nfaces = adfront->GetNFL(); + trials ++; + + + if (trials % 1000 == 0) + { + (*testout) << "\n"; + for (int i = 1; i <= canuse.Size(); i++) + { + (*testout) << foundmap.Get(i) << "/" + << canuse.Get(i) << "/" + << ruleused.Get(i) << " map/can/use rule " << rules.Get(i)->Name() << "\n"; + } + (*testout) << "\n"; + } + + + int baselineindex = adfront -> SelectBaseLine (p1, p2, blgeominfo1, blgeominfo2, qualclass); + + + found = 1; + + his = Dist (p1, p2); + + Point3d pmid = Center (p1, p2); + hshould = CalcLocalH (pmid, mesh.GetH (pmid)); + if (gh < hshould) hshould = gh; + + mesh.RestrictLocalH (pmid, hshould); + + h = hshould; + + double hinner = (3 + qualclass) * max2 (his, hshould); + + adfront ->GetLocals (baselineindex, locpoints, mpgeominfo, loclines, + pindex, lindex, 2*hinner); + //(*testout) << "h for locals: " << 2*hinner << endl; + + + //(*testout) << "locpoints " << locpoints << endl; + + if (qualclass > mparam.giveuptol2d) + { + PrintMessage (3, "give up with qualclass ", qualclass); + PrintMessage (3, "number of frontlines = ", adfront->GetNFL()); + // throw NgException ("Give up 2d meshing"); + break; + } + + /* + if (found && qualclass > 60) + { + found = 0; + } + */ + // morerisc = ((qualclass > 20) && (qualclass % 2 == 1)); + // morerisc = 1; + morerisc = 0; + + + PointIndex gpi1 = adfront -> GetGlobalIndex (pindex.Get(loclines[0].I1())); + PointIndex gpi2 = adfront -> GetGlobalIndex (pindex.Get(loclines[0].I2())); + + + debugflag = + debugparam.haltsegment && + ( (debugparam.haltsegmentp1 == gpi1) && + (debugparam.haltsegmentp2 == gpi2) || + (debugparam.haltsegmentp1 == gpi2) && + (debugparam.haltsegmentp2 == gpi1)) || + debugparam.haltnode && + ( (debugparam.haltsegmentp1 == gpi1) || + (debugparam.haltsegmentp2 == gpi1)); + + + if (debugparam.haltface && debugparam.haltfacenr == facenr) + { + debugflag = 1; + cout << "set debugflag" << endl; + } + + if (debugparam.haltlargequalclass && qualclass > 50) + debugflag = 1; + + + // problem recognition ! + if (found && + (gpi1 < illegalpoint.Size()+PointIndex::BASE) && + (gpi2 < illegalpoint.Size()+PointIndex::BASE) ) + { + if (illegalpoint[gpi1] || illegalpoint[gpi2]) + found = 0; + } + + + Point2d p12d, p22d; + + if (found) + { + oldnp = locpoints.Size(); + oldnl = loclines.Size(); + + if (debugflag) + (*testout) << "define new transformation" << endl; + + DefineTransformation (p1, p2, blgeominfo1, blgeominfo2); + + plainpoints.SetSize (locpoints.Size()); + plainzones.SetSize (locpoints.Size()); + + // (*testout) << endl; + + // (*testout) << "3d->2d transformation" << endl; + + for (int i = 1; i <= locpoints.Size(); i++) + { + // (*testout) << "pindex(i) = " << pindex[i-1] << endl; + TransformToPlain (locpoints.Get(i), + mpgeominfo.Get(i), + plainpoints.Elem(i), h, plainzones.Elem(i)); + // (*testout) << mpgeominfo.Get(i).GetPGI(1).u << " " << mpgeominfo.Get(i).GetPGI(1).v << " "; + // (*testout) << plainpoints.Get(i).X() << " " << plainpoints.Get(i).Y() << endl; + //(*testout) << "transform " << locpoints.Get(i) << " to " << plainpoints.Get(i).X() << " " << plainpoints.Get(i).Y() << endl; + } + // (*testout) << endl << endl << endl; + + + p12d = plainpoints.Get(1); + p22d = plainpoints.Get(2); + + /* + // last idea on friday + plainzones.Elem(1) = 0; + plainzones.Elem(2) = 0; + */ + + + /* + // old netgen: + for (i = 2; i <= loclines.Size(); i++) // don't remove first line + { + z1 = plainzones.Get(loclines.Get(i).I1()); + z2 = plainzones.Get(loclines.Get(i).I2()); + + if (z1 && z2 && (z1 != z2) || (z1 == -1) || (z2 == -1) ) + { + loclines.DeleteElement(i); + lindex.DeleteElement(i); + oldnl--; + i--; + } + } + + // for (i = 1; i <= plainpoints.Size(); i++) + // if (plainzones.Elem(i) == -1) + // plainpoints.Elem(i) = Point2d (1e4, 1e4); + */ + + + + for (int i = 2; i <= loclines.Size(); i++) // don't remove first line + { + // (*testout) << "loclines(i) = " << loclines.Get(i).I1() << " - " << loclines.Get(i).I2() << endl; + z1 = plainzones.Get(loclines.Get(i).I1()); + z2 = plainzones.Get(loclines.Get(i).I2()); + + + // one inner point, one outer + if ( (z1 >= 0) != (z2 >= 0)) + { + int innerp = (z1 >= 0) ? 1 : 2; + if (IsLineVertexOnChart (locpoints.Get(loclines.Get(i).I1()), + locpoints.Get(loclines.Get(i).I2()), + innerp, + adfront->GetLineGeomInfo (lindex.Get(i), innerp))) + // pgeominfo.Get(loclines.Get(i).I(innerp)))) + { + + if (!morerisc) + { + // use one end of line + int pini, pouti; + Vec2d v; + + pini = loclines.Get(i).I(innerp); + pouti = loclines.Get(i).I(3-innerp); + + Point2d pin (plainpoints.Get(pini)); + Point2d pout (plainpoints.Get(pouti)); + v = pout - pin; + double len = v.Length(); + if (len <= 1e-6) + (*testout) << "WARNING(js): inner-outer: short vector" << endl; + else + v /= len; + + /* + // don't elongate line towards base-line !! + if (Vec2d (pin, p12d) * v > 0 && + Vec2d (pin, p22d) * v > 0) + v *= -1; + */ + + Point2d newpout = pin + 1000 * v; + newpout = pout; + + + plainpoints.Append (newpout); + Point3d pout3d = locpoints.Get(pouti); + locpoints.Append (pout3d); + + plainzones.Append (0); + pindex.Append (-1); + oldnp++; + loclines.Elem(i).I(3-innerp) = oldnp; + } + else + plainzones.Elem(loclines.Get(i).I(3-innerp)) = 0; + + + // (*testout) << "inner - outer correction" << endl; + } + else + { + // remove line + loclines.DeleteElement(i); + lindex.DeleteElement(i); + oldnl--; + i--; + } + } + + else if (z1 > 0 && z2 > 0 && (z1 != z2) || (z1 < 0) && (z2 < 0) ) + { + loclines.DeleteElement(i); + lindex.DeleteElement(i); + oldnl--; + i--; + } + } + + + + + + legalpoints.SetSize(plainpoints.Size()); + for (int i = 1; i <= legalpoints.Size(); i++) + legalpoints.Elem(i) = 1; + + double avy = 0; + for (int i = 1; i <= plainpoints.Size(); i++) + avy += plainpoints.Elem(i).Y(); + avy *= 1./plainpoints.Size(); + + + for (int i = 1; i <= plainpoints.Size(); i++) + { + if (plainzones.Elem(i) < 0) + { + plainpoints.Elem(i) = Point2d (1e4, 1e4); + legalpoints.Elem(i) = 0; + } + if (pindex.Elem(i) == -1) + { + legalpoints.Elem(i) = 0; + } + + + if (plainpoints.Elem(i).Y() < -1e-10*avy) // changed + { + legalpoints.Elem(i) = 0; + } + } + /* + for (i = 3; i <= plainpoints.Size(); i++) + if (sqr (plainpoints.Get(i).X()) + sqr (plainpoints.Get(i).Y()) + > sqr (2 + 0.2 * qualclass)) + legalpoints.Elem(i) = 0; + */ + + /* + int clp = 0; + for (i = 1; i <= plainpoints.Size(); i++) + if (legalpoints.Get(i)) + clp++; + (*testout) << "legalpts: " << clp << "/" << plainpoints.Size() << endl; + + // sort legal/illegal lines + int lastleg = 2; + int firstilleg = oldnl; + + while (lastleg < firstilleg) + { + while (legalpoints.Get(loclines.Get(lastleg).I1()) && + legalpoints.Get(loclines.Get(lastleg).I2()) && + lastleg < firstilleg) + lastleg++; + while ( ( !legalpoints.Get(loclines.Get(firstilleg).I1()) || + !legalpoints.Get(loclines.Get(firstilleg).I2())) && + lastleg < firstilleg) + firstilleg--; + + if (lastleg < firstilleg) + { + swap (loclines.Elem(lastleg), loclines.Elem(firstilleg)); + swap (lindex.Elem(lastleg), lindex.Elem(firstilleg)); + } + } + + (*testout) << "leglines " << lastleg << "/" << oldnl << endl; + */ + + + GetChartBoundary (chartboundpoints, + chartboundpoints3d, + chartboundlines, h); + + oldnp = plainpoints.Size(); + + maxlegalpoint = locpoints.Size(); + maxlegalline = loclines.Size(); + + + + if (mparam.checkchartboundary) + { + for (int i = 1; i <= chartboundpoints.Size(); i++) + { + plainpoints.Append (chartboundpoints.Get(i)); + locpoints.Append (chartboundpoints3d.Get(i)); + legalpoints.Append (0); + } + + + for (int i = 1; i <= chartboundlines.Size(); i++) + { + INDEX_2 line (chartboundlines.Get(i).I1()+oldnp, + chartboundlines.Get(i).I2()+oldnp); + loclines.Append (line); + // (*testout) << "line: " << line.I1() << "-" << line.I2() << endl; + } + } + + oldnl = loclines.Size(); + oldnp = plainpoints.Size(); + } + + + /* + if (qualclass > 100) + { + multithread.drawing = 1; + glrender(1); + cout << "qualclass 100, nfl = " << adfront->GetNFL() << endl; + } + */ + + if (found) + { + rulenr = ApplyRules (plainpoints, legalpoints, maxlegalpoint, + loclines, maxlegalline, locelements, + dellines, qualclass); + // (*testout) << "Rule Nr = " << rulenr << endl; + if (!rulenr) + { + found = 0; + if ( debugflag || debugparam.haltnosuccess ) + PrintWarning ("no rule found"); + } + } + + for (int i = 1; i <= locelements.Size() && found; i++) + { + const Element2d & el = locelements.Get(i); + + for (int j = 1; j <= el.GetNP(); j++) + if (el.PNum(j) <= oldnp && pindex.Get(el.PNum(j)) == -1) + { + found = 0; + PrintSysError ("meshing2, index missing"); + } + } + + + if (found) + { + locpoints.SetSize (plainpoints.Size()); + upgeominfo.SetSize(locpoints.Size()); + + for (int i = oldnp+1; i <= plainpoints.Size(); i++) + { + int err = + TransformFromPlain (plainpoints.Elem(i), locpoints.Elem(i), + upgeominfo.Elem(i), h); + + if (err) + { + found = 0; + + if ( debugflag || debugparam.haltnosuccess ) + PrintSysError ("meshing2, Backtransformation failed"); + + break; + } + } + } + + + // for (i = 1; i <= oldnl; i++) + // adfront -> ResetClass (lindex[i]); + + + /* + double violateminh; + if (qualclass <= 10) + violateminh = 3; + else + violateminh = 3 * qualclass; + + if (uselocalh && found) // && qualclass <= 10) + { + for (i = 1; i <= locelements.Size(); i++) + { + Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1)); + Point3d pmax = pmin; + for (j = 2; j <= 3; j++) + { + const Point3d & hp = + locpoints.Get(locelements.Get(i).PNum(j)); + pmin.SetToMin (hp); + pmax.SetToMax (hp); + } + double minh = mesh.GetMinH (pmin, pmax); + if (h > violateminh * minh) + { + found = 0; + loclines.SetSize (oldnl); + locpoints.SetSize (oldnp); + } + } + } + */ + + + if (found) + { + double violateminh = 3 + 0.1 * sqr (qualclass); + double minh = 1e8; + double newedgemaxh = 0; + for (int i = oldnl+1; i <= loclines.Size(); i++) + { + double eh = Dist (locpoints.Get(loclines.Get(i).I1()), + locpoints.Get(loclines.Get(i).I2())); + + // Markus (brute force method to avoid bad elements on geometries like \_/ ) + //if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I1()))) found = 0; + //if(eh > 4.*mesh.GetH(locpoints.Get(loclines.Get(i).I2()))) found = 0; + // Markus end + + if (eh > newedgemaxh) + newedgemaxh = eh; + } + + for (int i = 1; i <= locelements.Size(); i++) + { + Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1)); + Point3d pmax = pmin; + for (int j = 2; j <= locelements.Get(i).GetNP(); j++) + { + const Point3d & hp = + locpoints.Get(locelements.Get(i).PNum(j)); + pmin.SetToMin (hp); + pmax.SetToMax (hp); + } + double eh = mesh.GetMinH (pmin, pmax); + if (eh < minh) + minh = eh; + } + + for (int i = 1; i <= locelements.Size(); i++) + for (int j = 1; j <= locelements.Get(i).GetNP(); j++) + if (Dist2 (locpoints.Get(locelements.Get(i).PNum(j)), pmid) > hinner*hinner) + found = 0; + + // cout << "violate = " << newedgemaxh / minh << endl; + static double maxviolate = 0; + if (newedgemaxh / minh > maxviolate) + { + maxviolate = newedgemaxh / minh; + // cout << "max minhviolate = " << maxviolate << endl; + } + + + if (newedgemaxh > violateminh * minh) + { + found = 0; + loclines.SetSize (oldnl); + locpoints.SetSize (oldnp); + + if ( debugflag || debugparam.haltnosuccess ) + PrintSysError ("meshing2, maxh too large"); + + + } + } + + + + /* + // test good ComputeLineGeoInfo + if (found) + { + // is line on chart ? + for (i = oldnl+1; i <= loclines.Size(); i++) + { + int gisize; + void *geominfo; + + if (ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()), + locpoints.Get(loclines.Get(i).I2()), + gisize, geominfo)) + found = 0; + } + } + */ + + + // changed for OCC meshing + if (found) + { + // take geominfo from dellines + // upgeominfo.SetSize(locpoints.Size()); + + /* + for (i = 1; i <= dellines.Size(); i++) + for (j = 1; j <= 2; j++) + { + upgeominfo.Elem(loclines.Get(dellines.Get(i)).I(j)) = + adfront -> GetLineGeomInfo (lindex.Get(dellines.Get(i)), j); + } + */ + + + for (int i = 1; i <= locelements.Size(); i++) + for (int j = 1; j <= locelements.Get(i).GetNP(); j++) + { + int pi = locelements.Get(i).PNum(j); + if (pi <= oldnp) + { + + if (ChooseChartPointGeomInfo (mpgeominfo.Get(pi), upgeominfo.Elem(pi))) + { + // cannot select, compute new one + PrintWarning ("calc point geominfo instead of using"); + if (ComputePointGeomInfo (locpoints.Get(pi), upgeominfo.Elem(pi))) + { + found = 0; + PrintSysError ("meshing2d, geominfo failed"); + } + } + } + } + + /* + // use upgeominfo from ProjectFromPlane + for (i = oldnp+1; i <= locpoints.Size(); i++) + { + if (ComputePointGeomInfo (locpoints.Get(i), upgeominfo.Elem(i))) + { + found = 0; + if ( debugflag || debugparam.haltnosuccess ) + PrintSysError ("meshing2d, compute geominfo failed"); + } + } + */ + } + + + if (found && mparam.checkoverlap) + { + // cout << "checkoverlap" << endl; + // test for overlaps + + Point3d hullmin(1e10, 1e10, 1e10); + Point3d hullmax(-1e10, -1e10, -1e10); + + for (int i = 1; i <= locelements.Size(); i++) + for (int j = 1; j <= locelements.Get(i).GetNP(); j++) + { + const Point3d & p = locpoints.Get(locelements.Get(i).PNum(j)); + hullmin.SetToMin (p); + hullmax.SetToMax (p); + } + hullmin += Vec3d (-his, -his, -his); + hullmax += Vec3d ( his, his, his); + + surfeltree.GetIntersecting (hullmin, hullmax, intersecttrias); + + critpoints.SetSize (0); + for (int i = oldnp+1; i <= locpoints.Size(); i++) + critpoints.Append (locpoints.Get(i)); + + for (int i = 1; i <= locelements.Size(); i++) + { + const Element2d & tri = locelements.Get(i); + if (tri.GetNP() == 3) + { + const Point3d & tp1 = locpoints.Get(tri.PNum(1)); + const Point3d & tp2 = locpoints.Get(tri.PNum(2)); + const Point3d & tp3 = locpoints.Get(tri.PNum(3)); + + Vec3d tv1 (tp1, tp2); + Vec3d tv2 (tp1, tp3); + + double lam1, lam2; + for (lam1 = 0.2; lam1 <= 0.8; lam1 += 0.2) + for (lam2 = 0.2; lam2 + lam1 <= 0.8; lam2 += 0.2) + { + Point3d hp = tp1 + lam1 * tv1 + lam2 * tv2; + critpoints.Append (hp); + } + } + else if (tri.GetNP() == 4) + { + const Point3d & tp1 = locpoints.Get(tri.PNum(1)); + const Point3d & tp2 = locpoints.Get(tri.PNum(2)); + const Point3d & tp3 = locpoints.Get(tri.PNum(3)); + const Point3d & tp4 = locpoints.Get(tri.PNum(4)); + + double l1, l2; + for (l1 = 0.1; l1 <= 0.9; l1 += 0.1) + for (l2 = 0.1; l2 <= 0.9; l2 += 0.1) + { + Point3d hp; + hp.X() = + (1-l1)*(1-l2) * tp1.X() + + l1*(1-l2) * tp2.X() + + l1*l2 * tp3.X() + + (1-l1)*l2 * tp4.X(); + hp.Y() = + (1-l1)*(1-l2) * tp1.Y() + + l1*(1-l2) * tp2.Y() + + l1*l2 * tp3.Y() + + (1-l1)*l2 * tp4.Y(); + hp.Z() = + (1-l1)*(1-l2) * tp1.Z() + + l1*(1-l2) * tp2.Z() + + l1*l2 * tp3.Z() + + (1-l1)*l2 * tp4.Z(); + + + critpoints.Append (hp); + } + } + } + /* + for (i = oldnl+1; i <= loclines.Size(); i++) + { + Point3d hp = locpoints.Get(loclines.Get(i).I1()); + Vec3d hv(hp, locpoints.Get(loclines.Get(i).I2())); + int ncp = 2; + for (j = 1; j <= ncp; j++) + critpoints.Append ( hp + (double(j)/(ncp+1)) * hv); + } + */ + + + /* + for (i = oldnp+1; i <= locpoints.Size(); i++) + { + const Point3d & p = locpoints.Get(i); + */ + + + for (int i = 1; i <= critpoints.Size(); i++) + { + const Point3d & p = critpoints.Get(i); + + + /* + for (j = 1; j <= mesh.GetNSE(); j++) + { + */ + int jj; + for (jj = 1; jj <= intersecttrias.Size(); jj++) + { + int j = intersecttrias.Get(jj); + const Element2d & el = mesh.SurfaceElement(j); + + int ntrig = (el.GetNP() == 3) ? 1 : 2; + + int jl; + for (jl = 1; jl <= ntrig; jl++) + { + Point3d tp1, tp2, tp3; + + if (jl == 1) + { + tp1 = mesh.Point(el.PNum(1)); + tp2 = mesh.Point(el.PNum(2)); + tp3 = mesh.Point(el.PNum(3)); + } + else + { + tp1 = mesh.Point(el.PNum(1)); + tp2 = mesh.Point(el.PNum(3)); + tp3 = mesh.Point(el.PNum(4)); + } + + int onchart = 0; + for (int k = 1; k <= el.GetNP(); k++) + if (BelongsToActiveChart (mesh.Point(el.PNum(k)), + el.GeomInfoPi(k))) + onchart = 1; + if (!onchart) + continue; + + Vec3d e1(tp1, tp2); + Vec3d e2(tp1, tp3); + Vec3d n = Cross (e1, e2); + n /= n.Length(); + double lam1, lam2, lam3; + lam3 = n * Vec3d (tp1, p); + LocalCoordinates (e1, e2, Vec3d (tp1, p), lam1, lam2); + + if (fabs (lam3) < 0.1 * hshould && + lam1 > 0 && lam2 > 0 && (lam1 + lam2) < 1) + { +#ifdef DEVELOP + cout << "overlap" << endl; + (*testout) << "overlap:" << endl + << "tri = " << tp1 << "-" << tp2 << "-" << tp3 << endl + << "point = " << p << endl + << "lam1, 2 = " << lam1 << ", " << lam2 << endl + << "lam3 = " << lam3 << endl; + + // cout << "overlap !!!" << endl; +#endif + for (int k = 1; k <= 5; k++) + adfront -> IncrementClass (lindex.Get(1)); + + found = 0; + + if ( debugflag || debugparam.haltnosuccess ) + PrintWarning ("overlapping"); + + + if (debugparam.haltoverlap) + { + debugflag = 1; + } + + /* + multithread.drawing = 1; + glrender(1); + */ + } + } + } + } + } + + + if (found) + { + // check, whether new front line already exists + + for (int i = oldnl+1; i <= loclines.Size(); i++) + { + int nlgpi1 = loclines.Get(i).I1(); + int nlgpi2 = loclines.Get(i).I2(); + if (nlgpi1 <= pindex.Size() && nlgpi2 <= pindex.Size()) + { + nlgpi1 = adfront->GetGlobalIndex (pindex.Get(nlgpi1)); + nlgpi2 = adfront->GetGlobalIndex (pindex.Get(nlgpi2)); + + int exval = adfront->ExistsLine (nlgpi1, nlgpi2); + if (exval) + { + cout << "ERROR: new line exits, val = " << exval << endl; + (*testout) << "ERROR: new line exits, val = " << exval << endl; + found = 0; + + + if (debugparam.haltexistingline) + debugflag = 1; + + } + } + } + + } + + + /* + if (found) + { + // check, whether new triangles insert edges twice + for (i = 1; i <= locelements.Size(); i++) + for (j = 1; j <= 3; j++) + { + int tpi1 = locelements.Get(i).PNumMod (j); + int tpi2 = locelements.Get(i).PNumMod (j+1); + if (tpi1 <= pindex.Size() && tpi2 <= pindex.Size()) + { + tpi1 = adfront->GetGlobalIndex (pindex.Get(tpi1)); + tpi2 = adfront->GetGlobalIndex (pindex.Get(tpi2)); + + if (doubleedge.Used (INDEX_2(tpi1, tpi2))) + { + if (debugparam.haltexistingline) + debugflag = 1; + cerr << "ERROR Insert edge " + << tpi1 << " - " << tpi2 << " twice !!!" << endl; + found = 0; + } + doubleedge.Set (INDEX_2(tpi1, tpi2), 1); + } + } + } + */ + + + if (found) + { + // everything is ok, perform mesh update + + ruleused.Elem(rulenr)++; + + + pindex.SetSize(locpoints.Size()); + + for (int i = oldnp+1; i <= locpoints.Size(); i++) + { + globind = mesh.AddPoint (locpoints.Get(i)); + pindex.Elem(i) = adfront -> AddPoint (locpoints.Get(i), globind); + } + + for (int i = oldnl+1; i <= loclines.Size(); i++) + { + /* + for (j = 1; j <= locpoints.Size(); j++) + { + (*testout) << j << ": " << locpoints.Get(j) << endl; + } + */ + + /* + ComputeLineGeoInfo (locpoints.Get(loclines.Get(i).I1()), + locpoints.Get(loclines.Get(i).I2()), + gisize, geominfo); + */ + + if (pindex.Get(loclines.Get(i).I1()) == -1 || + pindex.Get(loclines.Get(i).I2()) == -1) + { + (*testout) << "pindex is 0" << endl; + } + + if (!upgeominfo.Get(loclines.Get(i).I1()).trignum || + !upgeominfo.Get(loclines.Get(i).I2()).trignum) + { + cout << "new el: illegal geominfo" << endl; + } + + adfront -> AddLine (pindex.Get(loclines.Get(i).I1()), + pindex.Get(loclines.Get(i).I2()), + upgeominfo.Get(loclines.Get(i).I1()), + upgeominfo.Get(loclines.Get(i).I2())); + } + for (int i = 1; i <= locelements.Size(); i++) + { + Element2d mtri(locelements.Get(i).GetNP()); + mtri = locelements.Get(i); + mtri.SetIndex (facenr); + + + // compute triangle geominfo: + // (*testout) << "triggeominfo: "; + for (int j = 1; j <= locelements.Get(i).GetNP(); j++) + { + mtri.GeomInfoPi(j) = upgeominfo.Get(locelements.Get(i).PNum(j)); + // (*testout) << mtri.GeomInfoPi(j).trignum << " "; + } + // (*testout) << endl; + + for (int j = 1; j <= locelements.Get(i).GetNP(); j++) + { + mtri.PNum(j) = + locelements.Elem(i).PNum(j) = + adfront -> GetGlobalIndex (pindex.Get(locelements.Get(i).PNum(j))); + } + + + + + mesh.AddSurfaceElement (mtri); + cntelem++; + // cout << "elements: " << cntelem << endl; + + + + Box<3> box; + box.Set (mesh[mtri[0]]); + box.Add (mesh[mtri[1]]); + box.Add (mesh[mtri[2]]); + surfeltree.Insert (box, mesh.GetNSE()); + + const Point3d & sep1 = mesh.Point (mtri.PNum(1)); + const Point3d & sep2 = mesh.Point (mtri.PNum(2)); + const Point3d & sep3 = mesh.Point (mtri.PNum(3)); + + double trigarea = Cross (Vec3d (sep1, sep2), + Vec3d (sep1, sep3)).Length() / 2; + + if (mtri.GetNP() == 4) + { + const Point3d & sep4 = mesh.Point (mtri.PNum(4)); + trigarea += Cross (Vec3d (sep1, sep3), + Vec3d (sep1, sep4)).Length() / 2; + } + + meshedarea += trigarea; + + if(maxarea > 0 && meshedarea-meshedarea_before > maxarea) + { + cerr << "meshed area = " << meshedarea-meshedarea_before << endl + << "maximal area = " << maxarea << endl + << "GIVING UP" << endl; + return MESHING2_GIVEUP; + } + + + + for (int j = 1; j <= locelements.Get(i).GetNP(); j++) + { + int gpi = locelements.Get(i).PNum(j); + + int oldts = trigsonnode.Size(); + if (gpi >= oldts+PointIndex::BASE) + { + trigsonnode.SetSize (gpi+1-PointIndex::BASE); + illegalpoint.SetSize (gpi+1-PointIndex::BASE); + for (int k = oldts+PointIndex::BASE; + k <= gpi; k++) + { + trigsonnode[k] = 0; + illegalpoint[k] = 0; + } + } + + trigsonnode[gpi]++; + + if (trigsonnode[gpi] > 20) + { + illegalpoint[gpi] = 1; + // cout << "illegal point: " << gpi << endl; + (*testout) << "illegal point: " << gpi << endl; + } + + static int mtonnode = 0; + if (trigsonnode[gpi] > mtonnode) + mtonnode = trigsonnode[gpi]; + } + // cout << "els = " << cntelem << " trials = " << trials << endl; + // if (trials > 100) return; + } + + for (int i = 1; i <= dellines.Size(); i++) + adfront -> DeleteLine (lindex.Get(dellines.Get(i))); + + // rname = rules.Get(rulenr)->Name(); +#ifdef MYGRAPH + if (silentflag<3) + { + plotsurf.DrawPnL(locpoints, loclines); + plotsurf.Plot(testmode, testmode); + } +#endif + + if (morerisc) + { + cout << "generated due to morerisc" << endl; + // multithread.drawing = 1; + // glrender(1); + } + + + + + if ( debugparam.haltsuccess || debugflag ) + { + // adfront -> PrintOpenSegments (*testout); + cout << "success of rule" << rules.Get(rulenr)->Name() << endl; + multithread.drawing = 1; + multithread.testmode = 1; + multithread.pause = 1; + + + /* + extern STLGeometry * stlgeometry; + stlgeometry->ClearMarkedSegs(); + for (i = 1; i <= loclines.Size(); i++) + { + stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()), + locpoints.Get(loclines.Get(i).I2())); + } + */ + + (*testout) << "success of rule" << rules.Get(rulenr)->Name() << endl; + (*testout) << "trials = " << trials << endl; + + (*testout) << "locpoints " << endl; + for (int i = 1; i <= pindex.Size(); i++) + (*testout) << adfront->GetGlobalIndex (pindex.Get(i)) << endl; + + (*testout) << "old number of lines = " << oldnl << endl; + for (int i = 1; i <= loclines.Size(); i++) + { + (*testout) << "line "; + for (int j = 1; j <= 2; j++) + { + int hi = 0; + if (loclines.Get(i).I(j) >= 1 && + loclines.Get(i).I(j) <= pindex.Size()) + hi = adfront->GetGlobalIndex (pindex.Get(loclines.Get(i).I(j))); + + (*testout) << hi << " "; + } + (*testout) << " : " + << plainpoints.Get(loclines.Get(i).I1()) << " - " + << plainpoints.Get(loclines.Get(i).I2()) << " 3d: " + << locpoints.Get(loclines.Get(i).I1()) << " - " + << locpoints.Get(loclines.Get(i).I2()) + << endl; + } + + + + glrender(1); + } + } + else + { + adfront -> IncrementClass (lindex.Get(1)); + + if ( debugparam.haltnosuccess || debugflag ) + { + cout << "Problem with seg " << gpi1 << " - " << gpi2 + << ", class = " << qualclass << endl; + + (*testout) << "Problem with seg " << gpi1 << " - " << gpi2 + << ", class = " << qualclass << endl; + + multithread.drawing = 1; + multithread.testmode = 1; + multithread.pause = 1; + + + /* + extern STLGeometry * stlgeometry; + stlgeometry->ClearMarkedSegs(); + for (i = 1; i <= loclines.Size(); i++) + { + stlgeometry->AddMarkedSeg(locpoints.Get(loclines.Get(i).I1()), + locpoints.Get(loclines.Get(i).I2())); + } + */ + + for (int i = 1; i <= loclines.Size(); i++) + { + (*testout) << "line "; + for (int j = 1; j <= 2; j++) + { + int hi = 0; + if (loclines.Get(i).I(j) >= 1 && + loclines.Get(i).I(j) <= pindex.Size()) + hi = adfront->GetGlobalIndex (pindex.Get(loclines.Get(i).I(j))); + + (*testout) << hi << " "; + } + (*testout) << " : " + << plainpoints.Get(loclines.Get(i).I1()) << " - " + << plainpoints.Get(loclines.Get(i).I2()) << " 3d: " + << locpoints.Get(loclines.Get(i).I1()) << " - " + << locpoints.Get(loclines.Get(i).I2()) + << endl; + } + + + /* + cout << "p1gi = " << blgeominfo[0].trignum + << ", p2gi = " << blgeominfo[1].trignum << endl; + */ + + glrender(1); + } + + +#ifdef MYGRAPH + if (silentflag<3) + { + if (testmode || trials%2 == 0) + { + plotsurf.DrawPnL(locpoints, loclines); + plotsurf.Plot(testmode, testmode); + } + } +#endif + } + + } + + PrintMessage (3, "Surface meshing done"); + + adfront->PrintOpenSegments (*testout); + + multithread.task = savetask; + + + // cout << "surfeltree.depth = " << surfeltree.Tree().Depth() << endl; + EndMesh (); + + if (!adfront->Empty()) + return MESHING2_GIVEUP; + + return MESHING2_OK; + } + + + + + + + + + +} + + + + + + + +#ifdef OPENGL + +/* *********************** Draw Surface Meshing **************** */ + + +#include <visual.hpp> +#include <stlgeom.hpp> + +namespace netgen +{ + + extern STLGeometry * stlgeometry; + extern Mesh * mesh; + VisualSceneSurfaceMeshing vssurfacemeshing; + + + + void glrender (int wait) + { + // cout << "plot adfront" << endl; + + if (multithread.drawing) + { + // vssurfacemeshing.Render(); + Render (); + + if (wait || multithread.testmode) + { + multithread.pause = 1; + } + while (multithread.pause); + } + } + + + + VisualSceneSurfaceMeshing :: VisualSceneSurfaceMeshing () + : VisualScene() + { + ; + } + + VisualSceneSurfaceMeshing :: ~VisualSceneSurfaceMeshing () + { + ; + } + + void VisualSceneSurfaceMeshing :: DrawScene () + { + int i, j, k; + + if (loclines.Size() != changeval) + { + center = Point<3>(0,0,-5); + rad = 0.1; + + CalcTransformationMatrices(); + changeval = loclines.Size(); + } + + glClearColor(backcolor, backcolor, backcolor, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + SetLight(); + + // glEnable (GL_COLOR_MATERIAL); + + // glDisable (GL_SHADING); + // glColor3f (0.0f, 1.0f, 1.0f); + // glLineWidth (1.0f); + // glShadeModel (GL_SMOOTH); + + // glCallList (linelists.Get(1)); + + // SetLight(); + + glPushMatrix(); + glMultMatrixf (transformationmat); + + glShadeModel (GL_SMOOTH); + // glDisable (GL_COLOR_MATERIAL); + glEnable (GL_COLOR_MATERIAL); + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // glEnable (GL_LIGHTING); + + double shine = vispar.shininess; + double transp = vispar.transp; + + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); + glLogicOp (GL_COPY); + + + + /* + + float mat_col[] = { 0.2, 0.2, 0.8, 1 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); + + glPolygonOffset (1, 1); + glEnable (GL_POLYGON_OFFSET_FILL); + + float mat_colbl[] = { 0.8, 0.2, 0.2, 1 }; + float mat_cololdl[] = { 0.2, 0.8, 0.2, 1 }; + float mat_colnewl[] = { 0.8, 0.8, 0.2, 1 }; + + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glPolygonOffset (1, -1); + glLineWidth (3); + + for (i = 1; i <= loclines.Size(); i++) + { + if (i == 1) + { + glEnable (GL_POLYGON_OFFSET_FILL); + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbl); + } + else if (i <= oldnl) + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_cololdl); + else + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colnewl); + + int pi1 = loclines.Get(i).I1(); + int pi2 = loclines.Get(i).I2(); + + if (pi1 >= 1 && pi2 >= 1) + { + Point3d p1 = locpoints.Get(pi1); + Point3d p2 = locpoints.Get(pi2); + + glBegin (GL_LINES); + glVertex3f (p1.X(), p1.Y(), p1.Z()); + glVertex3f (p2.X(), p2.Y(), p2.Z()); + glEnd(); + } + + glDisable (GL_POLYGON_OFFSET_FILL); + } + + + glLineWidth (1); + + + glPointSize (5); + float mat_colp[] = { 1, 0, 0, 1 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); + glBegin (GL_POINTS); + for (i = 1; i <= locpoints.Size(); i++) + { + Point3d p = locpoints.Get(i); + glVertex3f (p.X(), p.Y(), p.Z()); + } + glEnd(); + + + glPopMatrix(); + */ + + float mat_colp[] = { 1, 0, 0, 1 }; + + float mat_col2d1[] = { 1, 0.5, 0.5, 1 }; + float mat_col2d[] = { 1, 1, 1, 1 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); + + double scalex = 0.1, scaley = 0.1; + + glBegin (GL_LINES); + for (i = 1; i <= loclines.Size(); i++) + { + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); + if (i == 1) + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d1); + + int pi1 = loclines.Get(i).I1(); + int pi2 = loclines.Get(i).I2(); + + if (pi1 >= 1 && pi2 >= 1) + { + Point2d p1 = plainpoints.Get(pi1); + Point2d p2 = plainpoints.Get(pi2); + + glBegin (GL_LINES); + glVertex3f (scalex * p1.X(), scaley * p1.Y(), -5); + glVertex3f (scalex * p2.X(), scaley * p2.Y(), -5); + glEnd(); + } + } + glEnd (); + + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); + glBegin (GL_POINTS); + for (i = 1; i <= plainpoints.Size(); i++) + { + Point2d p = plainpoints.Get(i); + glVertex3f (scalex * p.X(), scaley * p.Y(), -5); + } + glEnd(); + + + + + + + glDisable (GL_POLYGON_OFFSET_FILL); + + glPopMatrix(); + DrawCoordinateCross (); + DrawNetgenLogo (); + glFinish(); + + /* + glDisable (GL_POLYGON_OFFSET_FILL); + + // cout << "draw surfacemeshing" << endl; + // + // if (changeval != stlgeometry->GetNT()) + // BuildScene(); + // changeval = stlgeometry->GetNT(); + + + glClearColor(backcolor, backcolor, backcolor, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SetLight(); + + glPushMatrix(); + glLoadMatrixf (transmat); + glMultMatrixf (rotmat); + + glShadeModel (GL_SMOOTH); + glDisable (GL_COLOR_MATERIAL); + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + float mat_spec_col[] = { 1, 1, 1, 1 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, mat_spec_col); + + double shine = vispar.shininess; + double transp = vispar.transp; + + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shine); + glLogicOp (GL_COPY); + + + float mat_col[] = { 0.2, 0.2, 0.8, transp }; + float mat_colrt[] = { 0.2, 0.8, 0.8, transp }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); + + glPolygonOffset (1, 1); + glEnable (GL_POLYGON_OFFSET_FILL); + + glColor3f (1.0f, 1.0f, 1.0f); + + glEnable (GL_NORMALIZE); + + // glBegin (GL_TRIANGLES); + // for (j = 1; j <= stlgeometry -> GetNT(); j++) + // { + // glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col); + // if (j == geomtrig) + // glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colrt); + + + // const STLReadTriangle & tria = stlgeometry -> GetReadTriangle(j); + // glNormal3f (tria.normal.X(), + // tria.normal.Y(), + // tria.normal.Z()); + + // for (k = 0; k < 3; k++) + // { + // glVertex3f (tria.pts[k].X(), + // tria.pts[k].Y(), + // tria.pts[k].Z()); + // } + // } + // glEnd (); + + + + glDisable (GL_POLYGON_OFFSET_FILL); + + float mat_colbl[] = { 0.8, 0.2, 0.2, 1 }; + float mat_cololdl[] = { 0.2, 0.8, 0.2, 1 }; + float mat_colnewl[] = { 0.8, 0.8, 0.2, 1 }; + + + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glPolygonOffset (1, -1); + glLineWidth (3); + + for (i = 1; i <= loclines.Size(); i++) + { + if (i == 1) + { + glEnable (GL_POLYGON_OFFSET_FILL); + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colbl); + } + else if (i <= oldnl) + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_cololdl); + else + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colnewl); + + int pi1 = loclines.Get(i).I1(); + int pi2 = loclines.Get(i).I2(); + + if (pi1 >= 1 && pi2 >= 1) + { + Point3d p1 = locpoints.Get(pi1); + Point3d p2 = locpoints.Get(pi2); + + glBegin (GL_LINES); + glVertex3f (p1.X(), p1.Y(), p1.Z()); + glVertex3f (p2.X(), p2.Y(), p2.Z()); + glEnd(); + } + + glDisable (GL_POLYGON_OFFSET_FILL); + } + + + glLineWidth (1); + + + glPointSize (5); + float mat_colp[] = { 1, 0, 0, 1 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); + glBegin (GL_POINTS); + for (i = 1; i <= locpoints.Size(); i++) + { + Point3d p = locpoints.Get(i); + glVertex3f (p.X(), p.Y(), p.Z()); + } + glEnd(); + + + glPopMatrix(); + + + float mat_col2d1[] = { 1, 0.5, 0.5, 1 }; + float mat_col2d[] = { 1, 1, 1, 1 }; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); + + double scalex = 0.1, scaley = 0.1; + + glBegin (GL_LINES); + for (i = 1; i <= loclines.Size(); i++) + { + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d); + if (i == 1) + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_col2d1); + + int pi1 = loclines.Get(i).I1(); + int pi2 = loclines.Get(i).I2(); + + if (pi1 >= 1 && pi2 >= 1) + { + Point2d p1 = plainpoints.Get(pi1); + Point2d p2 = plainpoints.Get(pi2); + + glBegin (GL_LINES); + glVertex3f (scalex * p1.X(), scaley * p1.Y(), -5); + glVertex3f (scalex * p2.X(), scaley * p2.Y(), -5); + glEnd(); + } + } + glEnd (); + + + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_colp); + glBegin (GL_POINTS); + for (i = 1; i <= plainpoints.Size(); i++) + { + Point2d p = plainpoints.Get(i); + glVertex3f (scalex * p.X(), scaley * p.Y(), -5); + } + glEnd(); + + glFinish(); +*/ + } + + + void VisualSceneSurfaceMeshing :: BuildScene (int zoomall) + { + int i, j, k; + /* + center = stlgeometry -> GetBoundingBox().Center(); + rad = stlgeometry -> GetBoundingBox().Diam() / 2; + + CalcTransformationMatrices(); + */ + } + +} + + +#else +namespace netgen +{ + void glrender (int wait) + { ; } +} +#endif diff --git a/contrib/Netgen/libsrc/meshing/meshing2.hpp b/contrib/Netgen/libsrc/meshing/meshing2.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0912fa34c66325e01aa317be08d89a3b3a64c504 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing2.hpp @@ -0,0 +1,156 @@ +#ifndef FILE_MESHING2 +#define FILE_MESHING2 + +/**************************************************************************/ +/* File: meshing2.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + + + +enum MESHING2_RESULT +{ + MESHING2_OK = 0, + MESHING2_GIVEUP = 1, +}; + + +/* + +The basis class for 2D mesh generation. +Has the method GenerateMesh + +For surface mesh generation, or non-Euklidean meshing, +derive from Meshing2, and replace transformation. + +*/ + +class Meshing2 +{ + /// the current advancing front + AdFront2 * adfront; + /// rules for mesh generation + ARRAY<netrule*> rules; + /// statistics + ARRAY<int> ruleused, canuse, foundmap; + /// + Box<3> boundingbox; + /// + double starttime; + /// + double maxarea; + +public: + /// + Meshing2 (const Box<3> & aboundingbox); + + /// + virtual ~Meshing2 (); + + /// Load rules, either from file, or compiled rules + void LoadRules (const char * filename); + + /// + MESHING2_RESULT GenerateMesh (Mesh & mesh, double gh, int facenr); + + /// + void AddPoint (const Point3d & p, PointIndex globind, MultiPointGeomInfo * mgi = NULL, + bool pointonsurface = true); + + /// + void AddBoundaryElement (INDEX i1, INDEX i2, + const PointGeomInfo & gi1, const PointGeomInfo & gi2); + + /// + void SetStartTime (double astarttime); + + /// + void SetMaxArea (double amaxarea); + +protected: + /// + virtual void StartMesh (); + /// + virtual void EndMesh (); + /// + virtual double CalcLocalH (const Point3d & p, double gh) const; + + /// + virtual void DefineTransformation (const Point3d & p1, const Point3d & p2, + const PointGeomInfo * geominfo1, + const PointGeomInfo * geominfo2); + /// + virtual void TransformToPlain (const Point3d & locpoint, const MultiPointGeomInfo & geominfo, + Point2d & plainpoint, double h, int & zone); + /// return 0 .. ok + /// return >0 .. cannot transform point to true surface + virtual int TransformFromPlain (Point2d & plainpoint, + Point3d & locpoint, + PointGeomInfo & geominfo, + double h); + + /// projects to surface + /// return 0 .. ok + virtual int BelongsToActiveChart (const Point3d & p, + const PointGeomInfo & gi); + + /// computes geoinfo data for line with respect to + /// selected chart + virtual int ComputePointGeomInfo (const Point3d & p, + PointGeomInfo & gi); + + /// Tries to select unique geominfo on active chart + /// return 0: success + /// return 1: failed + virtual int ChooseChartPointGeomInfo (const MultiPointGeomInfo & mpgi, + PointGeomInfo & pgi); + + + + /* + tests, whether endpoint (= 1 or 2) of line segment p1-p2 + is inside of the selected chart. The endpoint must be on the + chart + */ + virtual int IsLineVertexOnChart (const Point3d & p1, const Point3d & p2, + int endpoint, const PointGeomInfo & geominfo); + + /* + get (projected) boundary of current chart + */ + virtual void GetChartBoundary (ARRAY<Point2d> & points, + ARRAY<Point3d> & points3d, + ARRAY<INDEX_2> & lines, double p) const; + + virtual double Area () const; + + +/** Applies 2D rules. + Tests all 2D rules */ + int ApplyRules (ARRAY<Point2d> & lpoints, + ARRAY<int> & legalpoints, + int maxlegalpoint, + ARRAY<INDEX_2> & llines, + int maxlegelline, + ARRAY<Element2d> & elements, ARRAY<INDEX> & dellines, + int tolerance); + + +}; + + + + + + + + +#endif + + + + + + + diff --git a/contrib/Netgen/libsrc/meshing/meshing3.cpp b/contrib/Netgen/libsrc/meshing/meshing3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..075fd6b384b97db7ff7ff8cf1cfaec5f4933bdd5 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing3.cpp @@ -0,0 +1,1292 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + +double minother; +double minwithoutother; + + + + + +MeshingStat3d :: MeshingStat3d () +{ + cntsucc = cnttrials = cntelem = qualclass = 0; + vol0 = h = 1; + problemindex = 1; +} + + +Meshing3 :: Meshing3 (const string & rulefilename) +{ + tolfak = 1; + + LoadRules (rulefilename.c_str(), NULL); + adfront = new AdFront3; + + problems.SetSize (rules.Size()); + foundmap.SetSize (rules.Size()); + canuse.SetSize (rules.Size()); + ruleused.SetSize (rules.Size()); + + for (int i = 1; i <= rules.Size(); i++) + { + problems.Elem(i) = new char[255]; + foundmap.Elem(i) = 0; + canuse.Elem(i) = 0; + ruleused.Elem(i) = 0; + } +} + + +Meshing3 :: Meshing3 (const char ** rulep) +{ + tolfak = 1; + + LoadRules (NULL, rulep); + adfront = new AdFront3; + + problems.SetSize (rules.Size()); + foundmap.SetSize (rules.Size()); + canuse.SetSize (rules.Size()); + ruleused.SetSize (rules.Size()); + + for (int i = 0; i < rules.Size(); i++) + { + problems[i] = new char[255]; + foundmap[i] = 0; + canuse[i] = 0; + ruleused[i] = 0; + } +} + +Meshing3 :: ~Meshing3 () +{ + delete adfront; + for (int i = 0; i < rules.Size(); i++) + { + delete [] problems[i]; + delete rules[i]; + } +} + + + +static double CalcLocH (const ARRAY<Point3d> & locpoints, + const ARRAY<MiniElement2d> & locfaces, + double h) +{ + return h; + + // was war das ???? + + int i, j; + double hi, h1, d, dn, sum, weight, wi; + Point3d p0, pc; + Vec3d n, v1, v2; + + p0.X() = p0.Y() = p0.Z() = 0; + for (j = 1; j <= 3; j++) + { + p0.X() += locpoints.Get(locfaces.Get(1).PNum(j)).X(); + p0.Y() += locpoints.Get(locfaces.Get(1).PNum(j)).Y(); + p0.Z() += locpoints.Get(locfaces.Get(1).PNum(j)).Z(); + } + p0.X() /= 3; p0.Y() /= 3; p0.Z() /= 3; + + v1 = locpoints.Get(locfaces.Get(1).PNum(2)) - + locpoints.Get(locfaces.Get(1).PNum(1)); + v2 = locpoints.Get(locfaces.Get(1).PNum(3)) - + locpoints.Get(locfaces.Get(1).PNum(1)); + + h1 = v1.Length(); + n = Cross (v2, v1); + n /= n.Length(); + + sum = 0; + weight = 0; + + for (i = 1; i <= locfaces.Size(); i++) + { + pc.X() = pc.Y() = pc.Z() = 0; + for (j = 1; j <= 3; j++) + { + pc.X() += locpoints.Get(locfaces.Get(i).PNum(j)).X(); + pc.Y() += locpoints.Get(locfaces.Get(i).PNum(j)).Y(); + pc.Z() += locpoints.Get(locfaces.Get(i).PNum(j)).Z(); + } + pc.X() /= 3; pc.Y() /= 3; pc.Z() /= 3; + + d = Dist (p0, pc); + dn = n * (pc - p0); + hi = Dist (locpoints.Get(locfaces.Get(i).PNum(1)), + locpoints.Get(locfaces.Get(i).PNum(2))); + + if (dn > -0.2 * h1) + { + wi = 1 / (h1 + d); + wi *= wi; + } + else + wi = 0; + + sum += hi * wi; + weight += wi; + } + + return sum/weight; +} + + +PointIndex Meshing3 :: AddPoint (const Point3d & p, PointIndex globind) +{ + return adfront -> AddPoint (p, globind); +} + +void Meshing3 :: AddBoundaryElement (const Element2d & elem) +{ + MiniElement2d mini(elem.GetNP()); + for (int j = 0; j < elem.GetNP(); j++) + mini[j] = elem[j]; + adfront -> AddFace(mini); +} + + +void Meshing3 :: AddBoundaryElement (const MiniElement2d & elem) +{ + adfront -> AddFace(elem); +} + +int Meshing3 :: AddConnectedPair (const INDEX_2 & apair) +{ + return adfront -> AddConnectedPair (apair); +} + +MESHING3_RESULT Meshing3 :: +GenerateMesh (Mesh & mesh, const MeshingParameters & mp) +{ + static int meshing3_timer = NgProfiler::CreateTimer ("Meshing3::GenerateMesh"); + static int meshing3_timer_a = NgProfiler::CreateTimer ("Meshing3::GenerateMesh a"); + static int meshing3_timer_b = NgProfiler::CreateTimer ("Meshing3::GenerateMesh b"); + static int meshing3_timer_c = NgProfiler::CreateTimer ("Meshing3::GenerateMesh c"); + static int meshing3_timer_d = NgProfiler::CreateTimer ("Meshing3::GenerateMesh d"); + NgProfiler::RegionTimer reg (meshing3_timer); + + + ARRAY<Point3d > locpoints; // local points + ARRAY<MiniElement2d> locfaces; // local faces + ARRAY<PointIndex> pindex; // mapping from local to front point numbering + ARRAY<int> allowpoint; // point is allowd ? + ARRAY<INDEX> findex; // mapping from local to front face numbering + //INDEX_2_HASHTABLE<int> connectedpairs(100); // connecgted pairs for prism meshing + + ARRAY<Point3d > plainpoints; // points in reference coordinates + ARRAY<int> delpoints, delfaces; // points and lines to be deleted + ARRAY<Element> locelements; // new generated elements + + int i, j, oldnp, oldnf; + int found; + referencetransform trans; + int rotind; + INDEX globind; + Point3d inp; + float err; + + INDEX locfacesplit; //index for faces in outer area + + bool loktestmode = false; + + int uselocalh = mp.uselocalh; + + // int giveuptol = mp.giveuptol; // + MeshingStat3d stat; // statistics + int plotstat_oldne = -1; + + + // for star-shaped domain meshing + ARRAY<MeshPoint> grouppoints; + ARRAY<MiniElement2d> groupfaces; + ARRAY<PointIndex> grouppindex; + ARRAY<INDEX> groupfindex; + + + float minerr; + int hasfound; + double tetvol; + // int giveup = 0; + + + ARRAY<Point3d> tempnewpoints; + ARRAY<MiniElement2d> tempnewfaces; + ARRAY<int> tempdelfaces; + ARRAY<Element> templocelements; + + + stat.h = mp.maxh; + + adfront->SetStartFront (mp.baseelnp); + + + found = 0; + stat.vol0 = adfront -> Volume(); + tetvol = 0; + + stat.qualclass = 1; + + while (1) + { + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + // break if advancing front is empty + if (!mp.baseelnp && adfront->Empty()) + break; + + // break, if advancing front has no elements with + // mp.baseelnp nodes + if (mp.baseelnp && adfront->Empty (mp.baseelnp)) + break; + + locpoints.SetSize(0); + locfaces.SetSize(0); + locelements.SetSize(0); + pindex.SetSize(0); + findex.SetSize(0); + + INDEX_2_HASHTABLE<int> connectedpairs(100); // connected pairs for prism meshing + + // select base-element (will be locface[1]) + // and get local environment of radius (safety * h) + + + int baseelem = adfront -> SelectBaseElement (); + if (mp.baseelnp && adfront->GetFace (baseelem).GetNP() != mp.baseelnp) + { + adfront->IncrementClass (baseelem); + continue; + } + + const MiniElement2d & bel = adfront->GetFace (baseelem); + const Point3d & p1 = adfront->GetPoint (bel.PNum(1)); + const Point3d & p2 = adfront->GetPoint (bel.PNum(2)); + const Point3d & p3 = adfront->GetPoint (bel.PNum(3)); + + // (*testout) << endl << "base = " << bel << endl; + + + Point3d pmid = Center (p1, p2, p3); + + double his = (Dist (p1, p2) + Dist(p1, p3) + Dist(p2, p3)) / 3; + double hshould; + + hshould = mesh.GetH (pmid); + + if (adfront->GetFace (baseelem).GetNP() == 4) + hshould = max2 (his, hshould); + + double hmax = (his > hshould) ? his : hshould; + + // qualclass should come from baseelem !!!!! + double hinner = hmax * (1 + stat.qualclass); + double houter = hmax * (1 + 2 * stat.qualclass); + + NgProfiler::StartTimer (meshing3_timer_a); + stat.qualclass = + adfront -> GetLocals (baseelem, locpoints, locfaces, + pindex, findex, connectedpairs, + houter, hinner, + locfacesplit); + NgProfiler::StopTimer (meshing3_timer_a); + + // (*testout) << "locfaces = " << endl << locfaces << endl; + + int pi1 = pindex.Get(locfaces[0].PNum(1)); + int pi2 = pindex.Get(locfaces[0].PNum(2)); + int pi3 = pindex.Get(locfaces[0].PNum(3)); + + //loktestmode = 1; + testmode = loktestmode; //changed + // loktestmode = testmode = (adfront->GetFace (baseelem).GetNP() == 4) && (rules.Size() == 5); + + loktestmode = stat.qualclass > 5; + + + if (loktestmode) + { + (*testout) << "baseel = " << baseelem << ", ind = " << findex.Get(1) << endl; + (*testout) << "pi = " << pi1 << ", " << pi2 << ", " << pi3 << endl; + } + + + + + + if (testmode) + { + (*testout) << "baseelem = " << baseelem << " qualclass = " << stat.qualclass << endl; + (*testout) << "locpoints = " << endl << locpoints << endl; + (*testout) << "connected = " << endl << connectedpairs << endl; + } + + + + // loch = CalcLocH (locpoints, locfaces, h); + + stat.nff = adfront->GetNF(); + stat.vol = adfront->Volume(); + if (stat.vol < 0) break; + + oldnp = locpoints.Size(); + oldnf = locfaces.Size(); + + + allowpoint.SetSize(locpoints.Size()); + if (uselocalh && stat.qualclass <= 3) + for (i = 1; i <= allowpoint.Size(); i++) + { + allowpoint.Elem(i) = + (mesh.GetH (locpoints.Get(i)) > 0.4 * hshould / mp.sloppy) ? 2 : 1; + } + else + allowpoint = 2; + + + + if (stat.qualclass >= mp.starshapeclass && + mp.baseelnp != 4) + { + NgProfiler::RegionTimer reg1 (meshing3_timer_b); + // star-shaped domain removing + + grouppoints.SetSize (0); + groupfaces.SetSize (0); + grouppindex.SetSize (0); + groupfindex.SetSize (0); + + adfront -> GetGroup (findex[0], grouppoints, groupfaces, + grouppindex, groupfindex); + + bool onlytri = 1; + for (i = 0; i < groupfaces.Size(); i++) + if (groupfaces[i].GetNP() != 3) + onlytri = 0; + + if (onlytri && groupfaces.Size() <= 20 + 2*stat.qualclass && + FindInnerPoint (grouppoints, groupfaces, inp)) + { + (*testout) << "inner point found" << endl; + + for (i = 1; i <= groupfaces.Size(); i++) + adfront -> DeleteFace (groupfindex.Get(i)); + + for (i = 1; i <= groupfaces.Size(); i++) + for (j = 1; j <= locfaces.Size(); j++) + if (findex.Get(j) == groupfindex.Get(i)) + delfaces.Append (j); + + + delfaces.SetSize (0); + + INDEX npi; + Element newel; + + npi = mesh.AddPoint (inp); + newel.SetNP(4); + newel.PNum(4) = npi; + + for (i = 1; i <= groupfaces.Size(); i++) + { + for (j = 1; j <= 3; j++) + { + newel.PNum(j) = + adfront->GetGlobalIndex + (grouppindex.Get(groupfaces.Get(i).PNum(j))); + } + mesh.AddVolumeElement (newel); + } + continue; + } + } + + found = 0; + hasfound = 0; + minerr = 1e6; + + // int optother = 0; + + /* + for (i = 1; i <= locfaces.Size(); i++) + { + (*testout) << "Face " << i << ": "; + for (j = 1; j <= locfaces.Get(i).GetNP(); j++) + (*testout) << pindex.Get(locfaces.Get(i).PNum(j)) << " "; + (*testout) << endl; + } + for (i = 1; i <= locpoints.Size(); i++) + { + (*testout) << "p" << i + << ", gi = " << pindex.Get(i) + << " = " << locpoints.Get(i) << endl; + } + */ + + minother = 1e10; + minwithoutother = 1e10; + + bool impossible = 1; + + for (rotind = 1; rotind <= locfaces[0].GetNP(); rotind++) + { + // set transformatino to reference coordinates + + if (locfaces.Get(1).GetNP() == 3) + { + trans.Set (locpoints.Get(locfaces.Get(1).PNumMod(1+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(2+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(3+rotind)), hshould); + } + else + { + trans.Set (locpoints.Get(locfaces.Get(1).PNumMod(1+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(2+rotind)), + locpoints.Get(locfaces.Get(1).PNumMod(4+rotind)), hshould); + } + + trans.ToPlain (locpoints, plainpoints); + + + for (i = 1; i <= allowpoint.Size(); i++) + { + if (plainpoints.Get(i).Z() > 0) + { + //if(loktestmode) + // (*testout) << "plainpoints.Get(i).Z() = " << plainpoints.Get(i).Z() << " > 0" << endl; + allowpoint.Elem(i) = 0; + } + } + + stat.cnttrials++; + + + if (stat.cnttrials % 100 == 0) + { + (*testout) << "\n"; + for (i = 1; i <= canuse.Size(); i++) + { + (*testout) << foundmap.Get(i) << "/" + << canuse.Get(i) << "/" + << ruleused.Get(i) << " map/can/use rule " << rules.Get(i)->Name() << "\n"; + } + (*testout) << endl; + } + + NgProfiler::StartTimer (meshing3_timer_c); + + found = ApplyRules (plainpoints, allowpoint, + locfaces, locfacesplit, connectedpairs, + locelements, delfaces, + stat.qualclass, mp.sloppy, rotind, err); + + if (found >= 0) impossible = 0; + if (found < 0) found = 0; + + + NgProfiler::StopTimer (meshing3_timer_c); + + if (!found) loktestmode = 0; + + NgProfiler::RegionTimer reg2 (meshing3_timer_d); + + if (loktestmode) + { + (*testout) << "plainpoints = " << endl << plainpoints << endl; + (*testout) << "Applyrules found " << found << endl; + } + + if (found) stat.cntsucc++; + + locpoints.SetSize (plainpoints.Size()); + for (i = oldnp+1; i <= plainpoints.Size(); i++) + trans.FromPlain (plainpoints.Elem(i), locpoints.Elem(i)); + + + + // avoid meshing from large to small mesh-size + if (uselocalh && found && stat.qualclass <= 3) + { + for (i = 1; i <= locelements.Size(); i++) + { + Point3d pmin = locpoints.Get(locelements.Get(i).PNum(1)); + Point3d pmax = pmin; + for (j = 2; j <= 4; j++) + { + const Point3d & hp = locpoints.Get(locelements.Get(i).PNum(j)); + pmin.SetToMin (hp); + pmax.SetToMax (hp); + } + + if (mesh.GetMinH (pmin, pmax) < 0.4 * hshould / mp.sloppy) + found = 0; + } + } + if (found) + { + for (i = 1; i <= locelements.Size(); i++) + for (j = 1; j <= 4; j++) + { + const Point3d & hp = locpoints.Get(locelements.Get(i).PNum(j)); + if (Dist (hp, pmid) > hinner) + found = 0; + } + } + + + if (found) + ruleused.Elem(found)++; + + + // plotstat->Plot(stat); + + if (stat.cntelem != plotstat_oldne) + { + plotstat_oldne = stat.cntelem; + + PrintMessageCR (5, "El: ", stat.cntelem, + // << " trials: " << stat.cnttrials + " faces: ", stat.nff, + " vol = ", float(100 * stat.vol / stat.vol0)); + + multithread.percent = 100 - 100.0 * stat.vol / stat.vol0; + } + + + if (found && (!hasfound || err < minerr) ) + { + + if (testmode) + { + (*testout) << "found is active, 3" << endl; + for (i = 1; i <= plainpoints.Size(); i++) + { + (*testout) << "p"; + if (i <= pindex.Size()) + (*testout) << pindex.Get(i) << ": "; + else + (*testout) << "new: "; + (*testout) << plainpoints.Get(i) << endl; + } + } + + + + hasfound = found; + minerr = err; + + tempnewpoints.SetSize (0); + for (i = oldnp+1; i <= locpoints.Size(); i++) + tempnewpoints.Append (locpoints.Get(i)); + + tempnewfaces.SetSize (0); + for (i = oldnf+1; i <= locfaces.Size(); i++) + tempnewfaces.Append (locfaces.Get(i)); + + tempdelfaces.SetSize (0); + for (i = 1; i <= delfaces.Size(); i++) + tempdelfaces.Append (delfaces.Get(i)); + + templocelements.SetSize (0); + for (i = 1; i <= locelements.Size(); i++) + templocelements.Append (locelements.Get(i)); + + /* + optother = + strcmp (problems[found], "other") == 0; + */ + } + + locpoints.SetSize (oldnp); + locfaces.SetSize (oldnf); + delfaces.SetSize (0); + locelements.SetSize (0); + } + + + + if (hasfound) + { + + /* + if (optother) + (*testout) << "Other is optimal" << endl; + + if (minother < minwithoutother) + { + (*testout) << "Other is better, " << minother << " less " << minwithoutother << endl; + } + */ + + for (i = 1; i <= tempnewpoints.Size(); i++) + locpoints.Append (tempnewpoints.Get(i)); + for (i = 1; i <= tempnewfaces.Size(); i++) + locfaces.Append (tempnewfaces.Get(i)); + for (i = 1; i <= tempdelfaces.Size(); i++) + delfaces.Append (tempdelfaces.Get(i)); + for (i = 1; i <= templocelements.Size(); i++) + locelements.Append (templocelements.Get(i)); + + + if (loktestmode) + { + (*testout) << "apply rule" << endl; + for (i = 1; i <= locpoints.Size(); i++) + { + (*testout) << "p"; + if (i <= pindex.Size()) + (*testout) << pindex.Get(i) << ": "; + else + (*testout) << "new: "; + (*testout) << locpoints.Get(i) << endl; + } + } + + + + pindex.SetSize(locpoints.Size()); + + for (i = oldnp+1; i <= locpoints.Size(); i++) + { + globind = mesh.AddPoint (locpoints.Get(i)); + pindex.Elem(i) = adfront -> AddPoint (locpoints.Get(i), globind); + } + + for (i = 1; i <= locelements.Size(); i++) + { + Point3d * hp1, * hp2, * hp3, * hp4; + hp1 = &locpoints.Elem(locelements.Get(i).PNum(1)); + hp2 = &locpoints.Elem(locelements.Get(i).PNum(2)); + hp3 = &locpoints.Elem(locelements.Get(i).PNum(3)); + hp4 = &locpoints.Elem(locelements.Get(i).PNum(4)); + + tetvol += (1.0 / 6.0) * ( Cross ( *hp2 - *hp1, *hp3 - *hp1) * (*hp4 - *hp1) ); + + for (j = 1; j <= locelements.Get(i).NP(); j++) + locelements.Elem(i).PNum(j) = + adfront -> GetGlobalIndex (pindex.Get(locelements.Get(i).PNum(j))); + + mesh.AddVolumeElement (locelements.Get(i)); + stat.cntelem++; + } + + for (i = oldnf+1; i <= locfaces.Size(); i++) + { + for (j = 1; j <= locfaces.Get(i).GetNP(); j++) + locfaces.Elem(i).PNum(j) = + pindex.Get(locfaces.Get(i).PNum(j)); + // (*testout) << "add face " << locfaces.Get(i) << endl; + adfront->AddFace (locfaces.Get(i)); + } + + for (i = 1; i <= delfaces.Size(); i++) + adfront->DeleteFace (findex.Get(delfaces.Get(i))); + } + else + { + adfront->IncrementClass (findex.Get(1)); + if (impossible && mp.check_impossible) + { + (*testout) << "skip face since it is impossible" << endl; + for (j = 0; j < 100; j++) + adfront->IncrementClass (findex.Get(1)); + } + } + + locelements.SetSize (0); + delpoints.SetSize(0); + delfaces.SetSize(0); + + if (stat.qualclass >= mp.giveuptol) + break; + } + + PrintMessage (5, ""); // line feed after statistics + + for (i = 1; i <= ruleused.Size(); i++) + (*testout) << setw(4) << ruleused.Get(i) + << " times used rule " << rules.Get(i) -> Name() << endl; + + + if (!mp.baseelnp && adfront->Empty()) + return MESHING3_OK; + + if (mp.baseelnp && adfront->Empty (mp.baseelnp)) + return MESHING3_OK; + + if (stat.vol < -1e-15) + return MESHING3_NEGVOL; + + return MESHING3_NEGVOL; +} + + + + +enum blocktyp { BLOCKUNDEF, BLOCKINNER, BLOCKBOUND, BLOCKOUTER }; + +void Meshing3 :: BlockFill (Mesh & mesh, double gh) +{ + PrintMessage (3, "Block-filling called (obsolete) "); + + int i, j(0), i1, i2, i3, j1, j2, j3; + int n1, n2, n3, n, min1, min2, min3, max1, max2, max3; + int changed, filled; + double xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0); + double xminb, xmaxb, yminb, ymaxb, zminb, zmaxb; + //double rad = 0.7 * gh; + + for (i = 1; i <= adfront->GetNP(); i++) + { + const Point3d & p = adfront->GetPoint(i); + if (i == 1) + { + xmin = xmax = p.X(); + ymin = ymax = p.Y(); + zmin = zmax = p.Z(); + } + else + { + if (p.X() < xmin) xmin = p.X(); + if (p.X() > xmax) xmax = p.X(); + if (p.Y() < ymin) ymin = p.Y(); + if (p.Y() > ymax) ymax = p.Y(); + if (p.Z() < zmin) zmin = p.Z(); + if (p.Z() > zmax) zmax = p.Z(); + } + } + + xmin -= 5 * gh; + ymin -= 5 * gh; + zmin -= 5 * gh; + + n1 = int ((xmax-xmin) / gh + 5); + n2 = int ((ymax-ymin) / gh + 5); + n3 = int ((zmax-zmin) / gh + 5); + n = n1 * n2 * n3; + + PrintMessage (5, "n1 = ", n1, " n2 = ", n2, " n3 = ", n3); + + ARRAY<blocktyp> inner(n); + ARRAY<int> pointnr(n), frontpointnr(n); + + + // initialize inner to 1 + + for (i = 1; i <= n; i++) + inner.Elem(i) = BLOCKUNDEF; + + + // set blocks cutting surfaces to 0 + + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & el = adfront->GetFace(i); + xminb = xmax; xmaxb = xmin; + yminb = ymax; ymaxb = ymin; + zminb = zmax; zmaxb = zmin; + + for (j = 1; j <= 3; j++) + { + const Point3d & p = adfront->GetPoint (el.PNum(j)); + if (p.X() < xminb) xminb = p.X(); + if (p.X() > xmaxb) xmaxb = p.X(); + if (p.Y() < yminb) yminb = p.Y(); + if (p.Y() > ymaxb) ymaxb = p.Y(); + if (p.Z() < zminb) zminb = p.Z(); + if (p.Z() > zmaxb) zmaxb = p.Z(); + } + + + + double filldist = 0.2; // globflags.GetNumFlag ("filldist", 0.4); + xminb -= filldist * gh; + xmaxb += filldist * gh; + yminb -= filldist * gh; + ymaxb += filldist * gh; + zminb -= filldist * gh; + zmaxb += filldist * gh; + + min1 = int ((xminb - xmin) / gh) + 1; + max1 = int ((xmaxb - xmin) / gh) + 1; + min2 = int ((yminb - ymin) / gh) + 1; + max2 = int ((ymaxb - ymin) / gh) + 1; + min3 = int ((zminb - zmin) / gh) + 1; + max3 = int ((zmaxb - zmin) / gh) + 1; + + + for (i1 = min1; i1 <= max1; i1++) + for (i2 = min2; i2 <= max2; i2++) + for (i3 = min3; i3 <= max3; i3++) + inner.Elem(i3 + (i2-1) * n3 + (i1-1) * n2 * n3) = BLOCKBOUND; + } + + + + + while (1) + { + int undefi = 0; + Point3d undefp; + + for (i1 = 1; i1 <= n1 && !undefi; i1++) + for (i2 = 1; i2 <= n2 && !undefi; i2++) + for (i3 = 1; i3 <= n3 && !undefi; i3++) + { + i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; + if (inner.Elem(i) == BLOCKUNDEF) + { + undefi = i; + undefp.X() = xmin + (i1-0.5) * gh; + undefp.Y() = ymin + (i2-0.5) * gh; + undefp.Z() = zmin + (i3-0.5) * gh; + } + } + + if (!undefi) + break; + + // PrintMessage (5, "Test point: ", undefp); + + if (adfront -> Inside (undefp)) + { + // (*mycout) << "inner" << endl; + inner.Elem(undefi) = BLOCKINNER; + } + else + { + // (*mycout) << "outer" << endl; + inner.Elem(undefi) = BLOCKOUTER; + } + + do + { + changed = 0; + for (i1 = 1; i1 <= n1; i1++) + for (i2 = 1; i2 <= n2; i2++) + for (i3 = 1; i3 <= n3; i3++) + { + i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; + + for (int k = 1; k <= 3; k++) + { + switch (k) + { + case 1: j = i + n2 * n3; break; + case 2: j = i + n3; break; + case 3: j = i + 1; break; + } + + if (j > n1 * n2 * n3) continue; + + if (inner.Elem(i) == BLOCKOUTER && inner.Elem(j) == BLOCKUNDEF) + { + changed = 1; + inner.Elem(j) = BLOCKOUTER; + } + if (inner.Elem(j) == BLOCKOUTER && inner.Elem(i) == BLOCKUNDEF) + { + changed = 1; + inner.Elem(i) = BLOCKOUTER; + } + if (inner.Elem(i) == BLOCKINNER && inner.Elem(j) == BLOCKUNDEF) + { + changed = 1; + inner.Elem(j) = BLOCKINNER; + } + if (inner.Elem(j) == BLOCKINNER && inner.Elem(i) == BLOCKUNDEF) + { + changed = 1; + inner.Elem(i) = BLOCKINNER; + } + } + } + } + while (changed); + + } + + + + filled = 0; + for (i = 1; i <= n; i++) + if (inner.Elem(i) == BLOCKINNER) + { + filled++; + } + PrintMessage (5, "Filled blocks: ", filled); + + for (i = 1; i <= n; i++) + { + pointnr.Elem(i) = 0; + frontpointnr.Elem(i) = 0; + } + + for (i1 = 1; i1 <= n1-1; i1++) + for (i2 = 1; i2 <= n2-1; i2++) + for (i3 = 1; i3 <= n3-1; i3++) + { + i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; + if (inner.Elem(i) == BLOCKINNER) + { + for (j1 = i1; j1 <= i1+1; j1++) + for (j2 = i2; j2 <= i2+1; j2++) + for (j3 = i3; j3 <= i3+1; j3++) + { + j = j3 + (j2-1) * n3 + (j1-1) * n2 * n3; + if (pointnr.Get(j) == 0) + { + Point3d hp(xmin + (j1-1) * gh, + ymin + (j2-1) * gh, + zmin + (j3-1) * gh); + pointnr.Elem(j) = mesh.AddPoint (hp); + frontpointnr.Elem(j) = + AddPoint (hp, pointnr.Elem(j)); + + } + } + } + } + + + for (i1 = 2; i1 <= n1-1; i1++) + for (i2 = 2; i2 <= n2-1; i2++) + for (i3 = 2; i3 <= n3-1; i3++) + { + i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; + if (inner.Elem(i) == BLOCKINNER) + { + int pn[9]; + pn[1] = pointnr.Get(i); + pn[2] = pointnr.Get(i+1); + pn[3] = pointnr.Get(i+n3); + pn[4] = pointnr.Get(i+n3+1); + pn[5] = pointnr.Get(i+n2*n3); + pn[6] = pointnr.Get(i+n2*n3+1); + pn[7] = pointnr.Get(i+n2*n3+n3); + pn[8] = pointnr.Get(i+n2*n3+n3+1); + static int elind[][4] = + { + { 1, 8, 2, 4 }, + { 1, 8, 4, 3 }, + { 1, 8, 3, 7 }, + { 1, 8, 7, 5 }, + { 1, 8, 5, 6 }, + { 1, 8, 6, 2 } + }; + for (j = 1; j <= 6; j++) + { + Element el(4); + for (int k = 1; k <= 4; k++) + el.PNum(k) = pn[elind[j-1][k-1]]; + + mesh.AddVolumeElement (el); + } + } + } + + + + for (i1 = 2; i1 <= n1-1; i1++) + for (i2 = 2; i2 <= n2-1; i2++) + for (i3 = 2; i3 <= n3-1; i3++) + { + i = i3 + (i2-1) * n3 + (i1-1) * n2 * n3; + if (inner.Elem(i) == BLOCKINNER) + { + int pi1(0), pi2(0), pi3(0), pi4(0); + + int pn1 = frontpointnr.Get(i); + int pn2 = frontpointnr.Get(i+1); + int pn3 = frontpointnr.Get(i+n3); + int pn4 = frontpointnr.Get(i+n3+1); + int pn5 = frontpointnr.Get(i+n2*n3); + int pn6 = frontpointnr.Get(i+n2*n3+1); + int pn7 = frontpointnr.Get(i+n2*n3+n3); + int pn8 = frontpointnr.Get(i+n2*n3+n3+1); + + for (int k = 1; k <= 6; k++) + { + switch (k) + { + case 1: // j3 = i3+1 + j = i + 1; + pi1 = pn2; + pi2 = pn6; + pi3 = pn4; + pi4 = pn8; + break; + case 2: // j3 = i3-1 + j = i - 1; + pi1 = pn1; + pi2 = pn3; + pi3 = pn5; + pi4 = pn7; + break; + case 3: // j2 = i2+1 + j = i + n3; + pi1 = pn3; + pi2 = pn4; + pi3 = pn7; + pi4 = pn8; + break; + case 4: // j2 = i2-1 + j = i - n3; + pi1 = pn1; + pi2 = pn5; + pi3 = pn2; + pi4 = pn6; + break; + case 5: // j1 = i1+1 + j = i + n3*n2; + pi1 = pn5; + pi2 = pn7; + pi3 = pn6; + pi4 = pn8; + break; + case 6: // j1 = i1-1 + j = i - n3*n2; + pi1 = pn1; + pi2 = pn2; + pi3 = pn3; + pi4 = pn4; + break; + } + + if (inner.Get(j) == BLOCKBOUND) + { + MiniElement2d face; + face.PNum(1) = pi4; + face.PNum(2) = pi1; + face.PNum(3) = pi3; + AddBoundaryElement (face); + + face.PNum(1) = pi1; + face.PNum(2) = pi4; + face.PNum(3) = pi2; + AddBoundaryElement (face); + + } + } + } + } +} + + + +static const AdFront3 * locadfront; +static int TestInner (const Point3d & p) +{ + return locadfront->Inside (p); +} +static int TestSameSide (const Point3d & p1, const Point3d & p2) +{ + return locadfront->SameSide (p1, p2); +} + + + + +void Meshing3 :: BlockFillLocalH (Mesh & mesh, + const MeshingParameters & mp) +{ + int i, j; + + double filldist = mp.filldist; + + (*testout) << "blockfill local h" << endl; + (*testout) << "rel filldist = " << filldist << endl; + PrintMessage (3, "blockfill local h"); + + /* + (*mycout) << "boxes: " << mesh.LocalHFunction().GetNBoxes() << endl + << "filldist = " << filldist << endl; + */ + ARRAY<Point3d> npoints; + + adfront -> CreateTrees(); + + Point3d mpmin, mpmax; + // mesh.GetBox (mpmin, mpmax); + bool firstp = 1; + + double maxh = 0; + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & el = adfront->GetFace(i); + for (j = 1; j <= 3; j++) + { + const Point3d & p1 = adfront->GetPoint (el.PNumMod(j)); + const Point3d & p2 = adfront->GetPoint (el.PNumMod(j+1)); + double hi = Dist (p1, p2); + if (hi > maxh) + { + maxh = hi; + //(*testout) << "reducing maxh to " << maxh << " because of " << p1 << " and " << p2 << endl; + } + + if (firstp) + { + mpmin = p1; + mpmax = p1; + firstp = 0; + } + else + { + mpmin.SetToMin (p1); + mpmax.SetToMax (p1); + } + } + } + + Point3d mpc = Center (mpmin, mpmax); + double d = max3(mpmax.X()-mpmin.X(), + mpmax.Y()-mpmin.Y(), + mpmax.Z()-mpmin.Z()) / 2; + mpmin = mpc - Vec3d (d, d, d); + mpmax = mpc + Vec3d (d, d, d); + Box3d meshbox (mpmin, mpmax); + + LocalH loch2 (mpmin, mpmax, 1); + + + if (mp.maxh < maxh) + { + maxh = mp.maxh; + //(*testout) << "reducing maxh to " << maxh << " because of mp.maxh" << endl; + } + + int changed; + do + { + mesh.LocalHFunction().ClearFlags(); + + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & el = adfront->GetFace(i); + Point3d pmin = adfront->GetPoint (el.PNum(1)); + Point3d pmax = pmin; + + for (j = 2; j <= 3; j++) + { + const Point3d & p = adfront->GetPoint (el.PNum(j)); + pmin.SetToMin (p); + pmax.SetToMax (p); + } + + + double filld = filldist * Dist (pmin, pmax); + + pmin = pmin - Vec3d (filld, filld, filld); + pmax = pmax + Vec3d (filld, filld, filld); + // (*testout) << "cut : " << pmin << " - " << pmax << endl; + mesh.LocalHFunction().CutBoundary (pmin, pmax); + } + + locadfront = adfront; + mesh.LocalHFunction().FindInnerBoxes (adfront, NULL); + + npoints.SetSize(0); + mesh.LocalHFunction().GetInnerPoints (npoints); + + changed = 0; + for (i = 1; i <= npoints.Size(); i++) + { + if (mesh.LocalHFunction().GetH(npoints.Get(i)) > 1.5 * maxh) + { + mesh.LocalHFunction().SetH (npoints.Get(i), maxh); + changed = 1; + } + } + } + while (changed); + + if (debugparam.slowchecks) + (*testout) << "Blockfill with points: " << endl; + for (i = 1; i <= npoints.Size(); i++) + { + if (meshbox.IsIn (npoints.Get(i))) + { + int gpnum = mesh.AddPoint (npoints.Get(i)); + adfront->AddPoint (npoints.Get(i), gpnum); + + if (debugparam.slowchecks) + { + (*testout) << npoints.Get(i) << endl; + if (!adfront->Inside(npoints.Get(i))) + { + cout << "add outside point" << endl; + (*testout) << "outside" << endl; + } + } + + } + } + + + + // find outer points + + loch2.ClearFlags(); + + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & el = adfront->GetFace(i); + Point3d pmin = adfront->GetPoint (el.PNum(1)); + Point3d pmax = pmin; + + for (j = 2; j <= 3; j++) + { + const Point3d & p = adfront->GetPoint (el.PNum(j)); + pmin.SetToMin (p); + pmax.SetToMax (p); + } + + loch2.SetH (Center (pmin, pmax), Dist (pmin, pmax)); + } + + for (i = 1; i <= adfront->GetNF(); i++) + { + const MiniElement2d & el = adfront->GetFace(i); + Point3d pmin = adfront->GetPoint (el.PNum(1)); + Point3d pmax = pmin; + + for (j = 2; j <= 3; j++) + { + const Point3d & p = adfront->GetPoint (el.PNum(j)); + pmin.SetToMin (p); + pmax.SetToMax (p); + } + + double filld = filldist * Dist (pmin, pmax); + pmin = pmin - Vec3d (filld, filld, filld); + pmax = pmax + Vec3d (filld, filld, filld); + loch2.CutBoundary (pmin, pmax); + } + + locadfront = adfront; + loch2.FindInnerBoxes (adfront, NULL); + + npoints.SetSize(0); + loch2.GetOuterPoints (npoints); + + for (i = 1; i <= npoints.Size(); i++) + { + if (meshbox.IsIn (npoints.Get(i))) + { + int gpnum = mesh.AddPoint (npoints.Get(i)); + adfront->AddPoint (npoints.Get(i), gpnum); + } + } +} + +} diff --git a/contrib/Netgen/libsrc/meshing/meshing3.hpp b/contrib/Netgen/libsrc/meshing/meshing3.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3a4732d1645da300533edf930114f377d820cda1 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshing3.hpp @@ -0,0 +1,130 @@ +#ifndef FILE_MESHING3 +#define FILE_MESHING3 + + + + +enum MESHING3_RESULT +{ + MESHING3_OK = 0, + MESHING3_GIVEUP = 1, + MESHING3_NEGVOL = 2, + MESHING3_OUTERSTEPSEXCEEDED = 3, + MESHING3_TERMINATE = 4, + MESHING3_BADSURFACEMESH = 5 +}; + + +/// 3d volume mesh generation +class Meshing3 +{ + /// current state of front + AdFront3 * adfront; + /// 3d generation rules + ARRAY<vnetrule*> rules; + /// counts how often a rule is used + ARRAY<int> ruleused, canuse, foundmap; + /// describes, why a rule is not applied + ARRAY<char*> problems; + /// tolerance criterion + double tolfak; +public: + /// + Meshing3 (const string & rulefilename); + /// + Meshing3 (const char ** rulep); + /// + virtual ~Meshing3 (); + + /// + void LoadRules (const char * filename, const char ** prules); + /// + MESHING3_RESULT GenerateMesh (Mesh & mesh, const MeshingParameters & mp); + + /// + int ApplyRules (ARRAY<Point3d> & lpoints, ARRAY<int> & allowpoint, + ARRAY<MiniElement2d> & lfaces, INDEX lfacesplit, + INDEX_2_HASHTABLE<int> & connectedpairs, + ARRAY<Element> & elements, + ARRAY<INDEX> & delfaces, int tolerance, + double sloppy, int rotind1, + float & retminerr); + + /// + PointIndex AddPoint (const Point3d & p, PointIndex globind); + /// + void AddBoundaryElement (const Element2d & elem); + /// + void AddBoundaryElement (const MiniElement2d & elem); + /// + int AddConnectedPair (const INDEX_2 & pair); + + /// + void BlockFill (Mesh & mesh, double gh); + /// + void BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp); + + /// uses points of adfront, and puts new elements into mesh + void Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp); + /// + friend class PlotVolMesh; + /// + friend void TestRules (); +}; + + + + +/// status of mesh generation +class MeshingStat3d +{ +public: + /// + MeshingStat3d (); + /// + int cntsucc; + /// + int cnttrials; + /// + int cntelem; + /// + int nff; + /// + int qualclass; + /// + double vol0; + /// + double vol; + /// + double h; + /// + int problemindex; +}; + + + + + +/* +template <typename POINTARRAY, typename FACEARRAY> +extern int FindInnerPoint (POINTARRAY & grouppoints, + FACEARRAY & groupfaces, + Point3d & p); + +*/ + + + + + +#endif + + + + + + + + + + diff --git a/contrib/Netgen/libsrc/meshing/meshtool.cpp b/contrib/Netgen/libsrc/meshing/meshtool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..386e2bec0523819539bd77e07487ebbcf05f2c50 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtool.cpp @@ -0,0 +1,999 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +//#include <csg.hpp> // MODIFIED FOR GMSH +//#include <geometry2d.hpp>// MODIFIED FOR GMSH + +namespace netgen +{ + + int CheckSurfaceMesh (const Mesh & mesh) + { + PrintMessage (3, "Check Surface mesh"); + + int nf = mesh.GetNSE(); + INDEX_2_HASHTABLE<int> edges(nf+2); + int i, j; + INDEX_2 i2; + int cnt1 = 0, cnt2 = 0; + + for (i = 1; i <= nf; i++) + for (j = 1; j <= 3; j++) + { + i2.I1() = mesh.SurfaceElement(i).PNumMod(j); + i2.I2() = mesh.SurfaceElement(i).PNumMod(j+1); + if (edges.Used(i2)) + { + int hi; + hi = edges.Get(i2); + if (hi != 1) + PrintSysError ("CheckSurfaceMesh, hi = ", hi); + edges.Set(i2, 2); + cnt2++; + } + else + { + Swap (i2.I1(), i2.I2()); + edges.Set(i2, 1); + cnt1++; + } + } + + + if (cnt1 != cnt2) + { + PrintUserError ("Surface mesh not consistent"); + // MyBeep(2); + // (*mycout) << "cnt1 = " << cnt1 << " cnt2 = " << cnt2 << endl; + return 0; + } + return 1; + } + + + + int CheckSurfaceMesh2 (const Mesh & mesh) + { + int i, j, k; + const Point<3> *tri1[3], *tri2[3]; + + for (i = 1; i <= mesh.GetNOpenElements(); i++) + { + PrintDot (); + for (j = 1; j < i; j++) + { + for (k = 1; k <= 3; k++) + { + tri1[k-1] = &mesh.Point (mesh.OpenElement(i).PNum(k)); + tri2[k-1] = &mesh.Point (mesh.OpenElement(j).PNum(k)); + } + if (IntersectTriangleTriangle (&tri1[0], &tri2[0])) + { + PrintSysError ("Surface elements are intersecting"); + (*testout) << "Intersecting: " << endl; + for (k = 0; k <= 2; k++) + (*testout) << *tri1[k] << " "; + (*testout) << endl; + for (k = 0; k <= 2; k++) + (*testout) << *tri2[k] << " "; + (*testout) << endl; + } + + } + } + return 0; + } + + + + + + static double TriangleQualityInst (const Point3d & p1, const Point3d & p2, + const Point3d & p3) + { + // quality 0 (worst) .. 1 (optimal) + + Vec3d v1, v2, v3; + double s1, s2, s3; + double an1, an2, an3; + + v1 = p2 - p1; + v2 = p3 - p1; + v3 = p3 - p2; + + an1 = Angle (v1, v2); + v1 *= -1; + an2 = Angle (v1, v3); + an3 = Angle (v2, v3); + + s1 = sin (an1/2); + s2 = sin (an2/2); + s3 = sin (an3/2); + + return 8 * s1 * s2 * s3; + } + + + + + + + + + + + + + + + void MeshQuality2d (const Mesh & mesh) + { + int ncl = 20, cl; + ARRAY<INDEX> incl(ncl); + INDEX i; + SurfaceElementIndex sei; + double qual; + + incl = 0; + + for (sei = 0; sei < mesh.GetNSE(); sei++) + { + qual = TriangleQualityInst (mesh[mesh[sei][0]], + mesh[mesh[sei][1]], + mesh[mesh[sei][2]]); + + cl = int ( (ncl-1e-3) * qual ) + 1; + incl.Elem(cl)++; + } + + (*testout) << endl << endl; + + (*testout) << "Points: " << mesh.GetNP() << endl; + (*testout) << "Surface Elements: " << mesh.GetNSE() << endl; + + (*testout) << endl; + (*testout) << "Elements in qualityclasses:" << endl; + (*testout).precision(2); + for (i = 1; i <= ncl; i++) + { + (*testout) << setw(4) << double (i-1)/ncl << " - " + << setw(4) << double (i) / ncl << ": " + << incl.Get(i) << endl; + } + } + + + static double TetElementQuality (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4) + { + double vol, l, l4, l5, l6; + + + Vec3d v1 = p2 - p1; + Vec3d v2 = p3 - p1; + Vec3d v3 = p4 - p1; + + vol = fabs ((Cross (v1, v2) * v3)) / 6; + l4 = Dist (p2, p3); + l5 = Dist (p2, p4); + l6 = Dist (p3, p4); + + l = v1.Length() + v2.Length() + v3.Length() + l4 + l5 + l6; + + if (vol <= 1e-8 * l * l * l) return 1e-10; + + return vol/(l*l*l) * 1832.82; // 6^4 * sqrt(2) + } + + + + + + double teterrpow = 2; + + double CalcTetBadness (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, double h) + { + double vol, l, ll, lll, ll1, ll2, ll3, ll4, ll5, ll6; + double err; + + Vec3d v1 (p1, p2); + Vec3d v2 (p1, p3); + Vec3d v3 (p1, p4); + + vol = -Determinant (v1, v2, v3) / 6; + + ll1 = v1.Length2(); + ll2 = v2.Length2(); + ll3 = v3.Length2(); + ll4 = Dist2 (p2, p3); + ll5 = Dist2 (p2, p4); + ll6 = Dist2 (p3, p4); + + ll = ll1 + ll2 + ll3 + ll4 + ll5 + ll6; + l = sqrt (ll); + lll = l * ll; + + if (vol <= 1e-24 * lll) + return 1e24; + + err = 0.0080187537 * lll / vol; // sqrt(216) / (6^4 * sqrt(2)) + + if (h > 0) + err += ll / (h * h) + + h * h * ( 1 / ll1 + 1 / ll2 + 1 / ll3 + + 1 / ll4 + 1 / ll5 + 1 / ll6 ) - 12; + + if (teterrpow == 2) + return err*err; + return pow (err, teterrpow); + } + + + double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, double h, + int pi, Vec<3> & grad) + { + double vol, l, ll, lll; + double err; + + const Point3d *pp1, *pp2, *pp3, *pp4; + + pp1 = &p1; + pp2 = &p2; + pp3 = &p3; + pp4 = &p4; + + switch (pi) + { + case 2: + { + swap (pp1, pp2); + swap (pp3, pp4); + break; + } + case 3: + { + swap (pp1, pp3); + swap (pp2, pp4); + break; + } + case 4: + { + swap (pp1, pp4); + swap (pp3, pp2); + break; + } + } + + + Vec3d v1 (*pp1, *pp2); + Vec3d v2 (*pp1, *pp3); + Vec3d v3 (*pp1, *pp4); + + Vec3d v4 (*pp2, *pp3); + Vec3d v5 (*pp2, *pp4); + Vec3d v6 (*pp3, *pp4); + + vol = -Determinant (v1, v2, v3) / 6; + + Vec3d gradvol; + Cross (v5, v4, gradvol); + gradvol *= (-1.0/6.0); + + + double ll1 = v1.Length2(); + double ll2 = v2.Length2(); + double ll3 = v3.Length2(); + double ll4 = v4.Length2(); + double ll5 = v5.Length2(); + double ll6 = v6.Length2(); + + ll = ll1 + ll2 + ll3 + ll4 + ll5 + ll6; + l = sqrt (ll); + lll = l * ll; + + if (vol <= 1e-24 * lll) + { + grad = Vec3d (0, 0, 0); + return 1e24; + } + + + + Vec3d gradll1 (*pp2, *pp1); + Vec3d gradll2 (*pp3, *pp1); + Vec3d gradll3 (*pp4, *pp1); + gradll1 *= 2; + gradll2 *= 2; + gradll3 *= 2; + + Vec3d gradll (gradll1); + gradll += gradll2; + gradll += gradll3; + + /* + Vec3d gradll; + gradll = v1+v2+v3; + gradll *= -2; + */ + + err = 0.0080187537 * lll / vol; + + + gradll *= (0.0080187537 * 1.5 * l / vol); + Vec3d graderr(gradll); + gradvol *= ( -0.0080187537 * lll / (vol * vol) ); + graderr += gradvol; + + if (h > 0) + { + /* + Vec3d gradll1 (*pp2, *pp1); + Vec3d gradll2 (*pp3, *pp1); + Vec3d gradll3 (*pp4, *pp1); + gradll1 *= 2; + gradll2 *= 2; + gradll3 *= 2; + */ + err += ll / (h*h) + + h*h * ( 1 / ll1 + 1 / ll2 + 1 / ll3 + + 1 / ll4 + 1 / ll5 + 1 / ll6 ) - 12; + + graderr += (1/(h*h) - h*h/(ll1*ll1)) * gradll1; + graderr += (1/(h*h) - h*h/(ll2*ll2)) * gradll2; + graderr += (1/(h*h) - h*h/(ll3*ll3)) * gradll3; + cout << "?"; + } + + + double errpow; + if (teterrpow == 2) + { + errpow = err*err; + grad = (2 * err) * graderr; + } + else + { + errpow = pow (err, teterrpow); + grad = (teterrpow * errpow / err) * graderr; + } + return errpow; + } + + + + + + /* + + double CalcTetBadness (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, double h) + { + double vol, l; + double err; + + + Vec3d v1 (p1, p2); + Vec3d v2 (p1, p3); + Vec3d v3 (p1, p4); + + vol = -Determinant (v1, v2, v3) / 6; + + double l1 = v1.Length(); + double l2 = v2.Length(); + double l3 = v3.Length(); + double l4 = Dist (p2, p3); + double l5 = Dist (p2, p4); + double l6 = Dist (p3, p4); + + l = l1 + l2 + l3 + l4 + l5 + l6; + + // just for timing + // l += 1e-40 * CalcTetBadnessNew (p1, p2, p3, p4, h); + + if (vol <= 1e-24 * l * l * l) + { + return 1e24; + } + + err = (l*l*l) / (1832.82 * vol); // 6^4 * sqrt(2) + + if (h > 0) + err += l / h + + h * (1 / l1 + 1/l2 + 1/l3 + 1/l4 + 1/l5 + 1/l6) - 12; + + return pow (err, teterrpow); + } + + + + double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, double h, + int pi, Vec3d & grad) + { + double vol, l; + double err; + + const Point3d *pp1, *pp2, *pp3, *pp4; + + pp1 = &p1; + pp2 = &p2; + pp3 = &p3; + pp4 = &p4; + + switch (pi) + { + case 2: + { + swap (pp1, pp2); + swap (pp3, pp4); + break; + } + case 3: + { + swap (pp1, pp3); + swap (pp2, pp4); + break; + } + case 4: + { + swap (pp1, pp4); + swap (pp3, pp2); + break; + } + } + + + Vec3d v1 (*pp1, *pp2); + Vec3d v2 (*pp1, *pp3); + Vec3d v3 (*pp1, *pp4); + + Vec3d v4 (*pp2, *pp3); + Vec3d v5 (*pp2, *pp4); + Vec3d v6 (*pp3, *pp4); + + + // Vec3d n; + // Cross (v1, v2, n); + // vol = - (n * v3) / 6; + + + vol = -Determinant (v1, v2, v3) / 6; + + Vec3d gradvol; + Cross (v5, v4, gradvol); + gradvol *= (-1.0/6.0); + + + double l1 = v1.Length(); + double l2 = v2.Length(); + double l3 = v3.Length(); + double l4 = v4.Length(); + double l5 = v5.Length(); + double l6 = v6.Length(); + + l = l1 + l2 + l3 +l4 + l5 + l6; + + Vec3d gradl1 (*pp2, *pp1); + Vec3d gradl2 (*pp3, *pp1); + Vec3d gradl3 (*pp4, *pp1); + gradl1 /= l1; + gradl2 /= l2; + gradl3 /= l3; + + Vec3d gradl (gradl1); + gradl += gradl2; + gradl += gradl3; + + + if (vol <= 1e-24 * l * l * l) + { + grad = Vec3d (0, 0, 0); + return 1e24; + } + + + double c1 = 1.0 / 1832.82; // 6^4 * sqrt(2) + err = c1 * (l*l*l) / vol; + + + gradl *= (c1 * 3 * l * l / vol); + Vec3d graderr(gradl); + gradvol *= ( -c1 * l * l * l / (vol * vol) ); + graderr+= gradvol; + + if (h > 0) + { + err += l / h + + h * ( 1 / l1 + 1 / l2 + 1 / l3 + + 1 / l4 + 1 / l5 + 1 / l6 ) - 12; + + graderr += (1/h - h/(l1*l1)) * gradl1; + graderr += (1/h - h/(l2*l2)) * gradl2; + graderr += (1/h - h/(l3*l3)) * gradl3; + cout << "?"; + } + + double errpow = pow (err, teterrpow); + grad = (teterrpow * errpow / err) * graderr; + + return errpow; + } + + */ + + + + + + /* + double CalcVolume (const ARRAY<Point3d> & points, + const Element & el) + { + Vec3d v1 = points.Get(el.PNum(2)) - + points.Get(el.PNum(1)); + Vec3d v2 = points.Get(el.PNum(3)) - + points.Get(el.PNum(1)); + Vec3d v3 = points.Get(el.PNum(4)) - + points.Get(el.PNum(1)); + + return -(Cross (v1, v2) * v3) / 6; + } + */ + + double CalcVolume (const ARRAY<Point3d> & points, + const ARRAY<Element> & elements) + { + double vol; + Vec3d v1, v2, v3; + + vol = 0; + for (int i = 0; i < elements.Size(); i++) + { + v1 = points.Get(elements[i][1]) - points.Get(elements[i][0]); + v2 = points.Get(elements[i][2]) - points.Get(elements[i][0]); + v3 = points.Get(elements[i][3]) - points.Get(elements[i][0]); + vol -= (Cross (v1, v2) * v3) / 6; + } + return vol; + } + + + + + void MeshQuality3d (const Mesh & mesh, ARRAY<int> * inclass) + { + int ncl = 20; + signed int cl; + ARRAY<INDEX> incl(ncl); + INDEX i; + double qual; + double sum = 0; + int nontet = 0; + + for (i = 1; i <= incl.Size(); i++) + incl.Elem(i) = 0; + + for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + { + if (mesh[ei].GetType() != TET) + { + nontet++; + continue; + } + + qual = TetElementQuality (mesh.Point(mesh[ei][0]), + mesh.Point(mesh[ei][1]), + mesh.Point(mesh[ei][2]), + mesh.Point(mesh[ei][3])); + + if (qual > 1) qual = 1; + cl = int (ncl * qual ) + 1; + + if (cl < 1) cl = 1; + if (cl > ncl) cl = ncl; + + incl.Elem(cl)++; + if (inclass) (*inclass)[ei] = cl; + sum += 1/qual; + } + + (*testout) << endl << endl; + (*testout) << "Points: " << mesh.GetNP() << endl; + (*testout) << "Volume Elements: " << mesh.GetNE() << endl; + if (nontet) + (*testout) << nontet << " non tetrahedral elements" << endl; + (*testout) << endl; + + (*testout) << "Volume elements in qualityclasses:" << endl; + (*testout).precision(2); + for (i = 1; i <= ncl; i++) + { + (*testout) << setw(4) << double (i-1)/ncl << " - " + << setw(4) << double (i) / ncl << ": " + << incl.Get(i) << endl; + } + (*testout) << "total error: " << sum << endl; + } + + + void SaveEdges (const Mesh & mesh, const char * geomfile, double h, char * filename) + { + ofstream of (filename); + int i; + const Segment * seg; + + of << "edges" << endl; + of << geomfile << endl; + of << h << endl; + + of << mesh.GetNP() << endl; + for (i = 1; i <= mesh.GetNP(); i++) + of << mesh.Point(i)(0) << " " + << mesh.Point(i)(1) << " " + << mesh.Point(i)(2) << "\n"; + + of << 2 * mesh.GetNSeg() << endl; + for (i = 1; i <= mesh.GetNSeg(); i++) + { + seg = &mesh.LineSegment(i); + + of << seg->p2 << " " << seg->p1 << " " << seg->si << "\n"; + } + + } + + + void SaveSurfaceMesh (const Mesh & mesh, + double h, + char * filename) + + { + INDEX i; + + ofstream outfile(filename); + + outfile << "surfacemesh" << endl; + outfile << h << endl; + + outfile << mesh.GetNP() << endl; + for (i = 1; i <= mesh.GetNP(); i++) + outfile << mesh.Point(i)(0) << " " + << mesh.Point(i)(1) << " " + << mesh.Point(i)(2) << endl; + + + + outfile << mesh.GetNSE() << endl; + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & el = mesh.SurfaceElement(i); + + if (mesh.GetFaceDescriptor(el.GetIndex()).DomainOut() == 0) + outfile << mesh.SurfaceElement(i).PNum(1) << " " + << mesh.SurfaceElement(i).PNum(2) << " " + << mesh.SurfaceElement(i).PNum(3) << endl; + if (mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() == 0) + outfile << mesh.SurfaceElement(i).PNum(1) << " " + << mesh.SurfaceElement(i).PNum(3) << " " + << mesh.SurfaceElement(i).PNum(2) << endl; + } + } + + +#ifdef OLD + void Save2DMesh ( + const Mesh & mesh2d, + const ARRAY<SplineSegment *> * splines, + ostream & outfile) + + { + int i, j; + outfile.precision (6); + + outfile << "areamesh2" << endl; + + + outfile << endl; + outfile << mesh2d.GetNSeg() << endl; + for (i = 1; i <= mesh2d.GetNSeg(); i++) + outfile << mesh2d.LineSegment(i).si << " " + << mesh2d.LineSegment(i).p1 << " " + << mesh2d.LineSegment(i).p2 << " " << endl; + + + outfile << mesh2d.GetNSE() << endl; + for (i = 1; i <= mesh2d.GetNSE(); i++) + { + outfile << mesh2d.SurfaceElement(i).GetIndex() << " "; + outfile << mesh2d.SurfaceElement(i).GetNP() << " "; + for (j = 1; j <= mesh2d.SurfaceElement(i).GetNP(); j++) + outfile << mesh2d.SurfaceElement(i).PNum(j) << " "; + outfile << endl; + } + + outfile << mesh2d.GetNP() << endl; + for (i = 1; i <= mesh2d.GetNP(); i++) + outfile << mesh2d.Point(i).X() << " " + << mesh2d.Point(i).Y() << endl; + + if (splines) + { + outfile << splines->Size() << endl; + for (i = 1; i <= splines->Size(); i++) + splines->Get(i) -> PrintCoeff (outfile); + } + else + outfile << "0" << endl; + } +#endif + + + + + + + void SaveVolumeMesh (const Mesh & mesh, + const CSGeometry & geometry, + char * filename) + { + INDEX i; + + ofstream outfile(filename); + outfile << "volumemesh" << endl; + + outfile << mesh.GetNSE() << endl; + for (i = 1; i <= mesh.GetNSE(); i++) + { + if (mesh.SurfaceElement(i).GetIndex()) + outfile << mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex ()).SurfNr() + << "\t"; + else + outfile << "0" << "\t"; + outfile << mesh.SurfaceElement(i)[0] << " " + << mesh.SurfaceElement(i)[1] << " " + << mesh.SurfaceElement(i)[2] << endl; + } + outfile << mesh.GetNE() << endl; + for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + outfile << mesh[ei].GetIndex() << "\t" + << mesh[ei][0] << " " << mesh[ei][1] << " " + << mesh[ei][2] << " " << mesh[ei][3] << endl; + + outfile << mesh.GetNP() << endl; + for (i = 1; i <= mesh.GetNP(); i++) + outfile << mesh.Point(i)(0) << " " + << mesh.Point(i)(1) << " " + << mesh.Point(i)(2) << endl; + +#ifdef SOLIDGEOM + outfile << geometry.GetNSurf() << endl; + for (i = 1; i <= geometry.GetNSurf(); i++) + geometry.GetSurface(i) -> Print (outfile); +#endif + } + + + + int CheckCode () + { + return 1; + + /* + char st[100]; + ifstream ist("pw"); + + if (!ist.good()) return 0; + ist >> st; + if (strcmp (st, "JKULinz") == 0) return 1; + return 0; + */ + } + + + + /* ******************** CheckMesh ******************************* */ + + /// Checks, whether mesh contains a valid 3d mesh + int CheckMesh3D (const Mesh & mesh) + { + INDEX_3_HASHTABLE<int> faceused(mesh.GetNE()/3); + INDEX i; + int j, k, l; + INDEX_3 i3; + int ok = 1; + ElementIndex ei; + + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & el = mesh.SurfaceElement(i); + + if (mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() == 0 || + mesh.GetFaceDescriptor(el.GetIndex()).DomainOut() == 0) + { + for (j = 1; j <= 3; j++) + i3.I(j) = el.PNum(j); + + i3.Sort(); + faceused.Set (i3, 1); + } + } + + for (ei = 0; ei < mesh.GetNE(); ei++) + { + const Element & el = mesh[ei]; + + for (j = 1; j <= 4; j++) + { + l = 0; + for (k = 1; k <= 4; k++) + { + if (j != k) + { + l++; + i3.I(l) = el.PNum(k); + } + } + + i3.Sort(); + if (faceused.Used(i3)) + faceused.Set(i3, faceused.Get(i3)+1); + else + faceused.Set (i3, 1); + } + } + + + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & el = mesh.SurfaceElement(i); + + for (j = 1; j <= 3; j++) + i3.I(j) = el.PNum(j); + + i3.Sort(); + k = faceused.Get (i3); + if (k != 2) + { + ok = 0; + (*testout) << "face " << i << " with points " + << i3.I1() << "-" << i3.I2() << "-" << i3.I3() + << " has " << k << " elements" << endl; + } + } + + for (ei = 0; ei < mesh.GetNE(); ei++) + { + const Element & el = mesh[ei]; + + for (j = 1; j <= 4; j++) + { + l = 0; + for (k = 1; k <= 4; k++) + { + if (j != k) + { + l++; + i3.I(l) = el.PNum(k); + } + } + + i3.Sort(); + k = faceused.Get(i3); + if (k != 2) + { + ok = 0; + (*testout) << "element " << ei << " with face " + << i3.I1() << "-" << i3.I2() << "-" + << i3.I3() + << " has " << k << " elements" << endl; + } + } + } + + + + + + /* + for (i = 1; i <= faceused.GetNBags(); i++) + for (j = 1; j <= faceused.GetBagSize(i); j++) + { + faceused.GetData(i, j, i3, k); + if (k != 2) + { + (*testout) << "Face: " << i3.I1() << "-" + << i3.I2() << "-" << i3.I3() << " has " + << k << " Faces " << endl; + cerr << "Face Error" << endl; + ok = 0; + } + } + */ + + + if (!ok) + { + (*testout) << "surfelements: " << endl; + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & el = mesh.SurfaceElement(i); + (*testout) << setw(5) << i << ":" + << setw(6) << el.GetIndex() + << setw(6) << el.PNum(1) + << setw(4) << el.PNum(2) + << setw(4) << el.PNum(3) << endl; + } + (*testout) << "volelements: " << endl; + for (ei = 0; ei < mesh.GetNE(); ei++) + { + const Element & el = mesh[ei]; + (*testout) << setw(5) << i << ":" + << setw(6) << el.GetIndex() + << setw(6) << el[0] << setw(4) << el[1] + << setw(4) << el[2] << setw(4) << el[3] << endl; + } + } + + + return ok; + } + + + + void RemoveProblem (Mesh & mesh, int domainnr) + { + int i, j, k; + + mesh.FindOpenElements(domainnr); + int np = mesh.GetNP(); + + BitArrayChar<PointIndex::BASE> ppoints(np); + + // int ndom = mesh.GetNDomains(); + + PrintMessage (3, "Elements before Remove: ", mesh.GetNE()); + // for (k = 1; k <= ndom; k++) + k = domainnr; + { + ppoints.Clear(); + + for (i = 1; i <= mesh.GetNOpenElements(); i++) + { + const Element2d & sel = mesh.OpenElement(i); + if (sel.GetIndex() == k) + { + for (j = 1; j <= sel.GetNP(); j++) + ppoints.Set (sel.PNum(j)); + } + } + + for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + { + const Element & el = mesh[ei]; + if (el.GetIndex() == k) + { + int todel = 0; + for (j = 0; j < el.GetNP(); j++) + if (ppoints.Test (el[j])) + todel = 1; + + if (el.GetNP() != 4) + todel = 0; + + if (todel) + { + mesh[ei].Delete(); + // ei--; + } + } + } + } + + mesh.Compress(); + PrintMessage (3, "Elements after Remove: ", mesh.GetNE()); + } + + +} diff --git a/contrib/Netgen/libsrc/meshing/meshtool.hpp b/contrib/Netgen/libsrc/meshing/meshtool.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9ffaad113cad58bf9f4c3f5926758b992b2f2376 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtool.hpp @@ -0,0 +1,83 @@ +#ifndef FILE_MESHTOOL +#define FILE_MESHTOOL + + +/// +extern void MeshQuality2d (const Mesh & mesh); + +/// +extern void MeshQuality3d (const Mesh & mesh, + ARRAY<int> * inclass = NULL); + +/// +extern void SaveEdges (const Mesh & mesh, + const char * geomfile, + double h, + char * filename); + +/// +extern void SaveSurfaceMesh (const Mesh & mesh, + double h, + char * filename); +/* +/// +extern void Save2DMesh ( + const Mesh & mesh2d, + const ARRAY<class SplineSegment*> * splines, + ostream & outfile); +*/ + +class Surface; +/// +extern void SaveVolumeMesh ( + const ARRAY<Point3d> & points, + const ARRAY<Element> & elements, + const ARRAY<Element> & volelements, + const ARRAY<Surface*> & surfaces, + char * filename); + +/// +void SaveVolumeMesh (const Mesh & mesh, + const class CSGeometry & geometry, + char * filename); + +/// +extern int CheckCode (); + + +/// +extern double CalcTetBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Point3d & p4, + double h); +/// +extern double CalcTetBadnessGrad (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Point3d & p4, + double h, int pi, + Vec<3> & grad); + + +/** Calculates volume of an element. + The volume of the tetrahedron el is computed + */ +// extern double CalcVolume (const ARRAY<Point3d> & points, +// const Element & el); + +/** The total volume of all elements is computed. + This function calculates the volume of the mesh */ +extern double CalcVolume (const ARRAY<Point3d> & points, + const ARRAY<Element> & elements); + +/// +extern int CheckSurfaceMesh (const Mesh & mesh); + +/// +extern int CheckSurfaceMesh2 (const Mesh & mesh); +/// +extern int CheckMesh3D (const Mesh & mesh); +/// +extern void RemoveProblem (Mesh & mesh, int domainnr); +#endif diff --git a/contrib/Netgen/libsrc/meshing/meshtype.cpp b/contrib/Netgen/libsrc/meshing/meshtype.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c7baf22146a68f0bcd976dc514ca4af4dc1436d --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtype.cpp @@ -0,0 +1,2632 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +namespace netgen +{ + + + ostream & operator<<(ostream & s, const MeshPoint & pt) + { + s << Point<3> (pt); + return s; + } + + /* + MultiPointGeomInfo :: MultiPointGeomInfo() + { + cnt = 0; + } + */ + + int MultiPointGeomInfo :: + AddPointGeomInfo (const PointGeomInfo & gi) + { + for (int k = 0; k < cnt; k++) + if (mgi[k].trignum == gi.trignum) + return 0; + + if (cnt < MULTIPOINTGEOMINFO_MAX) + { + mgi[cnt] = gi; + cnt++; + return 0; + } + + throw NgException ("Please report error: MPGI Size too small\n"); + } + + + /* + void MultiPointGeomInfo :: + Init () + { + cnt = 0; + } + + void MultiPointGeomInfo :: + DeleteAll () + { + cnt = 0; + } + */ + + + + Segment :: Segment() + { + p1 = -1; + p2 = -1; + edgenr = -1; + + singedge_left = 0.; + singedge_right = 0.; + seginfo = 0; + + si = -1; + + domin = -1; + domout = -1; + tlosurf = -1; + + surfnr1 = -1; + surfnr2 = -1; + pmid = -1; + meshdocval = 0; + /* + geominfo[0].trignum=-1; + geominfo[1].trignum=-1; + + epgeominfo[0].edgenr = 1; + epgeominfo[0].dist = 0; + epgeominfo[1].edgenr = 1; + epgeominfo[1].dist = 0; + */ + + bcname = 0; + } + + Segment::Segment (const Segment & other) + : p1(other.p1), + p2(other.p2), + edgenr(other.edgenr), + singedge_left(other.singedge_left), + singedge_right(other.singedge_right), + seginfo(other.seginfo), + si(other.si), + domin(other.domin), + domout(other.domout), + tlosurf(other.tlosurf), + geominfo(), + surfnr1(other.surfnr1), + surfnr2(other.surfnr2), + epgeominfo(), + pmid(other.pmid), + meshdocval(other.meshdocval), + hp_elnr(other.hp_elnr) + { + geominfo[0] = other.geominfo[0]; + geominfo[1] = other.geominfo[1]; + epgeominfo[0] = other.epgeominfo[0]; + epgeominfo[1] = other.epgeominfo[1]; + bcname = other.bcname; + } + + Segment& Segment::operator=(const Segment & other) + { + if (&other != this) + { + p1 = other.p1; + p2 = other.p2; + edgenr = other.edgenr; + singedge_left = other.singedge_left; + singedge_right = other.singedge_right; + seginfo = other.seginfo; + si = other.si; + domin = other.domin; + domout = other.domout; + tlosurf = other.tlosurf; + geominfo[0] = other.geominfo[0]; + geominfo[1] = other.geominfo[1]; + surfnr1 = other.surfnr1; + surfnr2 = other.surfnr2; + epgeominfo[0] = other.epgeominfo[0]; + epgeominfo[1] = other.epgeominfo[1]; + pmid = other.pmid; + meshdocval = other.meshdocval; + hp_elnr = other.hp_elnr; + bcname = other.bcname; + } + + return *this; + } + + + ostream & operator<<(ostream & s, const Segment & seg) + { + s << seg.p1 << "(gi=" << seg.geominfo[0].trignum << ") - " + << seg.p2 << "(gi=" << seg.geominfo[1].trignum << ")" + << " domin = " << seg.domin << ", domout = " << seg.domout + << " si = " << seg.si << ", edgenr = " << seg.edgenr; + return s; + } + + + Element2d :: Element2d () + { + for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) + { + pnum[i] = 0; + geominfo[i].trignum = 0; + } + np = 3; + index = 0; + badel = 0; + deleted = 0; + typ = TRIG; + orderx = ordery = 1; + refflag = 1; + strongrefflag = false; +#ifdef PARALLEL + isghost = 0; +#endif + } + + + Element2d :: Element2d (int anp) + { + for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) + { + pnum[i] = 0; + geominfo[i].trignum = 0; + } + np = anp; + index = 0; + badel = 0; + deleted = 0; + switch (np) + { + case 3: typ = TRIG; break; + case 4: typ = QUAD; break; + case 6: typ = TRIG6; break; + case 8: typ = QUAD8; break; + } + orderx = ordery = 1; + refflag = 1; + strongrefflag = false; +#ifdef PARALLEL + isghost = 0; +#endif + } + + Element2d :: Element2d (ELEMENT_TYPE atyp) + { + for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) + { + pnum[i] = 0; + geominfo[i].trignum = 0; + } + + SetType (atyp); + + index = 0; + badel = 0; + deleted = 0; + orderx = ordery = 1; + refflag = 1; + strongrefflag = false; +#ifdef PARALLEL + isghost = 0; +#endif + + } + + + + Element2d :: Element2d (int pi1, int pi2, int pi3) +{ + pnum[0] = pi1; + pnum[1] = pi2; + pnum[2] = pi3; + np = 3; + typ = TRIG; + pnum[3] = 0; + pnum[4] = 0; + pnum[5] = 0; + + for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) + geominfo[i].trignum = 0; + index = 0; + badel = 0; + refflag = 1; + strongrefflag = false; + deleted = 0; + orderx = ordery = 1; + +#ifdef PARALLEL + isghost = 0; +#endif + +} + +Element2d :: Element2d (int pi1, int pi2, int pi3, int pi4) +{ + pnum[0] = pi1; + pnum[1] = pi2; + pnum[2] = pi3; + pnum[3] = pi4; + np = 4; + typ = QUAD; + + pnum[4] = 0; + pnum[5] = 0; + + for (int i = 0; i < ELEMENT2D_MAXPOINTS; i++) + geominfo[i].trignum = 0; + index = 0; + badel = 0; + refflag = 1; + strongrefflag = false; + deleted = 0; + orderx = ordery = 1; + +#ifdef PARALLEL + isghost = 0; +#endif +} + + +/* +void Element2d :: SetType (ELEMENT_TYPE atyp) +{ + typ = atyp; + switch (typ) + { + case TRIG: np = 3; break; + case QUAD: np = 4; break; + case TRIG6: np = 6; break; + case QUAD6: np = 6; break; + default: + PrintSysError ("Element2d::SetType, illegal type ", typ); + } +} +*/ + + +void Element2d :: GetBox (const T_POINTS & points, Box3d & box) const +{ + box.SetPoint (points.Get(pnum[0])); + for (unsigned i = 1; i < np; i++) + box.AddPoint (points.Get(pnum[i])); +} + +bool Element2d :: operator==(const Element2d & el2) const +{ + bool retval = (el2.GetNP() == np); + for(int i= 0; retval && i<np; i++) + retval = (el2[i] == (*this)[i]); + + return retval; +} + + +void Element2d :: Invert2() +{ + switch (typ) + { + case TRIG: + { + Swap (pnum[1], pnum[2]); + break; + } + case QUAD: + { + Swap (pnum[0], pnum[3]); + Swap (pnum[1], pnum[2]); + break; + } + default: + { + cerr << "Element2d::Invert2, illegal element type " << int(typ) << endl; + } + } +} + +int Element2d::HasFace(const Element2d& el) const +{ + //nur f�r tets!!! hannes + for (int i = 1; i <= 3; i++) + { + if (PNumMod(i) == el[0] && + PNumMod(i+1) == el[1] && + PNumMod(i+2) == el[2]) + { + return 1; + } + } + return 0; +} + +void Element2d :: NormalizeNumbering2 () +{ + if (GetNP() == 3) + { + if (PNum(1) < PNum(2) && PNum(1) < PNum(3)) + return; + else + { + if (PNum(2) < PNum(3)) + { + PointIndex pi1 = PNum(2); + PNum(2) = PNum(3); + PNum(3) = PNum(1); + PNum(1) = pi1; + } + else + { + PointIndex pi1 = PNum(3); + PNum(3) = PNum(2); + PNum(2) = PNum(1); + PNum(1) = pi1; + } + } + } + else + { + int mini = 1; + for (int i = 2; i <= GetNP(); i++) + if (PNum(i) < PNum(mini)) mini = i; + + Element2d hel = (*this); + for (int i = 1; i <= GetNP(); i++) + PNum(i) = hel.PNumMod (i+mini-1); + } +} + + + + +ARRAY<IntegrationPointData*> ipdtrig; +ARRAY<IntegrationPointData*> ipdquad; + + +int Element2d :: GetNIP () const +{ + int nip; + switch (np) + { + case 3: nip = 1; break; + case 4: nip = 4; break; + default: nip = 0; break; + } + return nip; +} + +void Element2d :: +GetIntegrationPoint (int ip, Point2d & p, double & weight) const +{ + static double eltriqp[1][3] = + { + { 1.0/3.0, 1.0/3.0, 0.5 } + }; + + static double elquadqp[4][3] = + { + { 0, 0, 0.25 }, + { 0, 1, 0.25 }, + { 1, 0, 0.25 }, + { 1, 1, 0.25 } + }; + + double * pp = 0; + switch (typ) + { + case TRIG: pp = &eltriqp[0][0]; break; + case QUAD: pp = &elquadqp[ip-1][0]; break; + default: + PrintSysError ("Element2d::GetIntegrationPoint, illegal type ", typ); + } + + p.X() = pp[0]; + p.Y() = pp[1]; + weight = pp[2]; +} + +void Element2d :: +GetTransformation (int ip, const ARRAY<Point2d> & points, + DenseMatrix & trans) const +{ + int np = GetNP(); + static DenseMatrix pmat(2, np), dshape(2, np); + pmat.SetSize (2, np); + dshape.SetSize (2, np); + + Point2d p; + double w; + + GetPointMatrix (points, pmat); + GetIntegrationPoint (ip, p, w); + GetDShape (p, dshape); + + CalcABt (pmat, dshape, trans); + + /* + (*testout) << "p = " << p << endl + << "pmat = " << pmat << endl + << "dshape = " << dshape << endl + << "tans = " << trans << endl; + */ +} + +void Element2d :: +GetTransformation (int ip, class DenseMatrix & pmat, + class DenseMatrix & trans) const +{ + int np = GetNP(); + +#ifdef DEBUG + if (pmat.Width() != np || pmat.Height() != 2) + { + (*testout) << "GetTransofrmation: pmat doesn't fit" << endl; + return; + } +#endif + + ComputeIntegrationPointData (); + DenseMatrix * dshapep; + switch (typ) + { + case TRIG: dshapep = &ipdtrig.Get(ip)->dshape; break; + case QUAD: dshapep = &ipdquad.Get(ip)->dshape; break; + default: + PrintSysError ("Element2d::GetTransformation, illegal type ", typ); + } + + CalcABt (pmat, *dshapep, trans); +} + + + +void Element2d :: GetShape (const Point2d & p, Vector & shape) const +{ + if (shape.Size() != GetNP()) + { + cerr << "Element::GetShape: Length not fitting" << endl; + return; + } + + switch (typ) + { + case TRIG: + shape.Elem(1) = 1 - p.X() - p.Y(); + shape.Elem(2) = p.X(); + shape.Elem(3) = p.Y(); + break; + case QUAD: + shape.Elem(1) = (1-p.X()) * (1-p.Y()); + shape.Elem(2) = p.X() * (1-p.Y()); + shape.Elem(3) = p.X() * p.Y(); + shape.Elem(4) = (1-p.X()) * p.Y(); + break; + default: + PrintSysError ("Element2d::GetShape, illegal type ", typ); + } +} + + + +void Element2d :: GetShapeNew (const Point<2> & p, FlatVector & shape) const +{ + switch (typ) + { + case TRIG: + { + shape(0) = p(0); + shape(1) = p(1); + shape(2) = 1-p(0)-p(1); + break; + } + + case QUAD: + { + shape(0) = (1-p(0))*(1-p(1)); + shape(1) = p(0) *(1-p(1)); + shape(2) = p(0) * p(1) ; + shape(3) = (1-p(0))* p(1) ; + break; + } + } +} + + + + + + + + + +void Element2d :: +GetDShape (const Point2d & p, DenseMatrix & dshape) const +{ +#ifdef DEBUG + if (dshape.Height() != 2 || dshape.Width() != np) + { + PrintSysError ("Element::DShape: Sizes don't fit"); + return; + } +#endif + + switch (typ) + { + case TRIG: + dshape.Elem(1, 1) = -1; + dshape.Elem(1, 2) = 1; + dshape.Elem(1, 3) = 0; + dshape.Elem(2, 1) = -1; + dshape.Elem(2, 2) = 0; + dshape.Elem(2, 3) = 1; + break; + case QUAD: + dshape.Elem(1, 1) = -(1-p.Y()); + dshape.Elem(1, 2) = (1-p.Y()); + dshape.Elem(1, 3) = p.Y(); + dshape.Elem(1, 4) = -p.Y(); + dshape.Elem(2, 1) = -(1-p.X()); + dshape.Elem(2, 2) = -p.X(); + dshape.Elem(2, 3) = p.X(); + dshape.Elem(2, 4) = (1-p.X()); + break; + + default: + PrintSysError ("Element2d::GetDShape, illegal type ", typ); + } +} + + + + +void Element2d :: +GetDShapeNew (const Point<2> & p, MatrixFixWidth<2> & dshape) const +{ + switch (typ) + { + case TRIG: + { + dshape = 0; + dshape(0,0) = 1; + dshape(1,1) = 1; + dshape(2,0) = -1; + dshape(2,1) = -1; + break; + } + case QUAD: + { + dshape(0,0) = -(1-p(1)); + dshape(0,1) = -(1-p(0)); + + dshape(1,0) = (1-p(1)); + dshape(1,1) = -p(0); + + dshape(2,0) = p(1); + dshape(2,1) = p(0); + + dshape(3,0) = -p(1); + dshape(3,1) = (1-p(0)); + break; + } + } +} + + + + + +void Element2d :: +GetPointMatrix (const ARRAY<Point2d> & points, + DenseMatrix & pmat) const +{ + int np = GetNP(); + +#ifdef DEBUG + if (pmat.Width() != np || pmat.Height() != 2) + { + cerr << "Element::GetPointMatrix: sizes don't fit" << endl; + return; + } +#endif + + for (int i = 1; i <= np; i++) + { + const Point2d & p = points.Get(PNum(i)); + pmat.Elem(1, i) = p.X(); + pmat.Elem(2, i) = p.Y(); + } +} + + + + + +double Element2d :: CalcJacobianBadness (const ARRAY<Point2d> & points) const +{ + int i, j; + int nip = GetNIP(); + static DenseMatrix trans(2,2); + static DenseMatrix pmat; + + pmat.SetSize (2, GetNP()); + GetPointMatrix (points, pmat); + + double err = 0; + for (i = 1; i <= nip; i++) + { + GetTransformation (i, pmat, trans); + + // Frobenius norm + double frob = 0; + for (j = 1; j <= 4; j++) + frob += sqr (trans.Get(j)); + frob = sqrt (frob); + frob /= 2; + + double det = trans.Det(); + + if (det <= 0) + err += 1e12; + else + err += frob * frob / det; + } + + err /= nip; + return err; +} + + + +static const int qip_table[4][4] = + { { 0, 1, 0, 3 }, + { 0, 1, 1, 2 }, + { 3, 2, 0, 3 }, + { 3, 2, 1, 2 } + }; + +double Element2d :: +CalcJacobianBadnessDirDeriv (const ARRAY<Point2d> & points, + int pi, Vec2d & dir, double & dd) const +{ + if (typ == QUAD) + { + Mat<2,2> trans, dtrans; + Mat<2,4> vmat, pmat; + + for (int j = 0; j < 4; j++) + { + const Point2d & p = points.Get( (*this)[j] ); + pmat(0, j) = p.X(); + pmat(1, j) = p.Y(); + } + + vmat = 0.0; + vmat(0, pi-1) = dir.X(); + vmat(1, pi-1) = dir.Y(); + + double err = 0; + dd = 0; + + for (int i = 0; i < 4; i++) + { + int ix1 = qip_table[i][0]; + int ix2 = qip_table[i][1]; + int iy1 = qip_table[i][2]; + int iy2 = qip_table[i][3]; + + trans(0,0) = pmat(0, ix2) - pmat(0,ix1); + trans(1,0) = pmat(1, ix2) - pmat(1,ix1); + trans(0,1) = pmat(0, iy2) - pmat(0,iy1); + trans(1,1) = pmat(1, iy2) - pmat(1,iy1); + + double det = trans(0,0)*trans(1,1)-trans(1,0)*trans(0,1); + + if (det <= 0) + { + dd = 0; + return 1e12; + } + + dtrans(0,0) = vmat(0, ix2) - vmat(0,ix1); + dtrans(1,0) = vmat(1, ix2) - vmat(1,ix1); + dtrans(0,1) = vmat(0, iy2) - vmat(0,iy1); + dtrans(1,1) = vmat(1, iy2) - vmat(1,iy1); + + + // Frobenius norm + double frob = 0; + for (int j = 0; j < 4; j++) + frob += sqr (trans(j)); + frob = sqrt (frob); + + double dfrob = 0; + for (int j = 0; j < 4; j++) + dfrob += trans(j) * dtrans(j); + dfrob = dfrob / frob; + + frob /= 2; + dfrob /= 2; + + + // ddet = \sum_j det (m_j) with m_j = trans, except col j = dtrans + double ddet + = dtrans(0,0) * trans(1,1) - trans(0,1) * dtrans(1,0) + + trans(0,0) * dtrans(1,1) - dtrans(0,1) * trans(1,0); + + err += frob * frob / det; + dd += (2 * frob * dfrob * det - frob * frob * ddet) / (det * det); + } + + err /= 4; + dd /= 4; + return err; + } + + int nip = GetNIP(); + static DenseMatrix trans(2,2), dtrans(2,2); + static DenseMatrix pmat, vmat; + + pmat.SetSize (2, GetNP()); + vmat.SetSize (2, GetNP()); + + GetPointMatrix (points, pmat); + + vmat = 0.0; + vmat.Elem(1, pi) = dir.X(); + vmat.Elem(2, pi) = dir.Y(); + + + double err = 0; + dd = 0; + + for (int i = 1; i <= nip; i++) + { + GetTransformation (i, pmat, trans); + GetTransformation (i, vmat, dtrans); + + // Frobenius norm + double frob = 0; + for (int j = 1; j <= 4; j++) + frob += sqr (trans.Get(j)); + frob = sqrt (frob); + + double dfrob = 0; + for (int j = 1; j <= 4; j++) + dfrob += trans.Get(j) * dtrans.Get(j); + dfrob = dfrob / frob; + + frob /= 2; + dfrob /= 2; + + double det = trans(0,0)*trans(1,1)-trans(1,0)*trans(0,1); + + // ddet = \sum_j det (m_j) with m_j = trans, except col j = dtrans + double ddet + = dtrans(0,0) * trans(1,1) - trans(0,1) * dtrans(1,0) + + trans(0,0) * dtrans(1,1) - dtrans(0,1) * trans(1,0); + + if (det <= 0) + err += 1e12; + else + { + err += frob * frob / det; + dd += (2 * frob * dfrob * det - frob * frob * ddet) / (det * det); + } + } + + err /= nip; + dd /= nip; + return err; +} + + + +double Element2d :: +CalcJacobianBadness (const T_POINTS & points, const Vec<3> & n) const +{ + int i, j; + int nip = GetNIP(); + static DenseMatrix trans(2,2); + static DenseMatrix pmat; + + pmat.SetSize (2, GetNP()); + + Vec<3> t1, t2; + t1 = n.GetNormal(); + t2 = Cross (n, t1); + + for (i = 1; i <= GetNP(); i++) + { + Point3d p = points.Get(PNum(i)); + pmat.Elem(1, i) = p.X() * t1(0) + p.Y() * t1(1) + p.Z() * t1(2); + pmat.Elem(2, i) = p.X() * t2(0) + p.Y() * t2(1) + p.Z() * t2(2); + } + + double err = 0; + for (i = 1; i <= nip; i++) + { + GetTransformation (i, pmat, trans); + + // Frobenius norm + double frob = 0; + for (j = 1; j <= 4; j++) + frob += sqr (trans.Get(j)); + frob = sqrt (frob); + frob /= 2; + + double det = trans.Det(); + if (det <= 0) + err += 1e12; + else + err += frob * frob / det; + } + + err /= nip; + return err; +} + + + +void Element2d :: ComputeIntegrationPointData () const +{ + switch (np) + { + case 3: if (ipdtrig.Size()) return; break; + case 4: if (ipdquad.Size()) return; break; + } + + for (int i = 1; i <= GetNIP(); i++) + { + IntegrationPointData * ipd = new IntegrationPointData; + Point2d hp; + GetIntegrationPoint (i, hp, ipd->weight); + ipd->p(0) = hp.X(); + ipd->p(1) = hp.Y(); + ipd->p(2) = 0; + + ipd->shape.SetSize(GetNP()); + ipd->dshape.SetSize(2, GetNP()); + + GetShape (hp, ipd->shape); + GetDShape (hp, ipd->dshape); + + switch (np) + { + case 3: ipdtrig.Append (ipd); break; + case 4: ipdquad.Append (ipd); break; + } + } +} + + + + + + + + + + +ostream & operator<<(ostream & s, const Element2d & el) +{ + s << "np = " << el.GetNP(); + for (int j = 1; j <= el.GetNP(); j++) + s << " " << el.PNum(j); + return s; +} + + +ostream & operator<<(ostream & s, const Element & el) +{ + s << "np = " << el.GetNP(); + for (int j = 0; j < el.GetNP(); j++) + s << " " << int(el[j]); + return s; +} + + +Element :: Element () +{ + typ = TET; + np = 4; + for (int i = 0; i < ELEMENT_MAXPOINTS; i++) + pnum[i] = 0; + index = 0; + flags.marked = 1; + flags.badel = 0; + flags.reverse = 0; + flags.illegal = 0; + flags.illegal_valid = 0; + flags.badness_valid = 0; + flags.refflag = 1; + flags.strongrefflag = false; + flags.deleted = 0; + flags.fixed = 0; + orderx = ordery = orderz = 1; + +#ifdef PARALLEL + partitionNumber = -1; + isghost = 0; +#endif + +} + + +Element :: Element (int anp) +{ + np = anp; + int i; + for (i = 0; i < ELEMENT_MAXPOINTS; i++) + pnum[i] = 0; + index = 0; + flags.marked = 1; + flags.badel = 0; + flags.reverse = 0; + flags.illegal = 0; + flags.illegal_valid = 0; + flags.badness_valid = 0; + flags.refflag = 1; + flags.strongrefflag = false; + flags.deleted = 0; + flags.fixed = 0; + + switch (np) + { + case 4: typ = TET; break; + case 5: typ = PYRAMID; break; + case 6: typ = PRISM; break; + case 8: typ = HEX; break; + case 10: typ = TET10; break; + default: cerr << "Element::Element: unknown element with " << np << " points" << endl; + } + orderx = ordery = orderz = 1; + +#ifdef PARALLEL + isghost = 0; +#endif +} + +void Element :: SetOrder (const int aorder) + { + orderx = aorder; + ordery = aorder; + orderz = aorder; + } + + +void Element :: SetOrder (const int ox, const int oy, const int oz) +{ + orderx = ox; + ordery = oy; + orderz = oz; +} + + +Element :: Element (ELEMENT_TYPE type) +{ + SetType (type); + + int i; + for (i = 0; i < ELEMENT_MAXPOINTS; i++) + pnum[i] = 0; + index = 0; + flags.marked = 1; + flags.badel = 0; + flags.reverse = 0; + flags.illegal = 0; + flags.illegal_valid = 0; + flags.badness_valid = 0; + flags.refflag = 1; + flags.strongrefflag = false; + flags.deleted = 0; + flags.fixed = 0; + orderx = ordery = orderz = 1; + +#ifdef PARALLEL + isghost = 0; +#endif +} + + + + + +Element & Element :: operator= (const Element & el2) +{ + typ = el2.typ; + np = el2.np; + for (int i = 0; i < ELEMENT_MAXPOINTS; i++) + pnum[i] = el2.pnum[i]; + index = el2.index; + flags = el2.flags; + orderx = el2.orderx; + ordery = el2.ordery; + orderz = el2.orderz; + hp_elnr = el2.hp_elnr; + flags = el2.flags; + return *this; +} + + + +void Element :: SetNP (int anp) +{ + np = anp; + switch (np) + { + case 4: typ = TET; break; + case 5: typ = PYRAMID; break; + case 6: typ = PRISM; break; + case 8: typ = HEX; break; + case 10: typ = TET10; break; + // + default: break; + cerr << "Element::SetNP unknown element with " << np << " points" << endl; + } +} + + + +void Element :: SetType (ELEMENT_TYPE atyp) +{ + typ = atyp; + switch (atyp) + { + case TET: np = 4; break; + case PYRAMID: np = 5; break; + case PRISM: np = 6; break; + case HEX: np = 8; break; + case TET10: np = 10; break; + case PRISM12: np = 12; break; + } +} + + + +void Element :: Invert() +{ + switch (GetNP()) + { + case 4: + { + Swap (PNum(3), PNum(4)); + break; + } + case 5: + { + Swap (PNum(1), PNum(4)); + Swap (PNum(2), PNum(3)); + break; + } + case 6: + { + Swap (PNum(1), PNum(4)); + Swap (PNum(2), PNum(5)); + Swap (PNum(3), PNum(6)); + break; + } + } +} + + +void Element :: Print (ostream & ost) const +{ + ost << np << " Points: "; + for (int i = 1; i <= np; i++) + ost << pnum[i-1] << " " << endl; +} + +void Element :: GetBox (const T_POINTS & points, Box3d & box) const +{ + box.SetPoint (points.Get(PNum(1))); + box.AddPoint (points.Get(PNum(2))); + box.AddPoint (points.Get(PNum(3))); + box.AddPoint (points.Get(PNum(4))); +} + +double Element :: Volume (const T_POINTS & points) const +{ + Vec<3> v1 = points.Get(PNum(2)) - points.Get(PNum(1)); + Vec<3> v2 = points.Get(PNum(3)) - points.Get(PNum(1)); + Vec<3> v3 = points.Get(PNum(4)) - points.Get(PNum(1)); + + return -(Cross (v1, v2) * v3) / 6; +} + + +void Element :: GetFace2 (int i, Element2d & face) const +{ + static const int tetfaces[][5] = + { { 3, 2, 3, 4, 0 }, + { 3, 3, 1, 4, 0 }, + { 3, 1, 2, 4, 0 }, + { 3, 2, 1, 3, 0 } }; + + static const int pyramidfaces[][5] = + { { 4, 1, 4, 3, 2 }, + { 3, 1, 2, 5, 0 }, + { 3, 2, 3, 5, 0 }, + { 3, 3, 4, 5, 0 }, + { 3, 4, 1, 5, 0 } }; + + static const int prismfaces[][5] = + { + { 3, 1, 3, 2, 0 }, + { 3, 4, 5, 6, 0 }, + { 4, 1, 2, 5, 4 }, + { 4, 2, 3, 6, 5 }, + { 4, 3, 1, 4, 6 } + }; + + switch (np) + { + case 4: // tet + case 10: // tet + { + face.SetType(TRIG); + for (int j = 1; j <= 3; j++) + face.PNum(j) = PNum(tetfaces[i-1][j]); + break; + } + case 5: // pyramid + { + // face.SetNP(pyramidfaces[i-1][0]); + face.SetType ( (i == 1) ? QUAD : TRIG); + for (int j = 1; j <= face.GetNP(); j++) + face.PNum(j) = PNum(pyramidfaces[i-1][j]); + break; + } + case 6: // prism + { + // face.SetNP(prismfaces[i-1][0]); + face.SetType ( (i >= 3) ? QUAD : TRIG); + for (int j = 1; j <= face.GetNP(); j++) + face.PNum(j) = PNum(prismfaces[i-1][j]); + break; + } + } +} + + + +void Element :: GetTets (ARRAY<Element> & locels) const +{ + GetTetsLocal (locels); + int i, j; + for (i = 1; i <= locels.Size(); i++) + for (j = 1; j <= 4; j++) + locels.Elem(i).PNum(j) = PNum ( locels.Elem(i).PNum(j) ); +} + +void Element :: GetTetsLocal (ARRAY<Element> & locels) const +{ + int i, j; + locels.SetSize(0); + switch (GetType()) + { + case TET: + { + int linels[1][4] = + { { 1, 2, 3, 4 }, + }; + for (i = 0; i < 1; i++) + { + Element tet(4); + for (j = 1; j <= 4; j++) + tet.PNum(j) = linels[i][j-1]; + locels.Append (tet); + } + break; + } + case TET10: + { + int linels[8][4] = + { { 1, 5, 6, 7 }, + { 5, 2, 8, 9 }, + { 6, 8, 3, 10 }, + { 7, 9, 10, 4 }, + { 5, 6, 7, 9 }, + { 5, 6, 9, 8 }, + { 6, 7, 9, 10 }, + { 6, 8, 10, 9 } }; + for (i = 0; i < 8; i++) + { + Element tet(4); + for (j = 1; j <= 4; j++) + tet.PNum(j) = linels[i][j-1]; + locels.Append (tet); + } + break; + } + case PYRAMID: + { + int linels[2][4] = + { { 1, 2, 3, 5 }, + { 1, 3, 4, 5 } }; + for (i = 0; i < 2; i++) + { + Element tet(4); + for (j = 1; j <= 4; j++) + tet.PNum(j) = linels[i][j-1]; + locels.Append (tet); + } + break; + } + case PRISM: + case PRISM12: + { + int linels[3][4] = + { { 1, 2, 3, 4 }, + { 4, 2, 3, 5 }, + { 6, 5, 4, 3 } + }; + for (i = 0; i < 3; i++) + { + Element tet(4); + for (j = 0; j < 4; j++) + tet[j] = linels[i][j]; + locels.Append (tet); + } + break; + } + case HEX: + { + int linels[6][4] = + { { 1, 7, 2, 3 }, + { 1, 7, 3, 4 }, + { 1, 7, 4, 8 }, + { 1, 7, 8, 5 }, + { 1, 7, 5, 6 }, + { 1, 7, 6, 2 } + }; + for (i = 0; i < 6; i++) + { + Element tet(4); + for (j = 0; j < 4; j++) + tet[j] = linels[i][j]; + locels.Append (tet); + } + break; + } + default: + { + cerr << "GetTetsLocal not implemented for el with " << GetNP() << " nodes" << endl; + } + } +} + +bool Element :: operator==(const Element & el2) const +{ + bool retval = (el2.GetNP() == np); + for(int i= 0; retval && i<np; i++) + retval = (el2[i] == (*this)[i]); + + return retval; +} + + +#ifdef OLD +void Element :: GetNodesLocal (ARRAY<Point3d> & points) const +{ + const static double tetpoints[4][3] = + { { 0, 0, 0 }, + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }}; + + const static double prismpoints[6][3] = + { { 0, 0, 0 }, + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 1, 0, 1 }, + { 0, 1, 1 } }; + + const static double pyramidpoints[6][3] = + { { 0, 0, 0 }, + { 1, 0, 0 }, + { 1, 1, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } }; + + const static double tet10points[10][3] = + { { 0, 0, 0 }, + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 0.5, 0, 0 }, + { 0, 0.5, 0 }, + { 0, 0, 0.5 }, + { 0.5, 0.5, 0 }, + { 0.5, 0, 0.5 }, + { 0, 0.5, 0.5 } }; + + const static double hexpoints[8][3] = + { + { 0, 0, 0 }, + { 1, 0, 0 }, + { 1, 1, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 1, 0, 1 }, + { 1, 1, 1 }, + { 0, 1, 1 } + }; + + int np, i; + const double (*pp)[3]; + switch (GetType()) + { + case TET: + { + np = 4; + pp = tetpoints; + break; + } + case PRISM: + case PRISM12: + { + np = 6; + pp = prismpoints; + break; + } + case TET10: + { + np = 10; + pp = tet10points; + break; + } + case PYRAMID: + { + np = 5; + pp = pyramidpoints; + break; + } + case HEX: + { + np = 8; + pp = hexpoints; + break; + } + default: + { + cout << "GetNodesLocal not impelemented for element " << GetType() << endl; + np = 0; + } + } + + points.SetSize(0); + for (i = 0; i < np; i++) + points.Append (Point3d (pp[i][0], pp[i][1], pp[i][2])); +} +#endif + + + + + + +void Element :: GetNodesLocalNew (ARRAY<Point<3> > & points) const +{ + const static double tetpoints[4][3] = + { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 0, 0, 0 } + }; + + const static double prismpoints[6][3] = + { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 0 }, + { 1, 0, 1 }, + { 0, 1, 1 }, + { 0, 0, 1 } + }; + + const static double pyramidpoints[6][3] = + { { 0, 0, 0 }, + { 1, 0, 0 }, + { 1, 1, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } }; + + const static double tet10points[10][3] = + { { 0, 0, 0 }, + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 0.5, 0, 0 }, + { 0, 0.5, 0 }, + { 0, 0, 0.5 }, + { 0.5, 0.5, 0 }, + { 0.5, 0, 0.5 }, + { 0, 0.5, 0.5 } }; + + const static double hexpoints[8][3] = + { + { 0, 0, 0 }, + { 1, 0, 0 }, + { 1, 1, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + { 1, 0, 1 }, + { 1, 1, 1 }, + { 0, 1, 1 } + }; + + + + int np, i; + const double (*pp)[3]; + switch (GetType()) + { + case TET: + { + np = 4; + pp = tetpoints; + break; + } + case PRISM: + case PRISM12: + { + np = 6; + pp = prismpoints; + break; + } + case TET10: + { + np = 10; + pp = tet10points; + break; + } + case PYRAMID: + { + np = 5; + pp = pyramidpoints; + break; + } + case HEX: + { + np = 8; + pp = hexpoints; + break; + } + default: + { + cout << "GetNodesLocal not impelemented for element " << GetType() << endl; + np = 0; + } + } + + points.SetSize(0); + for (i = 0; i < np; i++) + points.Append (Point<3> (pp[i][0], pp[i][1], pp[i][2])); +} + + + + + + + + + + + + + + + + + +void Element :: GetSurfaceTriangles (ARRAY<Element2d> & surftrigs) const +{ + static int tet4trigs[][3] = + { { 2, 3, 4 }, + { 3, 1, 4 }, + { 1, 2, 4 }, + { 2, 1, 3 } }; + + static int tet10trigs[][3] = + { { 2, 8, 9 }, { 3, 10, 8}, { 4, 9, 10 }, { 9, 8, 10 }, + { 3, 6, 10 }, { 1, 7, 6 }, { 4, 10, 7 }, { 6, 7, 10 }, + { 1, 5, 7 }, { 2, 9, 5 }, { 4, 7, 9 }, { 5, 9, 7 }, + { 1, 6, 5 }, { 2, 5, 8 }, { 3, 8, 6 }, { 5, 6, 8 } + }; + + static int pyramidtrigs[][3] = + { + { 1, 3, 2 }, + { 1, 4, 3 }, + { 1, 2, 5 }, + { 2, 3, 5 }, + { 3, 4, 5 }, + { 4, 1, 5 } + }; + + static int prismtrigs[][3] = + { + { 1, 3, 2 }, + { 4, 5, 6 }, + { 1, 2, 4 }, + { 4, 2, 5 }, + { 2, 3, 5 }, + { 5, 3, 6 }, + { 3, 1, 6 }, + { 6, 1, 4 } + }; + + static int hextrigs[][3] = + { + { 1, 3, 2 }, + { 1, 4, 3 }, + { 5, 6, 7 }, + { 5, 7, 8 }, + { 1, 2, 6 }, + { 1, 6, 5 }, + { 2, 3, 7 }, + { 2, 7, 6 }, + { 3, 4, 8 }, + { 3, 8, 7 }, + { 4, 1, 8 }, + { 1, 5, 8 } + }; + + int j; + + int nf; + int (*fp)[3]; + + switch (GetType()) + { + case TET: + { + nf = 4; + fp = tet4trigs; + break; + } + case PYRAMID: + { + nf = 6; + fp = pyramidtrigs; + break; + } + case PRISM: + case PRISM12: + { + nf = 8; + fp = prismtrigs; + break; + } + case TET10: + { + nf = 16; + fp = tet10trigs; + break; + } + case HEX: + { + nf = 12; + fp = hextrigs; + break; + } + default: + { + nf = 0; + fp = NULL; + } + } + + + surftrigs.SetSize (nf); + for (j = 0; j < nf; j++) + { + surftrigs.Elem(j+1) = Element2d(TRIG); + surftrigs.Elem(j+1).PNum(1) = fp[j][0]; + surftrigs.Elem(j+1).PNum(2) = fp[j][1]; + surftrigs.Elem(j+1).PNum(3) = fp[j][2]; + } +} + + + + + +ARRAY< AutoPtr < IntegrationPointData > > ipdtet; +ARRAY< AutoPtr < IntegrationPointData > > ipdtet10; + + + +int Element :: GetNIP () const +{ + int nip; + switch (typ) + { + case TET: nip = 1; break; + case TET10: nip = 8; break; + default: nip = 0; break; + } + return nip; +} + +void Element :: +GetIntegrationPoint (int ip, Point<3> & p, double & weight) const +{ + static double eltetqp[1][4] = + { + { 0.25, 0.25, 0.25, 1.0/6.0 } + }; + + static double eltet10qp[8][4] = + { + { 0.585410196624969, 0.138196601125011, 0.138196601125011, 1.0/24.0 }, + { 0.138196601125011, 0.585410196624969, 0.138196601125011, 1.0/24.0 }, + { 0.138196601125011, 0.138196601125011, 0.585410196624969, 1.0/24.0 }, + { 0.138196601125011, 0.138196601125011, 0.138196601125011, 1.0/24.0 }, + { 1, 0, 0, 1 }, + { 0, 1, 0, 1 }, + { 0, 0, 1, 1 }, + { 0, 0, 0, 1 }, + }; + + double * pp; + switch (typ) + { + case TET: pp = &eltetqp[0][0]; break; + case TET10: pp = &eltet10qp[ip-1][0]; break; + } + + p(0) = pp[0]; + p(1) = pp[1]; + p(2) = pp[2]; + weight = pp[3]; +} + +void Element :: +GetTransformation (int ip, const T_POINTS & points, + DenseMatrix & trans) const +{ + int np = GetNP(); + static DenseMatrix pmat(3, np), dshape(3, np); + pmat.SetSize (3, np); + dshape.SetSize (3, np); + + Point<3> p; + double w; + + GetPointMatrix (points, pmat); + GetIntegrationPoint (ip, p, w); + GetDShape (p, dshape); + + CalcABt (pmat, dshape, trans); + + /* + (*testout) << "p = " << p << endl + << "pmat = " << pmat << endl + << "dshape = " << dshape << endl + << "tans = " << trans << endl; + */ +} + +void Element :: +GetTransformation (int ip, class DenseMatrix & pmat, + class DenseMatrix & trans) const +{ + int np = GetNP(); + + if (pmat.Width() != np || pmat.Height() != 3) + { + (*testout) << "GetTransofrmation: pmat doesn't fit" << endl; + return; + } + + ComputeIntegrationPointData (); + DenseMatrix * dshapep; + switch (GetType()) + { + case TET: dshapep = &ipdtet.Get(ip)->dshape; break; + case TET10: dshapep = &ipdtet10.Get(ip)->dshape; break; + } + + CalcABt (pmat, *dshapep, trans); +} + + + +void Element :: GetShape (const Point<3> & hp, Vector & shape) const +{ + Point3d p = hp; + + if (shape.Size() != GetNP()) + { + cerr << "Element::GetShape: Length not fitting" << endl; + return; + } + + switch (typ) + { + case TET: + { + shape.Elem(1) = 1 - p.X() - p.Y() - p.Z(); + shape.Elem(2) = p.X(); + shape.Elem(3) = p.Y(); + shape.Elem(4) = p.Z(); + break; + } + case TET10: + { + double lam1 = 1 - p.X() - p.Y() - p.Z(); + double lam2 = p.X(); + double lam3 = p.Y(); + double lam4 = p.Z(); + + shape.Elem(5) = 4 * lam1 * lam2; + shape.Elem(6) = 4 * lam1 * lam3; + shape.Elem(7) = 4 * lam1 * lam4; + shape.Elem(8) = 4 * lam2 * lam3; + shape.Elem(9) = 4 * lam2 * lam4; + shape.Elem(10) = 4 * lam3 * lam4; + + shape.Elem(1) = lam1 - + 0.5 * (shape.Elem(5) + shape.Elem(6) + shape.Elem(7)); + shape.Elem(2) = lam2 - + 0.5 * (shape.Elem(5) + shape.Elem(8) + shape.Elem(9)); + shape.Elem(3) = lam3 - + 0.5 * (shape.Elem(6) + shape.Elem(8) + shape.Elem(10)); + shape.Elem(4) = lam4 - + 0.5 * (shape.Elem(7) + shape.Elem(9) + shape.Elem(10)); + break; + } + + case PRISM: + { + Point<3> hp = p; + shape(0) = hp(0) * (1-hp(2)); + shape(1) = hp(1) * (1-hp(2)); + shape(2) = (1-hp(0)-hp(1)) * (1-hp(2)); + shape(3) = hp(0) * hp(2); + shape(4) = hp(1) * hp(2); + shape(5) = (1-hp(0)-hp(1)) * hp(2); + break; + } + case HEX: + { + Point<3> hp = p; + shape(0) = (1-hp(0))*(1-hp(1))*(1-hp(2)); + shape(1) = ( hp(0))*(1-hp(1))*(1-hp(2)); + shape(2) = ( hp(0))*( hp(1))*(1-hp(2)); + shape(3) = (1-hp(0))*( hp(1))*(1-hp(2)); + shape(4) = (1-hp(0))*(1-hp(1))*( hp(2)); + shape(5) = ( hp(0))*(1-hp(1))*( hp(2)); + shape(6) = ( hp(0))*( hp(1))*( hp(2)); + shape(7) = (1-hp(0))*( hp(1))*( hp(2)); + break; + } + } +} + + + +void Element :: GetShapeNew (const Point<3> & p, FlatVector & shape) const +{ + /* + if (shape.Size() < GetNP()) + { + cerr << "Element::GetShape: Length not fitting" << endl; + return; + } + */ + + switch (typ) + { + case TET: + { + shape(0) = p(0); + shape(1) = p(1); + shape(2) = p(2); + shape(3) = 1-p(0)-p(1)-p(2); + break; + } + + case PYRAMID: + { + double noz = 1-p(2); + if (noz == 0.0) noz = 1e-10; + + double xi = p(0) / noz; + double eta = p(1) / noz; + shape(0) = (1-xi)*(1-eta) * (noz); + shape(1) = ( xi)*(1-eta) * (noz); + shape(2) = ( xi)*( eta) * (noz); + shape(3) = (1-xi)*( eta) * (noz); + shape(4) = p(2); + break; + } + + case PRISM: + { + shape(0) = p(0) * (1-p(2)); + shape(1) = p(1) * (1-p(2)); + shape(2) = (1-p(0)-p(1)) * (1-p(2)); + shape(3) = p(0) * p(2); + shape(4) = p(1) * p(2); + shape(5) = (1-p(0)-p(1)) * p(2); + break; + } + case HEX: + { + shape(0) = (1-p(0))*(1-p(1))*(1-p(2)); + shape(1) = ( p(0))*(1-p(1))*(1-p(2)); + shape(2) = ( p(0))*( p(1))*(1-p(2)); + shape(3) = (1-p(0))*( p(1))*(1-p(2)); + shape(4) = (1-p(0))*(1-p(1))*( p(2)); + shape(5) = ( p(0))*(1-p(1))*( p(2)); + shape(6) = ( p(0))*( p(1))*( p(2)); + shape(7) = (1-p(0))*( p(1))*( p(2)); + break; + } + } +} + + + + +void Element :: +GetDShape (const Point<3> & hp, DenseMatrix & dshape) const +{ + Point3d p = hp; + + int np = GetNP(); + if (dshape.Height() != 3 || dshape.Width() != np) + { + cerr << "Element::DShape: Sizes don't fit" << endl; + return; + } + + int i, j; + double eps = 1e-6; + Vector shaper(np), shapel(np); + + for (i = 1; i <= 3; i++) + { + Point3d pr(p), pl(p); + pr.X(i) += eps; + pl.X(i) -= eps; + + GetShape (pr, shaper); + GetShape (pl, shapel); + for (j = 1; j <= np; j++) + dshape.Elem(i, j) = (shaper.Get(j) - shapel.Get(j)) / (2 * eps); + } +} + + + +void Element :: +GetDShapeNew (const Point<3> & p, MatrixFixWidth<3> & dshape) const +{ + switch (typ) + { + case TET: + { + dshape = 0; + dshape(0,0) = 1; + dshape(1,1) = 1; + dshape(2,2) = 1; + dshape(3,0) = -1; + dshape(3,1) = -1; + dshape(3,2) = -1; + break; + } + case PRISM: + { + dshape = 0; + dshape(0,0) = 1-p(2); + dshape(0,2) = -p(0); + dshape(1,1) = 1-p(2); + dshape(1,2) = -p(1); + dshape(2,0) = -(1-p(2)); + dshape(2,1) = -(1-p(2)); + dshape(2,2) = -(1-p(0)-p(1)); + + dshape(3,0) = p(2); + dshape(3,2) = p(0); + dshape(4,1) = p(2); + dshape(4,2) = p(1); + dshape(5,0) = -p(2); + dshape(5,1) = -p(2); + dshape(5,2) = 1-p(0)-p(1); + break; + } + + default: + { + int np = GetNP(); + double eps = 1e-6; + Vector shaper(np), shapel(np); + + for (int i = 1; i <= 3; i++) + { + Point3d pr(p), pl(p); + pr.X(i) += eps; + pl.X(i) -= eps; + + GetShapeNew (pr, shaper); + GetShapeNew (pl, shapel); + for (int j = 1; j <= np; j++) + dshape.Elem(j, i) = (shaper.Get(j) - shapel.Get(j)) / (2 * eps); + } + } + } +} + +void Element :: +GetPointMatrix (const T_POINTS & points, + DenseMatrix & pmat) const +{ + int np = GetNP(); + /* + if (pmat.Width() != np || pmat.Height() != 3) + { + cerr << "Element::GetPointMatrix: sizes don't fit" << endl; + return; + } + */ + for (int i = 1; i <= np; i++) + { + const Point3d & p = points.Get(PNum(i)); + pmat.Elem(1, i) = p.X(); + pmat.Elem(2, i) = p.Y(); + pmat.Elem(3, i) = p.Z(); + } +} + + + + + + +double Element :: CalcJacobianBadness (const T_POINTS & points) const +{ + int i, j; + int nip = GetNIP(); + static DenseMatrix trans(3,3); + static DenseMatrix pmat; + + pmat.SetSize (3, GetNP()); + GetPointMatrix (points, pmat); + + double err = 0; + for (i = 1; i <= nip; i++) + { + GetTransformation (i, pmat, trans); + + // Frobenius norm + double frob = 0; + for (j = 1; j <= 9; j++) + frob += sqr (trans.Get(j)); + frob = sqrt (frob); + frob /= 3; + + double det = -trans.Det(); + + if (det <= 0) + err += 1e12; + else + err += frob * frob * frob / det; + } + + err /= nip; + return err; +} + +double Element :: +CalcJacobianBadnessDirDeriv (const T_POINTS & points, + int pi, Vec<3> & dir, double & dd) const +{ + int i, j, k, l; + int nip = GetNIP(); + static DenseMatrix trans(3,3), dtrans(3,3), hmat(3,3); + static DenseMatrix pmat, vmat; + + pmat.SetSize (3, GetNP()); + vmat.SetSize (3, GetNP()); + + GetPointMatrix (points, pmat); + + for (i = 1; i <= np; i++) + for (j = 1; j <= 3; j++) + vmat.Elem(j, i) = 0; + for (j = 1; j <= 3; j++) + vmat.Elem(j, pi) = dir(j-1); + + + + double err = 0; + dd = 0; + + for (i = 1; i <= nip; i++) + { + GetTransformation (i, pmat, trans); + GetTransformation (i, vmat, dtrans); + + + // Frobenius norm + double frob = 0; + for (j = 1; j <= 9; j++) + frob += sqr (trans.Get(j)); + frob = sqrt (frob); + + double dfrob = 0; + for (j = 1; j <= 9; j++) + dfrob += trans.Get(j) * dtrans.Get(j); + dfrob = dfrob / frob; + + frob /= 3; + dfrob /= 3; + + + double det = trans.Det(); + double ddet = 0; + + for (j = 1; j <= 3; j++) + { + hmat = trans; + for (k = 1; k <= 3; k++) + hmat.Elem(k, j) = dtrans.Get(k, j); + ddet += hmat.Det(); + } + + + det *= -1; + ddet *= -1; + + + if (det <= 0) + err += 1e12; + else + { + err += frob * frob * frob / det; + dd += (3 * frob * frob * dfrob * det - frob * frob * frob * ddet) / (det * det); + } + } + + err /= nip; + dd /= nip; + return err; +} + +double Element :: +CalcJacobianBadnessGradient (const T_POINTS & points, + int pi, Vec<3> & grad) const +{ + int i, j, k, l; + int nip = GetNIP(); + static DenseMatrix trans(3,3), dtrans(3,3), hmat(3,3); + static DenseMatrix pmat, vmat; + + pmat.SetSize (3, GetNP()); + vmat.SetSize (3, GetNP()); + + GetPointMatrix (points, pmat); + + for (i = 1; i <= np; i++) + for (j = 1; j <= 3; j++) + vmat.Elem(j, i) = 0; + for (j = 1; j <= 3; j++) + vmat.Elem(j, pi) = 1.; + + + double err = 0; + + double dfrob[3]; + + grad = 0; + + for (i = 1; i <= nip; i++) + { + GetTransformation (i, pmat, trans); + GetTransformation (i, vmat, dtrans); + + // Frobenius norm + double frob = 0; + for (j = 1; j <= 9; j++) + frob += sqr (trans.Get(j)); + frob = sqrt (frob); + + for(k = 0; k<3; k++) + { + dfrob[k] = 0; + for (j = 1; j <= 3; j++) + dfrob[k] += trans.Get(k+1,j) * dtrans.Get(k+1,j); + dfrob[k] = dfrob[k] / (3.*frob); + } + + frob /= 3; + + double det = trans.Det(); + double ddet[3]; // = 0; + + for(k=1; k<=3; k++) + { + int km1 = (k > 1) ? (k-1) : 3; + int kp1 = (k < 3) ? (k+1) : 1; + ddet[k-1] = 0; + for(j=1; j<=3; j++) + { + int jm1 = (j > 1) ? (j-1) : 3; + int jp1 = (j < 3) ? (j+1) : 1; + + ddet[k-1] += (-1.)* dtrans.Get(k,j) * ( trans.Get(km1,jm1)*trans.Get(kp1,jp1) - + trans.Get(km1,jp1)*trans.Get(kp1,jm1) ); + } + } + + + det *= -1; + + if (det <= 0) + err += 1e12; + else + { + err += frob * frob * frob / det; + double fac = (frob * frob)/(det * det); + for(j=0; j<3; j++) + grad(j) += fac * (3 * dfrob[j] * det - frob * ddet[j]); + } + } + + err /= nip; + grad *= 1./nip; + return err; +} + + + + + + +void Element :: ComputeIntegrationPointData () const +{ + switch (GetType()) + { + case TET: if (ipdtet.Size()) return; break; + case TET10: if (ipdtet10.Size()) return; break; + default: + PrintSysError ("Element::ComputeIntegrationPoint, illegal type ", int(typ)); + } + + switch (GetType()) + { + case TET: ipdtet.SetSize(GetNIP()); break; + case TET10: ipdtet10.SetSize(GetNIP()); break; + } + + + for (int i = 1; i <= GetNIP(); i++) + { + IntegrationPointData * ipd = new IntegrationPointData; + GetIntegrationPoint (i, ipd->p, ipd->weight); + ipd->shape.SetSize(GetNP()); + ipd->dshape.SetSize(3, GetNP()); + + GetShape (ipd->p, ipd->shape); + GetDShape (ipd->p, ipd->dshape); + + switch (GetType()) + { + case TET: ipdtet.Elem(i).Reset(ipd); break; + case TET10: ipdtet10.Elem(i).Reset(ipd); break; + default: + PrintSysError ("Element::ComputeIntegrationPoint(2), illegal type ", int(typ)); + } + } +} + + + + + + + + +FaceDescriptor :: FaceDescriptor() +{ + surfnr = domin = domout = bcprop = 0; + domin_singular = domout_singular = 0.; + tlosurf = -1; + bcname = 0; + firstelement = -1; +} + +FaceDescriptor :: FaceDescriptor(const FaceDescriptor& other) + : surfnr(other.surfnr), domin(other.domin), domout(other.domout), + tlosurf(other.tlosurf), bcprop(other.bcprop), bcname(other.bcname), + domin_singular(other.domin_singular), domout_singular(other.domout_singular) +{ + firstelement = -1; +} + +FaceDescriptor :: +FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi) +{ + surfnr = surfnri; + domin = domini; + domout = domouti; + tlosurf = tlosurfi; + bcprop = surfnri; + domin_singular = domout_singular = 0.; + bcname = 0; + firstelement = -1; +} + +FaceDescriptor :: FaceDescriptor(const Segment & seg) +{ + surfnr = seg.si; + domin = seg.domin+1; + domout = seg.domout+1; + tlosurf = seg.tlosurf+1; + bcprop = 0; + domin_singular = domout_singular = 0.; + bcname = 0; + firstelement = -1; +} + +int FaceDescriptor :: SegmentFits (const Segment & seg) +{ + return + surfnr == seg.si && + domin == seg.domin+1 && + domout == seg.domout+1 && + tlosurf == seg.tlosurf+1; +} + + +string FaceDescriptor :: GetBCName () const +{ + if ( bcname ) + return *bcname; + else + return "default"; + +} + +/* +void FaceDescriptor :: SetBCName (string * bcn) +{ + bcname = bcn; +} +*/ + + +ostream & operator<<(ostream & s, const FaceDescriptor & fd) +{ + s << "surfnr = " << fd.surfnr + << ", domin = " << fd.domin + << ", domout = " << fd.domout + << ", tlosurf = " << fd.tlosurf + << ", bcprop = " << fd.bcprop + << ", domin_sing = " << fd.domin_singular + << ", domout_sing = " << fd.domout_singular; + return s; +} + + + + + + +Identifications :: Identifications (Mesh & amesh) + : mesh(amesh) +{ + identifiedpoints = new INDEX_2_HASHTABLE<int>(100); + identifiedpoints_nr = new INDEX_3_HASHTABLE<int>(100); + maxidentnr = 0; +} + +Identifications :: ~Identifications () +{ + delete identifiedpoints; + delete identifiedpoints_nr; +} + +void Identifications :: Delete () +{ + delete identifiedpoints; + identifiedpoints = new INDEX_2_HASHTABLE<int>(100); + delete identifiedpoints_nr; + identifiedpoints_nr = new INDEX_3_HASHTABLE<int>(100); + maxidentnr = 0; +} + +void Identifications :: Add (PointIndex pi1, PointIndex pi2, int identnr) +{ + // (*testout) << "Identification::Add, pi1 = " << pi1 << ", pi2 = " << pi2 << ", identnr = " << identnr << endl; + INDEX_2 pair (pi1, pi2); + identifiedpoints->Set (pair, identnr); + + INDEX_3 tripl (pi1, pi2, identnr); + identifiedpoints_nr->Set (tripl, 1); + + if (identnr > maxidentnr) maxidentnr = identnr; + + if (identnr+1 > idpoints_table.Size()) + idpoints_table.ChangeSize (identnr+1); + idpoints_table.Add (identnr, pair); + + // timestamp = NextTimeStamp(); +} + +int Identifications :: Get (PointIndex pi1, PointIndex pi2) const +{ + INDEX_2 pair(pi1, pi2); + if (identifiedpoints->Used (pair)) + return identifiedpoints->Get(pair); + else + return 0; +} + +bool Identifications :: Get (PointIndex pi1, PointIndex pi2, int nr) const +{ + INDEX_3 tripl(pi1, pi2, nr); + if (identifiedpoints_nr->Used (tripl)) + return 1; + else + return 0; +} + + + +int Identifications :: GetSymmetric (PointIndex pi1, PointIndex pi2) const +{ + INDEX_2 pair(pi1, pi2); + if (identifiedpoints->Used (pair)) + return identifiedpoints->Get(pair); + + pair = INDEX_2 (pi2, pi1); + if (identifiedpoints->Used (pair)) + return identifiedpoints->Get(pair); + + return 0; +} + + +void Identifications :: GetMap (int identnr, ARRAY<int,PointIndex::BASE> & identmap, bool symmetric) const +{ + identmap.SetSize (mesh.GetNP()); + identmap = 0; + + if (identnr) + for (int i = 0; i < idpoints_table[identnr].Size(); i++) + { + INDEX_2 pair = idpoints_table[identnr][i]; + identmap[pair.I1()] = pair.I2(); + if(symmetric) + identmap[pair.I2()] = pair.I1(); + } + + else + { + cout << "getmap, identnr = " << identnr << endl; + + for (int i = 1; i <= identifiedpoints_nr->GetNBags(); i++) + for (int j = 1; j <= identifiedpoints_nr->GetBagSize(i); j++) + { + INDEX_3 i3; + int dummy; + identifiedpoints_nr->GetData (i, j, i3, dummy); + + if (i3.I3() == identnr || !identnr) + { + identmap.Elem(i3.I1()) = i3.I2(); + if(symmetric) + identmap.Elem(i3.I2()) = i3.I1(); + } + } + } + +} + + +void Identifications :: GetPairs (int identnr, + ARRAY<INDEX_2> & identpairs) const +{ + identpairs.SetSize(0); + + if (identnr == 0) + for (int i = 1; i <= identifiedpoints->GetNBags(); i++) + for (int j = 1; j <= identifiedpoints->GetBagSize(i); j++) + { + INDEX_2 i2; + int nr; + identifiedpoints->GetData (i, j, i2, nr); + identpairs.Append (i2); + } + else + for (int i = 1; i <= identifiedpoints_nr->GetNBags(); i++) + for (int j = 1; j <= identifiedpoints_nr->GetBagSize(i); j++) + { + INDEX_3 i3; + int dummy; + identifiedpoints_nr->GetData (i, j, i3 , dummy); + + if (i3.I3() == identnr) + identpairs.Append (INDEX_2(i3.I1(), i3.I2())); + } +} + + +void Identifications :: SetMaxPointNr (int maxpnum) +{ + for (int i = 1; i <= identifiedpoints->GetNBags(); i++) + for (int j = 1; j <= identifiedpoints->GetBagSize(i); j++) + { + INDEX_2 i2; + int nr; + identifiedpoints->GetData (i, j, i2, nr); + + if (i2.I1() > maxpnum || i2.I2() > maxpnum) + { + i2.I1() = i2.I2() = -1; + identifiedpoints->SetData (i, j, i2, -1); + } + } +} + + +void Identifications :: Print (ostream & ost) const +{ + ost << "Identifications:" << endl; + ost << "pairs: " << endl << *identifiedpoints << endl; + ost << "pairs and nr: " << endl << *identifiedpoints_nr << endl; + ost << "table: " << endl << idpoints_table << endl; +} + + +MeshingParameters :: MeshingParameters () +{ + optimize3d = "cmdmustm"; + //optimize3d = "cmdmstm"; + optsteps3d = 3; + optimize2d = "smsmsmSmSmSm"; + optsteps2d = 3; + opterrpow = 2; + blockfill = 1; + filldist = 0.1; + safety = 5; + relinnersafety = 3; + uselocalh = 1; + grading = 0.3; + delaunay = 1; + maxh = 1e10; + minh = 0; + meshsizefilename = NULL; + startinsurface = 0; + checkoverlap = 1; + checkoverlappingboundary = 1; + checkchartboundary = 1; + curvaturesafety = 2; + segmentsperedge = 1; + parthread = 0; + + elsizeweight = 0.2; + giveuptol2d = 200; + giveuptol = 10; + maxoutersteps = 10; + starshapeclass = 5; + baseelnp = 0; + sloppy = 1; + + badellimit = 175; + check_impossible = 0; + secondorder = 0; +} + +void MeshingParameters :: Print (ostream & ost) const +{ + ost << "Meshing parameters: " << endl + << "optimize3d = " << optimize3d << endl + << "optsteps3d = " << optsteps3d << endl + << " optimize2d = " << optimize2d << endl + << " optsteps2d = " << optsteps2d << endl + << " opterrpow = " << opterrpow << endl + << " blockfill = " << blockfill << endl + << " filldist = " << filldist << endl + << " safety = " << safety << endl + << " relinnersafety = " << relinnersafety << endl + << " uselocalh = " << uselocalh << endl + << " grading = " << grading << endl + << " delaunay = " << delaunay << endl + << " maxh = " << maxh << endl; + if(meshsizefilename) + ost << " meshsizefilename = " << meshsizefilename << endl; + else + ost << " meshsizefilename = NULL" << endl; + ost << " startinsurface = " << startinsurface << endl + << " checkoverlap = " << checkoverlap << endl + << " checkchartboundary = " << checkchartboundary << endl + << " curvaturesafety = " << curvaturesafety << endl + << " segmentsperedge = " << segmentsperedge << endl + << " parthread = " << parthread << endl + << " elsizeweight = " << elsizeweight << endl + << " giveuptol2d = " << giveuptol2d << endl + << " giveuptol = " << giveuptol << endl + << " maxoutersteps = " << maxoutersteps << endl + << " starshapeclass = " << starshapeclass << endl + << " baseelnp = " << baseelnp << endl + << " sloppy = " << sloppy << endl + << " badellimit = " << badellimit << endl + << " secondorder = " << secondorder << endl + << " elementorder = " << elementorder << endl + << " quad = " << quad << endl + << " inverttets = " << inverttets << endl + << " inverttrigs = " << inverttrigs << endl; +} + +void MeshingParameters :: CopyFrom(const MeshingParameters & other) +{ + //strcpy(optimize3d,other.optimize3d); + optimize3d = other.optimize3d; + optsteps3d = other.optsteps3d; + //strcpy(optimize2d,other.optimize2d); + optimize2d = other.optimize2d; + optsteps2d = other.optsteps2d; + opterrpow = other.opterrpow; + blockfill = other.blockfill; + filldist = other.filldist; + safety = other.safety; + relinnersafety = other.relinnersafety; + uselocalh = other.uselocalh; + grading = other.grading; + delaunay = other.delaunay; + maxh = other.maxh; + //strcpy(const_cast<char*>(meshsizefilename), other.meshsizefilename); + //const_cast<char*>(meshsizefilename) = other.meshsizefilename; //??? + startinsurface = other.startinsurface; + checkoverlap = other.checkoverlap; + checkoverlappingboundary = other.checkoverlappingboundary; + checkchartboundary = other.checkchartboundary; + curvaturesafety = other.curvaturesafety; + segmentsperedge = other.segmentsperedge; + parthread = other.parthread; + elsizeweight = other.elsizeweight; + giveuptol2d = other.giveuptol2d; + giveuptol = other.giveuptol; + maxoutersteps = other.maxoutersteps; + starshapeclass = other.starshapeclass; + baseelnp = other.baseelnp; + sloppy = other.sloppy; + badellimit = other.badellimit; + secondorder = other.secondorder; + elementorder = other.elementorder; + quad = other.quad; + inverttets = other.inverttets; + inverttrigs = other.inverttrigs; +} + + +DebugParameters :: DebugParameters () +{ + slowchecks = 0; + haltsuccess = 0; + haltnosuccess = 0; + haltlargequalclass = 0; + haltsegment = 0; + haltsegmentp1 = 0; + haltsegmentp2 = 0; +}; + + + +} + diff --git a/contrib/Netgen/libsrc/meshing/meshtype.hpp b/contrib/Netgen/libsrc/meshing/meshtype.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fdae56b4546774e85ac67c666241e53c18979d08 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/meshtype.hpp @@ -0,0 +1,1229 @@ +#ifndef MESHTYPE +#define MESHTYPE + + +/**************************************************************************/ +/* File: meshtype.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Okt. 95 */ +/**************************************************************************/ + +/* + Classes for NETGEN +*/ + + +enum ELEMENT_TYPE { + SEGMENT = 1, SEGMENT3 = 2, + TRIG = 10, QUAD=11, TRIG6 = 12, QUAD6 = 13, QUAD8 = 14, + TET = 20, TET10 = 21, + PYRAMID = 22, PRISM = 23, PRISM12 = 24, + HEX = 25 +}; + +typedef int ELEMENT_EDGE[2]; // initial point, end point +typedef int ELEMENT_FACE[4]; // points, last one is -1 for trig + + +#define ELEMENT_MAXPOINTS 12 +#define ELEMENT2D_MAXPOINTS 8 + + +enum POINTTYPE { FIXEDPOINT = 1, EDGEPOINT = 2, SURFACEPOINT = 3, INNERPOINT = 4 }; +enum ELEMENTTYPE { FREEELEMENT, FIXEDELEMENT }; +enum OPTIMIZEGOAL { OPT_QUALITY, OPT_CONFORM, OPT_REST, OPT_WORSTCASE, OPT_LEGAL }; + + + +extern int GetTimeStamp(); +extern int NextTimeStamp(); + +class PointGeomInfo +{ +public: + int trignum; // for STL Meshing + double u, v; // for OCC Meshing + + PointGeomInfo () + : trignum(-1), u(0), v(0) { ; } +}; + +inline ostream & operator<< (ostream & ost, const PointGeomInfo & gi) +{ + return (ost << gi.trignum << " " << gi.u << " " << gi.v); +} + +inline istream & operator>> (istream & ist, PointGeomInfo & gi) +{ + return (ist >> gi.trignum >> gi.u >> gi.v); +} + + + +#define MULTIPOINTGEOMINFO_MAX 100 +class MultiPointGeomInfo +{ + int cnt; + PointGeomInfo mgi[MULTIPOINTGEOMINFO_MAX]; +public: + MultiPointGeomInfo () { cnt = 0; } + int AddPointGeomInfo (const PointGeomInfo & gi); + void Init () { cnt = 0; } + void DeleteAll () { cnt = 0; } + + int GetNPGI () const { return cnt; } + const PointGeomInfo & GetPGI (int i) const { return mgi[i-1]; } +}; + + +class EdgePointGeomInfo +{ +public: + int edgenr; + int body; // for ACIS + double u, v; // for OCC Meshing + double dist; // for 2d meshing + +public: + EdgePointGeomInfo () + : edgenr(0), body(0), dist(0.0), u(0.0), v(0.0) { ; } + + + EdgePointGeomInfo & operator= (const EdgePointGeomInfo & gi2) + { + edgenr = gi2.edgenr; + body = gi2.body; + dist = gi2.dist; + u = gi2.u; v = gi2.v; + return *this; + } +}; + +inline ostream & operator<< (ostream & ost, const EdgePointGeomInfo & gi) +{ + ost << "epgi: edgnr=" << gi.edgenr << ", dist=" << gi.dist; + return ost; +} + + + + + +class PointIndex +{ + int i; +public: + PointIndex () { ; } + PointIndex (int ai) : i(ai) { ; } + PointIndex & operator= (const PointIndex &ai) { i = ai.i; return *this; } + PointIndex & operator= (int ai) { i = ai; return *this; } + operator int () const { return i; } + int GetInt () const { return i; } + PointIndex operator++ (int) { int hi = i; i++; return PointIndex(hi); } + PointIndex operator-- (int) { int hi = i; i--; return PointIndex(hi); } + +#ifdef BASE0 + enum { BASE = 0 }; +#else + enum { BASE = 1 }; +#endif +}; + +inline istream & operator>> (istream & ist, PointIndex & pi) +{ + int i; ist >> i; pi = i; return ist; +} + +inline ostream & operator<< (ostream & ost, const PointIndex & pi) +{ + return (ost << pi.GetInt()); +} + + + + +class ElementIndex +{ + int i; +public: + ElementIndex () { ; } + ElementIndex (int ai) : i(ai) { ; } + ElementIndex & operator= (const ElementIndex & ai) { i = ai.i; return *this; } + ElementIndex & operator= (int ai) { i = ai; return *this; } + operator int () const { return i; } + ElementIndex & operator++ (int) { i++; return *this; } + ElementIndex & operator-- (int) { i--; return *this; } +}; + +inline istream & operator>> (istream & ist, ElementIndex & pi) +{ + int i; ist >> i; pi = i; return ist; +} + +inline ostream & operator<< (ostream & ost, const ElementIndex & pi) +{ + return (ost << int(pi)); +} + + +class SurfaceElementIndex +{ + int i; +public: + SurfaceElementIndex () { ; } + SurfaceElementIndex (int ai) : i(ai) { ; } + SurfaceElementIndex & operator= (const SurfaceElementIndex & ai) + { i = ai.i; return *this; } + SurfaceElementIndex & operator= (int ai) { i = ai; return *this; } + operator int () const { return i; } + SurfaceElementIndex & operator++ (int) { i++; return *this; } + SurfaceElementIndex & operator-- (int) { i--; return *this; } +}; + +inline istream & operator>> (istream & ist, SurfaceElementIndex & pi) +{ + int i; ist >> i; pi = i; return ist; +} + +inline ostream & operator<< (ostream & ost, const SurfaceElementIndex & pi) +{ + return (ost << int(pi)); +} + +class SegmentIndex +{ + int i; +public: + SegmentIndex () { ; } + SegmentIndex (int ai) : i(ai) { ; } + SegmentIndex & operator= (const SegmentIndex & ai) + { i = ai.i; return *this; } + SegmentIndex & operator= (int ai) { i = ai; return *this; } + operator int () const { return i; } + SegmentIndex & operator++ (int) { i++; return *this; } + SegmentIndex & operator-- (int) { i--; return *this; } +}; + +inline istream & operator>> (istream & ist, SegmentIndex & pi) +{ + int i; ist >> i; pi = i; return ist; +} + +inline ostream & operator<< (ostream & ost, const SegmentIndex & pi) +{ + return (ost << int(pi)); +} + + + + +/** + Point in the mesh. + Contains layer (a new feature in 4.3 for overlapping meshes. + */ +class MeshPoint : public Point<3> +{ + int layer; + double singular; // singular factor for hp-refinement + POINTTYPE type; + +#ifdef PARALLEL + bool isghost; +#endif + +public: + MeshPoint () : layer(1), singular(0.), type(INNERPOINT) +{ +#ifdef PARALLEL + isghost = 0; +#endif + ; +} + + MeshPoint (const Point<3> & ap, int alayer = 1, POINTTYPE apt = INNERPOINT) + : Point<3> (ap), layer(alayer), singular(0.),type(apt) + { +#ifdef PARALLEL + isghost = 0; +#endif + ; + } + + void SetPoint (const Point<3> & ap) + { + Point<3>::operator= (ap); + layer = 0; + singular = 0; +#ifdef PARALLEL + isghost = 0; +#endif + } + + int GetLayer() const { return layer; } + + POINTTYPE Type() const { return type; } + void SetType(POINTTYPE at) { type = at; } + + double Singularity() const { return singular; } + void Singularity(double s) { singular = s; } + bool IsSingular() const { return (singular != 0.0); } + +#ifdef PARALLEL + bool IsGhost () const { return isghost; } + void SetGhost ( bool aisghost ) { isghost = aisghost; } +#endif + +}; + +ostream & operator<<(ostream & s, const MeshPoint & pt); + + + + +typedef MoveableArray<MeshPoint,PointIndex::BASE> T_POINTS; +// typedef ARRAY<MeshPoint,PointIndex::BASE> T_POINTS; + + +class Element2d; +ostream & operator<<(ostream & s, const Element2d & el); + +/** + Triangle element for surface mesh generation. + */ +class Element2d +{ + /// point numbers + PointIndex pnum[ELEMENT2D_MAXPOINTS]; + /// geom info of points + PointGeomInfo geominfo[ELEMENT2D_MAXPOINTS]; + + /// surface nr + int index:16; + /// + ELEMENT_TYPE typ:6; + /// number of points + unsigned int np:4; + bool badel:1; + bool refflag:1; // marked for refinement + bool strongrefflag:1; + bool deleted:1; // element is deleted + + /// order for hp-FEM + unsigned int orderx:6; + unsigned int ordery:6; + +#ifdef PARALLEL + bool isghost; + int partitionNumber; +#endif + + /// a linked list for all segments in the same face + SurfaceElementIndex next; + +public: + /// + Element2d (); + /// + Element2d (int anp); + /// + Element2d (ELEMENT_TYPE type); + /// + Element2d (int pi1, int pi2, int pi3); + /// + Element2d (int pi1, int pi2, int pi3, int pi4); + /// + ELEMENT_TYPE GetType () const { return typ; } + /// + void SetType (ELEMENT_TYPE atyp) + { + typ = atyp; + switch (typ) + { + case TRIG: np = 3; break; + case QUAD: np = 4; break; + case TRIG6: np = 6; break; + case QUAD6: np = 6; break; + case QUAD8: np = 8; break; + default: + PrintSysError ("Element2d::SetType, illegal type ", typ); + } + } + /// + int GetNP() const { return np; } + /// + int GetNV() const + { + switch (typ) + { + case TRIG: + case TRIG6: return 3; + + case QUAD: + case QUAD8: + case QUAD6: return 4; + default: +#ifdef DEBUG + PrintSysError ("element2d::GetNV not implemented for typ", typ) +#endif + ; + } + return np; + } + + /// + PointIndex & operator[] (int i) { return pnum[i]; } + /// + const PointIndex & operator[] (int i) const { return pnum[i]; } + + /// + PointIndex & PNum (int i) { return pnum[i-1]; } + /// + const PointIndex & PNum (int i) const { return pnum[i-1]; } + /// + PointIndex & PNumMod (int i) { return pnum[(i-1) % np]; } + /// + const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; } + /// + + /// + PointGeomInfo & GeomInfoPi (int i) { return geominfo[i-1]; } + /// + const PointGeomInfo & GeomInfoPi (int i) const { return geominfo[i-1]; } + /// + PointGeomInfo & GeomInfoPiMod (int i) { return geominfo[(i-1) % np]; } + /// + const PointGeomInfo & GeomInfoPiMod (int i) const { return geominfo[(i-1) % np]; } + + + void SetIndex (int si) { index = si; } + /// + int GetIndex () const { return index; } + + int GetOrder () const { return orderx; } + void SetOrder (int aorder) { orderx = ordery = aorder; } + + + void GetOrder (int & ox, int & oy) const { ox = orderx, oy =ordery;}; + void GetOrder (int & ox, int & oy, int & oz) const { ox = orderx; oy = ordery; oz=0; } + void SetOrder (int ox, int oy, int oz) { orderx = ox; ordery = oy;} + void SetOrder (int ox, int oy) { orderx = ox; ordery = oy;} + + + /// + void GetBox (const T_POINTS & points, Box3d & box) const; + /// invert orientation + inline void Invert (); + /// + void Invert2 (); + /// first point number is smallest + inline void NormalizeNumbering (); + /// + void NormalizeNumbering2 (); + + bool BadElement() const { return badel; } + + friend ostream & operator<<(ostream & s, const Element2d & el); + friend class Mesh; + + + /// get number of 'integration points' + int GetNIP () const; + void GetIntegrationPoint (int ip, Point2d & p, double & weight) const; + void GetTransformation (int ip, const ARRAY<Point2d> & points, + class DenseMatrix & trans) const; + void GetTransformation (int ip, class DenseMatrix & pmat, + class DenseMatrix & trans) const; + + void GetShape (const Point2d & p, class Vector & shape) const; + void GetShapeNew (const Point<2> & p, class FlatVector & shape) const; + /// matrix 2 * np + void GetDShape (const Point2d & p, class DenseMatrix & dshape) const; + void GetDShapeNew (const Point<2> & p, class MatrixFixWidth<2> & dshape) const; + /// matrix 2 * np + void GetPointMatrix (const ARRAY<Point2d> & points, + class DenseMatrix & pmat) const; + + void ComputeIntegrationPointData () const; + + + double CalcJacobianBadness (const ARRAY<Point2d> & points) const; + double CalcJacobianBadness (const T_POINTS & points, + const Vec<3> & n) const; + double CalcJacobianBadnessDirDeriv (const ARRAY<Point2d> & points, + int pi, Vec2d & dir, double & dd) const; + + + + void Delete () { deleted = 1; pnum[0] = pnum[1] = pnum[2] = pnum[3] = PointIndex::BASE-1; } + bool IsDeleted () const + { +#ifdef DEBUG + if (pnum[0] < PointIndex::BASE && !deleted) + cerr << "Surfelement has illegal pnum, but not marked as deleted" << endl; +#endif + return deleted; + } + + void SetRefinementFlag (bool rflag = 1) + { refflag = rflag; } + bool TestRefinementFlag () const + { return refflag; } + + void SetStrongRefinementFlag (bool rflag = 1) + { strongrefflag = rflag; } + bool TestStrongRefinementFlag () const + { return strongrefflag; } + + + bool operator==(const Element2d & el2) const; + + int HasFace(const Element2d& el) const; + /// + int meshdocval; + /// + int hp_elnr; + +#ifdef PARALLEL + bool IsGhost () const { return isghost; } + void SetGhost ( bool aisghost ) { isghost = aisghost; } + + // by JS, only for 2D meshes ???? + int GetPartition () const { return partitionNumber; } + void SetPartition (int nr) { partitionNumber = nr; }; +#endif + +}; + + + + +class IntegrationPointData +{ +public: + Point<3> p; + double weight; + Vector shape; + DenseMatrix dshape; +}; + + + + +class Element; +ostream & operator<<(ostream & s, const Element & el); + + + +/** + Volume element + */ +class Element +{ +private: + /// point numbers + PointIndex pnum[ELEMENT_MAXPOINTS]; + /// + ELEMENT_TYPE typ:6; + /// number of points (4..tet, 5..pyramid, 6..prism, 8..hex, 10..quad tet, 12..quad prism) + int np:5; + /// + class flagstruct { + public: + bool marked:1; // marked for refinement + bool badel:1; // angles worse then limit + bool reverse:1; // for refinement a la Bey + bool illegal:1; // illegal, will be split or swaped + bool illegal_valid:1; // is illegal-flag valid ? + bool badness_valid:1; // is badness valid ? + bool refflag:1; // mark element for refinement + bool strongrefflag:1; + bool deleted:1; // element is deleted, will be removed from array + bool fixed:1; // don't change element in optimization + }; + + /// sub-domain index + short int index; + /// order for hp-FEM + unsigned int orderx:6; + unsigned int ordery:6; + unsigned int orderz:6; + /* unsigned int levelx:6; + unsigned int levely:6; + unsigned int levelz:6; */ + /// stored shape-badness of element + float badness; + +#ifdef PARALLEL + /// number of partition for parallel computation + int partitionNumber; + bool isghost; +#endif + +public: + flagstruct flags; + + /// + Element (); + /// + Element (int anp); + /// + Element (ELEMENT_TYPE type); + /// + Element & operator= (const Element & el2); + + /// + void SetNP (int anp); + /// + void SetType (ELEMENT_TYPE atyp); + /// + int GetNP () const { return np; } + /// + int GetNV() const + { + switch (typ) + { + case TET: + case TET10: + return 4; + case PRISM12: + case PRISM: + return 6; + case PYRAMID: + return 5; + case HEX: + return 8; + default: +#ifdef DEBUG + PrintSysError ("Element3d::GetNV not implemented for typ ", typ) +#endif + ; + } + return np; + } + + bool operator==(const Element & el2) const; + + // old style: + int NP () const { return np; } + + /// + ELEMENT_TYPE GetType () const { return typ; } + + /// + PointIndex & operator[] (int i) { return pnum[i]; } + /// + const PointIndex & operator[] (int i) const { return pnum[i]; } + + /// + PointIndex & PNum (int i) { return pnum[i-1]; } + /// + const PointIndex & PNum (int i) const { return pnum[i-1]; } + /// + PointIndex & PNumMod (int i) { return pnum[(i-1) % np]; } + /// + const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; } + + /// + void SetIndex (int si) { index = si; } + /// + int GetIndex () const { return index; } + + int GetOrder () const { return orderx; } + void SetOrder (const int aorder) ; + + void GetOrder (int & ox, int & oy, int & oz) const { ox = orderx; oy = ordery; oz = orderz; } + void SetOrder (const int ox, const int oy, const int oz); + // void GetLevel (int & ox, int & oy, int & oz) const { ox = levelx; oy = levely; oz = levelz; } + // void SetLevel (int ox, int oy, int oz) { levelx = ox; levely = oy; levelz = oz; } + + + /// + void GetBox (const T_POINTS & points, Box3d & box) const; + /// Calculates Volume of elemenet + double Volume (const T_POINTS & points) const; + /// + virtual void Print (ostream & ost) const; + /// + int GetNFaces () const + { + switch (typ) + { + case TET: + case TET10: return 4; + case PYRAMID: return 5; + case PRISM: + case PRISM12: return 5; + default: +#ifdef DEBUG + PrintSysError ("element3d::GetNFaces not implemented for typ", typ) +#endif + ; + } + return 0; + } + /// + inline void GetFace (int i, Element2d & face) const; + /// + void GetFace2 (int i, Element2d & face) const; + /// + void Invert (); + + /// split into 4 node tets + void GetTets (ARRAY<Element> & locels) const; + /// split into 4 node tets, local point nrs + void GetTetsLocal (ARRAY<Element> & locels) const; + /// returns coordinates of nodes + // void GetNodesLocal (ARRAY<Point<3> > & points) const; + void GetNodesLocalNew (ARRAY<Point<3> > & points) const; + + /// split surface into 3 node trigs + void GetSurfaceTriangles (ARRAY<Element2d> & surftrigs) const; + + + /// get number of 'integration points' + int GetNIP () const; + void GetIntegrationPoint (int ip, Point<3> & p, double & weight) const; + void GetTransformation (int ip, const T_POINTS & points, + class DenseMatrix & trans) const; + void GetTransformation (int ip, class DenseMatrix & pmat, + class DenseMatrix & trans) const; + + void GetShape (const Point<3> & p, class Vector & shape) const; + void GetShapeNew (const Point<3> & p, class FlatVector & shape) const; + /// matrix 2 * np + void GetDShape (const Point<3> & p, class DenseMatrix & dshape) const; + void GetDShapeNew (const Point<3> & p, class MatrixFixWidth<3> & dshape) const; + /// matrix 3 * np + void GetPointMatrix (const T_POINTS & points, + class DenseMatrix & pmat) const; + + void ComputeIntegrationPointData () const; + + + double CalcJacobianBadness (const T_POINTS & points) const; + double CalcJacobianBadnessDirDeriv (const T_POINTS & points, + int pi, Vec<3> & dir, double & dd) const; + double CalcJacobianBadnessGradient (const T_POINTS & points, + int pi, Vec<3> & grad) const; + + /// + friend ostream & operator<<(ostream & s, const Element & el); + + void SetRefinementFlag (bool rflag = 1) + { flags.refflag = rflag; } + int TestRefinementFlag () const + { return flags.refflag; } + + void SetStrongRefinementFlag (bool rflag = 1) + { flags.strongrefflag = rflag; } + int TestStrongRefinementFlag () const + { return flags.strongrefflag; } + + int Illegal () const + { return flags.illegal; } + int IllegalValid () const + { return flags.illegal_valid; } + void SetIllegal (int aillegal) + { + flags.illegal = aillegal ? 1 : 0; + flags.illegal_valid = 1; + } + void SetLegal (int alegal) + { + flags.illegal = alegal ? 0 : 1; + flags.illegal_valid = 1; + } + + void Delete () { flags.deleted = 1; } + bool IsDeleted () const + { +#ifdef DEBUG + if (pnum[0] < PointIndex::BASE && !flags.deleted) + cerr << "Volelement has illegal pnum, but not marked as deleted" << endl; +#endif + + return flags.deleted; + } + +#ifdef PARALLEL + int GetPartition () const { return partitionNumber; } + void SetPartition (int nr) { partitionNumber = nr; }; +#endif + + int hp_elnr; + +#ifdef PARALLEL + bool IsGhost () const { return isghost; } + + void SetGhost ( const bool aisghost ) { isghost = aisghost; } +#endif + + friend class Mesh; +}; + + +class Segment; +ostream & operator<<(ostream & s, const Segment & seg); + + +/** + Edge segment. + */ +class Segment +{ +public: + /// + Segment(); + Segment (const Segment& other); + + ~Segment() + { ; } + + friend ostream & operator<<(ostream & s, const Segment & seg); + + /// point index 1 + PointIndex p1; + /// point index 2 + PointIndex p2; + /// edge nr + int edgenr; + /// + double singedge_left; + double singedge_right; + + /// 0.. not first segment of segs, 1..first of class, 2..first of class, inverse + unsigned int seginfo:2; + + /// surface decoding index + int si; + /// domain number inner side + int domin; + /// domain number outer side + int domout; + /// top-level object number of surface + int tlosurf; + /// + PointGeomInfo geominfo[2]; + + /// surfaces describing edge + int surfnr1, surfnr2; + /// + EdgePointGeomInfo epgeominfo[2]; + /// + int pmid; // for second order + /// + int meshdocval; + +private: + string* bcname; + +public: + PointIndex operator[] (int i) const + { return (i == 0) ? p1 : p2; } + + PointIndex & operator[] (int i) + { return (i == 0) ? p1 : p2; } + + Segment& operator=(const Segment & other); + + + int hp_elnr; + + void SetBCName ( string * abcname ) + { + bcname = abcname; + } + + string * BCNamePtr () + { return bcname; } + + const string * BCNamePtr () const + { return bcname; } + + string GetBCName () const + { + if (! bcname ) + { + return "default"; + } + return *bcname; + } + + +}; + + +// class Surface; +class FaceDescriptor; +ostream & operator<< (ostream & s, const FaceDescriptor & fd); + +/// +class FaceDescriptor +{ + /// which surface, 0 if not available + int surfnr; + /// domain nr inside + int domin; + /// domain nr outside + int domout; + /// top level object number of surface + int tlosurf; + /// boundary condition property + int bcprop; + + /// + string * bcname; + /// root of linked list + SurfaceElementIndex firstelement; + +public: + /// + double domin_singular; + double domout_singular; +public: + FaceDescriptor(); + FaceDescriptor(int surfnri, int domini, int domouti, int tlosurfi); + FaceDescriptor(const Segment & seg); + FaceDescriptor(const FaceDescriptor& other); + ~FaceDescriptor() { ; } + + int SegmentFits (const Segment & seg); + + int SurfNr () const { return surfnr; } + int DomainIn () const { return domin; } + int DomainOut () const { return domout; } + int TLOSurface () const { return tlosurf; } + int BCProperty () const { return bcprop; } + string GetBCName () const; + // string * BCNamePtr () { return bcname; } + // const string * BCNamePtr () const { return bcname; } + void SetSurfNr (int sn) { surfnr = sn; } + void SetDomainIn (int di) { domin = di; } + void SetDomainOut (int dom) { domout = dom; } + void SetBCProperty (int bc) { bcprop = bc; } + void SetBCName (string * bcn) { bcname = bcn; } + + friend ostream & operator<<(ostream & s, const FaceDescriptor & fd); + friend class Mesh; +}; + + + + + + +class MeshingParameters +{ +public: + /** + 3d optimization strategy: + // m .. move nodes + // M .. move nodes, cheap functional + // s .. swap faces + // c .. combine elements + // d .. divide elements + // p .. plot, no pause + // P .. plot, Pause + // h .. Histogramm, no pause + // H .. Histogramm, pause + */ + const char * optimize3d; + /// number of 3d optimization steps + int optsteps3d; + /** + 2d optimization strategy: + // s .. swap, opt 6 lines/node + // S .. swap, optimal elements + // m .. move nodes + // p .. plot, no pause + // P .. plot, pause + // c .. combine + **/ + const char * optimize2d; + /// number of 2d optimization steps + int optsteps2d; + /// power of error (to approximate max err optimization) + double opterrpow; + /// do block filling ? + int blockfill; + /// block filling up to distance + double filldist; + /// radius of local environment (times h) + double safety; + /// radius of active environment (times h) + double relinnersafety; + /// use local h ? + int uselocalh; + /// grading for local h + double grading; + /// use delaunay meshing + int delaunay; + /// maximal mesh size + double maxh; + /// minimal mesh size + double minh; + /// file for meshsize + const char * meshsizefilename; + /// start surfacemeshing from everywhere in surface + int startinsurface; + /// check overlapping surfaces (debug) + int checkoverlap; + /// check overlapping surface mesh before volume meshing + int checkoverlappingboundary; + /// check chart boundary (sometimes too restrictive) + int checkchartboundary; + /// safty factor for curvatures (elemetns per radius) + double curvaturesafety; + /// minimal number of segments per edge + double segmentsperedge; + /// use parallel threads + int parthread; + /// weight of element size w.r.t element shape + double elsizeweight; + /// init with default values + + + /// from mp3: + /// give up quality class, 2d meshing + int giveuptol2d; + /// give up quality class, 3d meshing + int giveuptol; + /// maximal outer steps + int maxoutersteps; + /// class starting star-shape filling + int starshapeclass; + /// if non-zero, baseelement must have baseelnp points + int baseelnp; + /// quality tolerances are handled less careful + int sloppy; + + /// limit for max element angle (150-180) + double badellimit; + + bool check_impossible; + + /// + int secondorder; + /// high order element curvature + int elementorder; + /// quad-dominated surface meshing + int quad; + /// + int inverttets; + /// + int inverttrigs; + /// + int autozrefine; + /// + MeshingParameters (); + /// + void Print (ostream & ost) const; + + void CopyFrom(const MeshingParameters & other); +}; + + + +class DebugParameters +{ +public: + /// + int debugoutput; + /// use slow checks + int slowchecks; + /// + int haltsuccess; + /// + int haltnosuccess; + /// + int haltlargequalclass; + /// + int haltsegment; + /// + int haltnode; + /// + int haltsegmentp1; + /// + int haltsegmentp2; + /// + int haltexistingline; + /// + int haltoverlap; + /// + int haltface; + /// + int haltfacenr; + /// + DebugParameters (); +}; + + + + +inline void Element2d :: Invert() +{ + if (typ == TRIG) + Swap (PNum(2), PNum(3)); + else + Invert2(); +} + + + + +inline void Element2d :: NormalizeNumbering () +{ + if (GetNP() == 3) + { + if (PNum(1) < PNum(2) && PNum(1) < PNum(3)) + return; + else + { + if (PNum(2) < PNum(3)) + { + PointIndex pi1 = PNum(2); + PNum(2) = PNum(3); + PNum(3) = PNum(1); + PNum(1) = pi1; + } + else + { + PointIndex pi1 = PNum(3); + PNum(3) = PNum(2); + PNum(2) = PNum(1); + PNum(1) = pi1; + } + } + } + else + NormalizeNumbering2(); +} + + + +static const int gftetfacesa[4][3] = + { { 1, 2, 3 }, + { 2, 0, 3 }, + { 0, 1, 3 }, + { 1, 0, 2 } }; + +inline void Element :: GetFace (int i, Element2d & face) const +{ + if (typ == TET) + { + face.SetType(TRIG); + face[0] = pnum[gftetfacesa[i-1][0]]; + face[1] = pnum[gftetfacesa[i-1][1]]; + face[2] = pnum[gftetfacesa[i-1][2]]; + } + else + GetFace2 (i, face); +} + + + + + + + +/** + Identification of periodic surfaces, close surfaces, etc. + */ +class Identifications +{ +public: + enum ID_TYPE { UNDEFINED = 1, PERIODIC = 2, CLOSESURFACES = 3, CLOSEEDGES = 4}; + + +private: + class Mesh & mesh; + + /// identify points (thin layers, periodic b.c.) + INDEX_2_HASHTABLE<int> * identifiedpoints; + + /// the same, with info about the id-nr + INDEX_3_HASHTABLE<int> * identifiedpoints_nr; + + /// sorted by identification nr + TABLE<INDEX_2> idpoints_table; + + ARRAY<ID_TYPE> type; + + /// number of identifications (or, actually used identifications ?) + int maxidentnr; + +public: + /// + Identifications (class Mesh & amesh); + /// + ~Identifications (); + + void Delete (); + + /* + Identify points pi1 and pi2, due to + identification nr identnr + */ + void Add (PointIndex pi1, PointIndex pi2, int identnr); + + + int Get (PointIndex pi1, PointIndex pi2) const; + int GetSymmetric (PointIndex pi1, PointIndex pi2) const; + + bool Get (PointIndex pi1, PointIndex pi2, int identnr) const; + bool GetSymmetric (PointIndex pi1, PointIndex pi2, int identnr) const; + + /// + INDEX_2_HASHTABLE<int> & GetIdentifiedPoints () + { + return *identifiedpoints; + } + + bool Used (PointIndex pi1, PointIndex pi2) + { + return identifiedpoints->Used (INDEX_2 (pi1, pi2)); + } + + bool UsedSymmetric (PointIndex pi1, PointIndex pi2) + { + return + identifiedpoints->Used (INDEX_2 (pi1, pi2)) || + identifiedpoints->Used (INDEX_2 (pi2, pi1)); + } + + /// + void GetMap (int identnr, ARRAY<int,PointIndex::BASE> & identmap, bool symmetric = false) const; + /// + ID_TYPE GetType(int identnr) const + { + if(identnr <= type.Size()) + return type[identnr-1]; + else + return UNDEFINED; + } + void SetType(int identnr, ID_TYPE t) + { + while(type.Size() < identnr) + type.Append(UNDEFINED); + type[identnr-1] = t; + } + + /// + void GetPairs (int identnr, ARRAY<INDEX_2> & identpairs) const; + /// + int GetMaxNr () const { return maxidentnr; } + + /// remove secondorder + void SetMaxPointNr (int maxpnum); + + void Print (ostream & ost) const; +}; + + + + + + + +#endif + diff --git a/contrib/Netgen/libsrc/meshing/msghandler.cpp b/contrib/Netgen/libsrc/meshing/msghandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..88e30fb18ab02619299a2e3226945584b3a33fe5 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/msghandler.cpp @@ -0,0 +1,226 @@ +//File for handling warnings, errors, messages +#include <meshing.hpp> + +namespace netgen +{ + +int printmessage_importance = 5; +int printwarnings = 1; +int printerrors = 1; +int printdots = 1; +int printfnstart = 0; + +// extern void Ng_PrintDest(const MyStr& s); +extern void Ng_PrintDest(const char * s); + +//the dots for progression of program +void PrintDot(char ch) +{ + if (printdots) + { + char st[2]; + st[0] = ch; + st[1] = 0; + Ng_PrintDest(st); + } +} + +void PrintMessage(int importance, + const MyStr& s1, const MyStr& s2) +{ + if (importance <= printmessage_importance) + { + Ng_PrintDest(MyStr(" ")+s1+s2+MyStr("\n")); + } +} + +void PrintMessage(int importance, + const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4) +{ + if (importance <= printmessage_importance) + { + Ng_PrintDest(MyStr(" ")+s1+s2+s3+s4+MyStr("\n")); + } +} + +void PrintMessage(int importance, + const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (importance <= printmessage_importance) + { + Ng_PrintDest(MyStr(" ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); + } +} + +void PrintMessageCR(int importance, + const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (importance <= printmessage_importance) + { + Ng_PrintDest(MyStr(" ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\r")); + } +} + +void PrintFnStart(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (printfnstart) + Ng_PrintDest(MyStr(" Start Function: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); +} + +void PrintWarning(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (printwarnings) + Ng_PrintDest(MyStr(" WARNING: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); +} + +void PrintError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (printerrors) + Ng_PrintDest(MyStr(" ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); +} + +void PrintFileError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (printerrors) + Ng_PrintDest(MyStr(" FILE ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); +} + +void PrintUserError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + Ng_PrintDest(MyStr(" USER ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); +} + +void PrintSysError(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (printerrors) + Ng_PrintDest(MyStr(" SYSTEM ERROR: ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); +} + +void PrintTime(const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6, const MyStr& s7, const MyStr& s8) +{ + if (printmessage_importance >= 3) + Ng_PrintDest(MyStr(" Time = ")+s1+s2+s3+s4+s5+s6+s7+s8+MyStr("\n")); +} + + +static ARRAY<MyStr*> msgstatus_stack(0); +static ARRAY<double> threadpercent_stack(0); +static MyStr msgstatus = ""; + + + + +void ResetStatus() +{ + SetStatMsg("idle"); + + for (int i = 0; i < msgstatus_stack.Size(); i++) + delete msgstatus_stack[i]; + msgstatus_stack.SetSize(0); + threadpercent_stack.SetSize(0); + + // multithread.task = ""; + multithread.percent = 100.; +} + +void PushStatus(const MyStr& s) +{ + msgstatus_stack.Append(new MyStr (s)); + SetStatMsg(s); + threadpercent_stack.Append(0); +} + +void PushStatusF(const MyStr& s) +{ + msgstatus_stack.Append(new MyStr (s)); + SetStatMsg(s); + threadpercent_stack.Append(0); + PrintFnStart(s); +} + +void PopStatus() +{ + if (msgstatus_stack.Size()) + { + if (msgstatus_stack.Size() > 1) + SetStatMsg (*msgstatus_stack.Last()); + else + SetStatMsg (""); + delete msgstatus_stack.Last(); + msgstatus_stack.DeleteLast(); + threadpercent_stack.DeleteLast(); + if(threadpercent_stack.Size() > 0) + multithread.percent = threadpercent_stack.Last(); + else + multithread.percent = 100.; + } + else + { + PrintSysError("PopStatus failed"); + } +} + + + +/* +void SetStatMsgF(const MyStr& s) +{ + PrintFnStart(s); + SetStatMsg(s); +} +*/ + +void SetStatMsg(const MyStr& s) +{ + msgstatus = s; + multithread.task = msgstatus.c_str(); +} + +void SetThreadPercent(double percent) +{ + multithread.percent = percent; + if(threadpercent_stack.Size() > 0) + threadpercent_stack.Last() = percent; +} + + +void GetStatus(MyStr & s, double & percentage) +{ + if(threadpercent_stack.Size() > 0) + percentage = threadpercent_stack.Last(); + else + percentage = multithread.percent; + + if ( msgstatus_stack.Size() ) + s = *msgstatus_stack.Last(); + else + s = "idle"; +} + + +#ifdef SMALLLIB +#define SMALLLIBORNOTCL +#endif +#ifdef NOTCL +#define SMALLLIBORNOTCL +#endif + +#ifdef SMALLLIBORNOTCL +void Ng_PrintDest(const char * s){cout << s <<flush;} +double GetTime(){return 0;} +void MyError(const char * ch) +{ + cerr << ch << endl; +} +#endif + +} diff --git a/contrib/Netgen/libsrc/meshing/msghandler.hpp b/contrib/Netgen/libsrc/meshing/msghandler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..843cd1864934b75934d66109efb127ccb79bf949 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/msghandler.hpp @@ -0,0 +1,53 @@ +#ifndef FILE_MSGHANDLER +#define FILE_MSGHANDLER + +/**************************************************************************/ +/* File: msghandler.hh */ +/* Author: Johannes Gerstmayr */ +/* Date: 20. Nov. 99 */ +/**************************************************************************/ + + +extern void PrintDot(char ch = '.'); + + +//Message Pipeline: + +//importance: importance of message: 1=very important, 3=middle, 5=low, 7=unimportant +extern void PrintMessage(int importance, + const MyStr& s1, const MyStr& s2=MyStr()); +extern void PrintMessage(int importance, + const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4=MyStr()); +extern void PrintMessage(int importance, + const MyStr& s1, const MyStr& s2, const MyStr& s3, const MyStr& s4, + const MyStr& s5, const MyStr& s6=MyStr(), const MyStr& s7=MyStr(), const MyStr& s8=MyStr()); + +// CR without line-feed +extern void PrintMessageCR(int importance, + const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void PrintFnStart(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void PrintWarning(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void PrintError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void PrintFileError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void PrintSysError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void PrintUserError(const MyStr& s1, const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void PrintTime(const MyStr& s1="", const MyStr& s2="", const MyStr& s3="", const MyStr& s4="", + const MyStr& s5="", const MyStr& s6="", const MyStr& s7="", const MyStr& s8=""); +extern void SetStatMsg(const MyStr& s); + +extern void PushStatus(const MyStr& s); +extern void PushStatusF(const MyStr& s); +extern void PopStatus(); +extern void SetThreadPercent(double percent); +extern void GetStatus(MyStr & s, double & percentage); + + +#endif + diff --git a/contrib/Netgen/libsrc/meshing/netrule2.cpp b/contrib/Netgen/libsrc/meshing/netrule2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42fe341a501e0d1be503eb3b53889a0a5792a819 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/netrule2.cpp @@ -0,0 +1,229 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + +netrule :: netrule () +{ + name = new char[1]; + name[0] = char(0); + quality = 0; +} + +netrule :: ~netrule() +{ + // if(name != NULL) + delete [] name; + for(int i=0; i<oldutofreearea_i.Size(); i++) + delete oldutofreearea_i[i]; +} + + +/* +void netrule :: GetFreeArea (ARRAY<Point2d> & afreearea) + { + int i; + + afreearea.SetSize (freearea.Size()); + for (i = 1; i <= freearea.Size(); i++) + afreearea[i] = freearea[i]; + } +*/ + + +void netrule :: SetFreeZoneTransformation (const Vector & devp, int tolclass) +{ + double lam1 = 1.0/tolclass; + double lam2 = 1.-lam1; + + double mem1[100], mem2[100], mem3[100]; + + int vs = oldutofreearea.Height(); + FlatVector devfree(vs, mem1); + FlatVector devfree1(vs, mem2); + FlatVector devfree2(vs, mem3); + + if (tolclass <= oldutofreearea_i.Size()) + { + oldutofreearea_i[tolclass-1] -> Mult (devp, devfree); + } + else + { + oldutofreearea.Mult (devp, devfree1); + oldutofreearealimit.Mult (devp, devfree2); + devfree.Set2 (lam1, devfree1, lam2, devfree2); + } + + + int fzs = freezone.Size(); + transfreezone.SetSize (fzs); + + if (fzs > 0) + { + transfreezone[0].X() = lam1 * freezone[0].X() + lam2 * freezonelimit[0].X() + devfree[0]; + transfreezone[0].Y() = lam1 * freezone[0].Y() + lam2 * freezonelimit[0].Y() + devfree[1]; + fzmaxx = fzminx = transfreezone[0].X(); + fzmaxy = fzminy = transfreezone[0].Y(); + } + + for (int i = 1; i < fzs; i++) + { + transfreezone[i].X() = lam1 * freezone[i].X() + lam2 * freezonelimit[i].X() + devfree[2*i]; + transfreezone[i].Y() = lam1 * freezone[i].Y() + lam2 * freezonelimit[i].Y() + devfree[2*i+1]; + + if (transfreezone[i].X() > fzmaxx) fzmaxx = transfreezone[i].X(); + if (transfreezone[i].X() < fzminx) fzminx = transfreezone[i].X(); + if (transfreezone[i].Y() > fzmaxy) fzmaxy = transfreezone[i].Y(); + if (transfreezone[i].Y() < fzminy) fzminy = transfreezone[i].Y(); + } + + for (int i = 0; i < fzs; i++) + { + Point2d p1 = transfreezone[i]; + Point2d p2 = transfreezone[(i+1) % fzs]; + + Vec2d vn (p2.Y() - p1.Y(), p1.X() - p2.X()); + + double len2 = vn.Length2(); + + if (len2 < 1e-10) + { + freesetinequ(i, 0) = 0; + freesetinequ(i, 1) = 0; + freesetinequ(i, 2) = -1; + } + else + { + vn /= sqrt (len2); // should not be necessary + + freesetinequ(i,0) = vn.X(); + freesetinequ(i,1) = vn.Y(); + freesetinequ(i,2) = -(p1.X() * vn.X() + p1.Y() * vn.Y()); + } + + /* + freesetinequ(i,0) = vn.X(); + freesetinequ(i,1) = vn.Y(); + freesetinequ(i,2) = -(p1.X() * vn.X() + p1.Y() * vn.Y()); + */ + } +} + + +/* +int netrule :: IsInFreeZone2 (const Point2d & p) const +{ + for (int i = 0; i < transfreezone.Size(); i++) + { + if (freesetinequ(i, 0) * p.X() + + freesetinequ(i, 1) * p.Y() + + freesetinequ(i, 2) > 0) return 0; + } + return 1; +} +*/ + +int netrule :: IsLineInFreeZone2 (const Point2d & p1, const Point2d & p2) const +{ + int left, right, allleft, allright; + + if (p1.X() > fzmaxx && p2.X() > fzmaxx || + p1.X() < fzminx && p2.X() < fzminx || + p1.Y() > fzmaxy && p2.Y() > fzmaxy || + p1.Y() < fzminy && p2.Y() < fzminy) return 0; + + for (int i = 1; i <= transfreezone.Size(); i++) + { + if (freesetinequ.Get(i, 1) * p1.X() + freesetinequ.Get(i, 2) * p1.Y() + + freesetinequ.Get(i, 3) > -1e-8 && // -1e-6 + freesetinequ.Get(i, 1) * p2.X() + freesetinequ.Get(i, 2) * p2.Y() + + freesetinequ.Get(i, 3) > -1e-8 // -1e-6 + ) return 0; + } + + double nx = (p2.Y() - p1.Y()); + double ny = -(p2.X() - p1.X()); + double nl = sqrt (nx * nx + ny * ny); + if (nl > 1e-8) + { + nx /= nl; + ny /= nl; + double c = - (p1.X() * nx + p1.Y() * ny); + + allleft = 1; + allright = 1; + + for (int i = 1; i <= transfreezone.Size(); i++) + { + left = transfreezone.Get(i).X() * nx + transfreezone.Get(i).Y() + c < 1e-7; + right = transfreezone.Get(i).X() * nx + transfreezone.Get(i).Y() + c > -1e-7; + + if (!left) allleft = 0; + if (!right) allright = 0; + } + if (allleft || allright) return 0; + } + + return 1; +} + +int netrule :: ConvexFreeZone () const +{ + int n = transfreezone.Size(); + for (int i = 1; i <= n; i++) + { + const bool counterclockwise = CCW (transfreezone.Get(i), + transfreezone.Get(i % n + 1), + transfreezone.Get( (i+1) % n + 1 ), + 1e-7); + //(*testout) << "ccw " << counterclockwise << endl << " p1 " << transfreezone.Get(i) << " p2 " << transfreezone.Get(i % n + 1) + // << " p3 " << transfreezone.Get( (i+1) % n + 1 ) << endl; + if (!counterclockwise ) + return 0; + } + return 1; +} + + +/* +float netrule :: CalcPointDist (int pi, const Point2d & p) const +{ + float dx = p.X() - points.Get(pi).X(); + float dy = p.Y() - points.Get(pi).Y(); + const threefloat * tf = &tolerances.Get(pi); + + return tf->f1 * dx * dx + tf->f2 * dx * dy + tf->f3 * dy * dy; +} +*/ + +float netrule :: CalcLineError (int li, const Vec2d & v) const +{ + float dx = v.X() - linevecs.Get(li).X(); + float dy = v.Y() - linevecs.Get(li).Y(); + + const threefloat * ltf = &linetolerances.Get(li); + return ltf->f1 * dx * dx + ltf->f2 * dx * dy + ltf->f3 * dy * dy; +} + + + + +/* +int GetNRules () + { + return rules.Size(); + } +*/ + + + + + + + + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/netrule3.cpp b/contrib/Netgen/libsrc/meshing/netrule3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b7bdfd9c52110ac961e1f2dd38e5039839b2df3 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/netrule3.cpp @@ -0,0 +1,1140 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +// #define MARK +// #include <prof.h> + + +namespace netgen +{ + + +vnetrule :: vnetrule () +{ + name = new char[1]; + name[0] = char(0); + quality = 0; +} + +vnetrule :: ~vnetrule () +{ + // if (strlen(name)) + delete [] name; + for (int i = 1; i <= freefaces.Size(); i++) + delete freefaces.Elem(i); + for (int i = 1; i <= freesets.Size(); i++) + delete freesets.Elem(i); + for (int i = 1; i <= freeedges.Size(); i++) + delete freeedges.Elem(i); + for (int i = 1; i <= freefaceinequ.Size(); i++) + delete freefaceinequ.Elem(i); + delete oldutofreezone; + delete oldutofreezonelimit; +} + +int vnetrule :: TestFlag (char flag) const +{ + for (int i = 1; i <= flags.Size(); i++) + if (flags.Get(i) == flag) return 1; + return 0; +} + + +void vnetrule :: SetFreeZoneTransformation (const Vector & allp, int tolclass) +{ + int i, j; + // double nx, ny, nz, v1x, v1y, v1z, v2x, v2y, v2z; + double nl; + const threeint * ti; + int fs; + + double lam1 = 1.0/(2 * tolclass - 1); + double lam2 = 1-lam1; + + transfreezone.SetSize (freezone.Size()); + + int np = points.Size(); + int nfp = freezone.Size(); + Vector vp(np), vfp1(nfp), vfp2(nfp); + + + for (i = 1; i <= 3; i++) + { + for (j = 1; j <= np; j++) + vp.Elem(j) = allp.Get(i+3*j-3); + + oldutofreezone->Mult (vp, vfp1); + oldutofreezonelimit->Mult (vp, vfp2); + + vfp1 *= lam1; + vfp1.Add (lam2, vfp2); + + for (j = 1; j <= nfp; j++) + transfreezone.Elem(j).X(i) = vfp1.Elem(j); + } + + // MARK(setfz2); + + + fzbox.SetPoint (transfreezone.Elem(1)); + for (i = 2; i <= freezone.Size(); i++) + fzbox.AddPoint (transfreezone.Elem(i)); + + + // MARK(setfz3); + + + for (fs = 1; fs <= freesets.Size(); fs++) + { + ARRAY<threeint> & freesetfaces = *freefaces.Get(fs); + DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); + + for (i = 1; i <= freesetfaces.Size(); i++) + { + ti = &freesetfaces.Get(i); + const Point3d & p1 = transfreezone.Get(ti->i1); + const Point3d & p2 = transfreezone.Get(ti->i2); + const Point3d & p3 = transfreezone.Get(ti->i3); + + Vec3d v1(p1, p2); + Vec3d v2(p1, p3); + Vec3d n; + Cross (v1, v2, n); + + nl = n.Length(); + + if (nl < 1e-10) + { + freesetinequ.Set(1, 1, 0); + freesetinequ.Set(1, 2, 0); + freesetinequ.Set(1, 3, 0); + freesetinequ.Set(1, 4, -1); + } + else + { + // n /= nl; + + freesetinequ.Set(i, 1, n.X()/nl); + freesetinequ.Set(i, 2, n.Y()/nl); + freesetinequ.Set(i, 3, n.Z()/nl); + freesetinequ.Set(i, 4, + -(p1.X() * n.X() + p1.Y() * n.Y() + p1.Z() * n.Z()) / nl); + } + } + } + + /* + (*testout) << "Transformed freezone: " << endl; + for (i = 1; i <= transfreezone.Size(); i++) + (*testout) << transfreezone.Get(i) << " "; + (*testout) << endl; + */ +} + +int vnetrule :: ConvexFreeZone () const +{ + int i, j, k, fs; + + // (*mycout) << "Convex free zone...\n"; + + int ret1=1; + // int ret2=1; + + for (fs = 1; fs <= freesets.Size(); fs++) + { + const DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); + + // const ARRAY<int> & freeset = *freesets.Get(fs); + const ARRAY<twoint> & freesetedges = *freeedges.Get(fs); + // const ARRAY<threeint> & freesetfaces = *freefaces.Get(fs); + + for (i = 1; i <= freesetedges.Size(); i++) + { + j = freesetedges.Get(i).i1; //triangle j with opposite point k + k = freesetedges.Get(i).i2; + + if ( freesetinequ.Get(j, 1) * transfreezone.Get(k).X() + + freesetinequ.Get(j, 2) * transfreezone.Get(k).Y() + + freesetinequ.Get(j, 3) * transfreezone.Get(k).Z() + + freesetinequ.Get(j, 4) > 0 ) + { + ret1=0; + } + } + + } + + return ret1; +} + + +int vnetrule :: IsInFreeZone (const Point3d & p) const +{ + int i, fs; + char inthis; + + + for (fs = 1; fs <= freesets.Size(); fs++) + { + inthis = 1; + ARRAY<threeint> & freesetfaces = *freefaces.Get(fs); + DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); + + for (i = 1; i <= freesetfaces.Size() && inthis; i++) + { + if (freesetinequ.Get(i, 1) * p.X() + freesetinequ.Get(i, 2) * p.Y() + + freesetinequ.Get(i, 3) * p.Z() + freesetinequ.Get(i, 4) > 0) + inthis = 0; + } + + if (inthis) return 1; + } + + return 0; +} + + +int vnetrule :: IsTriangleInFreeZone (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const ARRAY<int> & pi, int newone) +{ + int fs; + int infreeset, cannot = 0; + + + static ARRAY<int> pfi(3), pfi2(3); + + // convert from local index to freeset index + int i, j; + for (i = 1; i <= 3; i++) + { + pfi.Elem(i) = 0; + if (pi.Get(i)) + { + for (j = 1; j <= freezonepi.Size(); j++) + if (freezonepi.Get(j) == pi.Get(i)) + pfi.Elem(i) = j; + } + } + + for (fs = 1; fs <= freesets.Size(); fs++) + { + const ARRAY<int> & freeseti = *freesets.Get(fs); + for (i = 1; i <= 3; i++) + { + pfi2.Elem(i) = 0; + for (j = 1; j <= freeseti.Size(); j++) + if (pfi.Get(i) == freeseti.Get(j)) + pfi2.Elem(i) = pfi.Get(i); + } + + infreeset = IsTriangleInFreeSet(p1, p2, p3, fs, pfi2, newone); + if (infreeset == 1) return 1; + if (infreeset == -1) cannot = -1; + } + + return cannot; +} + + + +int vnetrule :: IsTriangleInFreeSet (const Point3d & p1, const Point3d & p2, + const Point3d & p3, int fs, + const ARRAY<int> & pi, int newone) +{ + int i, ii; + Vec3d n; + int allleft, allright; + int hos1, hos2, hos3, os1, os2, os3; + double hf, lam1, lam2, f, c1, c2, alpha; + double v1n, v2n, h11, h12, h22, dflam1, dflam2; + double lam1old, lam2old, fold; + double hpx, hpy, hpz, v1x, v1y, v1z, v2x, v2y, v2z; + int act1, act2, act3, it; + int cntout; + static ARRAY<int> activefaces; + int isin; + + + // MARK(triinfz); + + ARRAY<threeint> & freesetfaces = *freefaces.Get(fs); + DenseMatrix & freesetinequ = *freefaceinequ.Get(fs); + + + int cnt = 0; + for (i = 1; i <= 3; i++) + if (pi.Get(i)) cnt++; + + /* + (*testout) << "trig in free set : " << p1 << " - " << p2 << " - " << p3 << endl; + (*testout) << "common points: " << cnt << endl; + */ + if (!newone) + cnt = 0; + + if (cnt == 1) + { + // MARK(triinfz1); + + int upi = 0, lpiu = 0; + for (i = 1; i <= 3; i++) + if (pi.Get(i)) + { + upi = i; + lpiu = pi.Get(i); + } + + Vec3d v1, v2; + switch (upi) + { + case 1: + { + v1 = p2 - p1; + v2 = p3 - p1; + break; + } + case 2: + { + v1 = p3 - p2; + v2 = p1 - p2; + break; + } + case 3: + { + v1 = p1 - p3; + v2 = p2 - p3; + break; + } + } + + v1 /= v1.Length(); + v2 /= v2.Length(); + Cross (v1, v2, n); + n /= n.Length(); + + // (*testout) << "Test new: " << endl; + for (i = 1; i <= freesetfaces.Size(); i++) + { + if ( (freesetfaces.Get(i).i1 == lpiu) || + (freesetfaces.Get(i).i2 == lpiu) || + (freesetfaces.Get(i).i3 == lpiu) ) + { + // freeface has point + + + Vec3d a (freesetinequ.Get(i, 1), + freesetinequ.Get(i, 2), + freesetinequ.Get(i, 3)); + + // if (1 - fabs (a * n) < 1e-8 ) + // continue; + + Vec3d an; + Cross (a, n, an); + double lan = an.Length(); + if (lan < 1e-10) + continue; + + an /= lan; + + int out1 = (a * v1) > 0; + int out2 = (a * v2) > 0; + // (*testout) << "out1, out2 = " << out1 << ", " << out2 << endl; + if (out1 && out2) + return 0; + + if (!out1 && !out2) + continue; + + + // if ( ( (an * v1) < 0) && ( (an * v2) < 0) ) // falsch !!!! + // an *= -1; + + // solve an = lam1 v1 + lam2 v2 + double vii11 = v1 * v1; + double vii12 = v1 * v2; + double vii22 = v2 * v2; + double det = vii11 * vii22 - vii12 * vii12; + if ( fabs (det) < 1e-10 ) + continue; + double rs1 = an * v1; + double rs2 = an * v2; + + double lambda1 = rs1 * vii22 - rs2 * vii12; + double lambda2 = rs2 * vii11 - rs1 * vii12; + + if (fabs (lambda1) > fabs (lambda2)) + { + if (lambda1 < 0) + an *= -1; + } + else + { + if (lambda2 < 0) + an *= -1; + } + + + if (lambda1 * lambda2 < 0 && 0) + { + if (fabs (lambda1) > 1e-14 && fabs (lambda2) > 1e-14) + { + // (*mycout) << "lambda1 lambda2 < 0" << endl; + (*testout) << "lambdai different" << endl; + (*testout) << "v1 = " << v1 << endl; + (*testout) << "v2 = " << v2 << endl; + (*testout) << "n = " << n << endl; + (*testout) << "a = " << a << endl; + (*testout) << "an = " << an << endl; + (*testout) << "a * v1 = " << (a * v1) << endl; + (*testout) << "a * v2 = " << (a * v2) << endl; + (*testout) << "an * v1 = " << (an * v1) << endl; + (*testout) << "an * v2 = " << (an * v2) << endl; + + (*testout) << "vii = " << vii11 << ", " << vii12 << ", " << vii22 << endl; + (*testout) << "lambdai = " << lambda1 << ", " << lambda2 << endl; + (*testout) << "rs = " << rs1 << ", " << rs2 << endl; + continue; + } + } + + if (out1) + v1 = an; + else + v2 = an; + } + } + + return 1; + + /* + (*testout) << "overlap trig " << p1 << p2 << p3 << endl; + (*testout) << "upi = " << upi << endl; + (*testout) << "v1 = " << v1 << " v2 = " << v2 << endl; + */ + + switch (upi) + { + case 1: + { + v1 = p2 - p1; + v2 = p3 - p1; + break; + } + case 2: + { + v1 = p3 - p2; + v2 = p1 - p2; + break; + } + case 3: + { + v1 = p1 - p3; + v2 = p2 - p3; + break; + } + } + + v1 /= v1.Length(); + v2 /= v2.Length(); + Cross (v1, v2, n); + n /= n.Length(); + + // (*testout) << "orig v1, v2 = " << v1 << ", " << v2 << endl; + + + for (i = 1; i <= freesetfaces.Size(); i++) + { + if ( (freesetfaces.Get(i).i1 == lpiu) || + (freesetfaces.Get(i).i2 == lpiu) || + (freesetfaces.Get(i).i3 == lpiu) ) + { + /* + (*testout) << "v1, v2, now = " << v1 << ", " << v2 << endl; + + // freeface has point + (*testout) << "freesetface: " + << freesetfaces.Get(i).i1 << " " + << freesetfaces.Get(i).i2 << " " + << freesetfaces.Get(i).i3 << " "; + */ + + Vec3d a (freesetinequ.Get(i, 1), + freesetinequ.Get(i, 2), + freesetinequ.Get(i, 3)); + // (*testout) << "a = " << a << endl; + + + Vec3d an; + Cross (a, n, an); + double lan = an.Length(); + + // (*testout) << "an = " << an << endl; + + if (lan < 1e-10) + continue; + + an /= lan; + + // (*testout) << "a*v1 = " << (a*v1) << " a*v2 = " << (a*v2) << endl; + + int out1 = (a * v1) > 0; + // int out2 = (a * v2) > 0; + + + // (*testout) << "out1, 2 = " << out1 << ", " << out2 << endl; + + + double vii11 = v1 * v1; + double vii12 = v1 * v2; + double vii22 = v2 * v2; + double det = vii11 * vii22 - vii12 * vii12; + if ( fabs (det) < 1e-10 ) + continue; + double rs1 = an * v1; + double rs2 = an * v2; + + double lambda1 = rs1 * vii22 - rs2 * vii12; + double lambda2 = rs2 * vii11 - rs1 * vii12; + + // (*testout) << "lambda1, lambda2 = " << lambda1 << ", " << lambda2 << endl; + + + if (fabs (lambda1) > fabs (lambda2)) + { + if (lambda1 < 0) + an *= -1; + } + else + { + if (lambda2 < 0) + an *= -1; + } + + + if (lambda1 * lambda2 < 0) + { + if (fabs (lambda1) > 1e-14 && fabs (lambda2) > 1e-14) + { + // (*mycout) << "lambda1 lambda2 < 0" << endl; + (*testout) << "lambdai different" << endl; + (*testout) << "v1 = " << v1 << endl; + (*testout) << "v2 = " << v2 << endl; + (*testout) << "n = " << n << endl; + (*testout) << "a = " << a << endl; + (*testout) << "an = " << an << endl; + (*testout) << "a * v1 = " << (a * v1) << endl; + (*testout) << "a * v2 = " << (a * v2) << endl; + (*testout) << "an * v1 = " << (an * v1) << endl; + (*testout) << "an * v2 = " << (an * v2) << endl; + + (*testout) << "vii = " << vii11 << ", " << vii12 << ", " << vii22 << endl; + (*testout) << "lambdai = " << lambda1 << ", " << lambda2 << endl; + (*testout) << "rs = " << rs1 << ", " << rs2 << endl; + continue; + } + } + + if (out1) + v1 = an; + else + v2 = an; + + + + } + } + + return 1; + } + + + + if (cnt == 2) + { + // (*testout) << "tripoitns: " << p1 << " " << p2 << " " << p3 << endl; + + // MARK(triinfz2); + + int pi1 = 0, pi2 = 0, pi3 = 0; + Vec3d a1, a2; // outer normals + Vec3d trivec; // vector from common edge to third point of triangle + for (i = 1; i <= 3; i++) + if (pi.Get(i)) + { + pi2 = pi1; + pi1 = pi.Get(i); + } + else + pi3 = i; + + switch (pi3) + { + case 1: trivec = (p1 - p2); break; + case 2: trivec = (p2 - p3); break; + case 3: trivec = (p3 - p2); break; + } + + ARRAY<int> lpi(freezonepi.Size()); + for (i = 1; i <= lpi.Size(); i++) + lpi.Elem(i) = 0; + lpi.Elem(pi1) = 1; + lpi.Elem(pi2) = 1; + + int ff1 = 0, ff2 = 0; + for (i = 1; i <= freesetfaces.Size(); i++) + { + if (lpi.Get(freesetfaces.Get(i).i1) + + lpi.Get(freesetfaces.Get(i).i2) + + lpi.Get(freesetfaces.Get(i).i3) == 2) + { + ff2 = ff1; + ff1 = i; + } + } + + if (ff2 == 0) + return 1; + + a1 = Vec3d (freesetinequ.Get(ff1, 1), + freesetinequ.Get(ff1, 2), + freesetinequ.Get(ff1, 3)); + a2 = Vec3d (freesetinequ.Get(ff2, 1), + freesetinequ.Get(ff2, 2), + freesetinequ.Get(ff2, 3)); + + if ( ( (a1 * trivec) > 0) || ( (a2 * trivec) > 0)) + return 0; + + return 1; + } + + + if (cnt == 3) + { + // MARK(triinfz3); + + ARRAY<int> lpi(freezonepi.Size()); + for (i = 1; i <= lpi.Size(); i++) + lpi.Elem(i) = 0; + + for (i = 1; i <= 3; i++) + lpi.Elem(pi.Get(i)) = 1; + + for (i = 1; i <= freesetfaces.Size(); i++) + { + if (lpi.Get(freesetfaces.Get(i).i1) + + lpi.Get(freesetfaces.Get(i).i2) + + lpi.Get(freesetfaces.Get(i).i3) == 3) + { + return 0; + } + } + return 1; + } + + // MARK(triinfz0); + + + os1 = os2 = os3 = 0; + activefaces.SetSize(0); + + // is point inside ? + + for (i = 1; i <= freesetfaces.Size(); i++) + { + hos1 = freesetinequ.Get(i, 1) * p1.X() + + freesetinequ.Get(i, 2) * p1.Y() + + freesetinequ.Get(i, 3) * p1.Z() + + freesetinequ.Get(i, 4) > -1E-5; + + hos2 = freesetinequ.Get(i, 1) * p2.X() + + freesetinequ.Get(i, 2) * p2.Y() + + freesetinequ.Get(i, 3) * p2.Z() + + freesetinequ.Get(i, 4) > -1E-5; + + hos3 = freesetinequ.Get(i, 1) * p3.X() + + freesetinequ.Get(i, 2) * p3.Y() + + freesetinequ.Get(i, 3) * p3.Z() + + freesetinequ.Get(i, 4) > -1E-5; + + if (hos1 && hos2 && hos3) return 0; + + if (hos1) os1 = 1; + if (hos2) os2 = 1; + if (hos3) os3 = 1; + + if (hos1 || hos2 || hos3) activefaces.Append (i); + } + + if (!os1 || !os2 || !os3) return 1; + + v1x = p2.X() - p1.X(); + v1y = p2.Y() - p1.Y(); + v1z = p2.Z() - p1.Z(); + + v2x = p3.X() - p1.X(); + v2y = p3.Y() - p1.Y(); + v2z = p3.Z() - p1.Z(); + + n.X() = v1y * v2z - v1z * v2y; + n.Y() = v1z * v2x - v1x * v2z; + n.Z() = v1x * v2y - v1y * v2x; + n /= n.Length(); + + allleft = allright = 1; + for (i = 1; i <= transfreezone.Size() && (allleft || allright); i++) + { + const Point3d & p = transfreezone.Get(i); + float scal = (p.X() - p1.X()) * n.X() + + (p.Y() - p1.Y()) * n.Y() + + (p.Z() - p1.Z()) * n.Z(); + + if ( scal > 1E-8 ) allleft = 0; + if ( scal < -1E-8 ) allright = 0; + } + + if (allleft || allright) return 0; + + + lam1old = lam2old = lam1 = lam2 = 1.0 / 3.0; + + + // testout << endl << endl << "Start minimizing" << endl; + + it = 0; + int minit; + minit = 1000; + fold = 1E10; + + + + while (1) + { + it++; + + if (it > 1000) return -1; + + if (lam1 < 0) lam1 = 0; + if (lam2 < 0) lam2 = 0; + if (lam1 + lam2 > 1) lam1 = 1 - lam2; + + if (it > minit) + { + (*testout) << "it = " << it << endl; + (*testout) << "lam1/2 = " << lam1 << " " << lam2 << endl; + } + + hpx = p1.X() + lam1 * v1x + lam2 * v2x; + hpy = p1.Y() + lam1 * v1y + lam2 * v2y; + hpz = p1.Z() + lam1 * v1z + lam2 * v2z; + + f = 0; + + h11 = h12 = h22 = dflam1 = dflam2 = 0; + cntout = 0; + + isin = 1; + + for (i = 1; i <= activefaces.Size(); i++) + { + ii = activefaces.Get(i); + + hf = freesetinequ.Get(ii, 1) * hpx + + freesetinequ.Get(ii, 2) * hpy + + freesetinequ.Get(ii, 3) * hpz + + freesetinequ.Get(ii, 4); + + if (hf > -1E-7) isin = 0; + + hf += 1E-4; + if (hf > 0) + { + f += hf * hf; + + v1n = freesetinequ.Get(ii, 1) * v1x + + freesetinequ.Get(ii, 2) * v1y + + freesetinequ.Get(ii, 3) * v1z; + v2n = freesetinequ.Get(ii, 1) * v2x + + freesetinequ.Get(ii, 2) * v2y + + freesetinequ.Get(ii, 3) * v2z; + + h11 += 2 * v1n * v1n; + h12 += 2 * v1n * v2n; + h22 += 2 * v2n * v2n; + dflam1 += 2 * hf * v1n; + dflam2 += 2 * hf * v2n; + cntout++; + } + } + + if (isin) return 1; + + if (it > minit) + { + (*testout) << "f = " << f + << " dfdlam = " << dflam1 << " " << dflam2 << endl; + (*testout) << "h = " << h11 << " " << h12 << " " << h22 << endl; + (*testout) << "active: " << cntout << endl; + (*testout) << "lam1-lam1old = " << (lam1 - lam1old) << endl; + (*testout) << "lam2-lam2old = " << (lam2 - lam2old) << endl; + } + + + if (f >= fold) + { + lam1 = 0.100000000000000 * lam1 + 0.9000000000000000 * lam1old; + lam2 = 0.100000000000000 * lam2 + 0.9000000000000000 * lam2old; + } + else + { + lam1old = lam1; + lam2old = lam2; + fold = f; + + + if (f < 1E-9) return 1; + + h11 += 1E-10; + h22 += 1E-10; + c1 = - ( h22 * dflam1 - h12 * dflam2) / (h11 * h22 - h12 * h12); + c2 = - (-h12 * dflam1 + h11 * dflam2) / (h11 * h22 - h12 * h12); + alpha = 1; + + + if (it > minit) + (*testout) << "c1/2 = " << c1 << " " << c2 << endl; + + act1 = lam1 <= 1E-6 && c1 <= 0; + act2 = lam2 <= 1E-6 && c2 <= 0; + act3 = lam1 + lam2 >= 1 - 1E-6 && c1 + c2 >= 0; + + if (it > minit) + (*testout) << "act1,2,3 = " << act1 << act2 << act3 << endl; + + if (act1 && act2 || act1 && act3 || act2 && act3) return 0; + + if (act1) + { + c1 = 0; + c2 = - dflam2 / h22; + } + + if (act2) + { + c1 = - dflam1 / h11; + c2 = 0; + } + + if (act3) + { + c1 = - (dflam1 - dflam2) / (h11 + h22 - 2 * h12); + c2 = -c1; + } + + if (it > minit) + (*testout) << "c1/2 now = " << c1 << " " << c2 << endl; + + + if (f > 100 * sqrt (sqr (c1) + sqr (c2))) return 0; + + + if (lam1 + alpha * c1 < 0 && !act1) + alpha = -lam1 / c1; + if (lam2 + alpha * c2 < 0 && !act2) + alpha = -lam2 / c2; + if (lam1 + lam2 + alpha * (c1 + c2) > 1 && !act3) + alpha = (1 - lam1 - lam2) / (c1 + c2); + + if (it > minit) + (*testout) << "alpha = " << alpha << endl; + + lam1 += alpha * c1; + lam2 += alpha * c2; + } + } +} + + + + +int vnetrule :: IsQuadInFreeZone (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Point3d & p4, + const ARRAY<int> & pi, int newone) +{ + int fs; + int infreeset, cannot = 0; + + + static ARRAY<int> pfi(4), pfi2(4); + + // convert from local index to freeset index + int i, j; + for (i = 1; i <= 4; i++) + { + pfi.Elem(i) = 0; + if (pi.Get(i)) + { + for (j = 1; j <= freezonepi.Size(); j++) + if (freezonepi.Get(j) == pi.Get(i)) + pfi.Elem(i) = j; + } + } + + for (fs = 1; fs <= freesets.Size(); fs++) + { + const ARRAY<int> & freeseti = *freesets.Get(fs); + for (i = 1; i <= 4; i++) + { + pfi2.Elem(i) = 0; + for (j = 1; j <= freeseti.Size(); j++) + if (pfi.Get(i) == freeseti.Get(j)) + pfi2.Elem(i) = pfi.Get(i); + } + + infreeset = IsQuadInFreeSet(p1, p2, p3, p4, fs, pfi2, newone); + if (infreeset == 1) return 1; + if (infreeset == -1) cannot = -1; + } + + return cannot; +} + + +int vnetrule :: IsQuadInFreeSet (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, + int fs, const ARRAY<int> & pi, int newone) +{ + int i; + + int cnt = 0; + for (i = 1; i <= 4; i++) + if (pi.Get(i)) cnt++; + + /* + (*testout) << "test quad in freeset: " << p1 << " - " << p2 << " - " << p3 << " - " << p4 << endl; + (*testout) << "pi = "; + for (i = 1; i <= pi.Size(); i++) + (*testout) << pi.Get(i) << " "; + (*testout) << endl; + (*testout) << "cnt = " << cnt << endl; + */ + if (cnt == 4) + { + return 1; + } + + if (cnt == 3) + { + return 1; + } + + static ARRAY<int> pi3(3); + int res; + + pi3.Elem(1) = pi.Get(1); + pi3.Elem(2) = pi.Get(2); + pi3.Elem(3) = pi.Get(3); + res = IsTriangleInFreeSet (p1, p2, p3, fs, pi3, newone); + if (res) return res; + + + pi3.Elem(1) = pi.Get(2); + pi3.Elem(2) = pi.Get(3); + pi3.Elem(3) = pi.Get(4); + res = IsTriangleInFreeSet (p2, p3, p4, fs, pi3, newone); + if (res) return res; + + pi3.Elem(1) = pi.Get(3); + pi3.Elem(2) = pi.Get(4); + pi3.Elem(3) = pi.Get(1); + res = IsTriangleInFreeSet (p3, p4, p1, fs, pi3, newone); + if (res) return res; + + pi3.Elem(1) = pi.Get(4); + pi3.Elem(2) = pi.Get(1); + pi3.Elem(3) = pi.Get(2); + res = IsTriangleInFreeSet (p4, p1, p2, fs, pi3, newone); + return res; +} + + + + + + + + + + + + +float vnetrule :: CalcPointDist (int pi, const Point3d & p) const +{ + float dx = p.X() - points.Get(pi).X(); + float dy = p.Y() - points.Get(pi).Y(); + float dz = p.Z() - points.Get(pi).Z(); + + // const threefloat * tf = &tolerances.Get(pi); + // return tf->f1 * dx * dx + tf->f2 * dx * dy + tf->f3 * dy * dy; + return tolerances.Get(pi) * (dx * dx + dy * dy + dz * dz); +} + + +int vnetrule :: TestOk () const +{ + ARRAY<int> cntpused(points.Size()); + ARRAY<int> edge1, edge2; + ARRAY<int> delf(faces.Size()); + int i, j, k; + int pi1, pi2; + int found; + + for (i = 1; i <= cntpused.Size(); i++) + cntpused.Elem(i) = 0; + for (i = 1; i <= faces.Size(); i++) + delf.Elem(i) = 0; + for (i = 1; i <= delfaces.Size(); i++) + delf.Elem(delfaces.Get(i)) = 1; + + + for (i = 1; i <= faces.Size(); i++) + if (delf.Get(i) || i > noldf) + for (j = 1; j <= faces.Get(i).GetNP(); j++) + cntpused.Elem(faces.Get(i).PNum(j))++; + + for (i = 1; i <= cntpused.Size(); i++) + if (cntpused.Get(i) > 0 && cntpused.Get(i) < 2) + { + return 0; + } + + + // (*testout) << endl; + for (i = 1; i <= faces.Size(); i++) + { + // (*testout) << "face " << i << endl; + for (j = 1; j <= faces.Get(i).GetNP(); j++) + { + pi1 = 0; pi2 = 0; + if (delf.Get(i)) + { + pi1 = faces.Get(i).PNumMod(j); + pi2 = faces.Get(i).PNumMod(j+1); + } + if (i > noldf) + { + pi1 = faces.Get(i).PNumMod(j+1); + pi2 = faces.Get(i).PNumMod(j); + } + + found = 0; + if (pi1) + { + for (k = 1; k <= edge1.Size(); k++) + if (edge1.Get(k) == pi1 && edge2.Get(k) == pi2) + { + found = 1; + edge1.DeleteElement(k); + edge2.DeleteElement(k); + k--; + // (*testout) << "Del edge " << pi1 << "-" << pi2 << endl; + } + if (!found) + { + edge1.Append (pi2); + edge2.Append (pi1); + // (*testout) << "Add edge " << pi1 << "-" << pi2 << endl; + } + } + } + } + + + if (edge1.Size() > 0) + { + return 0; + } + + /* + cntpused.SetSize(freezone.Size()); + for (i = 1; i <= cntpused.Size(); i++) + cntpused[i] = 0; + + for (i = 1; i <= freefaces.Size(); i++) + { + cntpused[freefaces[i].i1]++; + cntpused[freefaces[i].i2]++; + cntpused[freefaces[i].i3]++; + } + + for (i = 1; i <= cntpused.Size(); i++) + if (cntpused[i] < 3) + { + (*mycout) << "Fall 3" << endl; + return 0; + } + + + + for (i = 1; i <= freefaces.Size(); i++) + { + for (j = 1; j <= 3; j++) + { + if (j == 1) + { + pi1 = freefaces[i].i1; + pi2 = freefaces[i].i2; + } + if (j == 2) + { + pi1 = freefaces[i].i2; + pi2 = freefaces[i].i3; + } + if (j == 3) + { + pi1 = freefaces[i].i3; + pi2 = freefaces[i].i1; + } + + found = 0; + for (k = 1; k <= edge1.Size(); k++) + if (edge1[k] == pi1 && edge2[k] == pi2) + { + found = 1; + edge1.DeleteElement(k); + edge2.DeleteElement(k); + k--; + } + + if (!found) + { + edge1.Append (pi2); + edge2.Append (pi1); + } + } + } + + if (edge1.Size() > 0) + { + (*mycout) << "Fall 4" << endl; + return 0; + } + */ + return 1; +} + + +int vnetrule :: IsDelFace (int fn) const +{ + int i; + for (i = 1; i <= GetNDelF(); i++) + if (GetDelFace(i) == fn) return 1; + return 0; +} + +} diff --git a/contrib/Netgen/libsrc/meshing/parser2.cpp b/contrib/Netgen/libsrc/meshing/parser2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb502cfee3a88f063fe0cf7169d26a400afd4b3a --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/parser2.cpp @@ -0,0 +1,603 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +#ifdef WIN32 +#define COMMASIGN ':' +#else +#define COMMASIGN ',' +#endif + + +namespace netgen +{ + + +void LoadMatrixLine (istream & ist, DenseMatrix & m, int line) +{ + char ch; + int pnum; + float f; + + ist >> ch; + while (ch != '}') + { + ist.putback (ch); + ist >> f; + ist >> ch; + ist >> pnum; + + if (ch == 'x' || ch == 'X') + m.Elem(line, 2 * pnum - 1) = f; + if (ch == 'y' || ch == 'Y') + m.Elem(line, 2 * pnum) = f; + + ist >> ch; + if (ch == COMMASIGN) + ist >> ch; + } +} + + +void netrule :: LoadRule (istream & ist) +{ + char buf[256]; + char ch; + Point2d p; + INDEX_2 lin; + int i, j; + DenseMatrix tempoldutonewu(20, 20), tempoldutofreearea(20, 20), + tempoldutofreearealimit(20, 20); + + tempoldutonewu = 0; + tempoldutofreearea = 0; + tempoldutofreearealimit = 0; + + noldp = 0; + noldl = 0; + + ist.get (buf, sizeof(buf), '"'); + ist.get (ch); + ist.get (buf, sizeof(buf), '"'); + ist.get (ch); + + // if(name != NULL) + delete [] name; + name = new char[strlen (buf) + 1]; + strcpy (name, buf); + //(*testout) << "name " << name << endl; + // (*mycout) << "Rule " << name << " found." << endl; + + do + { + ist >> buf; + + //(*testout) << "buf " << buf << endl; + + if (strcmp (buf, "quality") == 0) + + { + ist >> quality; + } + + else if (strcmp (buf, "mappoints") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> p.X(); + ist >> ch; // ',' + ist >> p.Y(); + ist >> ch; // ')' + + points.Append (p); + noldp++; + + tolerances.SetSize (noldp); + tolerances.Elem(noldp).f1 = 1.0; + tolerances.Elem(noldp).f2 = 0; + tolerances.Elem(noldp).f3 = 1.0; + + ist >> ch; + while (ch != ';') + { + if (ch == '{') + { + ist >> tolerances.Elem(noldp).f1; + ist >> ch; // ',' + ist >> tolerances.Elem(noldp).f2; + ist >> ch; // ',' + ist >> tolerances.Elem(noldp).f3; + ist >> ch; // '}' + } + else if (ch == 'd') + { + // delpoints.Append (noldp); + ist >> ch; // 'e' + ist >> ch; // 'l' + } + + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + + else if (strcmp (buf, "maplines") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> lin.I1(); + ist >> ch; // ',' + ist >> lin.I2(); + ist >> ch; // ')' + + + //(*testout) << "read line " << lin.I1() << " " << lin.I2() << endl; + lines.Append (lin); + linevecs.Append (points.Get(lin.I2()) - points.Get(lin.I1())); + noldl++; + linetolerances.SetSize (noldl); + linetolerances.Elem(noldl).f1 = 0; + linetolerances.Elem(noldl).f2 = 0; + linetolerances.Elem(noldl).f3 = 0; + + //(*testout) << "mapl1" << endl; + ist >> ch; + while (ch != ';') + { + //(*testout) << "working on character \""<<ch<<"\""<< endl; + if (ch == '{') + { + ist >> linetolerances.Elem(noldl).f1; + ist >> ch; // ',' + ist >> linetolerances.Elem(noldl).f2; + ist >> ch; // ',' + ist >> linetolerances.Elem(noldl).f3; + ist >> ch; // '}' + } + else if (ch == 'd') + { + dellines.Append (noldl); + ist >> ch; // 'e' + ist >> ch; // 'l' + //(*testout) << "read del" << endl; + } + + ist >> ch; + //(*testout) << "read character \""<<ch<<"\""<< endl; + } + + ist >> ch; + //(*testout) << "read next character \""<<ch<<"\""<< endl; + } + + + ist.putback (ch); + } + + else if (strcmp (buf, "newpoints") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> p.X(); + ist >> ch; // ',' + ist >> p.Y(); + ist >> ch; // ')' + + points.Append (p); + + ist >> ch; + while (ch != ';') + { + if (ch == '{') + { + LoadMatrixLine (ist, tempoldutonewu, + 2 * (points.Size()-noldp) - 1); + + ist >> ch; // '{' + LoadMatrixLine (ist, tempoldutonewu, + 2 * (points.Size()-noldp)); + } + + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "newlines") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> lin.I1(); + ist >> ch; // ',' + ist >> lin.I2(); + ist >> ch; // ')' + + lines.Append (lin); + linevecs.Append (points.Get(lin.I2()) - points.Get(lin.I1())); + + ist >> ch; + while (ch != ';') + { + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "freearea") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> p.X(); + ist >> ch; // ',' + ist >> p.Y(); + ist >> ch; // ')' + + freezone.Append (p); + freezonelimit.Append (p); + + ist >> ch; + while (ch != ';') + { + if (ch == '{') + { + LoadMatrixLine (ist, tempoldutofreearea, + 2 * freezone.Size() - 1); + + ist >> ch; // '{' + LoadMatrixLine (ist, tempoldutofreearea, + 2 * freezone.Size()); + } + + ist >> ch; + } + + ist >> ch; + } + + for (i = 1; i <= tempoldutofreearealimit.Height(); i++) + for (j = 1; j <= tempoldutofreearealimit.Width(); j++) + tempoldutofreearealimit.Elem(i,j) = + tempoldutofreearea.Elem(i,j); + + + ist.putback (ch); + } + else if (strcmp (buf, "freearea2") == 0) + { + ist >> ch; + int freepi = 0; + tempoldutofreearealimit = 0; + + while (ch == '(') + { + freepi++; + + ist >> p.X(); + ist >> ch; // ',' + ist >> p.Y(); + ist >> ch; // ')' + + freezonelimit.Elem(freepi) = p; + + ist >> ch; + while (ch != ';') + { + if (ch == '{') + { + LoadMatrixLine (ist, tempoldutofreearealimit, + 2 * freepi - 1); + + ist >> ch; // '{' + LoadMatrixLine (ist, tempoldutofreearealimit, + 2 * freepi); + } + + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "elements") == 0) + { + ist >> ch; + + while (ch == '(') + { + elements.Append (Element2d()); + + ist >> elements.Last().PNum(1); + ist >> ch; // ',' + + if (ch == COMMASIGN) + { + ist >> elements.Last().PNum(2); + ist >> ch; // ',' + } + if (ch == COMMASIGN) + { + ist >> elements.Last().PNum(3); + ist >> ch; // ',' + } + if (ch == COMMASIGN) + { + elements.Last().SetType (QUAD); + ist >> elements.Last().PNum(4); + ist >> ch; // ',' + + // const Element2d & el = elements.Last(); + /* + orientations.Append (threeint(el.PNum(1), el.PNum(2), el.PNum(3))); + orientations.Append (threeint(el.PNum(2), el.PNum(3), el.PNum(4))); + orientations.Append (threeint(el.PNum(3), el.PNum(4), el.PNum(1))); + orientations.Append (threeint(el.PNum(4), el.PNum(1), el.PNum(2))); + */ + } + + ist >> ch; + while (ch != ';') + { + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "orientations") == 0) + + { + ist >> ch; + + while (ch == '(') + { + // threeint a = threeint(); + orientations.Append (threeint()); + + ist >> orientations.Last().i1; + ist >> ch; // ',' + ist >> orientations.Last().i2; + ist >> ch; // ',' + ist >> orientations.Last().i3; + ist >> ch; // ',' + + ist >> ch; + while (ch != ';') + { + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "endrule") != 0) + { + PrintSysError ("Parser error, unknown token ", buf); + } + } + while (!ist.eof() && strcmp (buf, "endrule") != 0); + + //(*testout) << "loadr1" << endl; + + oldutonewu.SetSize (2 * (points.Size() - noldp), 2 * noldp); + oldutofreearea.SetSize (2 * freezone.Size(), 2 * noldp); + oldutofreearealimit.SetSize (2 * freezone.Size(), 2 * noldp); + + for (i = 1; i <= oldutonewu.Height(); i++) + for (j = 1; j <= oldutonewu.Width(); j++) + oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j); + + for (i = 1; i <= oldutofreearea.Height(); i++) + for (j = 1; j <= oldutofreearea.Width(); j++) + oldutofreearea.Elem(i, j) = tempoldutofreearea.Elem(i, j); + + for (i = 1; i <= oldutofreearea.Height(); i++) + for (j = 1; j <= oldutofreearea.Width(); j++) + oldutofreearealimit.Elem(i, j) = tempoldutofreearealimit.Elem(i, j); + + freesetinequ.SetSize (freezone.Size()); + + + //(*testout) << "loadr2" << endl; + + { + char ok; + int minn; + ARRAY<int> pnearness (noldp); + + for (i = 1; i <= pnearness.Size(); i++) + pnearness.Elem(i) = 1000; + + for (j = 1; j <= 2; j++) + pnearness.Elem(GetPointNr (1, j)) = 0; + + //(*testout) << "loadr3" << endl; + do + { + ok = 1; + + for (i = 1; i <= noldl; i++) + { + minn = 1000; + for (j = 1; j <= 2; j++) + minn = min2 (minn, pnearness.Get(GetPointNr (i, j))); + + for (j = 1; j <= 2; j++) + if (pnearness.Get(GetPointNr (i, j)) > minn+1) + { + ok = 0; + pnearness.Elem(GetPointNr (i, j)) = minn+1; + } + } + } + while (!ok); + //(*testout) << "loadr4" << endl; + + lnearness.SetSize (noldl); + + for (i = 1; i <= noldl; i++) + { + lnearness.Elem(i) = 0; + for (j = 1; j <= 2; j++) + lnearness.Elem(i) += pnearness.Get(GetPointNr (i, j)); + } + } + //(*testout) << "loadr5" << endl; + + oldutofreearea_i.SetSize (10); + for (i = 0; i < oldutofreearea_i.Size(); i++) + { + oldutofreearea_i[i] = new DenseMatrix (oldutofreearea.Height(), oldutofreearea.Width()); + DenseMatrix & mati = *oldutofreearea_i[i]; + for (j = 0; j < oldutofreearea.Height(); j++) + for (int k = 0; k < oldutofreearea.Width(); k++) + mati(j,k) = 1.0 / (i+1) * oldutofreearea(j,k) + (1 - 1.0/(i+1)) * oldutofreearealimit(j,k); + } + + //(*testout) << "loadr6" << endl; +} + + + + +extern const char * triarules[]; +extern const char * quadrules[]; + +void Meshing2 :: LoadRules (const char * filename) +{ + char buf[256]; + istream * ist; + //char *tr1 = NULL; + string tr1; + + /* + ifstream ist (filename); + if (!ist.good()) + { + cerr << "Rule description file " << filename << " not found" << endl; + exit (1); + } + */ + + + if (filename) + { + // (*mycout) << "rule-filename = " << filename << endl; + ist = new ifstream (filename); + } + else + { + /* connect tetrules to one string */ + const char ** hcp; + + if (!mparam.quad) + { + hcp = triarules; + PrintMessage (3, "load internal triangle rules"); + } + else + { + hcp = quadrules; + PrintMessage (3, "load internal quad rules"); + // LoadRules ("rules/quad.rls"); + } + + size_t len = 0; + while (*hcp) + { + // (*testout) << "POS2 *hcp " << *hcp << endl; + len += strlen (*hcp); + hcp++; + } + //tr1 = new char[len+1]; + //tr1[0] = 0; + tr1.reserve(len+1); + + + if (!mparam.quad) + hcp = triarules; + else + hcp = quadrules; + + + //char * tt1 = tr1; + while (*hcp) + { + //strcat (tt1, *hcp); + //tt1 += strlen (*hcp); + tr1.append(*hcp); + hcp++; + } + +#ifdef WIN32 + // VC++ 2005 workaround + for(string::size_type i=0; i<tr1.size(); i++) + if(tr1[i] == ',') + tr1[i] = ':'; +#endif + + ist = new istringstream (tr1); + } + + + if (!ist->good()) + { + cerr << "Rule description file " << filename << " not found" << endl; + delete ist; + exit (1); + } + + while (!ist->eof()) + { + buf[0] = 0; + (*ist) >> buf; + + if (strcmp (buf, "rule") == 0) + { + //(*testout) << "found rule" << endl; + netrule * rule = new netrule; + //(*testout) << "fr1" << endl; + rule -> LoadRule(*ist); + //(*testout) << "fr2" << endl; + + rules.Append (rule); + } + //(*testout) << "loop" << endl; + } + //(*testout) << "POS3" << endl; + + delete ist; + //delete [] tr1; +} + +} diff --git a/contrib/Netgen/libsrc/meshing/parser3.cpp b/contrib/Netgen/libsrc/meshing/parser3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..382ae9dfc145a3d2aa6d0e5a6c9ab44092a3022c --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/parser3.cpp @@ -0,0 +1,1019 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +#ifdef WIN32 +#define COMMASIGN ':' +#else +#define COMMASIGN ',' +#endif + + +namespace netgen +{ + +extern const char * tetrules[]; + +void LoadVMatrixLine (istream & ist, DenseMatrix & m, int line) +{ + char ch; + int pnum; + float f; + + ist >> ch; + while (ch != '}') + { + ist.putback (ch); + ist >> f; + ist >> ch; + ist >> pnum; + + if (ch == 'x' || ch == 'X') + m.Elem(line, 3 * pnum - 2) = f; + if (ch == 'y' || ch == 'Y') + m.Elem(line, 3 * pnum - 1) = f; + if (ch == 'z' || ch == 'Z') + m.Elem(line, 3 * pnum ) = f; + + if (ch == 'p' || ch == 'P') + { + m.Elem(line , 3 * pnum-2) = f; + m.Elem(line+1, 3 * pnum-1) = f; + m.Elem(line+2, 3 * pnum ) = f; + } + + ist >> ch; + if (ch == COMMASIGN) + ist >> ch; + } +} + + + + + +int vnetrule :: NeighbourTrianglePoint (const threeint & t1, const threeint & t2) const +{ + ARRAY<int> tr1(3); + ARRAY<int> tr2(3); + tr1.Elem(1)=t1.i1; + tr1.Elem(2)=t1.i2; + tr1.Elem(3)=t1.i3; + tr2.Elem(1)=t2.i1; + tr2.Elem(2)=t2.i2; + tr2.Elem(3)=t2.i3; + + + int ret=0; + + for (int i=1; i<=3; i++) + { + for (int j=1; j<=3; j++) + { + if ((tr1.Get(i)==tr2.Get(j) && tr1.Get((i%3)+1)==tr2.Get((j%3)+1)) || + (tr1.Get(i)==tr2.Get((j%3)+1) && tr1.Get((i%3)+1)==tr2.Get(j))) + {ret = tr2.Get((j+1)%3+1);} + } + } + + return ret; + +} + +void vnetrule :: LoadRule (istream & ist) +{ + char buf[256]; + char ch, ok; + Point3d p; + Element2d face; + int i, j, i1, i2, i3, fs, ii, ii1, ii2, ii3; + twoint edge; + DenseMatrix tempoldutonewu(30, 20), + tempoldutofreezone(30, 20), + tempoldutofreezonelimit(30, 20), + tfz(20, 20), + tfzl(20, 20); + + tempoldutonewu = 0; + tempoldutofreezone = 0; + tfz = 0; + tfzl = 0; + + + noldp = 0; + noldf = 0; + + ist.get (buf, sizeof(buf), '"'); + ist.get (ch); + ist.get (buf, sizeof(buf), '"'); + ist.get (ch); + + delete [] name; + name = new char[strlen (buf) + 1]; + strcpy (name, buf); + // (*mycout) << "Rule " << name << " found." << endl; + + do + { + ist >> buf; + + if (strcmp (buf, "quality") == 0) + + { + ist >> quality; + } + + else if (strcmp (buf, "flags") == 0) + { + ist >> ch; + while (ch != ';') + { + flags.Append (ch); + ist >> ch; + } + } + + else if (strcmp (buf, "mappoints") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> p.X(); + ist >> ch; // ',' + ist >> p.Y(); + ist >> ch; // ',' + ist >> p.Z(); + ist >> ch; // ')' + + points.Append (p); + noldp++; + + tolerances.SetSize (noldp); + tolerances.Elem(noldp) = 1; + + ist >> ch; + while (ch != ';') + { + if (ch == '{') + { + ist >> tolerances.Elem(noldp); + ist >> ch; // '}' + } + + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + + else if (strcmp (buf, "mapfaces") == 0) + { + ist >> ch; + + while (ch == '(') + { + face.SetType(TRIG); + ist >> face.PNum(1); + ist >> ch; // ',' + ist >> face.PNum(2); + ist >> ch; // ',' + ist >> face.PNum(3); + ist >> ch; // ')' or ',' + if (ch == COMMASIGN) + { + face.SetType(QUAD); + ist >> face.PNum(4); + ist >> ch; // ')' + } + faces.Append (face); + noldf++; + + ist >> ch; + while (ch != ';') + { + if (ch == 'd') + { + delfaces.Append (noldf); + ist >> ch; // 'e' + ist >> ch; // 'l' + } + + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "mapedges") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> edge.i1; + ist >> ch; // ',' + ist >> edge.i2; + ist >> ch; // ')' + + edges.Append (edge); + + ist >> ch; + while (ch != ';') + { + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + + else if (strcmp (buf, "newpoints") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> p.X(); + ist >> ch; // ',' + ist >> p.Y(); + ist >> ch; // ',' + ist >> p.Z(); + ist >> ch; // ')' + + points.Append (p); + + ist >> ch; + while (ch != ';') + { + if (ch == '{') + { + LoadVMatrixLine (ist, tempoldutonewu, + 3 * (points.Size()-noldp) - 2); + + ist >> ch; // '{' + LoadVMatrixLine (ist, tempoldutonewu, + 3 * (points.Size()-noldp) - 1); + + ist >> ch; // '{' + LoadVMatrixLine (ist, tempoldutonewu, + 3 * (points.Size()-noldp) ); + } + + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "newfaces") == 0) + { + ist >> ch; + + while (ch == '(') + { + face.SetType(TRIG); + ist >> face.PNum(1); + ist >> ch; // ',' + ist >> face.PNum(2); + ist >> ch; // ',' + ist >> face.PNum(3); + ist >> ch; // ')' or ',' + if (ch == COMMASIGN) + { + face.SetType(QUAD); + ist >> face.PNum(4); + ist >> ch; // ')' + } + faces.Append (face); + + ist >> ch; + while (ch != ';') + { + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "freezone") == 0) + { + ist >> ch; + + while (ch == '(') + { + ist >> p.X(); + ist >> ch; // ',' + ist >> p.Y(); + ist >> ch; // ',' + ist >> p.Z(); + ist >> ch; // ')' + + freezone.Append (p); + + ist >> ch; + while (ch != ';') + { + if (ch == '{') + { + LoadVMatrixLine (ist, tempoldutofreezone, + 3 * freezone.Size() - 2); + + ist >> ch; // '{' + LoadVMatrixLine (ist, tempoldutofreezone, + 3 * freezone.Size() - 1); + + ist >> ch; // '{' + LoadVMatrixLine (ist, tempoldutofreezone, + 3 * freezone.Size() ); + } + + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + else if (strcmp (buf, "freezone2") == 0) + { + int k, nfp; + + nfp = 0; + ist >> ch; + + DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50); + hm3 = 0; + + while (ch == '{') + { + hm1 = 0; + nfp++; + LoadVMatrixLine (ist, hm1, 1); + + for (i = 1; i <= points.Size(); i++) + tfz.Elem(nfp, i) = hm1.Get(1, 3*i-2); + + + p.X() = p.Y() = p.Z() = 0; + for (i = 1; i <= points.Size(); i++) + { + p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X(); + p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y(); + p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z(); + } + freezone.Append (p); + freezonelimit.Append (p); + + hm2 = 0; + for (i = 1; i <= 3 * noldp; i++) + hm2.Elem(i, i) = 1; + for (i = 1; i <= 3 * noldp; i++) + for (j = 1; j <= 3 * (points.Size() - noldp); j++) + hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i); + + for (i = 1; i <= 3; i++) + for (j = 1; j <= 3 * noldp; j++) + { + double sum = 0; + for (k = 1; k <= 3 * points.Size(); k++) + sum += hm1.Get(i, k) * hm2.Get(k, j); + + hm3.Elem(i + 3 * (nfp-1), j) = sum; + } + + // (*testout) << "freepoint: " << p << endl; + + while (ch != ';') + ist >> ch; + + ist >> ch; + } + + tfzl = tfz; + + tempoldutofreezone = hm3; + tempoldutofreezonelimit = hm3; + ist.putback(ch); + } + + else if (strcmp (buf, "freezonelimit") == 0) + { + int k, nfp; + nfp = 0; + ist >> ch; + + DenseMatrix hm1(3, 50), hm2(50, 50), hm3(50, 50); + hm3 = 0; + + while (ch == '{') + { + hm1 = 0; + nfp++; + LoadVMatrixLine (ist, hm1, 1); + + for (i = 1; i <= points.Size(); i++) + tfzl.Elem(nfp, i) = hm1.Get(1, 3*i-2); + + + p.X() = p.Y() = p.Z() = 0; + for (i = 1; i <= points.Size(); i++) + { + p.X() += hm1.Get(1, 3*i-2) * points.Get(i).X(); + p.Y() += hm1.Get(1, 3*i-2) * points.Get(i).Y(); + p.Z() += hm1.Get(1, 3*i-2) * points.Get(i).Z(); + } + freezonelimit.Elem(nfp) = p; + + hm2 = 0; + for (i = 1; i <= 3 * noldp; i++) + hm2.Elem(i, i) = 1; + for (i = 1; i <= 3 * noldp; i++) + for (j = 1; j <= 3 * (points.Size() - noldp); j++) + hm2.Elem(j + 3 * noldp, i) = tempoldutonewu.Get(j, i); + + for (i = 1; i <= 3; i++) + for (j = 1; j <= 3 * noldp; j++) + { + double sum = 0; + for (k = 1; k <= 3 * points.Size(); k++) + sum += hm1.Get(i, k) * hm2.Get(k, j); + + hm3.Elem(i + 3 * (nfp-1), j) = sum; + } + + // (*testout) << "freepoint: " << p << endl; + + while (ch != ';') + ist >> ch; + + ist >> ch; + } + + tempoldutofreezonelimit = hm3; + ist.putback(ch); + } + + else if (strcmp (buf, "freeset") == 0) + { + freesets.Append (new ARRAY<int>); + + ist >> ch; + + while (ch != ';') + { + ist.putback (ch); + ist >> i; + freesets.Last()->Append(i); + ist >> ch; + } + } + + else if (strcmp (buf, "elements") == 0) + { + ist >> ch; + + while (ch == '(') + { + elements.Append (Element(TET)); + + // elements.Last().SetNP(1); + ist >> elements.Last().PNum(1); + ist >> ch; // ',' + + if (ch == COMMASIGN) + { + // elements.Last().SetNP(2); + ist >> elements.Last().PNum(2); + ist >> ch; // ',' + } + if (ch == COMMASIGN) + { + // elements.Last().SetNP(3); + ist >> elements.Last().PNum(3); + ist >> ch; // ',' + } + if (ch == COMMASIGN) + { + // elements.Last().SetNP(4); + elements.Last().SetType(TET); + ist >> elements.Last().PNum(4); + ist >> ch; // ',' + } + if (ch == COMMASIGN) + { + // elements.Last().SetNP(5); + elements.Last().SetType(PYRAMID); + ist >> elements.Last().PNum(5); + ist >> ch; // ',' + } + if (ch == COMMASIGN) + { + // elements.Last().SetNP(6); + elements.Last().SetType(PRISM); + ist >> elements.Last().PNum(6); + ist >> ch; // ',' + } + + /* + orientations.Append (fourint()); + orientations.Last().i1 = elements.Last().PNum(1); + orientations.Last().i2 = elements.Last().PNum(2); + orientations.Last().i3 = elements.Last().PNum(3); + orientations.Last().i4 = elements.Last().PNum(4); + */ + + ist >> ch; + while (ch != ';') + { + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + else if (strcmp (buf, "orientations") == 0) + + { + ist >> ch; + + while (ch == '(') + { + // fourint a = fourint(); + orientations.Append (fourint()); + + ist >> orientations.Last().i1; + ist >> ch; // ',' + ist >> orientations.Last().i2; + ist >> ch; // ',' + ist >> orientations.Last().i3; + ist >> ch; // ',' + ist >> orientations.Last().i4; + ist >> ch; // ',' + + + ist >> ch; + while (ch != ';') + { + ist >> ch; + } + + ist >> ch; + } + + ist.putback (ch); + } + + + else if (strcmp (buf, "endrule") != 0) + { + PrintSysError ("Parser3d, unknown token " , buf); + } + } + while (!ist.eof() && strcmp (buf, "endrule") != 0); + + + // (*testout) << endl; + // (*testout) << Name() << endl; + // (*testout) << "no1 = " << GetNO() << endl; + + oldutonewu.SetSize (3 * (points.Size() - noldp), 3 * noldp); + oldutonewu = 0; + + for (i = 1; i <= oldutonewu.Height(); i++) + for (j = 1; j <= oldutonewu.Width(); j++) + oldutonewu.Elem(i, j) = tempoldutonewu.Elem(i, j); + + + /* + oldutofreezone = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp); + oldutofreezonelimit = new SparseMatrixFlex (3 * freezone.Size(), 3 * noldp); + + oldutofreezone -> SetSymmetric(0); + oldutofreezonelimit -> SetSymmetric(0); + */ + + /* + oldutofreezone = new DenseMatrix (3 * freezone.Size(), 3 * noldp); + oldutofreezonelimit = new DenseMatrix (3 * freezone.Size(), 3 * noldp); + + for (i = 1; i <= oldutofreezone->Height(); i++) + for (j = 1; j <= oldutofreezone->Width(); j++) + // if (j == 4 || j >= 7) + { + if (tempoldutofreezone.Elem(i, j)) + (*oldutofreezone)(i, j) = tempoldutofreezone(i, j); + if (tempoldutofreezonelimit.Elem(i, j)) + (*oldutofreezonelimit)(i, j) = tempoldutofreezonelimit(i, j); + } + */ + + + + + oldutofreezone = new DenseMatrix (freezone.Size(), points.Size()); + oldutofreezonelimit = new DenseMatrix (freezone.Size(), points.Size()); + // oldutofreezone = new SparseMatrixFlex (freezone.Size(), points.Size()); + // oldutofreezonelimit = new SparseMatrixFlex (freezone.Size(), points.Size()); + + for (i = 1; i <= freezone.Size(); i++) + for (j = 1; j <= points.Size(); j++) + { + if (tfz.Elem(i, j)) + (*oldutofreezone).Elem(i, j) = tfz.Elem(i, j); + if (tfzl.Elem(i, j)) + (*oldutofreezonelimit).Elem(i, j) = tfzl.Elem(i, j); + } + + /* + (*testout) << "Rule " << Name() << endl; + (*testout) << "oldutofreezone = " << (*oldutofreezone) << endl; + (*testout) << "oldutofreezonelimit = " << (*oldutofreezonelimit) << endl; + */ + + freezonepi.SetSize (freezone.Size()); + for (i = 1; i <= freezonepi.Size(); i++) + freezonepi.Elem(i) = 0; + for (i = 1; i <= freezone.Size(); i++) + for (j = 1; j <= noldp; j++) + if (Dist (freezone.Get(i), points.Get(j)) < 1e-8) + freezonepi.Elem(i) = j; + + + + + for (i = 1; i <= elements.Size(); i++) + { + if (elements.Elem(i).GetNP() == 4) + { + orientations.Append (fourint()); + orientations.Last().i1 = elements.Get(i).PNum(1); + orientations.Last().i2 = elements.Get(i).PNum(2); + orientations.Last().i3 = elements.Get(i).PNum(3); + orientations.Last().i4 = elements.Get(i).PNum(4); + } + if (elements.Elem(i).GetNP() == 5) + { + orientations.Append (fourint()); + orientations.Last().i1 = elements.Get(i).PNum(1); + orientations.Last().i2 = elements.Get(i).PNum(2); + orientations.Last().i3 = elements.Get(i).PNum(3); + orientations.Last().i4 = elements.Get(i).PNum(5); + + orientations.Append (fourint()); + orientations.Last().i1 = elements.Get(i).PNum(1); + orientations.Last().i2 = elements.Get(i).PNum(3); + orientations.Last().i3 = elements.Get(i).PNum(4); + orientations.Last().i4 = elements.Get(i).PNum(5); + } + } + + + + if (freesets.Size() == 0) + { + freesets.Append (new ARRAY<int>); + for (i = 1; i <= freezone.Size(); i++) + freesets.Elem(1)->Append(i); + } + + + // testout << "Freezone: " << endl; + + // for (i = 1; i <= freezone.Size(); i++) + // (*testout) << "freepoint: " << freezone.Get(i) << endl; + Vector vp(points.Size()), vfp(freezone.Size()); + + + if (quality < 100) + { + for (i = 1; i <= 3; i++) + { + for (j = 1; j <= points.Size(); j++) + vp.Elem(j) = points.Get(j).X(i); + oldutofreezone->Mult(vp, vfp); + for (j = 1; j <= freezone.Size(); j++) + freezone.Elem(j).X(i) = vfp.Get(j); + } + // for (i = 1; i <= freezone.Size(); i++) + // (*testout) << "freepoint: " << freezone.Get(i) << endl; + } + + + for (fs = 1; fs <= freesets.Size(); fs++) + { + freefaces.Append (new ARRAY<threeint>); + + ARRAY<int> & freeset = *freesets.Elem(fs); + ARRAY<threeint> & freesetfaces = *freefaces.Last(); + + for (ii1 = 1; ii1 <= freeset.Size(); ii1++) + for (ii2 = 1; ii2 <= freeset.Size(); ii2++) + for (ii3 = 1; ii3 <= freeset.Size(); ii3++) + if (ii1 < ii2 && ii1 < ii3 && ii2 != ii3) + { + i1 = freeset.Get(ii1); + i2 = freeset.Get(ii2); + i3 = freeset.Get(ii3); + + Vec3d v1, v2, n; + + v1 = freezone.Get(i3) - freezone.Get(i1); + v2 = freezone.Get(i2) - freezone.Get(i1); + n = Cross (v1, v2); + n /= n.Length(); + // (*testout) << "i1,2,3 = " << i1 << ", " << i2 << ", " << i3 << endl; + // (*testout) << "v1 = " << v1 << " v2 = " << v2 << " n = " << n << endl; + ok = 1; + for (ii = 1; ii <= freeset.Size(); ii++) + { + i = freeset.Get(ii); + // (*testout) << "i = " << i << endl; + if (i != i1 && i != i2 && i != i3) + if ( (freezone.Get(i) - freezone.Get(i1)) * n < 0 ) ok = 0; + } + + if (ok) + { + freesetfaces.Append (threeint()); + freesetfaces.Last().i1 = i1; + freesetfaces.Last().i2 = i2; + freesetfaces.Last().i3 = i3; + } + } + } + + for (fs = 1; fs <= freesets.Size(); fs++) + { + freefaceinequ.Append (new DenseMatrix (freefaces.Get(fs)->Size(), 4)); + } + + + { + int minn; + // ARRAY<int> pnearness (noldp); + pnearness.SetSize (noldp); + + for (i = 1; i <= pnearness.Size(); i++) + pnearness.Elem(i) = INT_MAX/10; + + for (j = 1; j <= GetNP(1); j++) + pnearness.Elem(GetPointNr (1, j)) = 0; + + do + { + ok = 1; + + for (i = 1; i <= noldf; i++) + { + minn = INT_MAX/10; + for (j = 1; j <= GetNP(i); j++) + minn = min2 (minn, pnearness.Get(GetPointNr (i, j))); + + for (j = 1; j <= GetNP(i); j++) + if (pnearness.Get(GetPointNr (i, j)) > minn+1) + { + ok = 0; + pnearness.Elem(GetPointNr (i, j)) = minn+1; + } + } + + for (i = 1; i <= edges.Size(); i++) + { + int pi1 = edges.Get(i).i1; + int pi2 = edges.Get(i).i2; + + if (pnearness.Get(pi1) > pnearness.Get(pi2)+1) + { + ok = 0; + pnearness.Elem(pi1) = pnearness.Get(pi2)+1; + } + if (pnearness.Get(pi2) > pnearness.Get(pi1)+1) + { + ok = 0; + pnearness.Elem(pi2) = pnearness.Get(pi1)+1; + } + } + + + for (i = 1; i <= elements.Size(); i++) + if (elements.Get(i).GetNP() == 6) // prism rule + { + for (j = 1; j <= 3; j++) + { + int pi1 = elements.Get(i).PNum(j); + int pi2 = elements.Get(i).PNum(j+3); + + if (pnearness.Get(pi1) > pnearness.Get(pi2)+1) + { + ok = 0; + pnearness.Elem(pi1) = pnearness.Get(pi2)+1; + } + if (pnearness.Get(pi2) > pnearness.Get(pi1)+1) + { + ok = 0; + pnearness.Elem(pi2) = pnearness.Get(pi1)+1; + } + } + } + } + while (!ok); + + maxpnearness = 0; + for (i = 1; i <= pnearness.Size(); i++) + maxpnearness = max2 (maxpnearness, pnearness.Get(i)); + + + fnearness.SetSize (noldf); + + for (i = 1; i <= noldf; i++) + { + fnearness.Elem(i) = 0; + for (j = 1; j <= GetNP(i); j++) + fnearness.Elem(i) += pnearness.Get(GetPointNr (i, j)); + } + + // (*testout) << "rule " << name << ", pnear = " << pnearness << endl; + } + + + //Table of edges: + for (fs = 1; fs <= freesets.Size(); fs++) + { + freeedges.Append (new ARRAY<twoint>); + + // ARRAY<int> & freeset = *freesets.Get(fs); + ARRAY<twoint> & freesetedges = *freeedges.Last(); + ARRAY<threeint> & freesetfaces = *freefaces.Get(fs); + int k,l; + INDEX ind; + + for (k = 1; k <= freesetfaces.Size(); k++) + { + threeint tr = freesetfaces.Get(k); + + for (l = k+1; l <= freesetfaces.Size(); l++) + { + ind = NeighbourTrianglePoint(freesetfaces.Get(k), freesetfaces.Get(l)); + if (!ind) continue; + + INDEX_3 f1(freesetfaces.Get(k).i1, + freesetfaces.Get(k).i2, + freesetfaces.Get(k).i3); + INDEX_3 f2(freesetfaces.Get(l).i1, + freesetfaces.Get(l).i2, + freesetfaces.Get(l).i3); + INDEX_2 ed(0, 0); + for (int f11 = 1; f11 <= 3; f11++) + for (int f12 = 1; f12 <= 3; f12++) + if (f11 != f12) + for (int f21 = 1; f21 <= 3; f21++) + for (int f22 = 1; f22 <= 3; f22++) + if (f1.I(f11) == f2.I(f21) && f1.I(f12) == f2.I(f22)) + { + ed.I(1) = f1.I(f11); + ed.I(2) = f1.I(f12); + } + // (*testout) << "ed = " << ed.I(1) << "-" << ed.I(2) << endl; + // (*testout) << "ind = " << ind << " ed = " << ed << endl; + for (int eli = 1; eli <= GetNOldF(); eli++) + { + if (GetNP(eli) == 4) + { + for (int elr = 1; elr <= 4; elr++) + { + if (GetPointNrMod (eli, elr) == ed.I(1) && + GetPointNrMod (eli, elr+2) == ed.I(2)) + { + /* + (*testout) << "ed is diagonal of rectangle" << endl; + (*testout) << "ed = " << ed.I(1) << "-" << ed.I(2) << endl; + (*testout) << "ind = " << ind << endl; + */ + ind = 0; + } + + } + } + } + + if (ind) + { + /* + (*testout) << "new edge from face " << k + << " = (" << freesetfaces.Get(k).i1 + << ", " << freesetfaces.Get(k).i2 + << ", " << freesetfaces.Get(k).i3 + << "), point " << ind << endl; + */ + freesetedges.Append(twoint(k,ind)); + } + } + } + } + +} + + + + + +void Meshing3 :: LoadRules (const char * filename, const char ** prules) +{ + char buf[256]; + istream * ist; + char *tr1 = NULL; + + if (filename) + { + PrintMessage (3, "rule-filename = ", filename); + ist = new ifstream (filename); + } + else + { + /* connect tetrules to one string */ + PrintMessage (3, "Use internal rules"); + if (!prules) prules = tetrules; + + const char ** hcp = prules; + size_t len = 0; + while (*hcp) + { + len += strlen (*hcp); + hcp++; + } + tr1 = new char[len+1]; + tr1[0] = 0; + hcp = prules; // tetrules; + + + char * tt1 = tr1; + while (*hcp) + { + strcat (tt1, *hcp); + tt1 += strlen (*hcp); + hcp++; + } + + +#ifdef WIN32 + // VC++ 2005 workaround + for(size_t i=0; i<len; i++) + if(tr1[i] == ',') + tr1[i] = ':'; +#endif + + ist = new istringstream (tr1); + } + + if (!ist->good()) + { + cerr << "Rule description file " << filename << " not found" << endl; + delete ist; + exit (1); + } + + while (!ist->eof()) + { + buf[0] = 0; + (*ist) >> buf; + + if (strcmp (buf, "rule") == 0) + { + vnetrule * rule = new vnetrule; + rule -> LoadRule(*ist); + rules.Append (rule); + if (!rule->TestOk()) + { + PrintSysError ("Parser3d: Rule ", rules.Size(), " not ok"); + exit (1); + } + } + else if (strcmp (buf, "tolfak") == 0) + { + (*ist) >> tolfak; + } + } + delete ist; + delete [] tr1; +} +} diff --git a/contrib/Netgen/libsrc/meshing/prism2rls.cpp b/contrib/Netgen/libsrc/meshing/prism2rls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e696554c0fef82fbafcb0633917eddcaaf5de27 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/prism2rls.cpp @@ -0,0 +1,457 @@ +namespace netgen +{ +const char * prismrules2[] = { +"tolfak 0.5\n",\ +"\n",\ +"rule \"prism on quad\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0, -0.86);\n",\ +"(0.5, 1, -0.86);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(1, 5, 2) del;\n",\ +"(4, 3, 6) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3, 6);\n",\ +"(1, 5, 6, 4);\n",\ +"\n",\ +"elements\n",\ +"(1, 5, 2, 4, 6, 3);\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 3, 4, 6);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ +"{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ +"{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 4 5 6 7;\n",\ +"\n",\ +"freeset\n",\ +"2 3 4 5 6 8;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"prism on quad, one trig\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0, -0.86);\n",\ +"(0.5, 1, -0.86);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(1, 5, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3, 6);\n",\ +"(1, 5, 6, 4);\n",\ +"(4, 6, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 5, 2, 4, 6, 3);\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 3, 4, 6);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ +"{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ +"{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 4 5 6 7;\n",\ +"\n",\ +"freeset\n",\ +"2 3 4 5 6 8;\n",\ +"\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"prism on 2 quad\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0, -0.86);\n",\ +"(0.5, 1, -0.86);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 5, 6, 3) del;\n",\ +"(1, 5, 2) del;\n",\ +"(4, 3, 6) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 5, 6, 4);\n",\ +"\n",\ +"elements\n",\ +"(1, 5, 2, 4, 6, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 4 5 6 7;\n",\ +"\n",\ +"freeset\n",\ +"2 3 4 6;\n",\ +"\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"prism on 2 quad, one trig\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0, -0.86);\n",\ +"(0.5, 1, -0.86);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 5, 6, 3) del;\n",\ +"(1, 5, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 5, 6, 4);\n",\ +"(4, 6, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 5, 2, 4, 6, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.3 P1, -0.1 P2, -0.1 P3, 0.3 P4, 0.3 P5, 0.3 P6 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0.25 P1, 0 P2, 0 P3, 0.25 P4, 0.25 P5, 0.25 P6 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 4 5 6 7;\n",\ +"\n",\ +"freeset\n",\ +"2 3 4 6;\n",\ +"\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"prism on 2 quada\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0, -0.86);\n",\ +"(0.5, 1, -0.86);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(5, 1, 4, 6) del;\n",\ +"(1, 5, 2) del;\n",\ +"(4, 3, 6) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3, 6);\n",\ +"\n",\ +"elements\n",\ +"(1, 5, 2, 4, 6, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ -0.1 P1, 0.3 P2, 0.3 P3, -0.1 P4, 0.3 P5, 0.3 P6 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 0 P1, 0.25 P2, 0.25 P3, 0 P4, 0.25 P5, 0.25 P6 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5 6 7;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 6;\n",\ +"\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"fill prism\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0, -0.86);\n",\ +"(0.5, 1, -0.86);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 5, 6, 3) del;\n",\ +"(5, 1, 4, 6) del;\n",\ +"(1, 5, 2) del;\n",\ +"(4, 3, 6) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 5, 2, 4, 6, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 4 5;\n",\ +"\n",\ +"freeset\n",\ +"2 3 4 6;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"prism on 3 quad, one trig\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0, -0.86);\n",\ +"(0.5, 1, -0.86);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 5, 6, 3) del;\n",\ +"(5, 1, 4, 6) del;\n",\ +"(1, 5, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 6, 3);\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 5, 2, 4, 6, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 4 5;\n",\ +"\n",\ +"freeset\n",\ +"2 3 4 6;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"flat prism\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(0.5, 0.866, 0);\n",\ +"(0, 0, -1);\n",\ +"(1, 0, -1);\n",\ +"(0.5, 0.866, -1);\n",\ +"\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(5, 4, 6) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 4);\n",\ +"(4, 2, 5);\n",\ +"(2, 3, 5);\n",\ +"(5, 3, 6);\n",\ +"(3, 1, 6);\n",\ +"(6, 1, 4);\n",\ +"\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 5, 4, 6);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"endrule\n",\ +"\n",\ +0}; +} diff --git a/contrib/Netgen/libsrc/meshing/pyramid2rls.cpp b/contrib/Netgen/libsrc/meshing/pyramid2rls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a97e7f13e594ee25b0a2308233b15132331d989c --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/pyramid2rls.cpp @@ -0,0 +1,309 @@ +namespace netgen +{ +const char * pyramidrules2[] = { +"tolfak 0.5\n",\ +"\n",\ +"rule \"Pyramid on quad\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.5, -0.5) \n",\ +" { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ +" { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 5);\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"small Pyramid on quad\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.5, -0.1 )\n",\ +" { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ +" { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 5);\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"connect pyramid\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0.5, -0.5);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 5);\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"pyramid with one trig\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0.5, -0.5);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 1, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 };\n",\ +"{ 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 };\n",\ +"{ 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 };\n",\ +"{ 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 };\n",\ +"{ 0.333 P1, 0.333 P4, 0.334 P5, 0 P2 };\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 3, 4, 5);\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"freeset\n",\ +"2 3 5 6;\n",\ +"freeset\n",\ +"3 4 5 7;\n",\ +"freeset \n",\ +"1 4 5 8;\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"pyramid with two trig\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0.5, -0.5);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 1, 5) del;\n",\ +"(3, 2, 5) del;\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"pyramid with two trig, left\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0.5, -0.5);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 1, 5) del;\n",\ +"(1, 4, 5) del;\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(3, 4, 5);\n",\ +"(2, 3, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +0}; +} diff --git a/contrib/Netgen/libsrc/meshing/pyramidrls.cpp b/contrib/Netgen/libsrc/meshing/pyramidrls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4e997c1fea470d99cebb3d21bf815b33d02b745 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/pyramidrls.cpp @@ -0,0 +1,263 @@ +namespace netgen +{ +const char * pyramidrules[] = { +"tolfak 0.5\n",\ +"\n",\ +"rule \"Pyramid on quad\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.5, -0.5) \n",\ +" { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ +" { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 5);\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"small Pyramid on quad\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.5, -0.1 )\n",\ +" { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 } \n",\ +" { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 5);\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.4 P5, -0.1 P1, -0.1 P2, -0.1 P3, -0.1 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"connect pyramid\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0.5, -0.5);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 5);\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"pyramid with one trig\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0.5, -0.5);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 1, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(2, 3, 5);\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 0.34 P2, 0.34 P3, 0.34 P5, -0.02 P1 };\n",\ +"{ 0.34 P3, 0.34 P4, 0.34 P5, -0.02 P1 };\n",\ +"{ 0.34 P1, 0.34 P4, 0.34 P5, -0.02 P3 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 0.333 P2, 0.333 P3, 0.334 P5, 0 P1 };\n",\ +"{ 0.333 P3, 0.333 P4, 0.334 P5, 0 P1 };\n",\ +"{ 0.333 P1, 0.333 P4, 0.334 P5, 0 P3 };\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 3, 4, 5);\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"freeset\n",\ +"2 3 5 6;\n",\ +"freeset\n",\ +"3 4 5 7;\n",\ +"freeset \n",\ +"1 4 5 8;\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"pyramid with two trig\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(1, 1, 0);\n",\ +"(0, 1, 0);\n",\ +"(0.5, 0.5, -0.5);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3, 4) del;\n",\ +"(2, 1, 5) del;\n",\ +"(3, 2, 5) del;\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(3, 4, 5);\n",\ +"(4, 1, 5);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +0}; +} diff --git a/contrib/Netgen/libsrc/meshing/quadrls.cpp b/contrib/Netgen/libsrc/meshing/quadrls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c2cd23b778abf62d7f8dcc6a9bf23d53dd14a93 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/quadrls.cpp @@ -0,0 +1,887 @@ +namespace netgen +{ +const char * quadrules[] = { +"rule \"Free Quad (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 1) { 1 X2 } { };\n",\ +"(0, 1) { } { };\n",\ +"\n",\ +"newlines\n",\ +"(3, 2);\n",\ +"(4, 3);\n",\ +"(1, 4);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 1.5) { 1.5 X2 } { };\n",\ +"(-0.5, 1.5) { -0.5 X2 } { };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Free Quad (5)\"\n",\ +"\n",\ +"quality 5\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 1) { 1 X2 } { };\n",\ +"(0, 1) { } { };\n",\ +"\n",\ +"newlines\n",\ +"(3, 2);\n",\ +"(4, 3);\n",\ +"(1, 4);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 1.5) { 1.5 X2 } { };\n",\ +"(-0.5, 1.5) { -0.5 X2 } { };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X2 } { };\n",\ +"(0, 1) { } { };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Quad Right (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0, 1) { } { 1 y3 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 4);\n",\ +"(4, 3);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(-0.5, 1.5) { } { 1.5 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Quad P Right (2)\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0, 1) { -1 X2, 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 4);\n",\ +"(4, 3);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.2, 0.5) { 0.7 X2, 0.5 X3 } { 0.5 Y3 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(-0.5, 1.5) { -2 X2, 1.5 X3 } { 1.5 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { -1 X2, 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"Quad P Right (150)\"\n",\ +"\n",\ +"quality 150\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 4)\n;",\ +"(4, 3)\n;",\ +"(3, 2)\n;",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.2, 0.5) { 0.7 X2, 0.5 X3 } { 0.5 Y3 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(-0.5, 1.5) { -2 X2, 1.5 X3 } { 1.5 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"Quad Right PL (2)\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(1, 4);\n",\ +"(4, 3);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"(-0.2, 0.5) { -0.1 X2, -0.1 X3, 0.6 X4 } { -0.1 Y2, -0.1 Y3, 0.6 Y4 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3);\n",\ +"(1, 3, 4);\n",\ +"(1, 2, 4);\n",\ +"(4, 2, 3);\n",\ +"\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left Quad (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(3, 4);\n",\ +"(4, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left P Quad (2)\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 4);\n",\ +"(4, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"(-0.2, 0.6) { -0.2 X2, 0.6 X3 } { 0.6 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X2, 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 0.5) { 0.5 X3 } { 0.5 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left P Quad (150)\"\n",\ +"\n",\ +"quality 150\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 4);\n",\ +"(4, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 1.5) { 1.5 X2, 1.5 X3 } { 1.5 Y3 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"(-0.2, 0.6) { -0.2 X2, 0.6 X3 } { 0.6 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X2, -1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 0.5) { 0.5 X3 } { 0.5 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left Quad RP (2)\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0, 1);\n",\ +"(1, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(3, 4);\n",\ +"(4, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.2, 0.5) { 0.6 X2, 0.6 X4, -0.1 X3 } { 0.6 Y2, 0.6 Y4, -0.1 Y3 };\n",\ +"(1, 1) { 1 X4 } { 1 Y4 };\n",\ +"(0.5, 1.2) { -0.1 X2, 0.6 X3, 0.6 X4 } { -0.1 Y2, 0.6 Y3, 0.6 Y4 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.5) { 0.5 X2, 0.5 X4 } { 0.5 Y2, 0.5 Y4 };\n",\ +"(1, 1) { 1 X4 } { 1 Y4 };\n",\ +"(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ +"(0, 1) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4, 3);\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 4);\n",\ +"(1, 4, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Two left (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 4) del;\n",\ +"(4, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Two Right (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"(3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(1, 4);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"(-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Right 120 (1)\"\n",\ +"\n",\ +"quality 1000\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 4);\n",\ +"(4, 3);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(1, 1.732) { -2 X2, 2 X3 } { 2 Y3 };\n",\ +"(0, 1.732) { -3 X2, 2 X3 } { 2 Y3 };\n",\ +"(-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4);\n",\ +"(2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left 120 (1)\"\n",\ +"\n",\ +"quality 1000\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(-0.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(3, 4);\n",\ +"(4, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 };\n",\ +"(1, 1.732) { 2 X2, 2 X3 } { 2 Y3 };\n",\ +"(0, 1.732) { -1 X2, 2 X3 } { 2 Y3 };\n",\ +"(-0.5, 0.866) { 1 X3 } {1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4);\n",\ +"(2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left Right (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"(4, 1) del;\n",\ +"\n",\ +"\n",\ +"newlines\n",\ +"(4, 3);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0.5, 1.5) { -0.25 X2, 0.75 X3, 0.75 X4 } { 0.75 Y3, 0.75 Y4 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0.5, 1) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Fill Quad\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"(3, 4) del;\n",\ +"(4, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { 1 Y2 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Fill Triangle\"\n",\ +"\n",\ +"quality 10\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0.5, 0.86);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"(3, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { 1 Y2 };\n",\ +"(0.5, 0.86) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Right 60 (1)\"\n",\ +"\n",\ +"quality 10\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0) { 0.5, 0, 1.0 };\n",\ +"(0.5, 0.866) { 0.6, 0, 0.8 };\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Vis A Vis (2)\"\n",\ +"\n",\ +"quality 2\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1);\n",\ +"(0, 1);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(1, 4);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.5) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y3, -0.25 Y4 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"(-0.5, 0.5) { -0.25 X2, -0.25 X3, 0.75 X4 } { -0.25 Y3, 0.75 Y4 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.5) { 0.5 X2, 0.5 X3 } { 0.5 Y3 };\n",\ +"(1, 1) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1) { 1 X4 } { 1 Y4 };\n",\ +"(0, 0.5) { 0.5 X4 } { 0.5 Y4 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"orientations\n",\ +"(1, 3, 4);\n",\ +"(2, 3, 4);\n",\ +"(1, 2, 3);\n",\ +"(1, 2, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Triangle Vis A Vis (200)\"\n",\ +"\n",\ +"quality 200\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.2, 0.693) { 0.8 X2, 0.8 X3 } { 0.8 Y2, 0.8 Y3 };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(-0.2, 0.693) { -0.6 X2, 0.8 X3 } { -0.6 Y2, 0.8 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"2 h Vis A Vis (1)\"\n",\ +"\n",\ +"quality 3000\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1.732);\n",\ +"(0, 1.732);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 5);\n",\ +"(5, 4);\n",\ +"(3, 5);\n",\ +"(5, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { 1 Y2 };\n",\ +"(1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 };\n",\ +"(1, 1.732) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1.732) { 1 X4 } { 1 Y4 };\n",\ +"(-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 5);\n",\ +"(3, 4, 5);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +0}; +} diff --git a/contrib/Netgen/libsrc/meshing/refine.cpp b/contrib/Netgen/libsrc/meshing/refine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ed792cb262c0a1ec4b420ae26c0215eaf30db2d --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/refine.cpp @@ -0,0 +1,732 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + void Refinement :: Refine (Mesh & mesh) + { + // reduce 2nd order + mesh.ComputeNVertices(); + mesh.SetNP(mesh.GetNV()); + + + INDEX_2_HASHTABLE<int> between(mesh.GetNP() + 5); + + int oldne, oldns, oldnf; + + // refine edges + + ARRAY<EdgePointGeomInfo,PointIndex::BASE> epgi; + + oldns = mesh.GetNSeg(); + for (SegmentIndex si = 0; si < oldns; si++) + { + const Segment & el = mesh.LineSegment(si); + + INDEX_2 i2 = INDEX_2::Sort(el.p1, el.p2); + PointIndex pinew; + EdgePointGeomInfo ngi; + + if (between.Used(i2)) + { + pinew = between.Get(i2); + ngi = epgi[pinew]; + } + else + { + Point<3> pnew; + + PointBetween (mesh.Point (el.p1), + mesh.Point (el.p2), 0.5, + el.surfnr1, el.surfnr2, + el.epgeominfo[0], el.epgeominfo[1], + pnew, ngi); + + pinew = mesh.AddPoint (pnew); + between.Set (i2, pinew); + + + if (pinew >= epgi.Size()+PointIndex::BASE) + epgi.SetSize (pinew+1-PointIndex::BASE); + epgi[pinew] = ngi; + } + + Segment ns1 = el; + Segment ns2 = el; + ns1.p2 = pinew; + ns1.epgeominfo[1] = ngi; + ns2.p1 = pinew; + ns2.epgeominfo[0] = ngi; + + mesh.LineSegment(si) = ns1; + mesh.AddSegment (ns2); + } + + // refine surface elements + ARRAY<PointGeomInfo,PointIndex::BASE> surfgi (8*mesh.GetNP()); + for (int i = PointIndex::BASE; + i < surfgi.Size()+PointIndex::BASE; i++) + surfgi[i].trignum = -1; + + + oldnf = mesh.GetNSE(); + for (SurfaceElementIndex sei = 0; sei < oldnf; sei++) + { + int j, k; + const Element2d & el = mesh.SurfaceElement(sei); + + switch (el.GetType()) + { + case TRIG: + case TRIG6: + { + ArrayMem<int,6> pnums(6); + ArrayMem<PointGeomInfo,6> pgis(6); + + static int betw[3][3] = + { { 2, 3, 4 }, + { 1, 3, 5 }, + { 1, 2, 6 } }; + + for (j = 1; j <= 3; j++) + { + pnums.Elem(j) = el.PNum(j); + pgis.Elem(j) = el.GeomInfoPi(j); + } + + for (j = 0; j < 3; j++) + { + PointIndex pi1 = pnums.Elem(betw[j][0]); + PointIndex pi2 = pnums.Elem(betw[j][1]); + + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + + Point<3> pb; + PointGeomInfo pgi; + PointBetween (mesh.Point (pi1), + mesh.Point (pi2), 0.5, + mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(), + el.GeomInfoPi (betw[j][0]), + el.GeomInfoPi (betw[j][1]), + pb, pgi); + + + pgis.Elem(4+j) = pgi; + if (between.Used(i2)) + pnums.Elem(4+j) = between.Get(i2); + else + { + pnums.Elem(4+j) = mesh.AddPoint (pb); + between.Set (i2, pnums.Get(4+j)); + } + + if (surfgi.Size() < pnums.Elem(4+j)) + surfgi.SetSize (pnums.Elem(4+j)); + surfgi.Elem(pnums.Elem(4+j)) = pgis.Elem(4+j); + } + + + static int reftab[4][3] = + { { 1, 6, 5 }, + { 2, 4, 6 }, + { 3, 5, 4 }, + { 6, 4, 5 } }; + + int ind = el.GetIndex(); + for (j = 0; j < 4; j++) + { + Element2d nel(TRIG); + for (k = 1; k <= 3; k++) + { + nel.PNum(k) = pnums.Get(reftab[j][k-1]); + nel.GeomInfoPi(k) = pgis.Get(reftab[j][k-1]); + } + nel.SetIndex(ind); + + if (j == 0) + mesh.SurfaceElement(sei) = nel; + else + mesh.AddSurfaceElement(nel); + } + break; + } + case QUAD: + case QUAD6: + case QUAD8: + { + ArrayMem<int,9> pnums(9); + ArrayMem<PointGeomInfo,9> pgis(9); + + static int betw[5][3] = + { { 1, 2, 5 }, + { 2, 3, 6 }, + { 3, 4, 7 }, + { 1, 4, 8 }, + { 5, 7, 9 } }; + + for (j = 1; j <= 4; j++) + { + pnums.Elem(j) = el.PNum(j); + pgis.Elem(j) = el.GeomInfoPi(j); + } + + for (j = 0; j < 5; j++) + { + int pi1 = pnums.Elem(betw[j][0]); + int pi2 = pnums.Elem(betw[j][1]); + + INDEX_2 i2 (pi1, pi2); + i2.Sort(); + + if (between.Used(i2)) + { + pnums.Elem(5+j) = between.Get(i2); + pgis.Elem(5+j) = surfgi.Get(pnums.Elem(4+j)); + } + else + { + Point<3> pb; + PointBetween (mesh.Point (pi1), + mesh.Point (pi2), 0.5, + mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(), + el.GeomInfoPi (betw[j][0]), + el.GeomInfoPi (betw[j][1]), + pb, pgis.Elem(5+j)); + + pnums.Elem(5+j) = mesh.AddPoint (pb); + + between.Set (i2, pnums.Get(5+j)); + + if (surfgi.Size() < pnums.Elem(5+j)) + surfgi.SetSize (pnums.Elem(5+j)); + surfgi.Elem(pnums.Elem(5+j)) = pgis.Elem(5+j); + } + } + + static int reftab[4][4] = + { + { 1, 5, 9, 8 }, + { 5, 2, 6, 9 }, + { 8, 9, 7, 4 }, + { 9, 6, 3, 7 } }; + + int ind = el.GetIndex(); + for (j = 0; j < 4; j++) + { + Element2d nel(QUAD); + for (k = 1; k <= 4; k++) + { + nel.PNum(k) = pnums.Get(reftab[j][k-1]); + nel.GeomInfoPi(k) = pgis.Get(reftab[j][k-1]); + } + nel.SetIndex(ind); + + if (j == 0) + mesh.SurfaceElement(sei) = nel; + else + mesh.AddSurfaceElement(nel); + } + break; + } + default: + PrintSysError ("Refine: undefined surface element type ", int(el.GetType())); + } + } + + // refine volume elements + oldne = mesh.GetNE(); + for (ElementIndex ei = 0; ei < oldne; ei++) + { + int j, k; + + const Element & el = mesh.VolumeElement(ei); + switch (el.GetType()) + { + case TET: + case TET10: + { + ArrayMem<int,10> pnums(10); + static int betw[6][3] = + { { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 4, 10 } }; + + int elrev = el.flags.reverse; + + for (j = 1; j <= 4; j++) + pnums.Elem(j) = el.PNum(j); + if (elrev) + swap (pnums.Elem(3), pnums.Elem(4)); + + for (j = 0; j < 6; j++) + { + INDEX_2 i2; + i2.I1() = pnums.Get(betw[j][0]); + i2.I2() = pnums.Get(betw[j][1]); + i2.Sort(); + + if (between.Used(i2)) + pnums.Elem(5+j) = between.Get(i2); + else + { + pnums.Elem(5+j) = mesh.AddPoint + (Center (mesh.Point(i2.I1()), + mesh.Point(i2.I2()))); + between.Set (i2, pnums.Elem(5+j)); + } + } + + static int reftab[8][4] = + { { 1, 5, 6, 7 }, + { 5, 2, 8, 9 }, + { 6, 8, 3, 10 }, + { 7, 9, 10, 4 }, + { 5, 6, 7, 9 }, + { 5, 6, 9, 8 }, + { 6, 7, 9, 10 }, + { 6, 8, 10, 9 } }; + /* + { { 1, 5, 6, 7 }, + { 5, 2, 8, 9 }, + { 6, 8, 3, 10 }, + { 7, 9, 10, 4 }, + { 5, 6, 7, 9 }, + { 5, 6, 8, 9 }, + { 6, 7, 9, 10 }, + { 6, 8, 9, 10 } }; + */ + static bool reverse[8] = + { + false, false, false, false, false, true, false, true + }; + + int ind = el.GetIndex(); + for (j = 0; j < 8; j++) + { + Element nel; + for (k = 1; k <= 4; k++) + nel.PNum(k) = pnums.Get(reftab[j][k-1]); + nel.SetIndex(ind); + nel.flags.reverse = reverse[j]; + if (elrev) + { + nel.flags.reverse = !nel.flags.reverse; + swap (nel.PNum(3), nel.PNum(4)); + } + + if (j == 0) + mesh.VolumeElement(ei) = nel; + else + mesh.AddVolumeElement (nel); + } + break; + } + case HEX: + { + ArrayMem<int,27> pnums(27); + static int betw[13][3] = + { { 1, 2, 9 }, + { 3, 4, 10 }, + { 4, 1, 11 }, + { 2, 3, 12 }, + { 5, 6, 13 }, + { 7, 8, 14 }, + { 8, 5, 15 }, + { 6, 7, 16 }, + { 1, 5, 17 }, + { 2, 6, 18 }, + { 3, 7, 19 }, + { 4, 8, 20 }, + { 2, 8, 21 }, + }; + + static int fbetw[12][3] = + { { 1, 3, 22 }, + { 2, 4, 22 }, + { 5, 7, 23 }, + { 6, 8, 23 }, + { 1, 6, 24 }, + { 2, 5, 24 }, + { 2, 7, 25 }, + { 3, 6, 25 }, + { 3, 8, 26 }, + { 4, 7, 26 }, + { 1, 8, 27 }, + { 4, 5, 27 }, + }; + + + pnums = -1; + + for (j = 1; j <= 8; j++) + pnums.Elem(j) = el.PNum(j); + + + for (j = 0; j < 13; j++) + { + INDEX_2 i2; + i2.I1() = pnums.Get(betw[j][0]); + i2.I2() = pnums.Get(betw[j][1]); + i2.Sort(); + + if (between.Used(i2)) + pnums.Elem(9+j) = between.Get(i2); + else + { + pnums.Elem(9+j) = mesh.AddPoint + (Center (mesh.Point(i2.I1()), + mesh.Point(i2.I2()))); + between.Set (i2, pnums.Elem(9+j)); + } + } + + for (j = 0; j < 6; j++) + { + INDEX_2 i2a, i2b; + i2a.I1() = pnums.Get(fbetw[2*j][0]); + i2a.I2() = pnums.Get(fbetw[2*j][1]); + i2a.Sort(); + i2b.I1() = pnums.Get(fbetw[2*j+1][0]); + i2b.I2() = pnums.Get(fbetw[2*j+1][1]); + i2b.Sort(); + + if (between.Used(i2a)) + pnums.Elem(22+j) = between.Get(i2a); + else if (between.Used(i2b)) + pnums.Elem(22+j) = between.Get(i2b); + else + { + pnums.Elem(22+j) = mesh.AddPoint + (Center (mesh.Point(i2a.I1()), + mesh.Point(i2a.I2()))); + + between.Set (i2a, pnums.Elem(22+j)); + } + } + + static int reftab[8][8] = + { { 1, 9, 22, 11, 17, 24, 21, 27 }, + { 9, 2, 12, 22, 24, 18, 25, 21 }, + { 11, 22, 10, 4, 27, 21, 26, 20}, + { 22, 12, 3, 10, 21, 25, 19, 26}, + { 17, 24, 21, 27, 5, 13, 23, 15}, + { 24, 18, 25, 21, 13, 6, 16, 23}, + { 27, 21, 26, 20, 15, 23, 14, 8}, + { 21, 25, 19, 26, 23, 16, 7, 14} }; + + + int ind = el.GetIndex(); + for (j = 0; j < 8; j++) + { + Element nel(HEX); + for (k = 1; k <= 8; k++) + nel.PNum(k) = pnums.Get(reftab[j][k-1]); + nel.SetIndex(ind); + + if (j == 0) + mesh.VolumeElement(ei) = nel; + else + mesh.AddVolumeElement (nel); + } + break; + } + case PRISM: + { + ArrayMem<int,18> pnums(18); + static int betw[9][3] = + { { 3, 1, 7 }, + { 1, 2, 8 }, + { 3, 2, 9 }, + { 6, 4, 10 }, + { 4, 5, 11 }, + { 6, 5, 12 }, + { 1, 4, 13 }, + { 3, 6, 14 }, + { 2, 5, 15 }, + }; + +// he: 15.jul 08, old version is wrong +// produces double points ad quad faces and inconsistent mesh +// static int fbetw[6][3] = +// { { 1, 6, 16 }, +// { 3, 4, 16 }, +// { 1, 5, 17 }, +// { 2, 4, 17 }, +// { 2, 6, 18 }, +// { 3, 5, 18 }, +// }; + + static int fbetw[6][3] = + { { 7, 10, 16 }, + { 14, 13, 16 }, + { 11, 8, 17 }, + { 13, 15, 17 }, + { 12, 9, 18 }, + { 14, 15, 18 }, + }; + + //int elrev = el.flags.reverse; + pnums = -1; + + for (j = 1; j <= 6; j++) + pnums.Elem(j) = el.PNum(j); + // if (elrev) + // swap (pnums.Elem(3), pnums.Elem(4)); + + for (j = 0; j < 9; j++) + { + INDEX_2 i2; + i2.I1() = pnums.Get(betw[j][0]); + i2.I2() = pnums.Get(betw[j][1]); + i2.Sort(); + + if (between.Used(i2)) + pnums.Elem(7+j) = between.Get(i2); + else + { + pnums.Elem(7+j) = mesh.AddPoint + (Center (mesh.Point(i2.I1()), + mesh.Point(i2.I2()))); + between.Set (i2, pnums.Elem(7+j)); + } + } + + for (j = 0; j < 3; j++) + { + INDEX_2 i2a, i2b; + i2a.I1() = pnums.Get(fbetw[2*j][0]); + i2a.I2() = pnums.Get(fbetw[2*j][1]); + i2a.Sort(); + i2b.I1() = pnums.Get(fbetw[2*j+1][0]); + i2b.I2() = pnums.Get(fbetw[2*j+1][1]); + i2b.Sort(); + + if (between.Used(i2a)) + pnums.Elem(16+j) = between.Get(i2a); + else if (between.Used(i2b)) + pnums.Elem(16+j) = between.Get(i2b); + else + { + pnums.Elem(16+j) = mesh.AddPoint + (Center (mesh.Point(i2a.I1()), + mesh.Point(i2a.I2()))); + + between.Set (i2a, pnums.Elem(16+j)); + } + } + + + static int reftab[8][6] = + { { 1, 8, 7, 13, 17, 16 }, + { 7, 8, 9, 16, 17, 18 }, + { 7, 9, 3, 16, 18, 14 }, + { 8, 2, 9, 17, 15, 18 }, + { 13, 17, 16, 4, 11, 10 }, + { 16, 17, 18, 10, 11, 12 }, + { 16, 18, 14, 10, 12, 6 }, + { 17, 15, 18, 11, 5, 12 } }; + + + int ind = el.GetIndex(); + for (j = 0; j < 8; j++) + { + Element nel(PRISM); + for (k = 1; k <= 6; k++) + nel.PNum(k) = pnums.Get(reftab[j][k-1]); + nel.SetIndex(ind); + + + //nel.flags.reverse = reverse[j]; + //if (elrev) + // { + //nel.flags.reverse = 1 - nel.flags.reverse; + //swap (nel.PNum(3), nel.PNum(4)); + + + if (j == 0) + mesh.VolumeElement(ei) = nel; + else + mesh.AddVolumeElement (nel); + } + break; + } + default: + PrintSysError ("Refine: undefined volume element type ", int(el.GetType())); + } + } + + + // update identification tables + for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) + { + ARRAY<int,PointIndex::BASE> identmap; + mesh.GetIdentifications().GetMap (i, identmap); + + for (int j = 1; j <= between.GetNBags(); j++) + for (int k = 1; k <= between.GetBagSize(j); k++) + { + INDEX_2 i2; + int newpi; + between.GetData (j, k, i2, newpi); + INDEX_2 oi2(identmap.Get(i2.I1()), + identmap.Get(i2.I2())); + oi2.Sort(); + if (between.Used (oi2)) + { + int onewpi = between.Get(oi2); + mesh.GetIdentifications().Add (newpi, onewpi, i); + } + } + + } + + mesh.ComputeNVertices(); + return; + + int cnttrials = 10; + int wrongels = 0; + for (int i = 1; i <= mesh.GetNE(); i++) + if (mesh.VolumeElement(i).Volume(mesh.Points()) < 0) + { + wrongels++; + mesh.VolumeElement(i).flags.badel = 1; + } + else + mesh.VolumeElement(i).flags.badel = 0; + + if (wrongels) + { + cout << "WARNING: " << wrongels << " with wrong orientation found" << endl; + + int np = mesh.GetNP(); + ARRAY<Point<3> > should(np); + ARRAY<Point<3> > can(np); + for (int i = 1; i <= np; i++) + { + should.Elem(i) = can.Elem(i) = mesh.Point(i); + } + for (int i = 1; i <= between.GetNBags(); i++) + for (int j = 1; j <= between.GetBagSize(i); j++) + { + INDEX_2 parent; + int child; + between.GetData (i, j, parent, child); + can.Elem(child) = Center (can.Elem(parent.I1()), + can.Elem(parent.I2())); + } + + BitArray boundp(np); + boundp.Clear(); + for (int i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + for (int j = 1; j <= sel.GetNP(); j++) + boundp.Set(sel.PNum(j)); + } + + + double lam = 0.5; + + while (lam < 0.9 && cnttrials > 0) + { + lam = 2; + do + { + lam *= 0.5; + cnttrials--; + + cout << "lam = " << lam << endl; + + for (int i = 1; i <= np; i++) + if (boundp.Test(i)) + { + for (int j = 0; j < 3; j++) + mesh.Point(i)(j) = + lam * should.Get(i)(j) + + (1-lam) * can.Get(i)(j); + } + else + mesh.Point(i) = can.Get(i); + + + BitArray free (mesh.GetNP()), fhelp(mesh.GetNP()); + free.Clear(); + for (int i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + if (el.Volume(mesh.Points()) < 0) + for (int j = 1; j <= el.GetNP(); j++) + free.Set (el.PNum(j)); + } + for (int k = 1; k <= 3; k++) + { + fhelp.Clear(); + for (int i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + int freeel = 0; + for (int j = 1; j <= el.GetNP(); j++) + if (free.Test(el.PNum(j))) + freeel = 1; + if (freeel) + for (int j = 1; j <= el.GetNP(); j++) + fhelp.Set (el.PNum(j)); + } + free.Or (fhelp); + } + + (*testout) << "smooth points: " << endl; + for (int i = 1; i <= free.Size(); i++) + if (free.Test(i)) + (*testout) << "p " << i << endl; + + (*testout) << "surf points: " << endl; + for (int i = 1; i <= mesh.GetNSE(); i++) + for (int j = 1; j <= 3; j++) + (*testout) << mesh.SurfaceElement(i).PNum(j) << endl; + + + + mesh.CalcSurfacesOfNode(); + free.Invert(); + mesh.FixPoints (free); + mesh.ImproveMesh (OPT_REST); + + + wrongels = 0; + for (int i = 1; i <= mesh.GetNE(); i++) + { + if (mesh.VolumeElement(i).Volume(mesh.Points()) < 0) + { + wrongels++; + mesh.VolumeElement(i).flags.badel = 1; + (*testout) << "wrong el: "; + for (int j = 1; j <= 4; j++) + (*testout) << mesh.VolumeElement(i).PNum(j) << " "; + (*testout) << endl; + } + else + mesh.VolumeElement(i).flags.badel = 0; + } + cout << "wrongels = " << wrongels << endl; + } + while (wrongels && cnttrials > 0); + + for (int i = 1; i <= np; i++) + can.Elem(i) = mesh.Point(i); + } + } + + if (cnttrials <= 0) + { + cerr << "ERROR: Sorry, reverted elements" << endl; + } + + mesh.ComputeNVertices(); + } +} diff --git a/contrib/Netgen/libsrc/meshing/ruler2.cpp b/contrib/Netgen/libsrc/meshing/ruler2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6040ad2152724d9638ee76d80d4b24db8dd81293 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler2.cpp @@ -0,0 +1,641 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +namespace netgen +{ + + +static double CalcElementBadness (const ARRAY<Point2d> & points, + const Element2d & elem) +{ + // badness = sqrt(3) /36 * circumference^2 / area - 1 + + // h / li + li / h - 2 + + Vec2d v12, v13, v23; + double l12, l13, l23, cir, area; + static const double c = sqrt(3.0) / 36; + + v12 = points.Get(elem.PNum(2)) - points.Get(elem.PNum(1)); + v13 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(1)); + v23 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(2)); + + l12 = v12.Length(); + l13 = v13.Length(); + l23 = v23.Length(); + + cir = l12 + l13 + l23; + area = 0.5 * (v12.X() * v13.Y() - v12.Y() * v13.X()); + if (area < 1e-6) + { + return 1e8; + } + + if (testmode) + { + (*testout) << "l = " << l12 << " + " << l13 << " + " << l23 << " = " + << cir << ", area = " << area << endl; + (*testout) << "shapeerr = " << 10 * (c * cir * cir / area - 1) << endl + << "sizeerr = " << 1/l12 + l12 + 1/l13 + l13 + 1/l23 + l23 - 6 + << endl; + } + + return 10 * (c * cir * cir / area - 1) + + 1/l12 + l12 + 1/l13 + l13 + 1/l23 + l23 - 6; +} + + + +int Meshing2 ::ApplyRules (ARRAY<Point2d> & lpoints, + ARRAY<int> & legalpoints, + int maxlegalpoint, + ARRAY<INDEX_2> & llines, + int maxlegalline, + ARRAY<Element2d> & elements, + ARRAY<INDEX> & dellines, int tolerance) +{ + int i, j, ri, nlok, npok, incnpok, refpi, locli = 0; + + double maxerr = 0.5 + 0.3 * tolerance; + double minelerr = 2 + 0.5 * tolerance * tolerance; + + + bool ok; + int found; // rule number + Vector oldu, newu; + Point2d np; + Vec2d linevec; + int oldnp; + INDEX_2 loclin; + double hf, elerr; + int noldlp, noldll; + int loctestmode; + + static ARRAY<int> pused, pmap, pfixed; + static ARRAY<int, 1> lmap, lused; + static ARRAY<int> pnearness, lnearness; + + static ARRAY<Point2d> tempnewpoints; + static ARRAY<INDEX_2> tempnewlines; + static ARRAY<int> tempdellines; + static ARRAY<Element2d> tempelements; + + + + elements.SetSize (0); + dellines.SetSize (0); + + noldlp = lpoints.Size(); + noldll = llines.Size(); + + pused.SetSize (maxlegalpoint); + lused.SetSize (maxlegalline); + pnearness.SetSize (noldlp); + lnearness.SetSize (llines.Size()); + + + testmode = debugparam.debugoutput; + loctestmode = testmode; + + if (loctestmode) + { + (*testout) << endl << endl << "Check new environment" << endl; + (*testout) << "tolerance = " << tolerance << endl; + for (i = 1; i <= lpoints.Size(); i++) + (*testout) << "P" << i << " = " << lpoints.Get(i) << endl; + (*testout) << endl; + for (i = 1; i <= llines.Size(); i++) + (*testout) << "(" << llines.Get(i).I1() << "-" << llines.Get(i).I2() << ")" << endl; + } + + // check every rule + + found = 0; + + + for (i = 1; i <= noldlp; i++) + pnearness.Set(i, 1000); + + for (j = 1; j <= 2; j++) + pnearness.Set(llines.Get(1).I(j), 0); + + + do + { + ok = 1; + for (i = 1; i <= maxlegalline; i++) + { + const INDEX_2 & hline = llines.Get(i); + + /* + int minn = INT_MAX-1; + for (j = 1; j <= 2; j++) + { + int hi = pnearness.Get(hline.I(j)); + if (hi < minn) minn = hi; + } + */ + int minn = pnearness.Get(hline.I1()); + int minn2 = pnearness.Get(hline.I2()); + if (minn2 < minn) + minn = minn2; + + /* + for (j = 1; j <= 2; j++) + { + int hpi = hline.I(j); + if (pnearness.Get(hpi) > minn+1) + { + ok = 0; + pnearness.Set(hpi, minn+1); + } + } + */ + int hpi = hline.I1(); + if (pnearness.Get(hpi) > minn+1) + { + ok = 0; + pnearness.Set(hpi, minn+1); + } + hpi = hline.I2(); + if (pnearness.Get(hpi) > minn+1) + { + ok = 0; + pnearness.Set(hpi, minn+1); + } + } + } + while (!ok); + + for (i = 1; i <= maxlegalline /* lnearness.Size() */; i++) + { + lnearness.Set(i, 0); + for (j = 1; j <= 2; j++) + lnearness.Elem(i) += pnearness.Get(llines.Get(i).I(j)); + } + + + for (ri = 1; ri <= rules.Size(); ri++) + { + netrule * rule = rules.Get(ri); + + if (loctestmode) + (*testout) << "Rule " << rule->Name() << endl; + + if (rule->GetQuality() > tolerance) continue; + + pmap.SetSize (rule->GetNP()); + lmap.SetSize (rule->GetNL()); + + lused = 0; + pused = 0; + pmap = 0; + lmap = 0; + + lused[1] = 1; // .Set (1, 1); + lmap[1] = 1; // .Set (1, 1); + + for (j = 0; j < 2; j++) + { + pmap.Elem(rule->GetLine(1)[j]) = llines[0][j]; + pused.Elem(llines[0][j])++; + } + + + nlok = 2; + + while (nlok >= 2) + { + + if (nlok <= rule->GetNOldL()) + + { + ok = 0; + while (!ok && lmap.Get(nlok) < maxlegalline /* llines.Size() */) + { + lmap.Elem(nlok)++; + locli = lmap.Get(nlok); + + if (!lused.Get(locli) && + lnearness.Get(locli) <= rule->GetLNearness (nlok) ) + { + ok = 1; + + loclin = llines.Get(locli); + linevec = lpoints.Get(loclin.I2()) - lpoints.Get(loclin.I1()); + + if (rule->CalcLineError (nlok, linevec) > maxerr) + { + ok = 0; + if(loctestmode) + (*testout) << "not ok pos1" << endl; + } + + for (j = 0; j < 2 && ok; j++) + { + // refpi = rule->GetPointNr (nlok, j); + refpi = rule->GetLine(nlok)[j]; + + if (pmap.Get(refpi) != 0) + { + if (pmap.Get(refpi) != loclin[j]) + { + ok = 0; + if(loctestmode) + (*testout) << "not ok pos2" << endl; + } + } + else + { + if (rule->CalcPointDist (refpi, lpoints.Get(loclin[j])) > maxerr + || !legalpoints.Get(loclin[j]) + || pused.Get(loclin[j])) + { + ok = 0; + if(loctestmode) + { + (*testout) << "nok pos3" << endl; + //if(rule->CalcPointDist (refpi, lpoints.Get(loclin[j])) > maxerr) + //(*testout) << "r1" << endl; + //if(!legalpoints.Get(loclin[j])) + //(*testout) << "r2 legalpoints " << legalpoints << " loclin " << loclin << " j " << j << endl; + //if(pused.Get(loclin[j])) + //(*testout) << "r3" << endl; + } + } + } + } + } + } + + if (ok) + { + lused.Elem (locli) = 1; + for (j = 0; j < 2; j++) + { + pmap.Set(rule->GetLine (nlok)[j], loclin[j]); + pused.Elem(loclin[j])++; + } + + nlok++; + } + else + { + lmap.Elem(nlok) = 0; + nlok--; + + lused.Elem (lmap.Get(nlok)) = 0; + for (j = 0; j < 2; j++) + { + pused.Elem(llines.Get(lmap.Get(nlok))[j]) --; + if (! pused.Get (llines.Get (lmap.Get (nlok))[j])) + pmap.Set (rule->GetLine (nlok)[j], 0); + } + } + } + + else + + { + + // all lines are mapped !! + + // map also all points: + + npok = 1; + incnpok = 1; + + pfixed.SetSize (pmap.Size()); + for (i = 0; i < pmap.Size(); i++) + pfixed[i] = (pmap[i] >= 1); + + while (npok >= 1) + { + + if (npok <= rule->GetNOldP()) + + { + if (pfixed.Get(npok)) + + { + if (incnpok) + npok++; + else + npok--; + } + + else + + { + ok = 0; + + if (pmap.Get(npok)) + pused.Elem(pmap.Get(npok))--; + + while (!ok && pmap.Get(npok) < maxlegalpoint) + { + ok = 1; + + pmap.Elem(npok)++; + + if (pused.Get(pmap.Get(npok))) + { + ok = 0; + } + else + { + if (rule->CalcPointDist (npok, lpoints.Get(pmap.Get(npok))) > maxerr + || !legalpoints.Get(pmap.Get(npok))) + + ok = 0; + } + } + + if (ok) + { + pused.Elem(pmap.Get(npok))++; + npok++; + incnpok = 1; + } + + else + + { + pmap.Elem(npok) = 0; + npok--; + incnpok = 0; + } + } + } + + else + + { + if (ok) + foundmap.Elem(ri)++; + + if (loctestmode) + (*testout) << "lines and points mapped" << endl; + + + ok = 1; + + // check orientations + + for (i = 1; i <= rule->GetNOrientations() && ok; i++) + { + if (CW (lpoints.Get(pmap.Get(rule->GetOrientation(i).i1)), + lpoints.Get(pmap.Get(rule->GetOrientation(i).i2)), + lpoints.Get(pmap.Get(rule->GetOrientation(i).i3))) ) + { + ok = 0; + if (loctestmode) + (*testout) << "Orientation " << i << " not ok" << endl; + } + } + + if (ok) + { + oldu.SetSize (2 * rule->GetNOldP()); + + for (i = 1; i <= rule->GetNOldP(); i++) + { + Vec2d ui(rule->GetPoint(i), lpoints.Get(pmap.Get(i))); + oldu.Set (2*i-1, ui.X()); + oldu.Set (2*i , ui.Y()); + } + + rule -> SetFreeZoneTransformation (oldu, tolerance); + } + + + if (ok && !rule->ConvexFreeZone()) + { + ok = 0; + if (loctestmode) + (*testout) << "freezone not convex" << endl; + + /* + static int cnt = 0; + cnt++; + if (cnt % 100 == 0) + { + cout << "freezone not convex, cnt = " << cnt << "; rule = " << rule->Name() << endl; + (*testout) << "freezone not convex, cnt = " << cnt << "; rule = " << rule->Name() << endl; + (*testout) << "tol = " << tolerance << endl; + (*testout) << "maxerr = " << maxerr << "; minerr = " << minelerr << endl; + (*testout) << "freezone = " << rule->GetTransFreeZone() << endl; + } + */ + } + + // check freezone: + + for (i = 1; i <= maxlegalpoint && ok; i++) + { + if ( !pused.Get(i) && + rule->IsInFreeZone (lpoints.Get(i)) ) + { + ok = 0; + if (loctestmode) + (*testout) << "Point " << i << " in freezone" << endl; + } + } + + + for (i = maxlegalpoint+1; i <= lpoints.Size() && ok; i++) + { + if ( rule->IsInFreeZone (lpoints.Get(i)) ) + { + ok = 0; + if (loctestmode) + (*testout) << "Point " << i << " in freezone" << endl; + } + } + + for (i = 1; i <= maxlegalline && ok; i++) + { + if (!lused.Get(i) && + rule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()), + lpoints.Get(llines.Get(i).I2()))) + { + ok = 0; + if (loctestmode) + (*testout) << "line " << llines.Get(i).I1() << "-" + << llines.Get(i).I2() << " in freezone" << endl; + } + } + for (i = maxlegalline+1; i <= llines.Size() && ok; i++) + { + if (rule->IsLineInFreeZone (lpoints.Get(llines.Get(i).I1()), + lpoints.Get(llines.Get(i).I2()))) + { + ok = 0; + if (loctestmode) + (*testout) << "line " << llines.Get(i).I1() << "-" + << llines.Get(i).I2() << " in freezone" << endl; + } + } + + + /* + // check orientations + + for (i = 1; i <= rule->GetNOrientations() && ok; i++) + { + if (CW (lpoints.Get(pmap.Get(rule->GetOrientation(i).i1)), + lpoints.Get(pmap.Get(rule->GetOrientation(i).i2)), + lpoints.Get(pmap.Get(rule->GetOrientation(i).i3))) ) + { + ok = 0; + if (loctestmode) + (*testout) << "Orientation " << i << " not ok" << endl; + } + } + */ + + + if (ok) + { + if (loctestmode) + (*testout) << "rule ok" << endl; + + // newu = rule->GetOldUToNewU() * oldu; + if (rule->GetNOldP() < rule->GetNP()) + { + newu.SetSize (rule->GetOldUToNewU().Height()); + rule->GetOldUToNewU().Mult (oldu, newu); + } + + // Setze neue Punkte: + + oldnp = rule->GetNOldP(); + + for (i = oldnp + 1; i <= rule->GetNP(); i++) + { + np = rule->GetPoint(i); + np.X() += newu.Elem (2 * (i-oldnp) - 1); + np.Y() += newu.Elem (2 * (i-oldnp)); + + pmap.Elem(i) = lpoints.Append (np); + } + + // Setze neue Linien: + + for (i = rule->GetNOldL() + 1; i <= rule->GetNL(); i++) + { + llines.Append (INDEX_2 (pmap.Get(rule->GetLine (i)[0]), + pmap.Get(rule->GetLine (i)[1]))); + } + + + // delete old lines: + for (i = 1; i <= rule->GetNDelL(); i++) + dellines.Append (lmap.Get(rule->GetDelLine(i))); + + // dellines.Append (lmap[rule->GetDelLines()]); + // lmap[rule->GetDelLines()]; + + + // insert new elements: + + for (i = 1; i <= rule->GetNE(); i++) + { + elements.Append (rule->GetElement(i)); + for (j = 1; j <= elements.Get(i).GetNP(); j++) + elements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j)); + } + + + elerr = 0; + for (i = 1; i <= elements.Size(); i++) + { + if (!mparam.quad) + hf = CalcElementBadness (lpoints, elements.Get(i)); + else + hf = elements.Get(i).CalcJacobianBadness (lpoints) * 5; + if (loctestmode) + (*testout) << "r " << rule->Name() << "bad = " << hf << endl; + if (hf > elerr) elerr = hf; + } + + if (loctestmode) + (*testout) << "error = " << elerr; + + + canuse.Elem(ri) ++; + + if (elerr < 0.99*minelerr) + { + + if (loctestmode) + { + (*testout) << "rule = " << rule->Name() << endl; + (*testout) << "class = " << tolerance << endl; + (*testout) << "lpoints: " << endl; + for (i = 1; i <= lpoints.Size(); i++) + (*testout) << lpoints.Get(i) << endl; + (*testout) << "llines: " << endl; + for (i = 1; i <= llines.Size(); i++) + (*testout) << llines.Get(i).I1() << " " << llines.Get(i).I2() << endl; + + (*testout) << "Freezone: "; + for (i = 1; i <= rule -> GetTransFreeZone().Size(); i++) + (*testout) << rule->GetTransFreeZone().Get(i) << endl; + } + + + minelerr = elerr; + found = ri; + + tempnewpoints = lpoints.Range (noldlp, lpoints.Size()); + tempnewlines = llines.Range (noldll, llines.Size()); + tempdellines = dellines; + tempelements = elements; + } + + lpoints.SetSize (noldlp); + llines.SetSize (noldll); + dellines.SetSize (0); + elements.SetSize (0); + ok = 0; + } + + npok = rule->GetNOldP(); + incnpok = 0; + } + } + + nlok = rule->GetNOldL(); + + lused.Set (lmap.Get(nlok), 0); + + for (j = 1; j <= 2; j++) + { + refpi = rule->GetPointNr (nlok, j); + pused.Elem(pmap.Get(refpi))--; + + if (pused.Get(pmap.Get(refpi)) == 0) + pmap.Set(refpi, 0); + } + } + } + } + + + if (found) + { + lpoints.Append (tempnewpoints); + llines.Append (tempnewlines); + dellines.Append (tempdellines); + elements.Append (tempelements); + } + + + return found; +} + + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/ruler2.hpp b/contrib/Netgen/libsrc/meshing/ruler2.hpp new file mode 100644 index 0000000000000000000000000000000000000000..696bafa94d8b2f6d476c4f8c1f1f3ca859c7696e --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler2.hpp @@ -0,0 +1,167 @@ +#ifndef FILE_NETRULE +#define FILE_NETRULE + +/// +class netrule +{ +private: + /// + typedef struct tf + { float f1, f2, f3; } threefloat; + + class threeint + { + public: int i1, i2, i3; + threeint() { } + threeint(int ai1, int ai2, int ai3) + { i1 = ai1; i2 = ai2; i3 = ai3; } + }; + + + /// + int quality; + /// + char * name; + /// + ARRAY<Point2d> points; + /// + ARRAY<INDEX_2> lines; + /// + ARRAY<Point2d> freezone, freezonelimit; + /// + ARRAY<Point2d> transfreezone; + + /// + ARRAY<int> dellines; + /// + ARRAY<Element2d> elements; + /// + ARRAY<threefloat> tolerances, linetolerances; + /// + ARRAY<threeint> orientations; + /// + DenseMatrix oldutonewu, oldutofreearea, oldutofreearealimit; + /// + ARRAY<DenseMatrix*> oldutofreearea_i; + /// + MatrixFixWidth<3> freesetinequ; + + /// + ARRAY<Vec2d> linevecs; + + /// + int noldp, noldl; + /// + float fzminx, fzmaxx, fzminy, fzmaxy; + + /// topological distance of line to base element + ARRAY<int> lnearness; + +public: + + /// + netrule (); + /// + ~netrule(); + + /// + int GetNP () const { return points.Size(); } + /// + int GetNL () const { return lines.Size(); } + /// + int GetNE () const { return elements.Size(); } + /// + int GetNOldP () const { return noldp; } + /// + int GetNOldL () const { return noldl; } + /// + int GetNDelL () const { return dellines.Size(); } + /// + int GetNOrientations () const { return orientations.Size(); } + /// + int GetQuality () const { return quality; } + /// + int GetLNearness (int li) const { return lnearness.Get(li); } + + /// + const Point2d & GetPoint (int i) const { return points.Get(i); } + /// + const INDEX_2 & GetLine (int i) const { return lines.Get(i); } + /// + const Element2d & GetElement (int i) const { return elements.Get(i); } + /// + const threeint & GetOrientation (int i) const { return orientations.Get(i); } + /// + int GetDelLine (int i) const { return dellines.Get(i); } + /// + const ARRAY<int> & GetDelLines() const { return dellines; } + /// + void GetFreeZone (ARRAY<Point2d> & afreearea); + /// + + double CalcPointDist (int pi, const Point2d & p) const + { + double dx = p.X() - points.Get(pi).X(); + double dy = p.Y() - points.Get(pi).Y(); + const threefloat * tfp = &tolerances.Get(pi); + return tfp->f1 * dx * dx + tfp->f2 * dx * dy + tfp->f3 * dy * dy; + } + + /// + float CalcLineError (int li, const Vec2d & v) const; + + /// + void SetFreeZoneTransformation (const Vector & u, int tolclass); + + /// + bool IsInFreeZone (const Point2d & p) const + { + if (p.X() < fzminx || p.X() > fzmaxx || + p.Y() < fzminy || p.Y() > fzmaxy) return 0; + + for (int i = 0; i < transfreezone.Size(); i++) + { + if (freesetinequ(i, 0) * p.X() + + freesetinequ(i, 1) * p.Y() + + freesetinequ(i, 2) > 0) return 0; + } + return 1; + } + + /// + int IsLineInFreeZone (const Point2d & p1, const Point2d & p2) const + { + if (p1.X() > fzmaxx && p2.X() > fzmaxx || + p1.X() < fzminx && p2.X() < fzminx || + p1.Y() > fzmaxy && p2.Y() > fzmaxy || + p1.Y() < fzminy && p2.Y() < fzminy) return 0; + return IsLineInFreeZone2 (p1, p2); + } + /// + int IsLineInFreeZone2 (const Point2d & p1, const Point2d & p2) const; + /// + int ConvexFreeZone () const; + /// + const ARRAY<Point2d> & GetTransFreeZone () { return transfreezone; } + + /// + int GetPointNr (int ln, int endp) const { return lines.Get(ln).I(endp); } + + /// + const DenseMatrix & GetOldUToNewU () const { return oldutonewu; } + /// + const DenseMatrix & GetOldUToFreeArea () const { return oldutofreearea; } + /// + const char * Name () const { return name; } + + /// + void LoadRule (istream & ist); +}; + + + +/** Draws 2D rules. + Visual testing of 2D meshing rules */ +extern void DrawRules (); +#endif + diff --git a/contrib/Netgen/libsrc/meshing/ruler3.cpp b/contrib/Netgen/libsrc/meshing/ruler3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30a812bcca770edb1125ce34dcc9ec18a1139766 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler3.cpp @@ -0,0 +1,1137 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ +extern double minother; +extern double minwithoutother; + + +static double CalcElementBadness (const ARRAY<Point3d> & points, + const Element & elem) +{ + double vol, l, l4, l5, l6; + if (elem.GetNP() != 4) + { + if (elem.GetNP() == 5) + { + double z = points.Get(elem.PNum(5)).Z(); + if (z > -1e-8) return 1e8; + return (-1 / z) - z; // - 2; + } + return 0; + } + + Vec3d v1 = points.Get(elem.PNum(2)) - points.Get(elem.PNum(1)); + Vec3d v2 = points.Get(elem.PNum(3)) - points.Get(elem.PNum(1)); + Vec3d v3 = points.Get(elem.PNum(4)) - points.Get(elem.PNum(1)); + + vol = - (Cross (v1, v2) * v3); + l4 = Dist (points.Get(elem.PNum(2)), points.Get(elem.PNum(3))); + l5 = Dist (points.Get(elem.PNum(2)), points.Get(elem.PNum(4))); + l6 = Dist (points.Get(elem.PNum(3)), points.Get(elem.PNum(4))); + + l = v1.Length() + v2.Length() + v3.Length() + l4 + l5 + l6; + + // testout << "vol = " << vol << " l = " << l << endl; + if (vol < 1e-8) return 1e10; + // (*testout) << "l^3/vol = " << (l*l*l / vol) << endl; + + double err = pow (l*l*l/vol, 1.0/3.0) / 12; + return err; +} + + + + + + +int Meshing3 :: ApplyRules +( + ARRAY<Point3d> & lpoints, // in: local points, out: old+new local points + ARRAY<int> & allowpoint, // in: 2 .. it is allowed to use pointi, 1..will be allowed later, 0..no means + ARRAY<MiniElement2d> & lfaces, // in: local faces, out: old+new local faces + INDEX lfacesplit, // for local faces in outer radius + INDEX_2_HASHTABLE<int> & connectedpairs, // connected pairs for prism-meshing + ARRAY<Element> & elements, // out: new elements + ARRAY<INDEX> & delfaces, // out: face indices of faces to delete + int tolerance, // quality class: 1 best + double sloppy, // quality strength + int rotind1, // how to rotate base element + float & retminerr // element error + ) + +{ + NgProfiler::RegionTimer regtot(97); + + int i, j, k, ri, nfok, npok, incnpok, refpi, locpi, locfi, locfr; + float hf, err, minerr, teterr, minteterr; + char ok, found, hc; + vnetrule * rule; + Vector oldu, newu, newu1, newu2, allp; + Vec3d ui; + Point3d np; + int oldnp, noldlp, noldlf; + const MiniElement2d * locface = NULL; + int loktestmode; + + + static ARRAY<int> pused; // point is already mapped + static ARRAY<char> fused; // face is already mapped + static ARRAY<int> pmap; // map of reference point to local point + static ARRAY<char> pfixed; // point mapped by face-map + static ARRAY<int> fmapi; // face in reference is mapped to face nr ... + static ARRAY<int> fmapr; // face in reference is rotated to map + static ARRAY<Point3d> transfreezone; // transformed free-zone + static int cnt = 0; + static INDEX_2_CLOSED_HASHTABLE<int> ledges(100); // edges in local environment + + static ARRAY<Point3d> tempnewpoints; + static ARRAY<MiniElement2d> tempnewfaces; + static ARRAY<int> tempdelfaces; + static ARRAY<Element> tempelements; + static ARRAY<Box3d> triboxes; // bounding boxes of local faces + + + static ARRAY<int, PointIndex::BASE> pnearness; + static ARRAY<int> fnearness; + + cnt++; + + delfaces.SetSize (0); + elements.SetSize (0); + + // determine topological distance of faces and points to + // base element + + pnearness.SetSize (lpoints.Size()); + fnearness.SetSize (lfacesplit); + + pnearness = INT_MAX/10; + for (j = 0; j < lfaces[0].GetNP(); j++) + pnearness[lfaces[0][j]] = 0; + + NgProfiler::RegionTimer reg2(98); + + NgProfiler::StartTimer (90); + + for (int loop = 0; loop < 2; loop++) + { + + for (i = 0; i < lfacesplit; i++) + { + const MiniElement2d & hface = lfaces[i]; + + int minn = INT_MAX-1; + for (j = 0; j < hface.GetNP(); j++) + { + int hi = pnearness[hface[j]]; + if (hi < minn) minn = hi; + } + if (minn < INT_MAX/10) + for (j = 0; j < hface.GetNP(); j++) + if (pnearness[hface[j]] > minn+1) + pnearness[hface[j]] = minn+1; + } + + for (i = 1; i <= connectedpairs.GetNBags(); i++) + for (j = 1; j <= connectedpairs.GetBagSize(i); j++) + { + INDEX_2 edge; + int val; + connectedpairs.GetData (i, j, edge, val); + + if (pnearness[edge.I1()] > pnearness[edge.I2()] + 1) + pnearness[edge.I1()] = pnearness[edge.I2()] + 1; + + if (pnearness[edge.I2()] > pnearness[edge.I1()] + 1) + pnearness[edge.I2()] = pnearness[edge.I1()] + 1; + } + + } + + for (i = 0; i < fnearness.Size(); i++) + { + int sum = 0; + for (j = 0; j < lfaces[i].GetNP(); j++) + sum += pnearness[lfaces[i][j]]; + fnearness[i] = sum; + } + + + NgProfiler::StopTimer (90); + NgProfiler::StartTimer (91); + + // find bounding boxes of faces + + triboxes.SetSize (lfaces.Size()); + for (i = 0; i < lfaces.Size(); i++) + { + const MiniElement2d & face = lfaces[i]; + triboxes[i].SetPoint (lpoints.Get(face[0])); + for (j = 1; j < face.GetNP(); j++) + triboxes[i].AddPoint (lpoints.Get(face[j])); + } + + NgProfiler::StopTimer (91); + NgProfiler::StartTimer (92); + + + bool useedges = 0; + for (ri = 0; ri < rules.Size(); ri++) + if (rules[ri]->GetNEd()) useedges = 1; + + if (useedges) + { + ledges.SetSize (5 * lfacesplit); + + for (j = 0; j < lfacesplit; j++) + // if (fnearness[j] <= 5) + { + const MiniElement2d & face = lfaces[j]; + int newp, oldp; + + newp = face[face.GetNP()-1]; + for (k = 0; k < face.GetNP(); k++) + { + oldp = newp; + newp = face[k]; + ledges.Set (INDEX_2::Sort(oldp, newp), 1); + } + } + } + + NgProfiler::StopTimer (92); + + NgProfiler::RegionTimer reg3(99); + + pused.SetSize (lpoints.Size()); + fused.SetSize (lfaces.Size()); + + found = 0; + minerr = tolfak * tolerance * tolerance; + minteterr = sloppy * tolerance; + + if (testmode) + (*testout) << "cnt = " << cnt << " class = " << tolerance << endl; + + + + // impossible, if no rule can be applied at any tolerance class + bool impossible = 1; + + + // check each rule: + + for (ri = 1; ri <= rules.Size(); ri++) + { + int base = (lfaces[0].GetNP() == 3) ? 100 : 200; + NgProfiler::RegionTimer regx1(base); + NgProfiler::RegionTimer regx(base+ri); + + sprintf (problems.Elem(ri), ""); + + rule = rules.Get(ri); + + if (rule->GetNP(1) != lfaces[0].GetNP()) + continue; + + if (rule->GetQuality() > tolerance) + { + if (rule->GetQuality() < 100) impossible = 0; + + if (testmode) + sprintf (problems.Elem(ri), "Quality not ok"); + continue; + } + + if (testmode) + sprintf (problems.Elem(ri), "no mapping found"); + + loktestmode = testmode || rule->TestFlag ('t') || tolerance > 5; + + if (loktestmode) + (*testout) << "Rule " << ri << " = " << rule->Name() << endl; + + pmap.SetSize (rule->GetNP()); + fmapi.SetSize (rule->GetNF()); + fmapr.SetSize (rule->GetNF()); + + fused = 0; + pused = 0; + pmap = 0; + fmapi = 0; + for (i = 1; i <= fmapr.Size(); i++) + fmapr.Set(i, rule->GetNP(i)); + + fused[0] = 1; + fmapi[0] = 1; + fmapr[0] = rotind1; + + + for (j = 1; j <= lfaces.Get(1).GetNP(); j++) + { + locpi = lfaces[0].PNumMod (j+rotind1); + pmap.Set (rule->GetPointNr (1, j), locpi); + pused.Elem(locpi)++; + } + + /* + map all faces + nfok .. first nfok-1 faces are mapped properly + */ + + nfok = 2; + NgProfiler::RegionTimer regfa(300); + NgProfiler::RegionTimer regx2(base+50+ri); + while (nfok >= 2) + { + + if (nfok <= rule->GetNOldF()) + { + // not all faces mapped + + ok = 0; + locfi = fmapi.Get(nfok); + locfr = fmapr.Get(nfok); + + int actfnp = rule->GetNP(nfok); + + while (!ok) + { + locfr++; + if (locfr == actfnp + 1) + { + locfr = 1; + locfi++; + if (locfi > lfacesplit) break; + } + + + if (fnearness.Get(locfi) > rule->GetFNearness (nfok) || + fused.Get(locfi) || + actfnp != lfaces.Get(locfi).GetNP() ) + { + // face not feasible in any rotation + + locfr = actfnp; + } + else + { + + ok = 1; + + locface = &lfaces.Get(locfi); + + + // reference point already mapped differently ? + for (j = 1; j <= actfnp && ok; j++) + { + locpi = pmap.Get(rule->GetPointNr (nfok, j)); + + if (locpi && locpi != locface->PNumMod(j+locfr)) + ok = 0; + } + + // local point already used or point outside tolerance ? + for (j = 1; j <= actfnp && ok; j++) + { + refpi = rule->GetPointNr (nfok, j); + + if (pmap.Get(refpi) == 0) + { + locpi = locface->PNumMod (j + locfr); + + if (pused.Get(locpi)) + ok = 0; + else + { + const Point3d & lp = lpoints.Get(locpi); + const Point3d & rp = rule->GetPoint(refpi); + + if ( Dist2 (lp, rp) * rule->PointDistFactor(refpi) > minerr) + { + impossible = 0; + ok = 0; + } + } + } + } + } + } + + + if (ok) + { + // map face nfok + + fmapi.Set (nfok, locfi); + fmapr.Set (nfok, locfr); + fused.Set (locfi, 1); + + for (j = 1; j <= rule->GetNP (nfok); j++) + { + locpi = locface->PNumMod(j+locfr); + + if (rule->GetPointNr (nfok, j) <= 3 && + pmap.Get(rule->GetPointNr(nfok, j)) != locpi) + (*testout) << "change face1 point, mark1" << endl; + + pmap.Set(rule->GetPointNr (nfok, j), locpi); + pused.Elem(locpi)++; + } + + nfok++; + } + else + { + // backtrack one face + fmapi.Set (nfok, 0); + fmapr.Set (nfok, rule->GetNP(nfok)); + nfok--; + + fused.Set (fmapi.Get(nfok), 0); + for (j = 1; j <= rule->GetNP (nfok); j++) + { + refpi = rule->GetPointNr (nfok, j); + pused.Elem(pmap.Get(refpi))--; + + if (pused.Get(pmap.Get(refpi)) == 0) + { + pmap.Set(refpi, 0); + } + } + } + } + + else + + { + NgProfiler::RegionTimer regfb(301); + + // all faces are mapped + // now map all isolated points: + + if (loktestmode) + { + (*testout) << "Faces Ok" << endl; + sprintf (problems.Elem(ri), "Faces Ok"); + } + + npok = 1; + incnpok = 1; + + pfixed.SetSize (pmap.Size()); + for (i = 1; i <= pmap.Size(); i++) + pfixed.Set(i, (pmap.Get(i) != 0) ); + + while (npok >= 1) + { + + if (npok <= rule->GetNOldP()) + { + + if (pfixed.Get(npok)) + + { + if (incnpok) + npok++; + else + npok--; + } + + else + + { + locpi = pmap.Elem(npok); + ok = 0; + + if (locpi) + pused.Elem(locpi)--; + + while (!ok && locpi < lpoints.Size()) + { + ok = 1; + locpi++; + + if (pused.Get(locpi) || + pnearness.Get(locpi) > rule->GetPNearness(npok)) + { + ok = 0; + } + else if (allowpoint.Get(locpi) != 2) + { + ok = 0; + if (allowpoint.Get(locpi) == 1) + impossible = 0; + } + else + { + const Point3d & lp = lpoints.Get(locpi); + const Point3d & rp = rule->GetPoint(npok); + + if ( Dist2 (lp, rp) * rule->PointDistFactor(npok) > minerr) + { + ok = 0; + impossible = 0; + } + } + } + + + if (ok) + { + pmap.Set (npok, locpi); + + if (npok <= 3) + (*testout) << "set face1 point, mark3" << endl; + + pused.Elem(locpi)++; + npok++; + incnpok = 1; + } + + else + + { + pmap.Set (npok, 0); + + if (npok <= 3) + (*testout) << "set face1 point, mark4" << endl; + + npok--; + incnpok = 0; + } + } + } + + else + + { + NgProfiler::RegionTimer regfa2(302); + + // all points are mapped + + if (loktestmode) + { + (*testout) << "Mapping found!!: Rule " << rule->Name() << endl; + for (i = 1; i <= pmap.Size(); i++) + (*testout) << pmap.Get(i) << " "; + (*testout) << endl; + sprintf (problems.Elem(ri), "mapping found"); + (*testout) << rule->GetNP(1) << " = " << lfaces.Get(1).GetNP() << endl; + } + + ok = 1; + + + // check mapedges: + for (i = 1; i <= rule->GetNEd(); i++) + { + INDEX_2 in2(pmap.Get(rule->GetEdge(i).i1), + pmap.Get(rule->GetEdge(i).i2)); + in2.Sort(); + if (!ledges.Used (in2)) ok = 0; + } + + + // check prism edges: + for (i = 1; i <= rule->GetNE(); i++) + { + const Element & el = rule->GetElement (i); + if (el.GetType() == PRISM) + { + for (j = 1; j <= 3; j++) + { + INDEX_2 in2(pmap.Get(el.PNum(j)), + pmap.Get(el.PNum(j+3))); + in2.Sort(); + if (!connectedpairs.Used (in2)) ok = 0; + } + } + if (el.GetType() == PYRAMID) + { + if (loktestmode) + (*testout) << "map pyramid, rule = " << rule->Name() << endl; + for (j = 1; j <= 2; j++) + { + INDEX_2 in2; + if (j == 1) + { + in2.I1() = pmap.Get(el.PNum(2)); + in2.I2() = pmap.Get(el.PNum(3)); + } + else + { + in2.I1() = pmap.Get(el.PNum(1)); + in2.I2() = pmap.Get(el.PNum(4)); + } + in2.Sort(); + if (!connectedpairs.Used (in2)) + { + ok = 0; + if (loktestmode) + (*testout) << "no pair" << endl; + } + } + } + + } + + + + for (i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++) + fmapi.Set(i, 0); + + + if (ok) + { + foundmap.Elem(ri)++; + } + + + + + // deviation of existing points + + oldu.SetSize (3 * rule->GetNOldP()); + newu.SetSize (3 * (rule->GetNP() - rule->GetNOldP())); + allp.SetSize (3 * rule->GetNP()); + + for (i = 1; i <= rule->GetNOldP(); i++) + { + const Point3d & lp = lpoints.Get(pmap.Get(i)); + const Point3d & rp = rule->GetPoint(i); + oldu.Set (3*i-2, lp.X()-rp.X()); + oldu.Set (3*i-1, lp.Y()-rp.Y()); + oldu.Set (3*i , lp.Z()-rp.Z()); + + allp.Set (3*i-2, lp.X()); + allp.Set (3*i-1, lp.Y()); + allp.Set (3*i , lp.Z()); + } + + if (rule->GetNP() > rule->GetNOldP()) + { + newu.SetSize (rule->GetOldUToNewU().Height()); + rule->GetOldUToNewU().Mult (oldu, newu); + } + + // int idiff = 3 * (rule->GetNP()-rule->GetNOldP()); + int idiff = 3 * rule->GetNOldP(); + for (i = rule->GetNOldP()+1; i <= rule->GetNP(); i++) + { + const Point3d & rp = rule->GetPoint(i); + allp.Set (3*i-2, rp.X() + newu.Get(3*i-2 - idiff)); + allp.Set (3*i-1, rp.Y() + newu.Get(3*i-1 - idiff)); + allp.Set (3*i , rp.Z() + newu.Get(3*i - idiff)); + } + + rule->SetFreeZoneTransformation (allp, + tolerance + int(sloppy)); + + if (!rule->ConvexFreeZone()) + { + ok = 0; + sprintf (problems.Elem(ri), "Freezone not convex"); + + if (loktestmode) + (*testout) << "Freezone not convex" << endl; + } + + if (loktestmode) + { + const ARRAY<Point3d> & fz = rule->GetTransFreeZone(); + (*testout) << "Freezone: " << endl; + for (i = 1; i <= fz.Size(); i++) + (*testout) << fz.Get(i) << endl; + } + + + // check freezone: + + for (i = 1; i <= lpoints.Size(); i++) + { + if ( !pused.Get(i) ) + { + const Point3d & lp = lpoints.Get(i); + + if (rule->fzbox.IsIn (lp)) + { + if (rule->IsInFreeZone(lp)) + { + if (loktestmode) + { + (*testout) << "Point " << i + << " in Freezone" << endl; + sprintf (problems.Elem(ri), + "locpoint %d in Freezone", i); + } + ok = 0; + break; + } + } + } + } + + for (i = 1; i <= lfaces.Size() && ok; i++) + { + static ARRAY<int> lpi(4); + + if (!fused.Get(i)) + { + int triin; + const MiniElement2d & lfacei = lfaces.Get(i); + + if (!triboxes.Elem(i).Intersect (rule->fzbox)) + triin = 0; + else + { + int li, lj; + for (li = 1; li <= lfacei.GetNP(); li++) + { + int lpii = 0; + int pi = lfacei.PNum(li); + for (lj = 1; lj <= rule->GetNOldP(); lj++) + if (pmap.Get(lj) == pi) + lpii = lj; + lpi.Elem(li) = lpii; + } + + + if (lfacei.GetNP() == 3) + { + triin = rule->IsTriangleInFreeZone + ( + lpoints.Get(lfacei.PNum(1)), + lpoints.Get(lfacei.PNum(2)), + lpoints.Get(lfacei.PNum(3)), lpi, 1 + ); + } + else + { + triin = rule->IsQuadInFreeZone + ( + lpoints.Get(lfacei.PNum(1)), + lpoints.Get(lfacei.PNum(2)), + lpoints.Get(lfacei.PNum(3)), + lpoints.Get(lfacei.PNum(4)), + lpi, 1 + ); + } + } + + + if (triin == -1) + { + ok = 0; + } + + if (triin == 1) + { +#ifdef TEST_JS + ok = 0; + + if (loktestmode) + { + (*testout) << "El with " << lfaces.Get(i).GetNP() << " points in freezone: " + << lfaces.Get(i).PNum(1) << " - " + << lfaces.Get(i).PNum(2) << " - " + << lfaces.Get(i).PNum(3) << " - " + << lfaces.Get(i).PNum(4) << endl; + for (int lj = 1; lj <= lfaces.Get(i).GetNP(); lj++) + (*testout) << lpoints.Get(lfaces.Get(i).PNum(lj)) << " "; + + (*testout) << endl; + + sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone", + lfaces.Get(i).PNum(1), lfaces.Get(i).PNum(2), + lfaces.Get(i).PNum(3)); + } +#else + if (loktestmode) + { + if (lfacei.GetNP() == 3) + { + (*testout) << "Triangle in freezone: " + << lfacei.PNum(1) << " - " + << lfacei.PNum(2) << " - " + << lfacei.PNum(3) + << ", or " + << lpoints.Get(lfacei.PNum(1)) << " - " + << lpoints.Get(lfacei.PNum(2)) << " - " + << lpoints.Get(lfacei.PNum(3)) + << endl; + (*testout) << "lpi = " << lpi.Get(1) << ", " + << lpi.Get(2) << ", " << lpi.Get(3) << endl; + } + else + (*testout) << "Quad in freezone: " + << lfacei.PNum(1) << " - " + << lfacei.PNum(2) << " - " + << lfacei.PNum(3) << " - " + << lfacei.PNum(4) + << ", or " + << lpoints.Get(lfacei.PNum(1)) << " - " + << lpoints.Get(lfacei.PNum(2)) << " - " + << lpoints.Get(lfacei.PNum(3)) << " - " + << lpoints.Get(lfacei.PNum(4)) + << endl; + + sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone", + int(lfaces.Get(i).PNum(1)), + int(lfaces.Get(i).PNum(2)), + int(lfaces.Get(i).PNum(3))); + } + + hc = 0; + for (k = rule->GetNOldF() + 1; k <= rule->GetNF(); k++) + { + if (rule->GetPointNr(k, 1) <= rule->GetNOldP() && + rule->GetPointNr(k, 2) <= rule->GetNOldP() && + rule->GetPointNr(k, 3) <= rule->GetNOldP()) + { + for (j = 1; j <= 3; j++) + if (lfaces.Get(i).PNumMod(j ) == pmap.Get(rule->GetPointNr(k, 1)) && + lfaces.Get(i).PNumMod(j+1) == pmap.Get(rule->GetPointNr(k, 3)) && + lfaces.Get(i).PNumMod(j+2) == pmap.Get(rule->GetPointNr(k, 2))) + { + fmapi.Elem(k) = i; + hc = 1; + + + // (*testout) << "found from other side: " +// << rule->Name() +// << " ( " << pmap.Get (rule->GetPointNr(k, 1)) +// << " - " << pmap.Get (rule->GetPointNr(k, 2)) +// << " - " << pmap.Get (rule->GetPointNr(k, 3)) << " ) " +// << endl; + + strcpy (problems.Elem(ri), "other"); + } + } + } + + if (!hc) + { + if (loktestmode) + { + (*testout) << "Triangle in freezone: " + << lfaces.Get(i).PNum(1) << " - " + << lfaces.Get(i).PNum(2) << " - " + << lfaces.Get(i).PNum(3) << endl; + + sprintf (problems.Elem(ri), "triangle (%d, %d, %d) in Freezone", + int (lfaces.Get(i).PNum(1)), + int (lfaces.Get(i).PNum(2)), + int (lfaces.Get(i).PNum(3))); + } + ok = 0; + } +#endif + } + } + + } + + + if (ok) + { + err = 0; + for (i = 1; i <= rule->GetNOldP(); i++) + { + hf = rule->CalcPointDist (i, lpoints.Get(pmap.Get(i))); + if (hf > err) err = hf; + } + + + if (loktestmode) + { + (*testout) << "Rule ok" << endl; + sprintf (problems.Elem(ri), "Rule ok, err = %f", err); + } + + + // newu = rule->GetOldUToNewU() * oldu; + + // set new points: + + oldnp = rule->GetNOldP(); + noldlp = lpoints.Size(); + noldlf = lfaces.Size(); + + + for (i = oldnp + 1; i <= rule->GetNP(); i++) + { + np = rule->GetPoint(i); + np.X() += newu.Elem (3 * (i-oldnp) - 2); + np.Y() += newu.Elem (3 * (i-oldnp) - 1); + np.Z() += newu.Elem (3 * (i-oldnp)); + + pmap.Elem(i) = lpoints.Append (np); + } + + // Set new Faces: + + for (i = rule->GetNOldF() + 1; i <= rule->GetNF(); i++) + if (!fmapi.Get(i)) + { + MiniElement2d nface(rule->GetNP(i)); + for (j = 1; j <= nface.GetNP(); j++) + nface.PNum(j) = pmap.Get(rule->GetPointNr (i, j)); + + lfaces.Append (nface); + } + + + // Delete old Faces: + + for (i = 1; i <= rule->GetNDelF(); i++) + delfaces.Append (fmapi.Get(rule->GetDelFace(i))); + for (i = rule->GetNOldF()+1; i <= rule->GetNF(); i++) + if (fmapi.Get(i)) + { + delfaces.Append (fmapi.Get(i)); + fmapi.Elem(i) = 0; + } + + + // check orientation + for (i = 1; i <= rule->GetNO() && ok; i++) + { + const fourint * fouri; + + fouri = &rule->GetOrientation(i); + Vec3d v1 (lpoints.Get(pmap.Get(fouri->i1)), + lpoints.Get(pmap.Get(fouri->i2))); + Vec3d v2 (lpoints.Get(pmap.Get(fouri->i1)), + lpoints.Get(pmap.Get(fouri->i3))); + Vec3d v3 (lpoints.Get(pmap.Get(fouri->i1)), + lpoints.Get(pmap.Get(fouri->i4))); + + Vec3d n; + Cross (v1, v2, n); + //if (n * v3 >= -1e-7*n.Length()*v3.Length()) // OR -1e-7??? + if (n * v3 >= -1e-9) + { + if (loktestmode) + { + sprintf (problems.Elem(ri), "Orientation wrong"); + (*testout) << "Orientation wrong ("<< n*v3 << ")" << endl; + } + ok = 0; + } + } + + + + // new points in free-zone ? + for (i = rule->GetNOldP() + 1; i <= rule->GetNP() && ok; i++) + if (!rule->IsInFreeZone (lpoints.Get(pmap.Get(i)))) + { + if (loktestmode) + { + (*testout) << "Newpoint " << lpoints.Get(pmap.Get(i)) + << " outside convex hull" << endl; + sprintf (problems.Elem(ri), "newpoint outside convex hull"); + } + ok = 0; + + } + + // insert new elements + + for (i = 1; i <= rule->GetNE(); i++) + { + elements.Append (rule->GetElement(i)); + for (j = 1; j <= elements.Get(i).NP(); j++) + elements.Elem(i).PNum(j) = pmap.Get(elements.Get(i).PNum(j)); + } + + + // Calculate Element badness + + teterr = 0; + for (i = 1; i <= elements.Size(); i++) + { + hf = CalcElementBadness (lpoints, elements.Get(i)); + if (hf > teterr) teterr = hf; + } + + /* + // keine gute Erfahrung am 25.1.2000, js + if (ok && teterr < 100 && + (rule->TestFlag('b') || tolerance > 10) ) + { + (*mycout) << "Reset teterr " + << rule->Name() + << " err = " << teterr + << endl; + teterr = 1; + } + */ + + // compare edgelength + if (rule->TestFlag('l')) + { + double oldlen = 0; + double newlen = 0; + + for (i = 1; i <= rule->GetNDelF(); i++) + { + const Element2d & face = + rule->GetFace (rule->GetDelFace(i)); + for (j = 1; j <= 3; j++) + { + const Point3d & p1 = + lpoints.Get(pmap.Get(face.PNumMod(j))); + const Point3d & p2 = + lpoints.Get(pmap.Get(face.PNumMod(j+1))); + oldlen += Dist(p1, p2); + } + } + + for (i = rule->GetNOldF()+1; i <= rule->GetNF(); i++) + { + const Element2d & face = rule->GetFace (i); + for (j = 1; j <= 3; j++) + { + const Point3d & p1 = + lpoints.Get(pmap.Get(face.PNumMod(j))); + const Point3d & p2 = + lpoints.Get(pmap.Get(face.PNumMod(j+1))); + newlen += Dist(p1, p2); + } + } + + if (oldlen < newlen) + { + ok = 0; + if (loktestmode) + sprintf (problems.Elem(ri), "oldlen < newlen"); + } + } + + + if (loktestmode) + (*testout) << "ok = " << int(ok) + << "teterr = " << teterr + << "minteterr = " << minteterr << endl; + + + if (ok && teterr < tolerance) + { + canuse.Elem(ri) ++; + /* + (*testout) << "can use rule " << rule->Name() + << ", err = " << teterr << endl; + for (i = 1; i <= pmap.Size(); i++) + (*testout) << pmap.Get(i) << " "; + (*testout) << endl; + */ + + if (strcmp (problems.Elem(ri), "other") == 0) + { + if (teterr < minother) + minother = teterr; + } + else + { + if (teterr < minwithoutother) + minwithoutother = teterr; + } + } + + + if (teterr > minteterr) impossible = 0; + + if (ok && teterr < minteterr) + { + + if (loktestmode) + (*testout) << "use rule" << endl; + + found = ri; + minteterr = teterr; + + if (testmode) + { + for (i = 1; i <= rule->GetNOldP(); i++) + { + (*testout) << "P" << i << ": Ref: " + << rule->GetPoint (i) << " is: " + << lpoints.Get(pmap.Get(i)) << endl; + } + } + + tempnewpoints.SetSize (0); + for (i = noldlp+1; i <= lpoints.Size(); i++) + tempnewpoints.Append (lpoints.Get(i)); + + tempnewfaces.SetSize (0); + for (i = noldlf+1; i <= lfaces.Size(); i++) + tempnewfaces.Append (lfaces.Get(i)); + + tempdelfaces.SetSize (0); + for (i = 1; i <= delfaces.Size(); i++) + tempdelfaces.Append (delfaces.Get(i)); + + tempelements.SetSize (0); + for (i = 1; i <= elements.Size(); i++) + tempelements.Append (elements.Get(i)); + } + + + lpoints.SetSize (noldlp); + lfaces.SetSize (noldlf); + delfaces.SetSize (0); + elements.SetSize (0); + } + + npok = rule->GetNOldP(); + incnpok = 0; + } + } + + nfok = rule->GetNOldF(); + + for (j = 1; j <= rule->GetNP (nfok); j++) + { + refpi = rule->GetPointNr (nfok, j); + pused.Elem(pmap.Get(refpi))--; + + if (pused.Get(pmap.Get(refpi)) == 0) + { + pmap.Set(refpi, 0); + } + } + + } + } + if (loktestmode) + (*testout) << "end rule" << endl; + } + + if (found) + { + for (i = 1; i <= tempnewpoints.Size(); i++) + lpoints.Append (tempnewpoints.Get(i)); + for (i = 1; i <= tempnewfaces.Size(); i++) + if (tempnewfaces.Get(i).PNum(1)) + lfaces.Append (tempnewfaces.Get(i)); + for (i = 1; i <= tempdelfaces.Size(); i++) + delfaces.Append (tempdelfaces.Get(i)); + for (i = 1; i <= tempelements.Size(); i++) + elements.Append (tempelements.Get(i)); + } + + retminerr = minerr; + + + if (impossible && found == 0) + return -1; + + return found; +} +} diff --git a/contrib/Netgen/libsrc/meshing/ruler3.hpp b/contrib/Netgen/libsrc/meshing/ruler3.hpp new file mode 100644 index 0000000000000000000000000000000000000000..483d83ed4ebf9d3b5e4fd1e7acaee36b3dcbcb38 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/ruler3.hpp @@ -0,0 +1,210 @@ +#ifndef FILE_RULER3 +#define FILE_RULER3 + + +/** + 3D element generation rule. + */ +class vnetrule +{ +private: + /// rule is applicable for quality classes above this value + int quality; + /// name of rule + char * name; + /// point coordinates in reference position + ARRAY<Point3d> points; + /// old and new faces in reference numbering + ARRAY<Element2d> faces; + /// additional edges of rule + ARRAY<twoint> edges; + + /// points of freezone in reference coordinates + ARRAY<Point3d> freezone; + /// points of freezone in reference coordinates if tolcalss to infty + ARRAY<Point3d> freezonelimit; + /// point index, if point equal to mappoint, otherwise 0 + ARRAY<int> freezonepi; + /// faces of each convex part of freezone + ARRAY<ARRAY<threeint>*> freefaces; + /// set of points of each convex part of freezone + ARRAY<ARRAY<int>*> freesets; + /// points of transformed freezone + ARRAY<Point3d> transfreezone; + /// edges of each convex part of freezone + ARRAY<ARRAY<twoint>*> freeedges; + + /// face numbers to be deleted + ARRAY<int> delfaces; + /// elements to be generated + ARRAY<Element> elements; + /// tolerances for points and faces (used ??) + ARRAY<double> tolerances, linetolerances; + /// transformation matrix + DenseMatrix oldutonewu; + /// transformation matrix: deviation old point to dev. freezone + DenseMatrix * oldutofreezone; + /** transformation matrix: deviation old point to dev. freezone, + quality class to infinity */ + DenseMatrix * oldutofreezonelimit; + + // can be deleted: + // BaseMatrix *outf, *outfl; + + /** + a point is outside of convex part of freezone, + iff mat * (point, 1) >= 0 for each component (correct ?) + */ + ARRAY<DenseMatrix*> freefaceinequ; + /// + ARRAY<fourint> orientations; + /** + flags specified in rule-description file: + t .. test rule + */ + ARRAY<char> flags; + + /** + topological distance of face to base element + non-connected: > 100 (??) + */ + ARRAY<int> fnearness; + ARRAY<int> pnearness; + int maxpnearness; + + /// number of old points in rule + int noldp; + /// number of new poitns in rule + int noldf; + /// box containing free-zone +public: + // double fzminx, fzmaxx, fzminy, fzmaxy, fzminz, fzmaxz; + Box3d fzbox; + +public: + + /// + vnetrule (); + /// + ~vnetrule (); + /// + int GetNP () const { return points.Size(); } + /// + int GetNF () const { return faces.Size(); } + /// + int GetNE () const { return elements.Size(); } + /// + int GetNO () const { return orientations.Size(); } + /// + int GetNEd () const { return edges.Size(); } + /// + int GetNOldP () const { return noldp; } + /// + int GetNOldF () const { return noldf; } + /// + int GetNDelF () const { return delfaces.Size(); } + /// + int GetQuality () const { return quality; } + /// + int GetFNearness (int fi) const { return fnearness.Get(fi); } + /// + int GetPNearness (int pi) const { return pnearness.Get(pi); } + /// + int GetMaxPNearness () const { return maxpnearness; } + + + /// + const Point3d & GetPoint (int i) const { return points.Get(i); } + /// + const Element2d & GetFace (int i) const { return faces.Get(i); } + /// + const Element & GetElement (int i) const { return elements.Get(i); } + /// + const twoint & GetEdge (int i) const { return edges.Get(i); } + /// + int GetDelFace (int i) const { return delfaces.Get(i); } + /// + int IsDelFace (int fn) const; + + /// + float CalcPointDist (int pi, const Point3d & p) const; + /// + double PointDistFactor (int pi) const + { + return tolerances.Get(pi); + } + /// + void SetFreeZoneTransformation (const Vector & allp, + int tolclass); + /// + int IsInFreeZone (const Point3d & p) const; + /** + 0 not in free-zone + 1 in free-zone + -1 maybe + */ + int IsTriangleInFreeZone (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const ARRAY<int> & pi, int newone); + /// + int IsQuadInFreeZone (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, + const ARRAY<int> & pi, int newone); + /// + int IsTriangleInFreeSet (const Point3d & p1, const Point3d & p2, + const Point3d & p3, int fs, const ARRAY<int> & pi, int newone); + + /// + int IsQuadInFreeSet (const Point3d & p1, const Point3d & p2, + const Point3d & p3, const Point3d & p4, + int fs, const ARRAY<int> & pi, int newone); + + /// + int ConvexFreeZone () const; + + /// if t1 and t2 are neighbourtriangles, NTP returns the opposite Point of t1 in t2 + int NeighbourTrianglePoint (const threeint & t1, const threeint & t2) const; + /// + const Point3d & GetTransFreeZone (int i) { return transfreezone.Get(i); } + + /// + int GetNP (int fn) const + { return faces.Get(fn).GetNP(); } + /// + int GetPointNr (int fn, int endp) const + { return faces.Get(fn).PNum(endp); } + /// + int GetPointNrMod (int fn, int endp) const + { return faces.Get(fn).PNumMod(endp); } + /// + const fourint & GetOrientation (int i) { return orientations.Get(i); } + + /// + int TestFlag (char flag) const; + + /// + const DenseMatrix & GetOldUToNewU () const { return oldutonewu; } + // + // const DenseMatrix & GetOldUToFreeZone () const { return oldutofreezone; } + // + // const DenseMatrix & GetOldUToFreeZoneLimit () const + // { return oldutofreezonelimit; } + /// + const char * Name () const { return name; } + /// + void LoadRule (istream & ist); + + /// + const ARRAY<Point3d> & GetTransFreeZone () { return transfreezone; } + /// + int TestOk () const; + + /// + friend void TestRules (); + /// + // friend void Plot3DRule (const ROT3D & r, char key); +}; + + + +#endif + diff --git a/contrib/Netgen/libsrc/meshing/secondorder.cpp b/contrib/Netgen/libsrc/meshing/secondorder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66c91cfea92c1aa01dabdb5e31c7da2591c077ae --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/secondorder.cpp @@ -0,0 +1,486 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + + + + + void Refinement :: MakeSecondOrder (Mesh & mesh) + { + int nseg, nse, ne; + + mesh.ComputeNVertices(); + mesh.SetNP(mesh.GetNV()); + + INDEX_2_HASHTABLE<int> between(mesh.GetNP() + 5); + + + bool thinlayers = 0; + for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++) + if (mesh[ei].GetType() == PRISM || + mesh[ei].GetType() == PRISM12) + thinlayers = 1; + + + nseg = mesh.GetNSeg(); + for (SegmentIndex si = 0; si < nseg; si++) + { + Segment & el = mesh.LineSegment(si); + + INDEX_2 i2 = INDEX_2::Sort (el.p1, el.p2); + + if (between.Used(i2)) + el.pmid = between.Get(i2); + else + { + Point<3> pb; + EdgePointGeomInfo ngi; + PointBetween (mesh.Point (el.p1), + mesh.Point (el.p2), 0.5, + el.surfnr1, el.surfnr2, + el.epgeominfo[0], el.epgeominfo[1], + pb, ngi); + + el.pmid = mesh.AddPoint (pb); + between.Set (i2, el.pmid); + } + } + + // refine surface elements + nse = mesh.GetNSE(); + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + { + int j; + const Element2d & el = mesh.SurfaceElement(sei); + + int onp(0); + + Element2d newel; + newel.SetIndex (el.GetIndex()); + + static int betw_trig[3][3] = + { { 1, 2, 3 }, + { 0, 2, 4 }, + { 0, 1, 5 } }; + static int betw_quad6[2][3] = + { { 0, 1, 4 }, + { 3, 2, 5 } }; + static int betw_quad8[4][3] = + { { 0, 1, 4 }, + { 3, 2, 5 }, + { 0, 3, 6 }, + { 1, 2, 7 } }; + int (*betw)[3](NULL); + + switch (el.GetType()) + { + case TRIG: + case TRIG6: + { + betw = betw_trig; + newel.SetType (TRIG6); + onp = 3; + break; + } + case QUAD: + case QUAD6: + case QUAD8: + { + if (thinlayers) + { + betw = betw_quad6; + newel.SetType (QUAD6); + } + else + { + betw = betw_quad8; + newel.SetType (QUAD8); + } + onp = 4; + break; + } + default: + PrintSysError ("Unhandled element in secondorder:", int(el.GetType())); + } + + for (j = 0; j < onp; j++) + newel[j] = el[j]; + + int nnp = newel.GetNP(); + for (j = 0; j < nnp-onp; j++) + { + int pi1 = newel[betw[j][0]]; + int pi2 = newel[betw[j][1]]; + + INDEX_2 i2 = INDEX_2::Sort (pi1, pi2); + + if (between.Used(i2)) + newel[onp+j] = between.Get(i2); + else + { + Point<3> pb; + PointGeomInfo newgi; + PointBetween (mesh.Point (pi1), + mesh.Point (pi2), 0.5, + mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(), + el.GeomInfoPi (betw[j][0]+1), + el.GeomInfoPi (betw[j][1]+1), + pb, newgi); + + newel[onp+j] = mesh.AddPoint (pb); + between.Set (i2, newel[onp+j]); + } + } + + mesh.SurfaceElement(sei) = newel; + } + + + // int i, j; + + + + // refine volume elements + ne = mesh.GetNE(); + for (int i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + int onp(0); + + Element newel; + newel.SetIndex (el.GetIndex()); + + static int betw_tet[6][3] = + { { 0, 1, 4 }, + { 0, 2, 5 }, + { 0, 3, 6 }, + { 1, 2, 7 }, + { 1, 3, 8 }, + { 2, 3, 9 } }; + static int betw_prism[6][3] = + { + { 0, 2, 6 }, + { 0, 1, 7 }, + { 1, 2, 8 }, + { 3, 5, 9 }, + { 3, 4, 10 }, + { 4, 5, 11 }, + }; + int (*betw)[3](NULL); + + switch (el.GetType()) + { + case TET: + case TET10: + { + betw = betw_tet; + newel.SetType (TET10); + onp = 4; + break; + } + case PRISM: + case PRISM12: + { + betw = betw_prism; + newel.SetType (PRISM12); + onp = 6; + break; + } + default: + PrintSysError ("MakeSecondOrder, illegal vol type ", el.GetType()); + } + + + for (int j = 1; j <= onp; j++) + newel.PNum(j) = el.PNum(j); + int nnp = newel.GetNP(); + + for (int j = 0; j < nnp-onp; j++) + { + INDEX_2 i2(newel[betw[j][0]], + newel[betw[j][1]]); + i2.Sort(); + + if (between.Used(i2)) + newel.PNum(onp+1+j) = between.Get(i2); + else + { + newel.PNum(onp+1+j) = mesh.AddPoint + (Center (mesh.Point(i2.I1()), + mesh.Point(i2.I2()))); + between.Set (i2, newel.PNum(onp+1+j)); + } + } + + mesh.VolumeElement (i) = newel; + } + + + // makes problems after linear mesh refinement, since + // 2nd order identifications are not removed + // update identification tables + for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++) + { + ARRAY<int,PointIndex::BASE> identmap; + mesh.GetIdentifications().GetMap (i, identmap); + + for (INDEX_2_HASHTABLE<int>::Iterator it = between.Begin(); + it != between.End(); it++) + { + INDEX_2 i2; + int newpi; + between.GetData (it, i2, newpi); + INDEX_2 oi2(identmap.Get(i2.I1()), + identmap.Get(i2.I2())); + oi2.Sort(); + if (between.Used (oi2)) + { + int onewpi = between.Get(oi2); + mesh.GetIdentifications().Add (newpi, onewpi, i); + } + } + + /* + for (int j = 1; j <= between.GetNBags(); j++) + for (int k = 1; k <= between.GetBagSize(j); k++) + { + INDEX_2 i2; + int newpi; + between.GetData (j, k, i2, newpi); + INDEX_2 oi2(identmap.Get(i2.I1()), + identmap.Get(i2.I2())); + oi2.Sort(); + if (between.Used (oi2)) + { + int onewpi = between.Get(oi2); + mesh.GetIdentifications().Add (newpi, onewpi, i); + } + } + */ + } + + + // mesh.mglevels++; + int oldsize = mesh.mlbetweennodes.Size(); + mesh.mlbetweennodes.SetSize(mesh.GetNP()); + for (int i = oldsize; i < mesh.GetNP(); i++) + mesh.mlbetweennodes[i] = INDEX_2(0,0); + + /* + for (i = 1; i <= between.GetNBags(); i++) + for (j = 1; j <= between.GetBagSize(i); j++) + { + INDEX_2 oldp; + int newp; + between.GetData (i, j, oldp, newp); + mesh.mlbetweennodes.Elem(newp) = oldp; + } + */ + + for (INDEX_2_HASHTABLE<int>::Iterator it = between.Begin(); + it != between.End(); it++) + { + mesh.mlbetweennodes[between.GetData (it)] = between.GetHash(it); + } + + mesh.ComputeNVertices(); + + // ValidateSecondOrder (mesh); + } + + + void Refinement :: ValidateSecondOrder (Mesh & mesh) + { + PrintMessage (3, "Validate mesh"); + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + // int i, j; + ARRAY<INDEX_2> parents(np); + + for (int i = 1; i <= np; i++) + parents.Elem(i) = INDEX_2(0,0); + + for (int i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + if (el.GetType() == TET10) + { + static int betweentab[6][3] = + { { 1, 2, 5 }, + { 1, 3, 6 }, + { 1, 4, 7 }, + { 2, 3, 8 }, + { 2, 4, 9 }, + { 3, 4, 10 } }; + for (int j = 0; j < 6; j++) + { + int f1 = el.PNum (betweentab[j][0]); + int f2 = el.PNum (betweentab[j][1]); + int son = el.PNum (betweentab[j][2]); + parents.Elem(son).I1() = f1; + parents.Elem(son).I2() = f2; + } + } + } + + ValidateRefinedMesh (mesh, parents); + } + + + void Refinement :: + ValidateRefinedMesh (Mesh & mesh, + ARRAY<INDEX_2> & parents) + { + // int i, j, k; + + // homotopy method + + int ne = mesh.GetNE(); + + int cnttrials = 100; + int wrongels = 0; + for (int i = 1; i <= ne; i++) + if (mesh.VolumeElement(i).CalcJacobianBadness (mesh.Points()) > 1e10) + { + wrongels++; + mesh.VolumeElement(i).flags.badel = 1; + } + else + mesh.VolumeElement(i).flags.badel = 0; + + double facok = 0; + double factry; + + BitArray illegalels(ne); + illegalels.Clear(); + + + if (wrongels) + { + cout << "WARNING: " << wrongels << " illegal element(s) found" << endl; + + int np = mesh.GetNP(); + ARRAY<Point<3> > should(np); + ARRAY<Point<3> > can(np); + + for (int i = 1; i <= np; i++) + { + should.Elem(i) = can.Elem(i) = mesh.Point(i); + } + + for (int i = 1; i <= parents.Size(); i++) + { + if (parents.Get(i).I1()) + can.Elem(i) = Center (can.Elem(parents.Get(i).I1()), + can.Elem(parents.Get(i).I2())); + } + + BitArray boundp(np); + boundp.Clear(); + for (int i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + for (int j = 1; j <= sel.GetNP(); j++) + boundp.Set(sel.PNum(j)); + } + + + (*testout) << "bpoints:" << endl; + for (int i = 1; i <= np; i++) + if (boundp.Test(i)) + (*testout) << i << endl; + + double lam = 0.5; + + while (facok < 1-1e-8 && cnttrials > 0) + { + lam *= 4; + if (lam > 2) lam = 2; + + do + { + // cout << "trials: " << cnttrials << endl; + lam *= 0.5; + cnttrials--; + + cout << "lam = " << lam << endl; + + factry = lam + (1-lam) * facok; + cout << "trying: " << factry << endl; + + for (int i = 1; i <= np; i++) + if (boundp.Test(i)) + { + for (int j = 0; j < 3; j++) + mesh.Point(i)(j) = + lam * should.Get(i)(j) + + (1-lam) * can.Get(i)(j); + } + else + mesh.Point(i) = Point<3> (can.Get(i)); + + // (*testout) << "bad els: " << endl; + wrongels = 0; + for (int i = 1; i <= ne; i++) + { + if (!illegalels.Test(i) && + mesh.VolumeElement(i). + CalcJacobianBadness(mesh.Points()) > 1e10) + { + wrongels++; + Element & el = mesh.VolumeElement(i); + el.flags.badel = 1; + + + if (lam < 1e-4) + illegalels.Set(i); + + + /* + (*testout) << i << ": "; + for (j = 1; j <= el.GetNP(); j++) + (*testout) << el.PNum(j) << " "; + (*testout) << endl; + */ + } + else + mesh.VolumeElement(i).flags.badel = 0; + } + cout << "wrongels = " << wrongels << endl; + } + while (wrongels && cnttrials > 0); + + mesh.CalcSurfacesOfNode(); + mesh.ImproveMeshJacobian (OPT_WORSTCASE); + + facok = factry; + for (int i = 1; i <= np; i++) + can.Elem(i) = mesh.Point(i); + } + } + + + + for (int i = 1; i <= ne; i++) + { + if (illegalels.Test(i)) + { + cout << "illegal element: " << i << endl; + mesh.VolumeElement(i).flags.badel = 1; + } + else + mesh.VolumeElement(i).flags.badel = 0; + } + + /* + if (cnttrials <= 0) + { + cerr << "ERROR: Sorry, illegal elements:" << endl; + } + */ + } + +} diff --git a/contrib/Netgen/libsrc/meshing/smoothing2.5.cpp b/contrib/Netgen/libsrc/meshing/smoothing2.5.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2789b785bcf4ea82f07efc9cf4d4e5d0e5105e81 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/smoothing2.5.cpp @@ -0,0 +1,265 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +namespace netgen +{ + + + void MeshOptimize2d :: ProjectBoundaryPoints(ARRAY<int> & surfaceindex, + const ARRAY<Point<3>* > & from, ARRAY<Point<3>* > & dest) + { + for(int i=0; i<surfaceindex.Size(); i++) + { + if(surfaceindex[i] >= 0) + { + *dest[i] = *from[i]; + ProjectPoint(surfaceindex[i],*dest[i]); + } + } + + + } + + void MeshOptimize2d :: ImproveVolumeMesh (Mesh & mesh) + { + + if (!faceindex) + { + PrintMessage (3, "Smoothing"); + + for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) + { + ImproveVolumeMesh (mesh); + if (multithread.terminate) + throw NgException ("Meshing stopped"); + } + faceindex = 0; + return; + } + + + + static int timer = NgProfiler::CreateTimer ("MeshSmoothing 2D"); + NgProfiler::RegionTimer reg (timer); + + + + CheckMeshApproximation (mesh); + + int i, j, k; + SurfaceElementIndex sei; + + ARRAY<SurfaceElementIndex> seia; + mesh.GetSurfaceElementsOfFace (faceindex, seia); + + bool mixed = 0; + for (i = 0; i < seia.Size(); i++) + if (mesh[seia[i]].GetNP() != 3) + { + mixed = 1; + break; + } + + + int loci; + double fact; + bool moveisok; + + PointGeomInfo ngi; + Point<3> origp; + + Vector x(3); + + ARRAY<MeshPoint, PointIndex::BASE> savepoints(mesh.GetNP()); + + ARRAY<int, PointIndex::BASE> nelementsonpoint(mesh.GetNP()); + nelementsonpoint = 0; + + for (i = 0; i < seia.Size(); i++) + { + const Element2d & el = mesh[seia[i]]; + for (j = 0; j < el.GetNP(); j++) + nelementsonpoint[el[j]]++; + } + + + TABLE<SurfaceElementIndex,PointIndex::BASE> elementsonpoint(nelementsonpoint); + for (i = 0; i < seia.Size(); i++) + { + const Element2d & el = mesh[seia[i]]; + for (j = 0; j < el.GetNP(); j++) + elementsonpoint.Add (el[j], seia[i]); + } + + + JacobianPointFunction pf(mesh.Points(),mesh.VolumeElements()); + + + +// Opti2SurfaceMinFunction surfminf(mesh); +// Opti2EdgeMinFunction edgeminf(mesh); +// Opti2SurfaceMinFunctionJacobian surfminfj(mesh); + + OptiParameters par; + par.maxit_linsearch = 8; + par.maxit_bfgs = 5; + + int np = mesh.GetNP(); + int ne = mesh.GetNE(); + + BitArray badnodes(np); + badnodes.Clear(); + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement(i); + double bad = el.CalcJacobianBadness (mesh.Points()); + if (bad > 1) + for (j = 1; j <= el.GetNP(); j++) + badnodes.Set (el.PNum(j)); + } + + + bool printeddot = 0; + char plotchar = '.'; + int modplot = 1; + if (mesh.GetNP() > 1000) + { + plotchar = '+'; + modplot = 10; + } + if (mesh.GetNP() > 10000) + { + plotchar = 'o'; + modplot = 100; + } + int cnt = 0; + + + ARRAY<SurfaceElementIndex> locelements(0); + ARRAY<int> locrots(0); + + for (PointIndex pi = PointIndex::BASE; + pi < mesh.GetNP()+PointIndex::BASE; pi++) + { + if (mesh[pi].Type() != SURFACEPOINT) + continue; + + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + int surfi(-1); + + if(elementsonpoint[pi].Size() == 0) + continue; + + Element2d & hel = mesh[elementsonpoint[pi][0]]; + + if(hel.GetIndex() != faceindex) + continue; + + cnt++; + if (cnt % modplot == 0 && writestatus) + { + printeddot = 1; + PrintDot (plotchar); + } + + + int hpi = 0; + for (j = 1; j <= hel.GetNP(); j++) + if (hel.PNum(j) == pi) + { + hpi = j; + break; + } + PointGeomInfo gi1 = hel.GeomInfoPi(hpi); + + locelements.SetSize(0); + locrots.SetSize (0); + + for (j = 0; j < elementsonpoint[pi].Size(); j++) + { + sei = elementsonpoint[pi][j]; + const Element2d & bel = mesh[sei]; + surfi = mesh.GetFaceDescriptor(bel.GetIndex()).SurfNr(); + + locelements.Append (sei); + + for (k = 1; k <= bel.GetNP(); k++) + if (bel.PNum(k) == pi) + { + locrots.Append (k); + break; + } + } + + + double lh = mesh.GetH(mesh.Point(pi)); + par.typx = lh; + + pf.SetPointIndex(pi); + + x = 0; + bool pok = (pf.Func (x) < 1e10); + + if (pok) + { + BFGS (x, pf, par); + + origp = mesh[pi]; + loci = 1; + fact = 1; + moveisok = false; + + + //optimizer loop (if whole distance is not possible, move only a bit!!!!) + while (loci <= 5 && !moveisok) + { + loci ++; + mesh[pi](0) = origp(0) + x.Get(1)*fact; + mesh[pi](1) = origp(1) + x.Get(2)*fact; + mesh[pi](2) = origp(2) + x.Get(3)*fact; + fact = fact/2.; + + + //cout << "origp " << origp << " newp " << mesh[pi]; + + ngi = gi1; + moveisok = (ProjectPointGI (surfi, mesh[pi], ngi) != 0); + + //cout << " projected " << mesh[pi] << endl; + + // point lies on same chart in stlsurface + + if (moveisok) + { + for (j = 0; j < locelements.Size(); j++) + mesh[locelements[j]].GeomInfoPi(locrots[j]) = ngi; + + //cout << "moved " << origp << " to " << mesh[pi] << endl; + } + else + { + mesh[pi] = origp; + } + + } + } + else + { + cout << "el not ok (point " << pi << ": " << mesh[pi] << ")" << endl; + } + } + + if (printeddot) + PrintDot ('\n'); + + CheckMeshApproximation (mesh); + mesh.SetNextTimeStamp(); + } + + +} diff --git a/contrib/Netgen/libsrc/meshing/smoothing2.cpp b/contrib/Netgen/libsrc/meshing/smoothing2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e43352828bd31f843634e22b9545552a47460ade --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/smoothing2.cpp @@ -0,0 +1,985 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#include <opti.hpp> + +namespace netgen +{ + + static const MeshOptimize2d * meshthis; + + +#ifdef OLD + + void CalcTriangleBadness (double x2, double x3, double y3, double metricweight, + double h, double & badness, double & g1x, double & g1y) + { + // badness = sqrt(3.0) /36 * circumference^2 / area - 1 + // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); + + Vec2d v23; + double l12, l13, l23, cir, area; + static const double c = sqrt(3.0) / 36; + double c1, c2, c3, c4; + + v23.X() = x3 - x2; + v23.Y() = y3; + + l12 = x2; + l13 = sqrt (x3*x3 + y3*y3); + l23 = v23.Length(); + + cir = l12 + l13 + l23; + area = 0.5 * x2 * y3; + + if (area <= 1e-24 * cir * cir) + { + g1x = 0; + g1y = 0; + badness = 1e10; + return; + } + + badness = c * cir * cir / area - 1; + + c1 = 2 * c * cir / area; + c2 = 0.5 * c * cir * cir / (area * area); + + g1x = c1 * ( - 1 - x3 / l13) - c2 * (-v23.Y()); + g1y = c1 * ( - y3 / l13) - c2 * ( v23.X()); + + // metricweight = 0.1; + if (metricweight > 0) + { + // area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); + // add: metricweight * (area / h^2 + h^2 / area - 2) + + const double area = x2 * y3; + const double dareax1 = -y3; + const double dareay1 = x3 - x2; + + const double areahh = area / (h * h); + const double fac = metricweight * (areahh - 1 / areahh) / area; + + badness += metricweight * (areahh + 1 / areahh - 2); + g1x += fac * dareax1; + g1y += fac * dareay1; + + /* + // add: metricweight * (l1^2/h^2 + l2^2/h^2 + l3^2/h2 + h^2/l1^2 + h^2/l2^2 + h^2/l3^2 - 6) + double h2 = h*h; + double l1 = x2*x2; + double l2 = x3*x3+y3*y3; + double l3 = (x2-x3)*(x2-x3)+y3*y3; + double dl1dx = 2*(-x2); + double dl1dy = 0; + double dl2dx = -2*x3; + double dl2dy = -2*y3; + + badness += (l1/h2 + l2/h2 + l3/h2 +h2/l1 + h2/l2 + h2/l3-6) * metricweight; + + g1x += metricweight * (dl1dx/h2-h2/(l1*l1)*dl1dx + dl2dx/h2-h2/(l2*l2)*dl2dx); + g1y += metricweight * (dl1dy/h2-h2/(l1*l1)*dl1dy + dl2dy/h2-h2/(l2*l2)*dl2dy); + */ + } + } + +#endif + + static const double c_trig = 0.14433756; // sqrt(3.0) / 12 + static const double c_trig4 = 0.57735026; // sqrt(3.0) / 3 + + inline double CalcTriangleBadness (double x2, double x3, double y3, + double metricweight, double h) + { + // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 + // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); + + double cir_2 = (x2*x2 + x3*x3 + y3*y3 - x2*x3); + double area = x2 * y3; + + if (area <= 1e-24 * cir_2) + return 1e10; + + double badness = c_trig4 * cir_2 / area - 1; + + if (metricweight > 0) + { + // add: metricweight * (area / h^2 + h^2 / area - 2) + + double areahh = area / (h * h); + badness += metricweight * (areahh + 1 / areahh - 2); + } + return badness; + } + + + inline void CalcTriangleBadness (double x2, double x3, double y3, double metricweight, + double h, double & badness, double & g1x, double & g1y) + { + // old: badness = sqrt(3.0) /36 * circumference^2 / area - 1 + // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 + // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); + + + double cir_2 = 2* (x2*x2 + x3*x3 + y3*y3 - x2*x3); + double area = 0.5 * x2 * y3; + + if (area <= 1e-24 * cir_2) + { + g1x = 0; + g1y = 0; + badness = 1e10; + return; + } + + badness = c_trig * cir_2 / area - 1; + + double c1 = -2 * c_trig / area; + double c2 = 0.5 * c_trig * cir_2 / (area * area); + g1x = c1 * (x2 + x3) + c2 * y3; + g1y = c1 * (y3) + c2 * (x2-x3); + + if (metricweight > 0) + { + // area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); + // add: metricweight * (area / h^2 + h^2 / area - 2) + + area = x2 * y3; + double dareax1 = -y3; + double dareay1 = x3 - x2; + + double areahh = area / (h * h); + double fac = metricweight * (areahh - 1 / areahh) / area; + + badness += metricweight * (areahh + 1 / areahh - 2); + g1x += fac * dareax1; + g1y += fac * dareay1; + } + } + + + + + + + + + +#ifdef OLD + double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double metricweight, + double h) + { + double badness; + double g1x, g1y; + + Vec3d e1 (p1, p2); + Vec3d e2 (p1, p3); + + double e1l = e1.Length() + 1e-24; + e1 /= e1l; + double e1e2 = (e1 * e2); + e2.Add (-e1e2, e1); + double e2l = e2.Length(); + + CalcTriangleBadness ( e1l, e1e2, e2l, + metricweight, h, badness, g1x, g1y); + return badness; + } +#endif + + + + + double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + double metricweight, + double h) + { + // badness = sqrt(3.0) / 12 * (\sum l_i^2) / area - 1 + // p1 = (0, 0), p2 = (x2, 0), p3 = (x3, y3); + + Vec3d e12(p1,p2); + Vec3d e13(p1,p3); + Vec3d e23(p2,p3); + + double l12_2 = e12.Length2(); + double l13_2 = e13.Length2(); + double l23_2 = e23.Length2(); + + double cir_2 = l12_2 + l13_2 + l23_2; + Vec3d area_v = Cross (e12, e13); + double area = 0.5 * area_v.Length(); + + if (area <= 1e-24 * cir_2) + return 1e10; + + double badness = c_trig * cir_2 / area - 1; + + if (metricweight > 0) + { + // area = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); + // add: metricweight * (area / h^2 + h^2 / area - 2) + + const double areahh = area / (h * h); + badness += metricweight * (areahh + 1 / areahh - 2); + } + + return badness; + } + + + double CalcTriangleBadness (const Point3d & p1, + const Point3d & p2, + const Point3d & p3, + const Vec3d & n, + double metricweight, + double h) + { + Vec3d v1 (p1, p2); + Vec3d v2 (p1, p3); + + Vec3d e1 = v1; + Vec3d e2 = v2; + + e1 -= (e1 * n) * n; + e1 /= (e1.Length() + 1e-24); + e2 = Cross (n, e1); + + return CalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), + metricweight, h); + } + + + + + + static MeshPoint sp1; + static PointGeomInfo gi1; + static Vec<3> normal, t1, t2; + static ARRAY<SurfaceElementIndex> locelements(0); + static ARRAY<int> locrots(0); + static ARRAY<double> lochs(0); + // static int locerr2; + static double locmetricweight = 0; + static double loch; + static int surfi, surfi2; + static int uselocalh; + + + class Opti2SurfaceMinFunction : public MinFunction + { + const Mesh & mesh; + public: + Opti2SurfaceMinFunction (const Mesh & amesh) + : mesh(amesh) + { } ; + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; + virtual double Func (const Vector & x) const; + }; + + double Opti2SurfaceMinFunction :: + Func (const Vector & x) const + { + Vector g(x.Size()); + return FuncGrad (x, g); + } + + + double Opti2SurfaceMinFunction :: + FuncGrad (const Vector & x, Vector & grad) const + { + Vec<3> n, vgrad; + Point<3> pp1; + double g1x, g1y; + double badness, hbadness; + + vgrad = 0; + badness = 0; + + meshthis -> GetNormalVector (surfi, sp1, gi1, n); + pp1 = sp1 + x(0) * t1 + x(1) * t2; + + // meshthis -> ProjectPoint (surfi, pp1); + // meshthis -> GetNormalVector (surfi, pp1, n); + + for (int j = 0; j < locelements.Size(); j++) + { + int roti = locrots[j]; + const Element2d & bel = mesh[locelements[j]]; + + Vec<3> e1 = mesh[bel.PNumMod(roti + 1)] - pp1; + Vec<3> e2 = mesh[bel.PNumMod(roti + 2)] - pp1; + + if (uselocalh) loch = lochs[j]; + + double e1l = e1.Length(); + if (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length()) + { + e1 /= e1l; + double e1e2 = e1 * e2; + e2 -= e1e2 * e1; + double e2l = e2.Length(); + + CalcTriangleBadness ( e1l, e1e2, e2l, locmetricweight, loch, + hbadness, g1x, g1y); + + badness += hbadness; + vgrad += g1x * e1 + (g1y/e2l) * e2; + } + else + { + (*testout) << "very very bad badness" << endl; + badness += 1e8; + } + } + + vgrad -= (vgrad * n) * n; + + grad(0) = vgrad * t1; + grad(1) = vgrad * t2; + return badness; + } + + + + + double Opti2SurfaceMinFunction :: + FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + Vec<3> n, vgrad; + Point<3> pp1; + double g1x, g1y; + double badness, hbadness; + + vgrad = 0; + badness = 0; + + meshthis -> GetNormalVector (surfi, sp1, gi1, n); + + pp1 = sp1 + x(0) * t1 + x(1) * t2; + + for (int j = 0; j < locelements.Size(); j++) + { + int roti = locrots[j]; + + const Element2d & bel = mesh[locelements[j]]; + + Vec<3> e1 = mesh[bel.PNumMod(roti + 1)] - pp1; + Vec<3> e2 = mesh[bel.PNumMod(roti + 2)] - pp1; + + if (uselocalh) loch = lochs[j]; + + double e1l = e1.Length(); + if (Determinant(e1, e2, n) > 1e-8 * e1l * e2.Length()) + { + e1 /= e1l; + double e1e2 = e1 * e2; + e2 -= e1e2 * e1; + double e2l = e2.Length(); + + CalcTriangleBadness ( e1l, e1e2, e2l, locmetricweight, loch, + hbadness, g1x, g1y); + + badness += hbadness; + vgrad += g1x * e1 + (g1y / e2l) * e2; + } + else + { + (*testout) << "very very bad badness" << endl; + badness += 1e8; + } + } + + vgrad -= (vgrad * n) * n; + deriv = dir(0) * (vgrad*t1) + dir(1) * (vgrad*t2); + + return badness; + } + + + + + + + + + + + + + class Opti2EdgeMinFunction : public MinFunction + { + const Mesh & mesh; + public: + Opti2EdgeMinFunction (const Mesh & amesh) + : mesh(amesh) { } ; + + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double Func (const Vector & x) const; + }; + + double Opti2EdgeMinFunction :: Func (const Vector & x) const + { + Vector g(x.Size()); + return FuncGrad (x, g); + } + + double Opti2EdgeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const + { + int j, rot; + Vec<3> n1, n2, v1, v2, e1, e2, vgrad; + Point<3> pp1; + Vec<2> g1; + double badness, hbadness; + + vgrad = 0.0; + badness = 0; + + pp1 = sp1 + x.Get(1) * t1; + meshthis -> ProjectPoint2 (surfi, surfi2, pp1); + + for (j = 0; j < locelements.Size(); j++) + { + rot = locrots[j]; + const Element2d & bel = mesh[locelements[j]]; + + v1 = mesh[bel.PNumMod(rot + 1)] - pp1; + v2 = mesh[bel.PNumMod(rot + 2)] - pp1; + + e1 = v1; + e2 = v2; + e1 /= e1.Length(); + e2 -= (e1 * e2) * e1; + e2 /= e2.Length(); + + if (uselocalh) loch = lochs[j]; + CalcTriangleBadness ( (e1 * v1), (e1 * v2), (e2 * v2), locmetricweight, loch, + hbadness, g1(0), g1(1)); + + badness += hbadness; + vgrad += g1(0) * e1 + g1(1) * e2; + } + + meshthis -> GetNormalVector (surfi, pp1, n1); + meshthis -> GetNormalVector (surfi2, pp1, n2); + + v1 = Cross (n1, n2); + v1.Normalize(); + + grad(0) = (vgrad * v1) * (t1 * v1); + + return badness; + } + + + + + class Opti2SurfaceMinFunctionJacobian : public MinFunction + { + const Mesh & mesh; + public: + Opti2SurfaceMinFunctionJacobian (const Mesh & amesh) + : mesh(amesh) + { } ; + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; + virtual double Func (const Vector & x) const; + }; + + double Opti2SurfaceMinFunctionJacobian :: + Func (const Vector & x) const + { + Vector g(x.Size()); + return FuncGrad (x, g); + } + + + double Opti2SurfaceMinFunctionJacobian :: + FuncGrad (const Vector & x, Vector & grad) const + { + // from 2d: + + int lpi, gpi; + Vec<3> n, vgrad; + Point<3> pp1; + Vec2d g1, vdir; + double badness, hbad, hderiv; + + vgrad = 0; + badness = 0; + + meshthis -> GetNormalVector (surfi, sp1, gi1, n); + + pp1 = sp1 + x(0) * t1 + x(1) * t2; + + // meshthis -> ProjectPoint (surfi, pp1); + // meshthis -> GetNormalVector (surfi, pp1, n); + + static ARRAY<Point2d> pts2d; + pts2d.SetSize(mesh.GetNP()); + + grad = 0; + + for (int j = 1; j <= locelements.Size(); j++) + { + lpi = locrots.Get(j); + const Element2d & bel = + mesh[locelements.Get(j)]; + + gpi = bel.PNum(lpi); + + for (int k = 1; k <= bel.GetNP(); k++) + { + PointIndex pi = bel.PNum(k); + pts2d.Elem(pi) = Point2d (t1 * (mesh.Point(pi) - sp1), + t2 * (mesh.Point(pi) - sp1)); + } + pts2d.Elem(gpi) = Point2d (x.Get(1), x.Get(2)); + + + for (int k = 1; k <= 2; k++) + { + if (k == 1) + vdir = Vec2d (1, 0); + else + vdir = Vec2d (0, 1); + + hbad = bel. + CalcJacobianBadnessDirDeriv (pts2d, lpi, vdir, hderiv); + + grad.Elem(k) += hderiv; + if (k == 1) + badness += hbad; + } + } + + + /* + vgrad.Add (-(vgrad * n), n); + + grad.Elem(1) = vgrad * t1; + grad.Elem(2) = vgrad * t2; + */ + return badness; + } + + + + + double Opti2SurfaceMinFunctionJacobian :: + FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + // from 2d: + + int j, k, lpi, gpi; + Vec<3> n, vgrad; + Point<3> pp1; + Vec2d g1, vdir; + double badness, hbad, hderiv; + + vgrad = 0; + badness = 0; + + meshthis -> GetNormalVector (surfi, sp1, gi1, n); + + // pp1 = sp1; + // pp1.Add2 (x.Get(1), t1, x.Get(2), t2); + pp1 = sp1 + x.Get(1) * t1 + x.Get(2) * t2; + + static ARRAY<Point2d> pts2d; + pts2d.SetSize(mesh.GetNP()); + + deriv = 0; + + for (j = 1; j <= locelements.Size(); j++) + { + lpi = locrots.Get(j); + const Element2d & bel = + mesh[locelements.Get(j)]; + + gpi = bel.PNum(lpi); + + for (k = 1; k <= bel.GetNP(); k++) + { + PointIndex pi = bel.PNum(k); + pts2d.Elem(pi) = Point2d (t1 * (mesh.Point(pi) - sp1), + t2 * (mesh.Point(pi) - sp1)); + } + pts2d.Elem(gpi) = Point2d (x.Get(1), x.Get(2)); + + + vdir = Vec2d (dir(0), dir(1)); + + hbad = bel. + CalcJacobianBadnessDirDeriv (pts2d, lpi, vdir, hderiv); + + deriv += hderiv; + badness += hbad; + } + + + return badness; + } + + + + + + + + MeshOptimize2d dummy; + + MeshOptimize2d :: MeshOptimize2d () + { + SetFaceIndex (0); + SetImproveEdges (0); + SetMetricWeight (0); + SetWriteStatus (1); + } + + + void MeshOptimize2d :: SelectSurfaceOfPoint (const Point<3> & p, + const PointGeomInfo & gi) + { + ; + } + + void MeshOptimize2d :: ImproveMesh (Mesh & mesh) + { + if (!faceindex) + { + PrintMessage (3, "Smoothing"); + + for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) + { + ImproveMesh (mesh); + if (multithread.terminate) + throw NgException ("Meshing stopped"); + } + faceindex = 0; + return; + } + + + + static int timer = NgProfiler::CreateTimer ("MeshSmoothing 2D"); + NgProfiler::RegionTimer reg (timer); + + + CheckMeshApproximation (mesh); + + SurfaceElementIndex sei; + + ARRAY<SurfaceElementIndex> seia; + mesh.GetSurfaceElementsOfFace (faceindex, seia); + + bool mixed = 0; + for (int i = 0; i < seia.Size(); i++) + if (mesh[seia[i]].GetNP() != 3) + { + mixed = 1; + break; + } + + int loci; + double fact; + int moveisok; + + PointGeomInfo ngi; + Point3d origp; + + Vec3d n1, n2; + Vector x(2), xedge(1); + + ARRAY<MeshPoint, PointIndex::BASE> savepoints(mesh.GetNP()); + uselocalh = mparam.uselocalh; + + ARRAY<int, PointIndex::BASE> nelementsonpoint(mesh.GetNP()); + + nelementsonpoint = 0; + for (int i = 0; i < seia.Size(); i++) + { + const Element2d & el = mesh[seia[i]]; + for (int j = 0; j < el.GetNP(); j++) + nelementsonpoint[el[j]]++; + } + + TABLE<SurfaceElementIndex,PointIndex::BASE> elementsonpoint(nelementsonpoint); + for (int i = 0; i < seia.Size(); i++) + { + const Element2d & el = mesh[seia[i]]; + for (int j = 0; j < el.GetNP(); j++) + elementsonpoint.Add (el[j], seia[i]); + } + + loch = mparam.maxh; + locmetricweight = metricweight; + meshthis = this; + + Opti2SurfaceMinFunction surfminf(mesh); + Opti2EdgeMinFunction edgeminf(mesh); + Opti2SurfaceMinFunctionJacobian surfminfj(mesh); + + OptiParameters par; + par.maxit_linsearch = 8; + par.maxit_bfgs = 5; + + /* + int i, j, k; + + if (improveedges) + for (i = 1; i <= mesh.GetNP(); i++) + if (mesh.PointType(i) == EDGEPOINT) + { + continue; + PrintDot (); + sp1 = mesh.Point(i); + + locelements.SetSize(0); + locrots.SetSize (0); + lochs.SetSize (0); + surfi = surfi2 = surfi3 = 0; + + for (j = 0; j < elementsonpoint[i].Size(); j++) + { + sei = elementsonpoint[i][j]; + const Element2d * bel = &mesh[sei]; + + if (!surfi) + surfi = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr(); + else if (surfi != mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr()) + { + if (surfi2 != 0 && surfi2 != + mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr()) + surfi3 = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr(); + else + surfi2 = mesh.GetFaceDescriptor(bel->GetIndex()).SurfNr(); + } + + locelements.Append (sei); + + if (bel->PNum(1) == i) + locrots.Append (1); + else if (bel->PNum(2) == i) + locrots.Append (2); + else + locrots.Append (3); + + if (uselocalh) + { + Point3d pmid = Center (mesh.Point(bel->PNum(1)), + mesh.Point(bel->PNum(2)), + mesh.Point(bel->PNum(3))); + lochs.Append (mesh.GetH(pmid)); + } + } + + if (surfi2 && !surfi3) + { + GetNormalVector (surfi, sp1, n1); + GetNormalVector (surfi2, sp1, n2); + t1 = Cross (n1, n2); + + xedge = 0; + BFGS (xedge, edgeminf, par, 1e-6); + + mesh.Point(i).X() += xedge.Get(1) * t1.X(); + mesh.Point(i).Y() += xedge.Get(1) * t1.Y(); + mesh.Point(i).Z() += xedge.Get(1) * t1.Z(); + ProjectPoint2 (surfi, surfi2, mesh.Point(i)); + } + } + */ + + + bool printeddot = 0; + char plotchar = '.'; + int modplot = 1; + if (mesh.GetNP() > 1000) + { + plotchar = '+'; + modplot = 10; + } + if (mesh.GetNP() > 10000) + { + plotchar = 'o'; + modplot = 100; + } + int cnt = 0; + + for (PointIndex pi = PointIndex::BASE; pi < mesh.GetNP()+PointIndex::BASE; pi++) + if (mesh[pi].Type() == SURFACEPOINT) + { + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + cnt++; + if (cnt % modplot == 0 && writestatus) + { + printeddot = 1; + PrintDot (plotchar); + } + + if (elementsonpoint[pi].Size() == 0) + continue; + + sp1 = mesh[pi]; + + Element2d & hel = mesh[elementsonpoint[pi][0]]; + + int hpi = 0; + for (int j = 1; j <= hel.GetNP(); j++) + if (hel.PNum(j) == pi) + { + hpi = j; + break; + } + + gi1 = hel.GeomInfoPi(hpi); + SelectSurfaceOfPoint (sp1, gi1); + + locelements.SetSize(0); + locrots.SetSize (0); + lochs.SetSize (0); + + for (int j = 0; j < elementsonpoint[pi].Size(); j++) + { + sei = elementsonpoint[pi][j]; + const Element2d & bel = mesh[sei]; + surfi = mesh.GetFaceDescriptor(bel.GetIndex()).SurfNr(); + + locelements.Append (sei); + + for (int k = 1; k <= bel.GetNP(); k++) + if (bel.PNum(k) == pi) + { + locrots.Append (k); + break; + } + + if (uselocalh) + { + Point3d pmid = Center (mesh[bel[0]], mesh[bel[1]], mesh[bel[2]]); + lochs.Append (mesh.GetH(pmid)); + } + } + + GetNormalVector (surfi, sp1, gi1, normal); + t1 = normal.GetNormal (); + t2 = Cross (normal, t1); + + // save points, and project to tangential plane + for (int j = 0; j < locelements.Size(); j++) + { + const Element2d & el = mesh[locelements[j]]; + for (int k = 0; k < el.GetNP(); k++) + savepoints[el[k]] = mesh[el[k]]; + } + + for (int j = 0; j < locelements.Size(); j++) + { + const Element2d & el = mesh[locelements[j]]; + for (int k = 0; k < el.GetNP(); k++) + { + PointIndex hhpi = el[k]; + double lam = normal * (mesh[hhpi] - sp1); + mesh[hhpi] -= lam * normal; + } + } + + x = 0; + par.typx = lochs[0]; + + if (mixed) + { + // (*testout) << "vorher : " << surfminfj.Func (x) << endl; + BFGS (x, surfminfj, par, 1e-6); + // (*testout) << "nachher: " << surfminfj.Func (x) << endl; + // (*testout) << "x = " << x << endl; + } + else + { + // (*testout) << "vorher : " << surfminf.Func (x) << endl; + BFGS (x, surfminf, par, 1e-6); + // (*testout) << "nachher: " << surfminf.Func (x) << endl; + // (*testout) << "x = " << x << endl; + } + + + origp = mesh[pi]; + loci = 1; + fact = 1; + moveisok = 0; + + // restore other points + for (int j = 0; j < locelements.Size(); j++) + { + const Element2d & el = mesh[locelements[j]]; + for (int k = 0; k < el.GetNP(); k++) + { + PointIndex hhpi = el[k]; + if (hhpi != pi) mesh[hhpi] = savepoints[hhpi]; + } + } + + + //optimizer loop (if whole distance is not possible, move only a bit!!!!) + while (loci <= 5 && !moveisok) + { + loci ++; + /* + mesh[pi].X() = origp.X() + (x.Get(1) * t1.X() + x.Get(2) * t2.X())*fact; + mesh[pi].Y() = origp.Y() + (x.Get(1) * t1.Y() + x.Get(2) * t2.Y())*fact; + mesh[pi].Z() = origp.Z() + (x.Get(1) * t1.Z() + x.Get(2) * t2.Z())*fact; + */ + Vec<3> hv = x(0) * t1 + x(1) * t2; + Point3d hnp = origp + Vec3d (hv); + mesh[pi](0) = hnp.X(); + mesh[pi](1) = hnp.Y(); + mesh[pi](2) = hnp.Z(); + + fact = fact/2.; + + // ProjectPoint (surfi, mesh[pi]); + // moveisok = CalcPointGeomInfo(surfi, ngi, mesh[pi]); + + ngi = gi1; + moveisok = ProjectPointGI (surfi, mesh[pi], ngi); + // point lies on same chart in stlsurface + + if (moveisok) + { + for (int j = 0; j < locelements.Size(); j++) + mesh[locelements[j]].GeomInfoPi(locrots[j]) = ngi; + } + else + { + mesh[pi] = Point<3> (origp); + } + + } + } + + if (printeddot) + PrintDot ('\n'); + + CheckMeshApproximation (mesh); + mesh.SetNextTimeStamp(); + } + + void MeshOptimize2d :: GetNormalVector(INDEX /* surfind */, const Point<3> & p, Vec<3> & nv) const + { + nv = Vec<3> (0, 0, 1); + } + + void MeshOptimize2d :: GetNormalVector(INDEX surfind, const Point<3> & p, PointGeomInfo & gi, Vec<3> & n) const + { + GetNormalVector (surfind, p, n); + } +} diff --git a/contrib/Netgen/libsrc/meshing/smoothing3.cpp b/contrib/Netgen/libsrc/meshing/smoothing3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55b3ad9ef4254afd2469758e1e9ac6226d2d72ff --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/smoothing3.cpp @@ -0,0 +1,1878 @@ +#include <mystdlib.h> + +#include "meshing.hpp" +#ifdef SOLIDGEOM +#include <csg.hpp> +#endif +#include <opti.hpp> + + +namespace netgen +{ + + + double MinFunctionSum :: Func (const Vector & x) const + { + double retval = 0; + for(int i=0; i<functions.Size(); i++) + retval += functions[i]->Func(x); + + return retval; + } + + void MinFunctionSum :: Grad (const Vector & x, Vector & g) const + { + g = 0.; + static Vector gi(3); + for(int i=0; i<functions.Size(); i++) + { + functions[i]->Grad(x,gi); + for(int j=0; j<g.Size(); j++) + g[j] += gi[j]; + } + } + + + double MinFunctionSum :: FuncGrad (const Vector & x, Vector & g) const + { + double retval = 0; + g = 0.; + static Vector gi(3); + for(int i=0; i<functions.Size(); i++) + { + retval += functions[i]->FuncGrad(x,gi); + for(int j=0; j<g.Size(); j++) + g[j] += gi[j]; + } + return retval; + } + + double MinFunctionSum :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + double retval = 0; + deriv = 0.; + double derivi; + for(int i=0; i<functions.Size(); i++) + { + retval += functions[i]->FuncDeriv(x,dir,derivi); + deriv += derivi; + } + return retval; + } + + double MinFunctionSum :: GradStopping (const Vector & x) const + { + double minfs(0), mini; + for(int i=0; i<functions.Size(); i++) + { + mini = functions[i]->GradStopping(x); + if(i==0 || mini < minfs) + minfs = mini; + } + return minfs; + } + + + void MinFunctionSum :: AddFunction(MinFunction & fun) + { + functions.Append(&fun); + } + + const MinFunction & MinFunctionSum :: Function(int i) const + { + return *functions[i]; + } + MinFunction & MinFunctionSum :: Function(int i) + { + return *functions[i]; + } + + + PointFunction1 :: PointFunction1 (Mesh::T_POINTS & apoints, + const ARRAY<INDEX_3> & afaces, + double ah) + : points(apoints), faces(afaces) + { + h = ah; + } + + + double PointFunction1 :: Func (const Vector & vp) const + { + double badness = 0; + Point<3> pp(vp(0), vp(1), vp(2)); + + for (int j = 0; j < faces.Size(); j++) + { + const INDEX_3 & el = faces[j]; + + double bad = CalcTetBadness (points[el.I1()], + points[el.I3()], + points[el.I2()], + pp, 0); + badness += bad; + } + + return badness; + } + + + double PointFunction1 :: + FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + static Vector hx(3); + static double eps = 1e-6; + + double dirlen = dir.L2Norm(); + if (dirlen < 1e-14) + { + deriv = 0; + return Func(x); + } + + hx.Set(1, x); + hx.Add(eps * h / dirlen, dir); + double fr = Func (hx); + hx.Set(1, x); + hx.Add(-eps * h / dirlen, dir); + double fl = Func (hx); + + deriv = (fr - fl) / (2 * eps * h) * dirlen; + + return Func(x); + } + + + double PointFunction1 :: FuncGrad (const Vector & x, Vector & g) const + { + static Vector hx(3); + static double eps = 1e-6; + + hx = x; + for (int i = 1; i <= 3; i++) + { + hx.Elem(i) = x.Get(i) + eps * h; + double fr = Func (hx); + hx.Elem(i) = x.Get(i) - eps * h; + double fl = Func (hx); + hx.Elem(i) = x.Get(i); + + g.Elem(i) = (fr - fl) / (2 * eps * h); + } + + return Func(x); + } + + double PointFunction1 :: GradStopping (const Vector & x) const + { + double f = Func(x); + return 1e-8 * f * f; + } + + + + + /* Cheap Functional depending of inner point inside triangular surface */ + + // is it used ???? + class CheapPointFunction1 : public MinFunction + { + Mesh::T_POINTS & points; + const ARRAY<INDEX_3> & faces; + DenseMatrix m; + double h; + public: + CheapPointFunction1 (Mesh::T_POINTS & apoints, + const ARRAY<INDEX_3> & afaces, + double ah); + + virtual double Func (const Vector & x) const; + virtual double FuncGrad (const Vector & x, Vector & g) const; + }; + + CheapPointFunction1 :: CheapPointFunction1 (Mesh::T_POINTS & apoints, + const ARRAY<INDEX_3> & afaces, + double ah) + : points(apoints), faces(afaces) + { + h = ah; + + + int nf = faces.Size(); + + m.SetSize (nf, 4); + + for (int i = 1; i <= nf; i++) + { + const Point3d & p1 = points[faces.Get(i).I1()]; + const Point3d & p2 = points[faces.Get(i).I2()]; + const Point3d & p3 = points[faces.Get(i).I3()]; + Vec3d v1 (p1, p2); + Vec3d v2 (p1, p3); + Vec3d n; + Cross (v1, v2, n); + n /= n.Length(); + + m.Elem(i, 1) = n.X(); + m.Elem(i, 2) = n.Y(); + m.Elem(i, 3) = n.Z(); + m.Elem(i, 4) = - (n.X() * p1.X() + n.Y() * p1.Y() + n.Z() * p1.Z()); + } + } + + double CheapPointFunction1 :: Func (const Vector & vp) const + { + + /* + int j; + double badness = 0; + Point3d pp(vp.Get(1), vp.Get(2), vp.Get(3)); + + for (j = 1; j <= faces.Size(); j++) + { + const INDEX_3 & el = faces.Get(j); + + double bad = CalcTetBadness (points.Get(el.I1()), + points.Get(el.I3()), + points.Get(el.I2()), + pp, 0); + badness += bad; + } + */ + + int i; + double badness = 0; + static Vector hv(4); + static Vector res; + res.SetSize (m.Height()); + + for (i = 1;i <= 3; i++) + hv.Elem(i) = vp.Get(i); + hv.Elem(4) = 1; + m.Mult (hv, res); + + for (i = 1; i <= res.Size(); i++) + { + if (res.Get(i) < 1e-10) + badness += 1e24; + else + badness += 1 / res.Get(i); + } + + return badness; + } + + + double CheapPointFunction1 :: FuncGrad (const Vector & x, Vector & g) const + { + static Vector hx(3); + static double eps = 1e-6; + + hx = x; + for (int i = 1; i <= 3; i++) + { + hx.Elem(i) = x.Get(i) + eps * h; + double fr = Func (hx); + hx.Elem(i) = x.Get(i) - eps * h; + double fl = Func (hx); + hx.Elem(i) = x.Get(i); + + g.Elem(i) = (fr - fl) / (2 * eps * h); + } + + return Func(x); + } + + + + + + + + + + + + + + + /* ************* PointFunction **************************** */ + + + class PointFunction + { + public: + Mesh::T_POINTS & points; + const Mesh::T_VOLELEMENTS & elements; + TABLE<INDEX,PointIndex::BASE> elementsonpoint; + PointIndex actpind; + double h; + + public: + PointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements); + + virtual void SetPointIndex (PointIndex aactpind); + void SetLocalH (double ah) { h = ah; } + double GetLocalH () const { return h; } + virtual double PointFunctionValue (const Point<3> & pp) const; + virtual double PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const; + virtual double PointFunctionValueDeriv (const Point<3> & pp, const Vec<3> & dir, double & deriv) const; + + int MovePointToInner (); + }; + + + PointFunction :: PointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements) + : points(apoints), elements(aelements), elementsonpoint(apoints.Size()) + { + INDEX i; + int j; + + for (i = 1; i <= elements.Size(); i++) + { + if (elements.Get(i).NP() == 4) + for (j = 1; j <= elements.Get(i).NP(); j++) + elementsonpoint.Add (elements.Get(i).PNum(j), i); + } + } + + void PointFunction :: SetPointIndex (PointIndex aactpind) + { + actpind = aactpind; + } + + double PointFunction :: PointFunctionValue (const Point<3> & pp) const + { + int j; + INDEX eli; + const Element * el; + double badness; + // ARRAY<const Point3d*> p(4); + Point<3> hp; + + badness = 0; + + hp = points[actpind]; + points[actpind] = Point<3> (pp); + + for (j = 0; j < elementsonpoint[actpind].Size(); j++) + { + eli = elementsonpoint[actpind][j]; + el = &elements.Get(eli); + badness += CalcTetBadness (points[el->PNum(1)], + points[el->PNum(2)], + points[el->PNum(3)], + points[el->PNum(4)], -1); + } + + points[actpind] = Point<3> (hp); + return badness; + } + + + double PointFunction :: PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const + { + double f;//, delta = h * 1e-6; + // Point<3> hpp; + + f = PointFunctionValue (pp); + + /* + hpp = pp; + hpp.X() = pp.X() + delta; + fr = PointFunctionValue (hpp); + hpp.X() = pp.X() - delta; + fl = PointFunctionValue (hpp); + grad.Elem(1) = (fr - fl) / (2 * delta); + + hpp = pp; + hpp.Y() = pp.Y() + delta; + fr = PointFunctionValue (hpp); + hpp.Y() = pp.Y() - delta; + fl = PointFunctionValue (hpp); + grad.Elem(2) = (fr - fl) / (2 * delta); + + hpp = pp; + hpp.Z() = pp.Z() + delta; + fr = PointFunctionValue (hpp); + hpp.Z() = pp.Z() - delta; + fl = PointFunctionValue (hpp); + grad.Elem(3) = (fr - fl) / (2 * delta); + */ + + + // new gradient calculation + // double badness; + Point<3> hp; + Vec<3> vgradi, vgrad(0,0,0); + + // badness = 0; + + hp = points[actpind]; + points[actpind] = Point<3> (pp); + + for (int j = 0; j < elementsonpoint[actpind].Size(); j++) + { + INDEX eli = elementsonpoint[actpind][j]; + const Element & el = elements.Get(eli); + + for (int k = 1; k <= 4; k++) + if (el.PNum(k) == actpind) + { + CalcTetBadnessGrad (points[el.PNum(1)], + points[el.PNum(2)], + points[el.PNum(3)], + points[el.PNum(4)], -1, k, vgradi); + + vgrad += vgradi; + } + } + + points[actpind] = Point<3> (hp); + + grad = vgrad; + return f; + } + + + double PointFunction :: PointFunctionValueDeriv (const Point<3> & pp, const Vec<3> & dir, + double & deriv) const + { + double f; + // Point<3> hpp; + + Vec<3> dirn (dir); + //double ldir = dir.Length(); + + int j, k; + INDEX eli; + // double badness; + Point<3> hp; + Vec<3> vgradi, vgrad(0,0,0); + + // badness = 0; + + hp = points[actpind]; + points[actpind] = pp; + f = 0; + + for (j = 0; j < elementsonpoint[actpind].Size(); j++) + { + eli = elementsonpoint[actpind][j]; + const Element & el = elements.Get(eli); + + for (k = 1; k <= 4; k++) + if (el.PNum(k) == actpind) + { + f += CalcTetBadnessGrad (points[el.PNum(1)], + points[el.PNum(2)], + points[el.PNum(3)], + points[el.PNum(4)], -1, k, vgradi); + + vgrad += vgradi; + } + } + + points[actpind] = Point<3> (hp); + deriv = dir * vgrad; + return f; + } + + int PointFunction :: MovePointToInner () + { + // try point movement + ARRAY<Element2d> faces; + + for (int j = 0; j < elementsonpoint[actpind].Size(); j++) + { + const Element & el = + elements.Get(elementsonpoint[actpind][j]); + + for (int k = 1; k <= 4; k++) + if (el.PNum(k) == actpind) + { + Element2d face; + el.GetFace (k, face); + Swap (face.PNum(2), face.PNum(3)); + faces.Append (face); + } + } + + Point3d hp; + int hi = FindInnerPoint (points, faces, hp); + if (hi) + { + // cout << "inner point found" << endl; + points[actpind] = Point<3> (hp); + } + else + ; + // cout << "no inner point found" << endl; + + /* + Point3d hp2; + int hi2 = FindInnerPoint (points, faces, hp2); + if (hi2) + { + cout << "new: inner point found" << endl; + } + else + cout << "new: no inner point found" << endl; + + (*testout) << "hi(orig) = " << hi << ", hi(new) = " << hi2; + if (hi != hi2) (*testout) << "hi different" << endl; + */ + + return hi; + } + + + + + + + class CheapPointFunction : public PointFunction + { + DenseMatrix m; + public: + CheapPointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements); + virtual void SetPointIndex (PointIndex aactpind); + virtual double PointFunctionValue (const Point<3> & pp) const; + virtual double PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const; + }; + + + CheapPointFunction :: CheapPointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements) + : PointFunction (apoints, aelements) + { + ; + } + + + void CheapPointFunction :: SetPointIndex (PointIndex aactpind) + { + actpind = aactpind; + + int ne = elementsonpoint[actpind].Size(); + int i, j; + int pi1, pi2, pi3; + + m.SetSize (ne, 4); + + for (i = 0; i < ne; i++) + { + pi1 = 0; + pi2 = 0; + pi3 = 0; + + const Element & el = elements.Get (elementsonpoint[actpind][i]); + for (j = 1; j <= 4; j++) + if (el.PNum(j) != actpind) + { + pi3 = pi2; + pi2 = pi1; + pi1 = el.PNum(j); + } + + const Point3d & p1 = points[pi1]; + Vec3d v1 (p1, points[pi2]); + Vec3d v2 (p1, points[pi3]); + Vec3d n; + Cross (v1, v2, n); + n /= n.Length(); + + Vec3d v (p1, points[actpind]); + double c = v * n; + + if (c < 0) + n *= -1; + + // n is inner normal + + m.Elem(i+1, 1) = n.X(); + m.Elem(i+1, 2) = n.Y(); + m.Elem(i+1, 3) = n.Z(); + m.Elem(i+1, 4) = - (n.X() * p1.X() + n.Y() * p1.Y() + n.Z() * p1.Z()); + } + } + + double CheapPointFunction :: PointFunctionValue (const Point<3> & pp) const + { + static Vector p4(4); + static Vector di; + int n = m.Height(); + + p4.Elem(1) = pp(0); + p4.Elem(2) = pp(1); + p4.Elem(3) = pp(2); + p4.Elem(4) = 1; + + di.SetSize (n); + m.Mult (p4, di); + + double sum = 0; + for (int i = 1; i <= n; i++) + { + if (di.Get(i) > 0) + sum += 1 / di.Get(i); + else + return 1e16; + } + return sum; + } + + + + + double CheapPointFunction :: PointFunctionValueGrad (const Point<3> & pp, Vec<3> & grad) const + { + static Vector p4(4); + static Vector di; + + int n = m.Height(); + + p4.Elem(1) = pp(0); + p4.Elem(2) = pp(1); + p4.Elem(3) = pp(2); + p4.Elem(4) = 1; + + di.SetSize (n); + m.Mult (p4, di); + + double sum = 0; + grad = 0; + for (int i = 1; i <= n; i++) + { + if (di.Get(i) > 0) + { + double idi = 1 / di.Get(i); + sum += idi; + grad(0) -= idi * idi * m.Get(i, 1); + grad(1) -= idi * idi * m.Get(i, 2); + grad(2) -= idi * idi * m.Get(i, 3); + } + else + { + return 1e16; + } + } + return sum; + } + + + + + + + + + class Opti3FreeMinFunction : public MinFunction + { + const PointFunction & pf; + Point<3> sp1; + + public: + Opti3FreeMinFunction (const PointFunction & apf); + void SetPoint (const Point<3> & asp1) { sp1 = asp1; } + virtual double Func (const Vector & x) const; + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; + virtual double GradStopping (const Vector & x) const; + virtual void ApproximateHesse (const Vector & x, + DenseMatrix & hesse) const; + }; + + Opti3FreeMinFunction :: Opti3FreeMinFunction (const PointFunction & apf) + : pf(apf) + { + ; + } + + double Opti3FreeMinFunction :: Func (const Vector & x) const + { + Point<3> pp; + for (int j = 0; j < 3; j++) + pp(j) = sp1(j) + x(j); + return pf.PointFunctionValue (pp); + } + + double Opti3FreeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const + { + Vec<3> vgrad; + Point<3> pp; + + for (int j = 0; j < 3; j++) + pp(j) = sp1(j) + x(j); + + double val = pf.PointFunctionValueGrad (pp, vgrad); + + for (int j = 0; j < 3; j++) + grad(j) = vgrad(j); + + return val; + } + + double Opti3FreeMinFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const + { + Point<3> pp; + + for (int j = 0; j < 3; j++) + pp(j) = sp1(j) + x(j); + + Vec<3> vdir; + for (int j = 0; j < 3; j++) + vdir(j) = dir(j); + + return pf.PointFunctionValueDeriv (pp, vdir, deriv); + } + + double Opti3FreeMinFunction :: GradStopping (const Vector & x) const + { + double f = Func(x); + return 1e-3 * f / pf.GetLocalH(); + } + + + void Opti3FreeMinFunction :: ApproximateHesse (const Vector & x, + DenseMatrix & hesse) const + { + int n = x.Size(); + + static Vector hx; + hx.SetSize(n); + + double eps = 1e-8; + double f, f11, f22; //, f12, f21 + + f = Func(x); + + for (int i = 1; i <= n; i++) + { + for (int j = 1; j < i; j++) + { + /* + hx = x; + hx.Elem(i) = x.Get(i) + eps; + hx.Elem(j) = x.Get(j) + eps; + f11 = Func(hx); + hx.Elem(i) = x.Get(i) + eps; + hx.Elem(j) = x.Get(j) - eps; + f12 = Func(hx); + hx.Elem(i) = x.Get(i) - eps; + hx.Elem(j) = x.Get(j) + eps; + f21 = Func(hx); + hx.Elem(i) = x.Get(i) - eps; + hx.Elem(j) = x.Get(j) - eps; + f22 = Func(hx); + */ + hesse.Elem(i, j) = hesse.Elem(j, i) = 0; + // (f11 + f22 - f12 - f21) / (2 * eps * eps); + } + + hx = x; + hx.Elem(i) = x.Get(i) + eps; + f11 = Func(hx); + hx.Elem(i) = x.Get(i) - eps; + f22 = Func(hx); + + hesse.Elem(i, i) = (f11 + f22 - 2 * f) / (eps * eps) + 1e-12; + } + } + + + + + + +#ifdef SOLIDGEOM + class Opti3SurfaceMinFunction : public MinFunction + { + const PointFunction & pf; + Point3d sp1; + const Surface * surf; + Vec3d t1, t2; + + public: + Opti3SurfaceMinFunction (const PointFunction & apf); + + void SetPoint (const Surface * asurf, const Point3d & asp1); + + void CalcNewPoint (const Vector & x, Point3d & np) const; + virtual double Func (const Vector & x) const; + virtual double FuncGrad (const Vector & x, Vector & g) const; + }; + + + Opti3SurfaceMinFunction :: Opti3SurfaceMinFunction (const PointFunction & apf) + : MinFunction(), pf(apf) + { + ; + } + + void Opti3SurfaceMinFunction :: SetPoint (const Surface * asurf, const Point3d & asp1) + { + Vec3d n; + sp1 = asp1; + surf = asurf; + + Vec<3> hn; + surf -> GetNormalVector (sp1, hn); + n = hn; + + n.GetNormal (t1); + t1 /= t1.Length(); + t2 = Cross (n, t1); + } + + + void Opti3SurfaceMinFunction :: CalcNewPoint (const Vector & x, + Point3d & np) const + { + np.X() = sp1.X() + x.Get(1) * t1.X() + x.Get(2) * t2.X(); + np.Y() = sp1.Y() + x.Get(1) * t1.Y() + x.Get(2) * t2.Y(); + np.Z() = sp1.Z() + x.Get(1) * t1.Z() + x.Get(2) * t2.Z(); + + Point<3> hnp = np; + surf -> Project (hnp); + np = hnp; + } + + + double Opti3SurfaceMinFunction :: Func (const Vector & x) const + { + Point3d pp1; + + CalcNewPoint (x, pp1); + return pf.PointFunctionValue (pp1); + } + + + + double Opti3SurfaceMinFunction :: FuncGrad (const Vector & x, Vector & grad) const + { + Vec3d n, vgrad; + Point3d pp1; + double badness; + static Vector freegrad(3); + + CalcNewPoint (x, pp1); + + badness = pf.PointFunctionValueGrad (pp1, freegrad); + vgrad.X() = freegrad.Get(1); + vgrad.Y() = freegrad.Get(2); + vgrad.Z() = freegrad.Get(3); + + Vec<3> hn; + surf -> GetNormalVector (pp1, hn); + n = hn; + + vgrad -= (vgrad * n) * n; + + grad.Elem(1) = vgrad * t1; + grad.Elem(2) = vgrad * t2; + + return badness; + } +#endif + + + + + + + + +#ifdef SOLIDGEOM + class Opti3EdgeMinFunction : public MinFunction + { + const PointFunction & pf; + Point3d sp1; + const Surface *surf1, *surf2; + Vec3d t1; + + public: + Opti3EdgeMinFunction (const PointFunction & apf); + + void SetPoint (const Surface * asurf1, const Surface * asurf2, + const Point3d & asp1); + void CalcNewPoint (const Vector & x, Point3d & np) const; + virtual double FuncGrad (const Vector & x, Vector & g) const; + virtual double Func (const Vector & x) const; + }; + + Opti3EdgeMinFunction :: Opti3EdgeMinFunction (const PointFunction & apf) + : MinFunction(), pf(apf) + { + ; + } + + void Opti3EdgeMinFunction :: SetPoint (const Surface * asurf1, + const Surface * asurf2, + const Point3d & asp1) + { + Vec3d n1, n2; + sp1 = asp1; + surf1 = asurf1; + surf2 = asurf2; + + Vec<3> hn1, hn2; + surf1 -> GetNormalVector (sp1, hn1); + surf2 -> GetNormalVector (sp1, hn2); + n1 = hn1; + n2 = hn2; + t1 = Cross (n1, n2); + } + + void Opti3EdgeMinFunction :: CalcNewPoint (const Vector & x, + Point3d & np) const +{ + np.X() = sp1.X() + x.Get(1) * t1.X(); + np.Y() = sp1.Y() + x.Get(1) * t1.Y(); + np.Z() = sp1.Z() + x.Get(1) * t1.Z(); + Point<3> hnp = np; + ProjectToEdge (surf1, surf2, hnp); + np = hnp; +} + +double Opti3EdgeMinFunction :: Func (const Vector & x) const +{ + Vector g(x.Size()); + return FuncGrad (x, g); +} + + +double Opti3EdgeMinFunction :: FuncGrad (const Vector & x, Vector & grad) const +{ + Vec3d n1, n2, v1, vgrad; + Point3d pp1; + double badness; + static Vector freegrad(3); + + CalcNewPoint (x, pp1); + + + badness = pf.PointFunctionValueGrad (pp1, freegrad); + + vgrad.X() = freegrad.Get(1); + vgrad.Y() = freegrad.Get(2); + vgrad.Z() = freegrad.Get(3); + + Vec<3> hn1, hn2; + surf1 -> GetNormalVector (pp1, hn1); + surf2 -> GetNormalVector (pp1, hn2); + n1 = hn1; + n2 = hn2; + + v1 = Cross (n1, n2); + v1 /= v1.Length(); + + grad.Elem(1) = (vgrad * v1) * (t1 * v1); + return badness; +} +#endif + + + + +double CalcBad (const Mesh::T_POINTS & points, const Element & elem, + double h) +{ + if (elem.GetType() == TET) + return CalcTetBadness (points[elem.PNum(1)], + points[elem.PNum(2)], + points[elem.PNum(3)], + points[elem.PNum(4)], h); + return 0; +} + + +extern double teterrpow; +double CalcTotalBad (const Mesh::T_POINTS & points, + const Mesh::T_VOLELEMENTS & elements) +{ + int i; + double sum = 0; + double elbad; + + tets_in_qualclass.SetSize(20); + for (i = 1; i <= 20; i++) + tets_in_qualclass.Elem(i) = 0; + + + for (i = 1; i <= elements.Size(); i++) + { + elbad = pow (max2(CalcBad (points, elements.Get(i), 0),1e-10), + 1/teterrpow); + + int qualclass = int (20 / elbad + 1); + if (qualclass < 1) qualclass = 1; + if (qualclass > 20) qualclass = 20; + tets_in_qualclass.Elem(qualclass)++; + + sum += elbad; + } + return sum; +} + +int WrongOrientation (const Mesh::T_POINTS & points, const Element & el) +{ + const Point3d & p1 = points[el.PNum(1)]; + const Point3d & p2 = points[el.PNum(2)]; + const Point3d & p3 = points[el.PNum(3)]; + const Point3d & p4 = points[el.PNum(4)]; + + Vec3d v1(p1, p2); + Vec3d v2(p1, p3); + Vec3d v3(p1, p4); + Vec3d n; + + Cross (v1, v2, n); + double vol = n * v3; + + return (vol > 0); +} + + + + + + + + + + + +/* ************* JacobianPointFunction **************************** */ + + + + +// class JacobianPointFunction : public MinFunction +// { +// public: +// Mesh::T_POINTS & points; +// const Mesh::T_VOLELEMENTS & elements; +// TABLE<INDEX> elementsonpoint; +// PointIndex actpind; + +// public: +// JacobianPointFunction (Mesh::T_POINTS & apoints, +// const Mesh::T_VOLELEMENTS & aelements); + +// virtual void SetPointIndex (PointIndex aactpind); +// virtual double Func (const Vector & x) const; +// virtual double FuncGrad (const Vector & x, Vector & g) const; +// virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; +// }; + + +JacobianPointFunction :: +JacobianPointFunction (Mesh::T_POINTS & apoints, + const Mesh::T_VOLELEMENTS & aelements) + : points(apoints), elements(aelements), elementsonpoint(apoints.Size()) +{ + INDEX i; + int j; + + for (i = 1; i <= elements.Size(); i++) + { + for (j = 1; j <= elements.Get(i).NP(); j++) + elementsonpoint.Add1 (elements.Get(i).PNum(j), i); + } + + onplane = false; +} + +void JacobianPointFunction :: SetPointIndex (PointIndex aactpind) +{ + actpind = aactpind; +} + + +double JacobianPointFunction :: Func (const Vector & v) const +{ + int j; + double badness = 0; + + Point<3> hp = points.Elem(actpind); + + points.Elem(actpind) = hp + Vec<3> (v.Get(1), v.Get(2), v.Get(3)); + + if(onplane) + points.Elem(actpind) -= (v.Get(1)*nv(0)+v.Get(2)*nv(1)+v.Get(3)*nv(2)) * nv; + + + for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) + { + int eli = elementsonpoint.Get(actpind, j); + badness += elements.Get(eli).CalcJacobianBadness (points); + } + + points.Elem(actpind) = hp; + + return badness; +} + + + + + +double JacobianPointFunction :: +FuncGrad (const Vector & x, Vector & g) const +{ + int j, k; + int lpi; + double badness = 0;//, hbad; + + Point<3> hp = points.Elem(actpind); + points.Elem(actpind) = hp + Vec<3> (x.Get(1), x.Get(2), x.Get(3)); + + if(onplane) + points.Elem(actpind) -= (x.Get(1)*nv(0)+x.Get(2)*nv(1)+x.Get(3)*nv(2)) * nv; + + Vec<3> hderiv; + //Vec3d vdir; + g.SetSize(3); + g = 0; + + for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) + { + int eli = elementsonpoint.Get(actpind, j); + const Element & el = elements.Get(eli); + + lpi = 0; + for (k = 1; k <= el.GetNP(); k++) + if (el.PNum(k) == actpind) + lpi = k; + if (!lpi) cerr << "loc point not found" << endl; + + badness += elements.Get(eli). + CalcJacobianBadnessGradient (points, lpi, hderiv); + + for(k=0; k<3; k++) + g.Elem(k+1) += hderiv(k); + + /* + for (k = 1; k <= 3; k++) + { + vdir = Vec3d(0,0,0); + vdir.X(k) = 1; + + hbad = elements.Get(eli). + CalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv); + //(*testout) << "hderiv " << k << ": " << hderiv << endl; + g.Elem(k) += hderiv; + if (k == 1) + badness += hbad; + } + */ + } + + if(onplane) + { + double scal = nv(0)*g.Get(1) + nv(1)*g.Get(2) + nv(2)*g.Get(3); + g.Elem(1) -= scal*nv(0); + g.Elem(2) -= scal*nv(1); + g.Elem(3) -= scal*nv(2); + } + + //(*testout) << "g = " << g << endl; + + + points.Elem(actpind) = hp; + + return badness; +} + + +double JacobianPointFunction :: +FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const +{ + int j, k; + int lpi; + double badness = 0; + + Point<3> hp = points.Elem(actpind); + points.Elem(actpind) = Point<3> (hp + Vec3d (x.Get(1), x.Get(2), x.Get(3))); + + if(onplane) + points.Elem(actpind) -= (Vec3d (x.Get(1), x.Get(2), x.Get(3))*nv) * nv; + + double hderiv; + deriv = 0; + Vec<3> vdir(dir.Get(1), dir.Get(2), dir.Get(3)); + + if(onplane) + { + double scal = vdir * nv; + vdir -= scal*nv; + } + + for (j = 1; j <= elementsonpoint.EntrySize(actpind); j++) + { + int eli = elementsonpoint.Get(actpind, j); + const Element & el = elements.Get(eli); + + lpi = 0; + for (k = 1; k <= el.GetNP(); k++) + if (el.PNum(k) == actpind) + lpi = k; + if (!lpi) cerr << "loc point not found" << endl; + + badness += elements.Get(eli). + CalcJacobianBadnessDirDeriv (points, lpi, vdir, hderiv); + deriv += hderiv; + } + + points.Elem(actpind) = hp; + + return badness; + +} + + + + + + + + + + +#ifdef SOLIDGEOMxxxx +void Mesh :: ImproveMesh (const CSGeometry & geometry, OPTIMIZEGOAL goal) +{ + INDEX i, eli; + int j; + int typ = 1; + + if (!&geometry || geometry.GetNSurf() == 0) + { + ImproveMesh (goal); + return; + } + + const char * savetask = multithread.task; + multithread.task = "Smooth Mesh"; + + + TABLE<INDEX> surfelementsonpoint(points.Size()); + Vector x(3), xsurf(2), xedge(1); + int surf, surf1, surf2, surf3; + + int uselocalh = mparam.uselocalh; + + (*testout).precision(8); + (*testout) << "Improve Mesh" << "\n"; + PrintMessage (3, "ImproveMesh"); + // (*mycout) << "Vol = " << CalcVolume (points, volelements) << endl; + + + for (i = 1; i <= surfelements.Size(); i++) + for (j = 1; j <= 3; j++) + surfelementsonpoint.Add1 (surfelements.Get(i).PNum(j), i); + + + PointFunction * pf; + if (typ == 1) + pf = new PointFunction(points, volelements); + else + pf = new CheapPointFunction(points, volelements); + + // pf->SetLocalH (h); + + Opti3FreeMinFunction freeminf(*pf); + Opti3SurfaceMinFunction surfminf(*pf); + Opti3EdgeMinFunction edgeminf(*pf); + + OptiParameters par; + par.maxit_linsearch = 20; + par.maxit_bfgs = 20; + + + + for (i = 1; i <= points.Size(); i++) + { + // if (ptyps.Get(i) == FIXEDPOINT) continue; + if (ptyps.Get(i) != INNERPOINT) continue; + + if (multithread.terminate) + throw NgException ("Meshing stopped"); + /* + if (multithread.terminate) + break; + */ + multithread.percent = 100.0 * i /points.Size(); + + if (points.Size() < 1000) + PrintDot (); + else + if (i % 10 == 0) + PrintDot ('+'); + + // (*testout) << "Now point " << i << "\n"; + // (*testout) << "Old: " << points.Get(i) << "\n"; + + pf->SetPointIndex (i); + + // if (uselocalh) + { + double lh = GetH (points.Get(i)); + pf->SetLocalH (GetH (points.Get(i))); + par.typx = lh / 10; + // (*testout) << "lh(" << points.Get(i) << ") = " << lh << "\n"; + } + + surf1 = surf2 = surf3 = 0; + + for (j = 1; j <= surfelementsonpoint.EntrySize(i); j++) + { + eli = surfelementsonpoint.Get(i, j); + int surfi = surfelements.Get(eli).GetIndex(); + + if (surfi) + { + surf = GetFaceDescriptor(surfi).SurfNr(); + + if (!surf1) + surf1 = surf; + else if (surf1 != surf) + { + if (!surf2) + surf2 = surf; + else if (surf2 != surf) + surf3 = surf; + } + } + else + { + surf1 = surf2 = surf3 = 1; // simulates corner point + } + } + + + if (surf2 && !surf3) + { + // (*testout) << "On Edge" << "\n"; + /* + xedge = 0; + edgeminf.SetPoint (geometry.GetSurface(surf1), + geometry.GetSurface(surf2), + points.Elem(i)); + BFGS (xedge, edgeminf, par); + + edgeminf.CalcNewPoint (xedge, points.Elem(i)); + */ + } + + if (surf1 && !surf2) + { + // (*testout) << "In Surface" << "\n"; + /* + xsurf = 0; + surfminf.SetPoint (geometry.GetSurface(surf1), + points.Get(i)); + BFGS (xsurf, surfminf, par); + + surfminf.CalcNewPoint (xsurf, points.Elem(i)); + */ + } + + if (!surf1) + { + // (*testout) << "In Volume" << "\n"; + x = 0; + freeminf.SetPoint (points.Elem(i)); + // par.typx = + BFGS (x, freeminf, par); + + points.Elem(i).X() += x.Get(1); + points.Elem(i).Y() += x.Get(2); + points.Elem(i).Z() += x.Get(3); + } + + // (*testout) << "New Point: " << points.Elem(i) << "\n" << "\n"; + + } + PrintDot ('\n'); + // (*mycout) << "Vol = " << CalcVolume (points, volelements) << endl; + + multithread.task = savetask; + +} +#endif + + + + +void Mesh :: ImproveMesh (OPTIMIZEGOAL goal) +{ + int typ = 1; + + (*testout) << "Improve Mesh" << "\n"; + PrintMessage (3, "ImproveMesh"); + + int np = GetNP(); + int ne = GetNE(); + + + ARRAY<double,PointIndex::BASE> perrs(np); + perrs = 1.0; + + double bad1 = 0; + double badmax = 0; + + if (goal == OPT_QUALITY) + { + for (int i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + if (el.GetType() != TET) + continue; + + double hbad = CalcBad (points, el, 0); + for (int j = 0; j < 4; j++) + perrs[el[j]] += hbad; + + bad1 += hbad; + } + + for (PointIndex i = PointIndex::BASE; i < np+PointIndex::BASE; i++) + if (perrs[i] > badmax) + badmax = perrs[i]; + badmax = 0; + } + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (points, volelements); + (*testout) << "Total badness = " << bad1 << endl; + PrintMessage (5, "Total badness = ", bad1); + } + + Vector x(3); + + (*testout).precision(8); + + //int uselocalh = mparam.uselocalh; + + + PointFunction * pf; + + if (typ == 1) + pf = new PointFunction(points, volelements); + else + pf = new CheapPointFunction(points, volelements); + + // pf->SetLocalH (h); + + Opti3FreeMinFunction freeminf(*pf); + + OptiParameters par; + par.maxit_linsearch = 20; + par.maxit_bfgs = 20; + + ARRAY<double, PointIndex::BASE> pointh (points.Size()); + + if(lochfunc) + { + for(int i=1; i<=points.Size(); i++) + pointh[i] = GetH(points.Get(i)); + } + else + { + pointh = 0; + for(int i=0; i<GetNE(); i++) + { + const Element & el = VolumeElement(i+1); + double h = pow(el.Volume(points),1./3.); + for(int j=1; j<=el.GetNV(); j++) + if(h > pointh[el.PNum(j)]) + pointh[el.PNum(j)] = h; + } + } + + + const char * savetask = multithread.task; + multithread.task = "Smooth Mesh"; + + for (PointIndex i = PointIndex::BASE; + i < points.Size()+PointIndex::BASE; i++) + if ( (*this)[i].Type() == INNERPOINT && perrs[i] > 0.01 * badmax) + { + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + multithread.percent = 100.0 * (i+1-PointIndex::BASE) / points.Size(); + + if (points.Size() < 1000) + PrintDot (); + else + if ( (i+1-PointIndex::BASE) % 10 == 0) + PrintDot ('+'); + + double lh = pointh[i]; + pf->SetLocalH (lh); + par.typx = lh; + + freeminf.SetPoint (points[i]); + pf->SetPointIndex (i); + + x = 0; + int pok; + pok = freeminf.Func (x) < 1e10; + + if (!pok) + { + pok = pf->MovePointToInner (); + + freeminf.SetPoint (points[i]); + pf->SetPointIndex (i); + } + + if (pok) + { + //*testout << "start BFGS, pok" << endl; + BFGS (x, freeminf, par); + //*testout << "BFGS complete, pok" << endl; + points[i](0) += x.Get(1); + points[i](1) += x.Get(2); + points[i](2) += x.Get(3); + } + } + PrintDot ('\n'); + + + delete pf; + + multithread.task = savetask; + + if (goal == OPT_QUALITY) + { + bad1 = CalcTotalBad (points, volelements); + (*testout) << "Total badness = " << bad1 << endl; + PrintMessage (5, "Total badness = ", bad1); + } +} + + + + +// Improve Condition number of Jacobian, any elements +void Mesh :: ImproveMeshJacobian (OPTIMIZEGOAL goal, const BitArray * usepoint) +{ + int i, j; + + (*testout) << "Improve Mesh Jacobian" << "\n"; + PrintMessage (3, "ImproveMesh Jacobian"); + + int np = GetNP(); + int ne = GetNE(); + + + Vector x(3); + + (*testout).precision(8); + + JacobianPointFunction pf(points, volelements); + + + OptiParameters par; + par.maxit_linsearch = 20; + par.maxit_bfgs = 20; + + BitArray badnodes(np); + badnodes.Clear(); + + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + double bad = el.CalcJacobianBadness (Points()); + if (bad > 1) + for (j = 1; j <= el.GetNP(); j++) + badnodes.Set (el.PNum(j)); + } + + ARRAY<double, PointIndex::BASE> pointh (points.Size()); + + if(lochfunc) + { + for(i = 1; i<=points.Size(); i++) + pointh[i] = GetH(points.Get(i)); + } + else + { + pointh = 0; + for(i=0; i<GetNE(); i++) + { + const Element & el = VolumeElement(i+1); + double h = pow(el.Volume(points),1./3.); + for(j=1; j<=el.GetNV(); j++) + if(h > pointh[el.PNum(j)]) + pointh[el.PNum(j)] = h; + } + } + + + + const char * savetask = multithread.task; + multithread.task = "Smooth Mesh Jacobian"; + + for (i = 1; i <= points.Size(); i++) + { + if ((*this)[PointIndex(i)].Type() != INNERPOINT) + continue; + + if(usepoint && !usepoint->Test(i)) + continue; + + //(*testout) << "improvejac, p = " << i << endl; + + if (goal == OPT_WORSTCASE && !badnodes.Test(i)) + continue; + // (*testout) << "smoot p " << i << endl; + + /* + if (multithread.terminate) + break; + */ + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + multithread.percent = 100.0 * i / points.Size(); + + if (points.Size() < 1000) + PrintDot (); + else + if (i % 10 == 0) + PrintDot ('+'); + + double lh = pointh[i]; + par.typx = lh; + + pf.SetPointIndex (i); + + x = 0; + int pok = (pf.Func (x) < 1e10); + + if (pok) + { + //*testout << "start BFGS, Jacobian" << endl; + BFGS (x, pf, par); + //*testout << "end BFGS, Jacobian" << endl; + points.Elem(i)(0) += x.Get(1); + points.Elem(i)(1) += x.Get(2); + points.Elem(i)(2) += x.Get(3); + } + else + { + cout << "el not ok" << endl; + } + } + PrintDot ('\n'); + + + multithread.task = savetask; +} + + + + +// Improve Condition number of Jacobian, any elements +void Mesh :: ImproveMeshJacobianOnSurface (const BitArray & usepoint, + const ARRAY< Vec<3>* > & nv, + OPTIMIZEGOAL goal, + const ARRAY< ARRAY<int,PointIndex::BASE>* > * idmaps) +{ + int i, j; + + (*testout) << "Improve Mesh Jacobian" << "\n"; + PrintMessage (3, "ImproveMesh Jacobian"); + + int np = GetNP(); + int ne = GetNE(); + + + Vector x(3); + + (*testout).precision(8); + + JacobianPointFunction pf(points, volelements); + + ARRAY< ARRAY<int,PointIndex::BASE>* > locidmaps; + const ARRAY< ARRAY<int,PointIndex::BASE>* > * used_idmaps; + + if(idmaps) + used_idmaps = idmaps; + else + { + used_idmaps = &locidmaps; + + for(i=1; i<=GetIdentifications().GetMaxNr(); i++) + { + if(GetIdentifications().GetType(i) == Identifications::PERIODIC) + { + locidmaps.Append(new ARRAY<int,PointIndex::BASE>); + GetIdentifications().GetMap(i,*locidmaps.Last(),true); + } + } + } + + + bool usesum = (used_idmaps->Size() > 0); + MinFunctionSum pf_sum; + + JacobianPointFunction * pf2ptr = NULL; + if(usesum) + { + pf2ptr = new JacobianPointFunction(points, volelements); + pf_sum.AddFunction(pf); + pf_sum.AddFunction(*pf2ptr); + } + + + OptiParameters par; + par.maxit_linsearch = 20; + par.maxit_bfgs = 20; + + BitArray badnodes(np); + badnodes.Clear(); + + for (i = 1; i <= ne; i++) + { + const Element & el = VolumeElement(i); + double bad = el.CalcJacobianBadness (Points()); + if (bad > 1) + for (j = 1; j <= el.GetNP(); j++) + badnodes.Set (el.PNum(j)); + } + + ARRAY<double, PointIndex::BASE> pointh (points.Size()); + + if(lochfunc) + { + for(i=1; i<=points.Size(); i++) + pointh[i] = GetH(points.Get(i)); + } + else + { + pointh = 0; + for(i=0; i<GetNE(); i++) + { + const Element & el = VolumeElement(i+1); + double h = pow(el.Volume(points),1./3.); + for(j=1; j<=el.GetNV(); j++) + if(h > pointh[el.PNum(j)]) + pointh[el.PNum(j)] = h; + } + } + + + const char * savetask = multithread.task; + multithread.task = "Smooth Mesh Jacobian"; + + for (i = 1; i <= points.Size(); i++) + if ( usepoint.Test(i) ) + { + //(*testout) << "improvejac, p = " << i << endl; + + if (goal == OPT_WORSTCASE && !badnodes.Test(i)) + continue; + // (*testout) << "smoot p " << i << endl; + + /* + if (multithread.terminate) + break; + */ + if (multithread.terminate) + throw NgException ("Meshing stopped"); + + multithread.percent = 100.0 * i / points.Size(); + + if (points.Size() < 1000) + PrintDot (); + else + if (i % 10 == 0) + PrintDot ('+'); + + double lh = pointh[i];//GetH(points.Get(i)); + par.typx = lh; + + pf.SetPointIndex (i); + + int brother = -1; + if(usesum) + { + for(j=0; brother == -1 && j<used_idmaps->Size(); j++) + { + if(i < (*used_idmaps)[j]->Size() + PointIndex::BASE) + { + brother = (*(*used_idmaps)[j])[i]; + if(brother == i || brother == 0) + brother = -1; + } + } + if(brother >= i) + { + pf2ptr->SetPointIndex(brother); + pf2ptr->SetNV(*nv[brother-1]); + } + } + + if(usesum && brother < i) + continue; + + //pf.UnSetNV(); x = 0; + //(*testout) << "before " << pf.Func(x); + + pf.SetNV(*nv[i-1]); + + x = 0; + int pok = (brother == -1) ? (pf.Func (x) < 1e10) : (pf_sum.Func (x) < 1e10); + + if (pok) + { + + if(brother == -1) + BFGS (x, pf, par); + else + BFGS (x, pf_sum, par); + + + for(j=1; j<=3; j++) + points.Elem(i)(j-1) += x.Get(j);// - scal*nv[i-1].X(j); + + if(brother != -1) + for(j=1; j<=3; j++) + points.Elem(brother)(j-1) += x.Get(j);// - scal*nv[brother-1].X(j); + + + } + else + { + cout << "el not ok" << endl; + (*testout) << "el not ok" << endl + << " func " << ((brother == -1) ? pf.Func(x) : pf_sum.Func (x)) << endl; + if(brother != -1) + (*testout) << " func1 " << pf.Func(x) << endl + << " func2 " << pf2ptr->Func(x) << endl; + } + } + + PrintDot ('\n'); + + delete pf2ptr; + for(i=0; i<locidmaps.Size(); i++) + delete locidmaps[i]; + + multithread.task = savetask; +} + + + + +} diff --git a/contrib/Netgen/libsrc/meshing/specials.cpp b/contrib/Netgen/libsrc/meshing/specials.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e224f4a7e98309164209350c6ebe8e347d6bd88c --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/specials.cpp @@ -0,0 +1,193 @@ +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + +// A special function for Hermann Landes, Erlangen + + +void CutOffAndCombine (Mesh & mesh, const Mesh & othermesh) +{ + int i, j; + int nse = othermesh.GetNSE(); + int onp = othermesh.GetNP(); + + int ne = mesh.GetNE(); + + PrintMessage (1, "other mesh has ", + othermesh.GetNP(), " points, ", + othermesh.GetNSE(), " surface elements."); + + ARRAY<Box3d> otherbounds(nse); + Box3d otherbox; + + double maxh = 0; + for (i = 1; i <= nse; i++) + { + const Element2d & sel = othermesh.SurfaceElement(i); + sel.GetBox(othermesh.Points(), otherbounds.Elem(i)); + + double loch = othermesh.GetH (othermesh.Point (sel.PNum(1))); + otherbounds.Elem(i).Increase(loch); + if (loch > maxh) maxh = loch; + } + + otherbox.SetPoint (othermesh.Point(1)); + for (i = 1; i <= othermesh.GetNP(); i++) + otherbox.AddPoint (othermesh.Point(i)); + otherbox.Increase (maxh); + + for (i = 1; i <= ne; i++) + { + Box3d box; + int remove = 0; + + const Element & el = mesh.VolumeElement(i); + el.GetBox(mesh.Points(), box); + + if (i % 10000 == 0) + cout << "+" << flush; + + if (box.Intersect(otherbox)) + { + for (j = 1; j <= nse && !remove; j++) + if (box.Intersect(otherbounds.Get(j))) + remove = 1; + } + + if (remove) + mesh.VolumeElement(i).Delete(); + } + cout << endl; + + BitArray connected(mesh.GetNP()); + connected.Clear(); + for (i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & el = mesh.SurfaceElement(i); + for (j = 1; j <= 3; j++) + connected.Set(el.PNum(j)); + } + + bool changed; + do + { + changed = 0; + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + int has = 0, hasnot = 0; + if (el[0]) + { + for (j = 0; j < 4; j++) + { + if (connected.Test(el[j])) + has = 1; + else + hasnot = 1; + } + if (has && hasnot) + { + changed = 1; + for (j = 0; j < 4; j++) + connected.Set (el[j]); + } + } + } + cout << "." << flush; + } + while (changed); + cout << endl; + + for (i = 1; i <= mesh.GetNE(); i++) + { + const Element & el = mesh.VolumeElement(i); + int hasnot = 0; + if (el[0]) + { + for (j = 0; j < 4; j++) + { + if (!connected.Test(el[j])) + hasnot = 1; + } + if (hasnot) + mesh.VolumeElement(i).Delete(); + } + } + + mesh.Compress(); + + mesh.FindOpenElements(); + BitArray locked(mesh.GetNP()); + locked.Set(); + for (i = 1; i <= mesh.GetNOpenElements(); i++) + for (j = 1; j <= 3; j++) + locked.Clear (mesh.OpenElement(i).PNum(j)); + + for (i = 1; i <= locked.Size(); i++) + if (locked.Test(i)) + { + mesh.AddLockedPoint (i); + } + + + + + ARRAY<int> pmat(onp); + + for (i = 1; i <= onp; i++) + pmat.Elem(i) = mesh.AddPoint (othermesh.Point(i)); + + int fnum = + mesh.AddFaceDescriptor (FaceDescriptor(0,0,1,0)); + + for (i = 1; i <= othermesh.GetNSE(); i++) + { + Element2d tri = othermesh.SurfaceElement(i); + for (j = 1; j <= 3; j++) + tri.PNum(j) = pmat.Get(tri.PNum(j)); + tri.SetIndex(fnum); + mesh.AddSurfaceElement (tri); + } + + for (i = 1; i <= onp; i++) + mesh.AddLockedPoint (pmat.Elem(i)); + + mesh.CalcSurfacesOfNode(); + mesh.CalcLocalH(); +} + + + + +void HelmholtzMesh (Mesh & mesh) +{ + int i; + double ri, ra, rinf; + + cout << "ri = "; + cin >> ri; + cout << "ra = "; + cin >> ra; + cout << "rinf = "; + cin >> rinf; + + double det = ri * ra * rinf - ri * ri * rinf; + double a = (ri - rinf) / det; + double b = (ri*ri - ra * rinf) / det; + for (i = 1; i <= mesh.GetNP(); i++) + { + Point<3> & p = mesh.Point(i); + double rold = sqrt (sqr(p(0)) + sqr(p(1)) + sqr(p(2))); + if (rold < ri) continue; + + double rnew = 1 / (a * rold - b); + double fac = rnew / rold; + p(0) *= fac; + p(1) *= fac; + p(2) *= fac; + } +} +} diff --git a/contrib/Netgen/libsrc/meshing/specials.hpp b/contrib/Netgen/libsrc/meshing/specials.hpp new file mode 100644 index 0000000000000000000000000000000000000000..700ba4596bf705f260ca5d7b355d5bd35c96fe7b --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/specials.hpp @@ -0,0 +1,16 @@ +#ifndef FILE_SPECIALS +#define FILE_SPECIALS + +/* + + Very special implementations .. + + */ + + +/// +extern void CutOffAndCombine (Mesh & mesh, const Mesh & othermesh); + +extern void HelmholtzMesh (Mesh & mesh); + +#endif diff --git a/contrib/Netgen/libsrc/meshing/tetrarls.cpp b/contrib/Netgen/libsrc/meshing/tetrarls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb28648b6a641e8d50527d51dac512f0d9273847 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/tetrarls.cpp @@ -0,0 +1,1466 @@ +namespace netgen +{ +const char * tetrules[] = { +"tolfak 0.5\n",\ +"\n",\ +"rule \"Free Tetrahedron\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0);\n",\ +"(0.5, 0.866, 0);\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.816)\n",\ +" { 0.333 X1, 0.333 X2, 0.333 X3 }\n",\ +" { 0.333 Y1, 0.333 Y2, 0.333 Y3 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(4, 1, 2);\n",\ +"(4, 2, 3);\n",\ +"(4, 3, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1.6 P4, -0.2 P1, -0.2 P2, -0.2 P3 };\n",\ +"{ -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 60\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"flags c;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 } ;\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"(4, 2, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n",\ +"\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.65 P3, 0.35 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 60 with edge(1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"flags c;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.8 };\n",\ +"(0.5, 0.866, 0) { 0.8 };\n",\ +"(0.5, 0.288, -0.816) { 0.8 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"mapedges\n",\ +"(3, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"(4, 2, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 };\n",\ +"{ 0.4 P2, 0.4 P4, 0.4 P3, -0.2 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P4, 0.3334 P3 };\n",\ +"{ 0.3333 P2, 0.3333 P4, 0.3334 P3 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point (1)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.5 P1, 0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, -0.5 P2, 0.5 P3, 0.5 P4 };\n",\ +"{ 0.5 P1, 0.5 P2, -0.5 P3, 0.5 P4 };\n",\ +"{ 0.8 P1, -0.1 P2, -0.1 P3, 0.4 P4 };\n",\ +"{ -0.1 P1, 0.8 P2, -0.1 P3, 0.4 P4 };\n",\ +"{ -0.1 P1, -0.1 P2, 0.8 P3, 0.4 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"{ 0.7 P1, 0.3 P4 };\n",\ +"{ 0.7 P2, 0.3 P4 };\n",\ +"{ 0.7 P3, 0.3 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point with edge(1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"mapedges\n",\ +"(1, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n",\ +"{ -0.05 P1, 0.7 P2, -0.05 P3, 0.4 P4 };\n",\ +"{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"{ 0.65 P2, 0.35 P4 };\n",\ +"{ 0.65 P3, 0.35 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point with 2 edges (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"mapedges\n",\ +"(1, 4);\n",\ +"(2, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n",\ +"{ -0.05 P1, -0.05 P2, 0.7 P3, 0.4 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"{ 0.65 P3, 0.35 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Point with 3 edges (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0.5, 0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"mapedges\n",\ +"(1, 4);\n",\ +"(2, 4);\n",\ +"(3, 4);\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(4, 3, 1);\n",\ +"(4, 2, 3);\n",\ +"(4, 1, 2);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ -0.35 P1, 0.45 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, -0.35 P2, 0.45 P3, 0.45 P4 };\n",\ +"{ 0.45 P1, 0.45 P2, -0.35 P3, 0.45 P4 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P2, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P2, 0.3334 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron Vis a Vis Triangle (1)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 0.866, 0) { 0.5 };\n",\ +"(0, 0, -0.816) { 0.5 };\n",\ +"(1, 0, -0.816) { 0.5 };\n",\ +"(0.5, 0.866, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(4, 6, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 4);\n",\ +"(2, 5, 4);\n",\ +"(2, 3, 6);\n",\ +"(2, 6, 5);\n",\ +"(3, 1, 4);\n",\ +"(3, 4, 6);\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"(4, 2, 3, 6);\n",\ +"(4, 2, 6, 5);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ -0.2 P1, 0.35 P2, 0.35 P3, -0.2 P4, 0.35 P5, 0.35 P6 };\n",\ +"{ 0.35 P1, -0.2 P2, 0.35 P3, 0.35 P4, -0.2 P5, 0.35 P6 };\n",\ +"{ 0.35 P1, 0.35 P2, -0.2 P3, 0.35 P4, 0.35 P5, -0.2 P6 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Octaeder 1\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.95 };\n",\ +"(0.5, 0.866, 0) { 0.95 };\n",\ +"(0.5, -0.288, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"(0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(2, 3, 5);\n",\ +"(3, 1, 6);\n",\ +"(3, 6, 5);\n",\ +"(2, 5, 4);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 4, 1, 2);\n",\ +"(3, 4, 2, 5);\n",\ +"(3, 4, 5, 6);\n",\ +"(3, 4, 6, 1);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 };\n",\ +"( 1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 1 Z4 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Octaeder 2\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.95 };\n",\ +"(0.5, 0.866, 0) { 0.95 };\n",\ +"(0.5, -0.288, -0.816) { 0.5 };\n",\ +"(1, 0.578, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(2, 3, 5);\n",\ +"(3, 1, 6);\n",\ +"(3, 6, 5);\n",\ +"(2, 5, 4);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 4, 1, 2);\n",\ +"(3, 4, 2, 5);\n",\ +"(3, 4, 5, 6);\n",\ +"(3, 4, 6, 1);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 };\n",\ +"\n",\ +"(0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 }\n",\ +" { 0.333 Y2, 0.333 Y4, 0.333 Y5 }\n",\ +" { 0.333 Z2, 0.333 Z4, 0.333 Z5 };\n",\ +"(0.9, 0.481, -0.272) { 0.333 X2, 0.333 X3, 0.333 X5 }\n",\ +" { 0.333 Y2, 0.333 Y3, 0.333 Y5 }\n",\ +" { 0.333 Z2, 0.333 Z3, 0.333 Z5 };\n",\ +"\n",\ +"(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"Octaeder 2a\"\n",\ +"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.95 };\n",\ +"(0.5, 0.866, 0) { 0.95 };\n",\ +"(0.5, -0.288, -0.816) { 0.5 };\n",\ +"(1, 0.578, -0.816) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(3, 2, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0, 0.578, -0.816)\n",\ +" { -1 X2, 1 X3, 1 X4 }\n",\ +" { -1 Y2, 1 Y3, 1 Y4 }\n",\ +" { -1 Z2, 1 Z3, 1 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 2, 4);\n",\ +"(3, 1, 6);\n",\ +"(3, 6, 5);\n",\ +"(2, 5, 4);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 4, 1, 2);\n",\ +"(3, 4, 2, 5);\n",\ +"(3, 4, 5, 6);\n",\ +"(3, 4, 6, 1);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(1, 0.578, -0.816) { 1 X5 } { 1 Y5 } { 1 Z5 };\n",\ +"\n",\ +"(0.9, 0.097, -0.544) { 0.333 X2, 0.333 X4, 0.333 X5 }\n",\ +" { 0.333 Y2, 0.333 Y4, 0.333 Y5 }\n",\ +" { 0.333 Z2, 0.333 Z4, 0.333 Z5 };\n",\ +"\n",\ +"(0.5, -0.097, -0.272) { 0.333 X2, 0.333 X4, 0.333 X1 }\n",\ +" { 0.333 Y2, 0.333 Y4, 0.333 Y1 }\n",\ +" { 0.333 Z2, 0.333 Z4, 0.333 Z1 };\n",\ +"\n",\ +"(-0.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 } { 0.5 Z4, 0.5 Z5 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Pyramid 1\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.288, -0.816) { 1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(1, 0.578, -0.816) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"(2, 3, 5);\n",\ +"(2, 5, 4);\n",\ +"(4, 5, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"(4, 2, 3, 5);\n",\ +"\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.288, -0.816) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(0, 1, -1) { 0.5 X3, 0.5 X4 } { 1 Y3 } { 1 Z4 };\n",\ +"(1.5, 1, -1.5) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 2 times 60\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.3 };\n",\ +"(0.5, 0.866, 0) { 0.3 };\n",\ +"(0.5, 0.288, -0.816) { 0.3 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(2, 4, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"(1, 4, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.4 P1, 0.4 P4, 0.4 P3, -0.2 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 0.3333 P1, 0.3333 P3, 0.3334 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Fill Tetrahedron (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.2 };\n",\ +"(0.5, 0.866, 0) { 0.2 };\n",\ +"(0.5, 0.288, -0.816) { 0.2 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(2, 4, 3) del;\n",\ +"(3, 4, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newfaces\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 120 (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.674, -0.544) { 1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.816)\n",\ +" { -0.5 X1, -0.5 X2, 1 X3, 1 X4 }\n",\ +" { -0.5 Y1, -0.5 Y2, 1 Y3, 1 Y4}\n",\ +" { -0.5 Z1, -0.5 Z2, 1 Z3, 1 Z4};\n",\ +"\n",\ +"newfaces\n",\ +"(1, 5, 3);\n",\ +"(3, 5, 2);\n",\ +"(1, 4, 5);\n",\ +"(2, 5, 4);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 4, 2, 5);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.3 P5, -0.3 P1 };\n",\ +"{ 1.3 P5, -0.3 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P5 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 2 times 120 (1)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.674, -0.544) { 0.8 };\n",\ +"(1.334, 0.77, -0.544) { 0.8 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(3, 2, 5) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.816) { 0.25 X1, -0.5 X2, 0.25 X3, 0.5 X4, 0.5 X5 }\n",\ +" { 0.25 Y1, -0.5 Y2, 0.25 Y3, 0.5 Y4, 0.5 Y5 }\n",\ +" { 0.25 Z1, -0.5 Z2, 0.25 Z3, 0.5 Z4, 0.5 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(6, 3, 1);\n",\ +"(6, 1, 4);\n",\ +"(6, 4, 2);\n",\ +"(6, 2, 5);\n",\ +"(6, 5, 3);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(2, 5, 3, 6);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.4 P6, -0.4 P2 };\n",\ +"{ 1.4 P6, -0.4 P1 };\n",\ +"{ 1.4 P6, -0.4 P3 };\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (4)\"\n",\ +"\n",\ +"quality 4\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.1 };\n",\ +"(0.5, 1, 0) { 0.1 };\n",\ +"(0.5, 0, -1) { 0.1 };\n",\ +"(0.5, 0.3, -0.3) { 0.1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 5, 4) del;\n",\ +"(1, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.1, -0.1)\n",\ +" { 0.333 X1, 0.333 X2, 0.334 X5 }\n",\ +" { 0.333 Y1, 0.333 Y2, 0.334 Y5 }\n",\ +" { 0.333 Z1, 0.333 Z2, 0.334 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(6, 2, 3) del;\n",\ +"(6, 4, 2) del;\n",\ +"(6, 5, 4) del;\n",\ +"(6, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(1, 5, 4, 6);\n",\ +"(1, 3, 5, 6);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.5 P6, -0.5 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 6 2 3;\n",\ +"\n",\ +"freeset\n",\ +"1 6 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 6 5 4;\n",\ +"\n",\ +"freeset\n",\ +"1 6 4 2;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"five Tetrahedron non convex (4)\"\n",\ +"\n",\ +"quality 4\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0, 0.8, -0.2) { 0.5 };\n",\ +"(0, 0.2, -0.8) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 3, 4) del;\n",\ +"(1, 4, 5) del;\n",\ +"(1, 5, 6) del;\n",\ +"(1, 6, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.1, 0.1, -0.1)\n",\ +" { 0.75 X1, 0.05 X2, 0.05 X3, 0.05 X4, 0.05 X5, 0.05 X6 }\n",\ +" { 0.75 Y1, 0.05 Y2, 0.05 Y3, 0.05 Y4, 0.05 Y5, 0.05 Y6 }\n",\ +" { 0.75 Z1, 0.05 Z2, 0.05 Z3, 0.05 Z4, 0.05 Z5, 0.05 Z6 };\n",\ +"\n",\ +"newfaces\n",\ +"(7, 2, 3);\n",\ +"(7, 3, 4);\n",\ +"(7, 4, 5);\n",\ +"(7, 5, 6);\n",\ +"(7, 6, 2);\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 7);\n",\ +"(1, 3, 4, 7);\n",\ +"(1, 4, 5, 7);\n",\ +"(1, 5, 6, 7);\n",\ +"(1, 6, 2, 7);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 1.5 P7, -0.5 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"{ 1 P7 };\n",\ +"\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 7 2 3;\n",\ +"\n",\ +"freeset\n",\ +"1 7 3 4;\n",\ +"\n",\ +"freeset\n",\ +"1 7 4 5;\n",\ +"\n",\ +"freeset\n",\ +"1 7 5 6;\n",\ +"\n",\ +"freeset\n",\ +"1 7 6 2;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 6\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"(0.5, 0.3, -0.3) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 5, 4) del;\n",\ +"(1, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"newpoints\n",\ +"(0.095, 0.003, -0.003)\n",\ +" { 0.9 X1, 0.09 X2, 0.01 X5 }\n",\ +" { 0.9 Y1, 0.09 Y2, 0.01 Y5 }\n",\ +" { 0.9 Z1, 0.09 Z2, 0.01 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(6, 2, 3) del;\n",\ +"(6, 4, 2) del;\n",\ +"(6, 5, 4) del;\n",\ +"(6, 3, 5) del;\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(1, 5, 4, 6);\n",\ +"(1, 3, 5, 6);\n",\ +"\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.499 P6, -0.5 P1, 0.001 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"\n",\ +"\n",\ +"freeset\n",\ +"1 6 2 3;\n",\ +"\n",\ +"freeset\n",\ +"1 6 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 6 5 4;\n",\ +"\n",\ +"freeset\n",\ +"1 6 4 2;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"(0.5, 0.4, -0.4) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(4, 5, 2) del;\n",\ +"(5, 3, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.925, 0.02, -0.02)\n",\ +" { 0.05 X1, 0.9 X2, 0.05 X5 }\n",\ +" { 0.05 Y1, 0.9 Y2, 0.05 Y5 }\n",\ +" { 0.05 Z1, 0.9 Z2, 0.05 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(3, 1, 6);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"(5, 3, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 1, 2, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(4, 5, 2, 6);\n",\ +"(5, 3, 2, 6);\n",\ +"\n",\ +"orientations\n",\ +"(3, 1, 2, 5);\n",\ +"(1, 4, 2, 5);\n",\ +"(2, 4, 5, 1);\n",\ +"(3, 2, 5, 1);\n",\ +"(5, 4, 2, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1.5 P6, -0.5 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"{ 1 P6 };\n",\ +"\n",\ +"freeset\n",\ +"3 1 2 6;\n",\ +"\n",\ +"freeset\n",\ +"1 4 2 6;\n",\ +"\n",\ +"freeset\n",\ +"4 5 2 6;\n",\ +"\n",\ +"freeset\n",\ +"5 3 2 6;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"three Tetrahedron non convex (4)\"\n",\ +"\n",\ +"quality 4\n",\ +"flags l;\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.25, -0.25)\n",\ +" { 0.25 X1, 0.25 X2, 0.25 X3, 0.25 X4 }\n",\ +" { 0.25 Y1, 0.25 Y2, 0.25 Y3, 0.25 Y4 }\n",\ +" { 0.25 Z1, 0.25 Z2, 0.25 Z3, 0.25 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3);\n",\ +"(5, 4, 2);\n",\ +"(5, 3, 4);\n",\ +"\n",\ +"elements\n",\ +"(2, 3, 1, 5);\n",\ +"(3, 4, 1, 5);\n",\ +"(4, 2, 1, 5;\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 4, 3);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.5 P5, -0.5 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"freeset\n",\ +"1 4 2 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"three Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(1, 3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.2, 0.1, -0.1)\n",\ +" { 0.7 X1, 0.1 X2, 0.1 X3, 0.1 X4 }\n",\ +" { 0.7 Y1, 0.1 Y2, 0.1 Y3, 0.1 Y4 }\n",\ +" { 0.7 Z1, 0.1 Z2, 0.1 Z3, 0.1 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3);\n",\ +"(5, 4, 2);\n",\ +"(5, 3, 4);\n",\ +"\n",\ +"elements\n",\ +"(2, 3, 1, 5);\n",\ +"(3, 4, 1, 5);\n",\ +"(4, 2, 1, 5;\n",\ +"\n",\ +"orientations\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.5 P5, -0.5 P1 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 3 4 5;\n",\ +"\n",\ +"freeset\n",\ +"1 4 2 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"four Tetrahedron non convex (6)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"(0.5, 0.4, -0.4) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"(4, 5, 2) del;\n",\ +"(5, 3, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.7, 0.08, -0.08) { 0.6 X2, 0.2 X5 } { 0.2 Y5 } { 0.2 Z5 };\n",\ +"\n",\ +"newfaces\n",\ +"(3, 1, 6);\n",\ +"(1, 4, 6);\n",\ +"(4, 5, 6);\n",\ +"(5, 3, 6);\n",\ +"\n",\ +"elements\n",\ +"(3, 1, 2, 6);\n",\ +"(1, 4, 2, 6);\n",\ +"(4, 5, 2, 6);\n",\ +"(5, 3, 2, 6);\n",\ +"\n",\ +"\n",\ +"orientations\n",\ +"(3, 1, 2, 5);\n",\ +"(5, 1, 2, 4);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 1, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, 0, -1) { 1 X4 } { 1 Y4 } { 1 Z4 };\n",\ +"(0.5, 0.4, -0.4) { 1 X5 } { 1 Y5 } { 1 Z5 };\n",\ +"(0.55, 0.12, -0.12) { 0.4 X2, 0.3 X5 } { 0.3 Y5 } { 0.3 Z5 };\n",\ +"\n",\ +"freeset\n",\ +"3 1 2 6;\n",\ +"\n",\ +"freeset\n",\ +"1 4 2 6;\n",\ +"\n",\ +"freeset\n",\ +"4 5 2 6;\n",\ +"\n",\ +"freeset\n",\ +"5 3 2 6;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 2 in 60 (12)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 0.5 };\n",\ +"(0.5, 1, 0) { 0.5 };\n",\ +"(0.5, 0, -1) { 0.5 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.1, -0.1)\n",\ +" { 0.4 X1, 0.4 X2, 0.1 X3, 0.1 X4 }\n",\ +" { 0.4 Y1, 0.4 Y2, 0.1 Y3, 0.1 Y4 }\n",\ +" { 0.4 Z1, 0.4 Z2, 0.1 Z3, 0.1 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(5, 2, 3);\n",\ +"(5, 3, 1);\n",\ +"(5, 4, 2);\n",\ +"(5, 1, 4);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 5);\n",\ +"(1, 2, 5, 4);\n",\ +"\n",\ +"freezone2\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1.5 P5, -0.25 P1, -0.25 P2 };\n",\ +"\n",\ +"freezonelimit\n",\ +"{ 1 P1 };\n",\ +"{ 1 P2 };\n",\ +"{ 1 P3 };\n",\ +"{ 1 P4 };\n",\ +"{ 1 P5 };\n",\ +"\n",\ +"freeset\n",\ +"1 2 3 5;\n",\ +"\n",\ +"freeset\n",\ +"1 2 4 5;\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Tetrahedron 120, but more than 180 (13)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 };\n",\ +"(0.5, 0.866, 0) { 1 };\n",\ +"(0.5, -0.866, 0) { 1 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"(1, 4, 2);\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0, -0.3) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"newfaces\n",\ +"(1, 5, 3);\n",\ +"(3, 5, 2);\n",\ +"(2, 5, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 5);\n",\ +"\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, -0.1, -0.4) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4} { 0.5 Z3, 0.5 Z4 };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Free Tetrahedron (14)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1.0 };\n",\ +"(0.5, 0.866, 0) { 1.0 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.2) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(4, 1, 2);\n",\ +"(4, 2, 3);\n",\ +"(4, 3, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, 0.288, -0.25) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Free Tetrahedron (15)\"\n",\ +"\n",\ +"quality 100\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1.0 };\n",\ +"(0.5, 0.866, 0) { 1.0 };\n",\ +"\n",\ +"mapfaces\n",\ +"(1, 2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.288, -0.1) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"newfaces\n",\ +"(4, 1, 2);\n",\ +"(4, 2, 3);\n",\ +"(4, 3, 1);\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3, 4);\n",\ +"\n",\ +"freezone\n",\ +"(0, 0, 0);\n",\ +"(1, 0, 0) { 1 X2 } { } { };\n",\ +"(0.5, 0.866, 0) { 1 X3 } { 1 Y3 } { };\n",\ +"(0.5, 0.288, -0.15) { 0.333 X2, 0.333 X3 } { 0.333 Y3 } { };\n",\ +"\n",\ +"endrule\n", +0}; +} diff --git a/contrib/Netgen/libsrc/meshing/topology.cpp b/contrib/Netgen/libsrc/meshing/topology.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5c860cdb249f77f71c9704a754e351c963ee145 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/topology.cpp @@ -0,0 +1,1464 @@ +#include <mystdlib.h> + +#include "meshing.hpp" + +#ifdef PARALLEL +#include <parallel.hpp> +#endif + +namespace netgen +{ + +MeshTopology :: MeshTopology (const Mesh & amesh) + : mesh(amesh) +{ + buildedges = 1; + buildfaces = 1; + vert2element = 0; + vert2surfelement = 0; + vert2segment = 0; + timestamp = -1; + + edge2vert.SetName ("edge2vert"); + face2vert.SetName ("face2vert"); + edges.SetName ("el2edge"); + faces.SetName ("el2face"); + surfedges.SetName ("surfel2edge"); + segedges.SetName ("segment2edge"); + surffaces.SetName ("surfel2face"); + surf2volelement.SetName ("surfel2el"); + face2surfel.SetName ("face2surfel"); +} + +MeshTopology :: ~MeshTopology () +{ + delete vert2element; + delete vert2surfelement; + delete vert2segment; +} + +void MeshTopology :: Update() +{ + static int timer = NgProfiler::CreateTimer ("topology"); + NgProfiler::RegionTimer reg (timer); + +#ifdef PARALLEL + ParallelMeshTopology & paralleltop = mesh.GetParallelTopology(); + + bool isparallel = 0; +#endif + + + if (timestamp > mesh.GetTimeStamp()) return; + + int ne = mesh.GetNE(); + int nse = mesh.GetNSE(); + int nseg = mesh.GetNSeg(); + int np = mesh.GetNP(); + int nv = mesh.GetNV(); + int nfa = 0; + int ned = edge2vert.Size(); + + PrintMessage (3, "Update mesh topology"); + + (*testout) << " UPDATE MESH TOPOLOGY " << endl; + (*testout) << "ne = " << ne << endl; + (*testout) << "nse = " << nse << endl; + (*testout) << "nseg = " << nseg << endl; + (*testout) << "np = " << np << endl; + (*testout) << "nv = " << nv << endl; + + delete vert2element; + delete vert2surfelement; + delete vert2segment; + + ARRAY<int,PointIndex::BASE> cnt(nv); + ARRAY<int> vnums; + + /* + generate: + vertex to element + vertex to surface element + vertex to segment + */ + + + cnt = 0; + for (ElementIndex ei = 0; ei < ne; ei++) + { + const Element & el = mesh[ei]; + int nelv = el.GetNV(); + for (int j = 0; j < nelv; j++) + cnt[el[j]]++; + } + + vert2element = new TABLE<int,PointIndex::BASE> (cnt); + for (ElementIndex ei = 0; ei < ne; ei++) + { + const Element & el = mesh[ei]; + int nelv = el.GetNV(); + for (int j = 0; j < nelv; j++) + vert2element->AddSave (el[j], ei+1); + } + + cnt = 0; + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + { + const Element2d & el = mesh[sei]; + int nelv = el.GetNV(); + for (int j = 0; j < nelv; j++) + cnt[el[j]]++; + } + + vert2surfelement = new TABLE<int,PointIndex::BASE> (cnt); + for (SurfaceElementIndex sei = 0; sei < nse; sei++) + { + const Element2d & el = mesh[sei]; + int nelv = el.GetNV(); + for (int j = 0; j < nelv; j++) + vert2surfelement->AddSave (el[j], sei+1); + } + + cnt = 0; + for (int i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + cnt[seg.p1]++; + cnt[seg.p2]++; + } + + vert2segment = new TABLE<int,PointIndex::BASE> (cnt); + for (int i = 1; i <= nseg; i++) + { + const Segment & seg = mesh.LineSegment(i); + vert2segment->AddSave (seg.p1, i); + vert2segment->AddSave (seg.p2, i); + } + + if (buildedges) + { + static int timer1 = NgProfiler::CreateTimer ("topology::buildedges"); + NgProfiler::RegionTimer reg1 (timer1); + + PrintMessage (5, "Update edges "); + + edges.SetSize(ne); + surfedges.SetSize(nse); + segedges.SetSize(nseg); + + for (int i = 0; i < ne; i++) + for (int j = 0; j < 12; j++) + edges[i][j] = 0; + for (int i = 0; i < nse; i++) + for (int j = 0; j < 4; j++) + surfedges[i][j] = 0; + + // keep existing edges + cnt = 0; + for (int i = 0; i < edge2vert.Size(); i++) + cnt[edge2vert[i][0]]++; + TABLE<int,PointIndex::BASE> vert2edge (cnt); + for (int i = 0; i < edge2vert.Size(); i++) + vert2edge.AddSave (edge2vert[i][0], i+1); + + // ensure all coarse grid and intermediate level edges + cnt = 0; + for (int i = mesh.mlbetweennodes.Begin(); i < mesh.mlbetweennodes.End(); i++) + { + int pa[2]; + pa[0] = mesh.mlbetweennodes[i].I1(); + pa[1] = mesh.mlbetweennodes[i].I2(); + if (pa[0] > pa[1]) Swap (pa[0], pa[1]); + if (pa[0] > 0) + cnt.Elem(pa[0])++; + } + TABLE<int,PointIndex::BASE> vert2vertcoarse (cnt); + for (int i = mesh.mlbetweennodes.Begin(); i < mesh.mlbetweennodes.End(); i++) + { + int pa[2]; + pa[0] = mesh.mlbetweennodes[i].I1(); + pa[1] = mesh.mlbetweennodes[i].I2(); + if (pa[0] > pa[1]) swap (pa[0], pa[1]); + if (pa[0] > 0) + vert2vertcoarse.AddSave1 (pa[0], pa[1]); + } + + + ARRAY<int,PointIndex::BASE> edgenr(nv); + ARRAY<int,PointIndex::BASE> edgeflag(nv); + edgeflag = 0; + + ned = edge2vert.Size(); + ARRAY<INDEX_3> missing; + + for (int i = 1; i <= nv; i++) + { + for (int j = 1; j <= vert2edge.EntrySize(i); j++) + { + int ednr = vert2edge.Get(i,j); + int i2 = edge2vert.Get(ednr)[1]; + edgeflag[i2] = i; + edgenr[i2] = ednr; + } + for (int j = 1; j <= vert2vertcoarse.EntrySize(i); j++) + { + int v2 = vert2vertcoarse.Get(i,j); + if (edgeflag[v2] < i) + { + ned++; + edgenr[v2] = ned; + edgeflag[v2] = i; + missing.Append (INDEX_3(i,v2,ned)); + } + } + + for (int j = 1; j <= vert2element->EntrySize(i); j++) + { + int elnr = vert2element->Get(i,j); + const Element & el = mesh.VolumeElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(eledges[k][1])); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) + continue; + + if (edgeflag[edge.I2()] < i) + { + ned++; + edgenr[edge.I2()] = ned; + edgeflag[edge.I2()] = i; + } + + int edgenum = edgenr[edge.I2()]; + if (edgedir) edgenum *= -1; + edges.Elem(elnr)[k] = edgenum; + } + } + + for (int j = 1; j <= vert2surfelement->EntrySize(i); j++) + { + int elnr = vert2surfelement->Get(i,j); + const Element2d & el = mesh.SurfaceElement (elnr); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(eledges[k][1])); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) + continue; + + if (edgeflag[edge.I2()] < i) + { + ned++; + edgenr[edge.I2()] = ned; + edgeflag[edge.I2()] = i; + } + + int edgenum = edgenr[edge.I2()]; + if (edgedir) edgenum *= -1; + surfedges.Elem(elnr)[k] = edgenum; + } + } + + for (int j = 1; j <= vert2segment->EntrySize(i); j++) + { + int elnr = vert2segment->Get(i,j); + const Segment & el = mesh.LineSegment (elnr); + + INDEX_2 edge(el.p1, el.p2); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + if (edge.I1() != i) + continue; + + if (edgeflag[edge.I2()] < i) + { + ned++; + edgenr[edge.I2()] = ned; + edgeflag[edge.I2()] = i; + } + int edgenum = edgenr[edge.I2()]; + + if (edgedir) edgenum *= -1; + segedges.Elem(elnr) = edgenum; + } + } + + + edge2vert.SetSize (ned); + for (int i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement (i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(eledges[k][1])); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + int edgenum = abs (edges.Elem(i)[k]); + + edge2vert.Elem(edgenum)[0] = edge.I1(); + edge2vert.Elem(edgenum)[1] = edge.I2(); + } + } + for (int i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement (i); + + int neledges = GetNEdges (el.GetType()); + const ELEMENT_EDGE * eledges = GetEdges (el.GetType()); + + for (int k = 0; k < neledges; k++) + { + INDEX_2 edge(el.PNum(eledges[k][0]), + el.PNum(eledges[k][1])); + + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + int edgenum = abs (surfedges.Elem(i)[k]); + + edge2vert.Elem(edgenum)[0] = edge.I1(); + edge2vert.Elem(edgenum)[1] = edge.I2(); + } + } + + for (int i = 1; i <= nseg; i++) + { + const Segment & el = mesh.LineSegment (i); + + INDEX_2 edge(el.p1, el.p2); + int edgedir = (edge.I1() > edge.I2()); + if (edgedir) swap (edge.I1(), edge.I2()); + + int edgenum = abs (segedges.Elem(i)); + + edge2vert.Elem(edgenum)[0] = edge.I1(); + edge2vert.Elem(edgenum)[1] = edge.I2(); + } + + for (int i = 1; i <= missing.Size(); i++) + { + INDEX_3 i3 = missing.Get(i); + edge2vert.Elem(i3.I3())[0] = i3.I1(); + edge2vert.Elem(i3.I3())[1] = i3.I2(); + } + + + /* + (*testout) << "edge table:" << endl; + (*testout) << "edge2vert:" << endl; + for (int i = 1; i <= edge2vert.Size(); i++) + (*testout) << "edge " << i << ", v1,2 = " << edge2vert.Elem(i)[0] << ", " << edge2vert.Elem(i)[1] << endl; + (*testout) << "surfedges:" << endl; + for (int i = 1; i <= surfedges.Size(); i++) + (*testout) << "el " << i << ", edges = " + << surfedges.Elem(i)[0] << ", " + << surfedges.Elem(i)[1] << ", " + << surfedges.Elem(i)[2] << endl; + */ + + + } + + + // cout << "build edges done" << endl; + + // generate faces + if (buildfaces) // && mesh.GetDimension() == 3) + { + int i, j; + + static int timer2 = NgProfiler::CreateTimer ("topology::buildfaces"); + NgProfiler::RegionTimer reg2 (timer2); + + PrintMessage (5, "Update faces "); + + faces.SetSize(ne); + surffaces.SetSize(nse); + + // face2vert.SetSize(0); // keep old faces + nfa = face2vert.Size(); + // INDEX_3_HASHTABLE<int> vert2face(ne+nse+1); + INDEX_3_CLOSED_HASHTABLE<int> vert2face(8*ne+2*nse+nfa+2); + + for (i = 1; i <= face2vert.Size(); i++) + { + INDEX_3 f; + f.I1() = face2vert.Get(i)[0]; + f.I2() = face2vert.Get(i)[1]; + f.I3() = face2vert.Get(i)[2]; + vert2face.Set (f, i); + } + + for (i = 1; i <= ne; i++) + { + const Element & el = mesh.VolumeElement (i); + + int nelfaces = GetNFaces (el.GetType()); + const ELEMENT_FACE * elfaces = GetFaces (el.GetType()); + + for (j = 0; j < 6; j++) + faces.Elem(i)[j] = 0; + for (j = 0; j < nelfaces; j++) + if (elfaces[j][3] == 0) + + { // triangle + + int facenum; + int facedir; + + INDEX_3 face(el.PNum(elfaces[j][0]), + el.PNum(elfaces[j][1]), + el.PNum(elfaces[j][2])); + + facedir = 0; + if (face.I1() > face.I2()) + { + swap (face.I1(), face.I2()); + facedir += 1; + } + if (face.I2() > face.I3()) + { + swap (face.I2(), face.I3()); + facedir += 2; + } + if (face.I1() > face.I2()) + { + swap (face.I1(), face.I2()); + facedir += 4; + } + + if (vert2face.Used (face)) + facenum = vert2face.Get(face); + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + INDEX_4 hface(face.I1(),face.I2(),face.I3(),0); + face2vert.Append (hface); + // face2vert.SetSize(face2vert.Size()+1); + } + + faces.Elem(i)[j] = 8*(facenum-1)+facedir+1; + } + + else + + { + // quad + int facenum; + int facedir; + INDEX_4Q face4(el.PNum(elfaces[j][0]), + el.PNum(elfaces[j][1]), + el.PNum(elfaces[j][2]), + el.PNum(elfaces[j][3])); + + facedir = 0; + if (min2 (face4.I1(), face4.I2()) > + min2 (face4.I4(), face4.I3())) + { // z - flip + facedir += 1; + swap (face4.I1(), face4.I4()); + swap (face4.I2(), face4.I3()); + } + if (min2 (face4.I1(), face4.I4()) > + min2 (face4.I2(), face4.I3())) + { // x - flip + facedir += 2; + swap (face4.I1(), face4.I2()); + swap (face4.I3(), face4.I4()); + } + if (face4.I2() > face4.I4()) + { // diagonal flip + facedir += 4; + swap (face4.I2(), face4.I4()); + } + // face4.Sort(); + + INDEX_3 face(face4.I1(), face4.I2(), face4.I3()); + + if (vert2face.Used (face)) + { + facenum = vert2face.Get(face); + } + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + // face2vert.SetSize(face2vert.Size()+1); + + INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I4()); + face2vert.Append (hface); + } + + faces.Elem(i)[j] = 8*(facenum-1)+facedir+1; + } + } + + face2surfel.SetSize(nfa+nse); + for (i = 1; i <= face2surfel.Size(); i++) + face2surfel.Elem(i) = 0; + + for (i = 1; i <= nse; i++) + { + const Element2d & el = mesh.SurfaceElement (i); + + const ELEMENT_FACE * elfaces = GetFaces (el.GetType()); + + if (elfaces[0][3] == 0) + + { // triangle + + int facenum; + int facedir; + + INDEX_3 face(el.PNum(elfaces[0][0]), + el.PNum(elfaces[0][1]), + el.PNum(elfaces[0][2])); + + facedir = 0; + if (face.I1() > face.I2()) + { + swap (face.I1(), face.I2()); + facedir += 1; + } + if (face.I2() > face.I3()) + { + swap (face.I2(), face.I3()); + facedir += 2; + } + if (face.I1() > face.I2()) + { + swap (face.I1(), face.I2()); + facedir += 4; + } + + if (vert2face.Used (face)) + facenum = vert2face.Get(face); + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + // face2vert.SetSize(face2vert.Size()+1); + INDEX_4 hface(face.I1(),face.I2(),face.I3(),0); + face2vert.Append (hface); + } + + surffaces.Elem(i) = 8*(facenum-1)+facedir+1; + face2surfel.Elem(facenum) = i; + } + + else + + { + // quad + int facenum; + int facedir; + + INDEX_4Q face4(el.PNum(elfaces[0][0]), + el.PNum(elfaces[0][1]), + el.PNum(elfaces[0][2]), + el.PNum(elfaces[0][3])); + + facedir = 0; + if (min2 (face4.I1(), face4.I2()) > + min2 (face4.I4(), face4.I3())) + { // z - orientation + facedir += 1; + swap (face4.I1(), face4.I4()); + swap (face4.I2(), face4.I3()); + } + if (min2 (face4.I1(), face4.I4()) > + min2 (face4.I2(), face4.I3())) + { // x - orientation + facedir += 2; + swap (face4.I1(), face4.I2()); + swap (face4.I3(), face4.I4()); + } + if (face4.I2() > face4.I4()) + { + facedir += 4; + swap (face4.I2(), face4.I4()); + } + + INDEX_3 face(face4.I1(), face4.I2(), face4.I3()); + + if (vert2face.Used (face)) + facenum = vert2face.Get(face); + else + { + nfa++; + vert2face.Set (face, nfa); + facenum = nfa; + + // face2vert.SetSize(face2vert.Size()+1); + INDEX_4 hface(face4.I1(),face4.I2(),face4.I3(),face4.I3()); + face2vert.Append (hface); + /* + face2vert.Last()[0] = face4.I1(); + face2vert.Last()[1] = face4.I2(); + face2vert.Last()[2] = face4.I3(); + face2vert.Last()[3] = face4.I3(); + */ + } + + surffaces.Elem(i) = 8*(facenum-1)+facedir+1; + face2surfel.Elem(facenum) = i; + } + } + + + surf2volelement.SetSize (nse); + for (i = 1; i <= nse; i++) + { + surf2volelement.Elem(i)[0] = 0; + surf2volelement.Elem(i)[1] = 0; + } + for (i = 1; i <= ne; i++) + for (j = 0; j < 6; j++) + { + int fnum = (faces.Get(i)[j]+7) / 8; + if (fnum > 0 && face2surfel.Elem(fnum)) + { + int sel = face2surfel.Elem(fnum); + surf2volelement.Elem(sel)[1] = + surf2volelement.Elem(sel)[0]; + surf2volelement.Elem(sel)[0] = i; + } + } + + face2vert.SetAllocSize (face2vert.Size()); + + /* + *testout << "face2vert: "; + face2vert.PrintMemInfo(cout); + *testout << "faces: "; + faces.PrintMemInfo(cout); + *testout << "hashtable: "; + vert2face.PrintMemInfo(cout); + */ + +#ifdef PARALLEL + (*testout) << " RESET Paralleltop" << endl; + + paralleltop.Reset (); +#endif + + ARRAY<char> face_els(nfa), face_surfels(nfa); + face_els = 0; + face_surfels = 0; + ARRAY<int> hfaces; + for (i = 1; i <= ne; i++) + { + GetElementFaces (i, hfaces); + for (j = 0; j < hfaces.Size(); j++) + face_els[hfaces[j]-1]++; + } + for (i = 1; i <= nse; i++) + face_surfels[GetSurfaceElementFace (i)-1]++; + + if (ne) + { + int cnt_err = 0; + for (i = 0; i < nfa; i++) + { + /* + (*testout) << "face " << i << " has " << int(face_els[i]) << " els, " + << int(face_surfels[i]) << " surfels, tot = " + << face_els[i] + face_surfels[i] << endl; + */ + if (face_els[i] + face_surfels[i] == 1) + { + cnt_err++; +#ifdef PARALLEL + if ( ntasks > 1 ) + { + if ( !paralleltop.DoCoarseUpdate() ) continue; + // "illegal" faces are exchange faces + /* + (*testout) << "exchange face : " << i << endl; + (*testout) << "points = " << face2vert[i] << endl; + */ +// (*testout) << "global points = "; +// for ( int j = 0; j < 3; j++ ) +// // (*testout) << face2vert[i].I(j+1) << " -> " +// // << paralleltop.GetLoc2Glob_Vert( face2vert[i].I(j+1) ) << ", "; +// (*testout) << endl; +// if ( !paralleltop.IsExchangeFace (i+1) ) +// paralleltop.SetRefinementFace (i+1); + + paralleltop.SetExchangeFace (i+1); + + for (int j = 0; j < 4; j++) + { + if ( face2vert[i].I(j+1) > 0 ) + paralleltop.SetExchangeVert(face2vert[i].I(j+1)); + } + + ARRAY<int> faceedges; + GetFaceEdges (i+1, faceedges); + for ( int j = 0; j < faceedges.Size(); j++) + { + paralleltop.SetExchangeEdge ( faceedges[j] ); + int v1, v2; + GetEdgeVertices(faceedges[j], v1, v2 ); + } + + /* + (*testout) << "pos = "; + for (int j = 0; j < 4; j++) + if (face2vert[i].I(j+1) >= 1) + (*testout) << mesh[(PointIndex)face2vert[i].I(j+1)] << " "; + (*testout) << endl; + */ + } + else + { +#endif + (*testout) << "illegal face : " << i << endl; + (*testout) << "points = " << face2vert[i] << endl; + (*testout) << "pos = "; + for (j = 0; j < 4; j++) + if (face2vert[i].I(j+1) >= 1) + (*testout) << mesh[(PointIndex)face2vert[i].I(j+1)] << " "; + (*testout) << endl; + + FlatArray<int> vertels = GetVertexElements (face2vert[i].I(1)); + for (int k = 0; k < vertels.Size(); k++) + { + int elfaces[10], orient[10]; + int nf = GetElementFaces (vertels[k], elfaces, orient); + for (int l = 0; l < nf; l++) + if (elfaces[l] == i) + { + (*testout) << "is face of element " << vertels[k] << endl; + + if (mesh.coarsemesh && mesh.hpelements->Size() == mesh.GetNE() ) + { + const HPRefElement & hpref_el = + (*mesh.hpelements) [ mesh.VolumeElement (vertels[k]).hp_elnr]; + (*testout) << "coarse eleme = " << hpref_el.coarse_elnr << endl; + } + + } + } +#ifdef PARALLEL + } +#endif + } + } + +#ifndef PARALLEL + if (cnt_err) + cout << cnt_err << " elements are not matching !!!" << endl; +#else + if (cnt_err && ntasks == 1) + cout << cnt_err << " elements are not matching !!!" << endl; + else if (cnt_err && ntasks > 1) + { + cout << "p" << id << ": " << cnt_err << " elements are not local" << endl; + isparallel = 1; + } + else if ( ntasks > 1 ) + cout << "p" << id << ": " << "Partition " << id << " is totally local" << endl; +#endif + + } + +#ifdef PARALLEL + + if ( isparallel ) + { + paralleltop.Update(); + if ( paralleltop.DoCoarseUpdate() ) + { + paralleltop.UpdateCoarseGrid(); + } + else + { + // paralleltop.UpdateRefinement(); + } + // paralleltop.Print(); + } + + +#endif + + + + + } + + + + /* +for (i = 1; i <= ne; i++) + { + (*testout) << "Element " << i << endl; + (*testout) << "PNums " << endl; + for( int l=1;l<=8;l++) *testout << mesh.VolumeElement(i).PNum(l) << "\t"; + *testout << endl; + (*testout) << "edges: " << endl; + for (j = 0; j < 9; j++) + (*testout) << edges.Elem(i)[j] << " "; + (*testout) << "faces: " << endl; + for (j = 0; j < 6; j++)m + (*testout) << faces.Elem(i)[j] << " "; + } + + for (i = 1; i <= nse; i++) + { + (*testout) << "SElement " << i << endl; + (*testout) << "PNums " << endl; + for( int l=1;l<=4;l++) *testout << mesh.SurfaceElement(i).PNum(l) << "\t"; + *testout << endl; + } + */ + timestamp = NextTimeStamp(); +} + + + + +int MeshTopology :: GetNVertices (ELEMENT_TYPE et) +{ + switch (et) + { + case SEGMENT: + case SEGMENT3: + return 2; + + case TRIG: + case TRIG6: + return 3; + + case QUAD: + case QUAD6: + case QUAD8: + return 4; + + case TET: + case TET10: + return 4; + + case PYRAMID: + return 5; + + case PRISM: + case PRISM12: + return 6; + + case HEX: + return 8; + + default: + cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; + } + return 0; +} + +int MeshTopology :: GetNEdges (ELEMENT_TYPE et) +{ + switch (et) + { + case SEGMENT: + case SEGMENT3: + return 1; + + case TRIG: + case TRIG6: + return 3; + + case QUAD: + case QUAD6: + case QUAD8: + return 4; + + case TET: + case TET10: + return 6; + + case PYRAMID: + return 8; + + case PRISM: + case PRISM12: + return 9; + + case HEX: + return 12; + + default: + cerr << "Ng_ME_GetNEdges, illegal element type " << et << endl; + } + return 0; +} + + +int MeshTopology :: GetNFaces (ELEMENT_TYPE et) +{ + switch (et) + { + case SEGMENT: + case SEGMENT3: + return 0; + + case TRIG: + case TRIG6: + return 1; + + case QUAD: + case QUAD6: + case QUAD8: + return 1; + + case TET: + case TET10: + return 4; + + case PYRAMID: + return 5; + + case PRISM: + case PRISM12: + return 5; + + case HEX: + return 6; + + default: + cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; + } + return 0; +} + + + + +const Point3d * MeshTopology :: GetVertices (ELEMENT_TYPE et) +{ + static Point3d segm_points [] = + { Point3d (1, 0, 0), + Point3d (0, 0, 0) }; + + static Point3d trig_points [] = + { Point3d ( 1, 0, 0 ), + Point3d ( 0, 1, 0 ), + Point3d ( 0, 0, 0 ) }; + + static Point3d quad_points [] = + { Point3d ( 0, 0, 0 ), + Point3d ( 1, 0, 0 ), + Point3d ( 1, 1, 0 ), + Point3d ( 0, 1, 0 ) }; + + static Point3d tet_points [] = + { Point3d ( 1, 0, 0 ), + Point3d ( 0, 1, 0 ), + Point3d ( 0, 0, 1 ), + Point3d ( 0, 0, 0 ) }; + + static Point3d pyramid_points [] = + { + Point3d ( 0, 0, 0 ), + Point3d ( 1, 0, 0 ), + Point3d ( 1, 1, 0 ), + Point3d ( 0, 1, 0 ), + Point3d ( 0, 0, 1-1e-7 ), + }; + + static Point3d prism_points[] = + { + Point3d ( 1, 0, 0 ), + Point3d ( 0, 1, 0 ), + Point3d ( 0, 0, 0 ), + Point3d ( 1, 0, 1 ), + Point3d ( 0, 1, 1 ), + Point3d ( 0, 0, 1 ) + }; + + + static Point3d hex_points [] = + { Point3d ( 0, 0, 0 ), + Point3d ( 1, 0, 0 ), + Point3d ( 1, 1, 0 ), + Point3d ( 0, 1, 0 ), + Point3d ( 0, 0, 1 ), + Point3d ( 1, 0, 1 ), + Point3d ( 1, 1, 1 ), + Point3d ( 0, 1, 1 ) }; + + + switch (et) + { + case SEGMENT: + case SEGMENT3: + return segm_points; + + case TRIG: + case TRIG6: + return trig_points; + + case QUAD: + case QUAD6: + case QUAD8: + return quad_points; + + case TET: + case TET10: + return tet_points; + + case PYRAMID: + return pyramid_points; + + case PRISM: + case PRISM12: + return prism_points; + + case HEX: + return hex_points; + default: + cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; + } + return 0; +} + + + + + + + + +void MeshTopology :: GetElementEdges (int elnr, ARRAY<int> & eledges) const +{ + int ned = GetNEdges (mesh.VolumeElement(elnr).GetType()); + eledges.SetSize (ned); + for (int i = 0; i < ned; i++) + eledges[i] = abs (edges.Get(elnr)[i]); +} +void MeshTopology :: GetElementFaces (int elnr, ARRAY<int> & elfaces, bool withorientation) const +{ + int i; + int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType()); + elfaces.SetSize (nfa); + for (i = 1; i <= nfa; i++) + { + elfaces.Elem(i) = (faces.Get(elnr)[i-1]-1) / 8 + 1; + if(withorientation) + { + int orient = (faces.Get(elnr)[i-1]-1) % 8; + if(orient == 1 || orient == 2 || orient == 4 || orient == 7) + elfaces.Elem(i) *= -1; + } + } +} + +void MeshTopology :: GetElementEdgeOrientations (int elnr, ARRAY<int> & eorient) const +{ + int i; + int ned = GetNEdges (mesh.VolumeElement(elnr).GetType()); + eorient.SetSize (ned); + for (i = 1; i <= ned; i++) + eorient.Elem(i) = (edges.Get(elnr)[i-1] > 0) ? 1 : -1; +} + +void MeshTopology :: GetElementFaceOrientations (int elnr, ARRAY<int> & forient) const +{ + int i; + int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType()); + forient.SetSize (nfa); + for (i = 1; i <= nfa; i++) + forient.Elem(i) = (faces.Get(elnr)[i-1]-1) % 8; +} + + + +int MeshTopology :: GetElementEdges (int elnr, int * eledges, int * orient) const +{ + int i; + // int ned = GetNEdges (mesh.VolumeElement(elnr).GetType()); + + if (mesh.GetDimension()==3 || 1) + { + if (orient) + { + for (i = 0; i < 12; i++) + { + if (!edges.Get(elnr)[i]) return i; + eledges[i] = abs (edges.Get(elnr)[i]); + orient[i] = (edges.Get(elnr)[i] > 0 ) ? 1 : -1; + } + } + else + { + for (i = 0; i < 12; i++) + { + if (!edges.Get(elnr)[i]) return i; + eledges[i] = abs (edges.Get(elnr)[i]); + } + } + return 12; + } + else + { + throw NgException("rethink implementation"); + /* + if (orient) + { + for (i = 0; i < 4; i++) + { + if (!surfedges.Get(elnr)[i]) return i; + eledges[i] = abs (surfedges.Get(elnr)[i]); + orient[i] = (surfedges.Get(elnr)[i] > 0 ) ? 1 : -1; + } + } + else + { + if (!surfedges.Get(elnr)[i]) return i; + for (i = 0; i < 4; i++) + eledges[i] = abs (surfedges.Get(elnr)[i]); + } + */ + return 4; + // return GetSurfaceElementEdges (elnr, eledges, orient); + } +} + +int MeshTopology :: GetElementFaces (int elnr, int * elfaces, int * orient) const +{ + int i; + // int nfa = GetNFaces (mesh.VolumeElement(elnr).GetType()); + if (orient) + { + for (i = 0; i < 6; i++) + { + if (!faces.Get(elnr)[i]) return i; + elfaces[i] = (faces.Get(elnr)[i]-1) / 8 + 1; + orient[i] = (faces.Get(elnr)[i]-1) % 8; + } + } + else + { + for (i = 0; i < 6; i++) + { + if (!faces.Get(elnr)[i]) return i; + elfaces[i] = (faces.Get(elnr)[i]-1) / 8 + 1; + } + } + return 6; +} + +void MeshTopology :: GetSurfaceElementEdges (int elnr, ARRAY<int> & eledges) const +{ + int i; + if (mesh.GetDimension()==3 || 1) + { + int ned = GetNEdges (mesh.SurfaceElement(elnr).GetType()); + eledges.SetSize (ned); + for (i = 1; i <= ned; i++) + eledges.Elem(i) = abs (surfedges.Get(elnr)[i-1]); + } + else + { + cout << "surfeledge(" << elnr << ") = " << flush; + eledges.SetSize(1); + eledges.Elem(1) = abs (segedges.Get(elnr)); + cout << eledges.Elem(1) << endl; + } +} + +int MeshTopology :: GetSurfaceElementFace (int elnr) const +{ + return (surffaces.Get(elnr)-1) / 8 + 1; +} + +void MeshTopology :: +GetSurfaceElementEdgeOrientations (int elnr, ARRAY<int> & eorient) const +{ + int ned = GetNEdges (mesh.SurfaceElement(elnr).GetType()); + eorient.SetSize (ned); + for (int i = 1; i <= ned; i++) + eorient.Elem(i) = (surfedges.Get(elnr)[i-1] > 0) ? 1 : -1; +} + +int MeshTopology :: GetSurfaceElementFaceOrientation (int elnr) const +{ + return (surffaces.Get(elnr)-1) % 8; +} + +int MeshTopology :: GetSurfaceElementEdges (int elnr, int * eledges, int * orient) const +{ + int i; + if (mesh.GetDimension() == 3 || 1) + { + if (orient) + { + for (i = 0; i < 4; i++) + { + if (!surfedges.Get(elnr)[i]) return i; + eledges[i] = abs (surfedges.Get(elnr)[i]); + orient[i] = (surfedges.Get(elnr)[i] > 0 ) ? 1 : -1; + } + } + else + { + for (i = 0; i < 4; i++) + { + if (!surfedges.Get(elnr)[i]) return i; + eledges[i] = abs (surfedges.Get(elnr)[i]); + } + } + return 4; + } + else + { + eledges[0] = abs (segedges.Get(elnr)); + if (orient) + orient[0] = segedges.Get(elnr) > 0 ? 1 : -1; + } + return 1; +} + + +void MeshTopology :: GetFaceVertices (int fnr, ARRAY<int> & vertices) const +{ + vertices.SetSize(4); + int i; + for (i = 1; i <= 4; i++) + vertices.Elem(i) = face2vert.Get(fnr)[i-1]; + if (vertices.Elem(4) == 0) + vertices.SetSize(3); +} + +void MeshTopology :: GetFaceVertices (int fnr, int * vertices) const +{ + for (int i = 0; i <= 3; i++) + vertices[i] = face2vert.Get(fnr)[i]; +} + + +void MeshTopology :: GetEdgeVertices (int ednr, int & v1, int & v2) const +{ + v1 = edge2vert.Get(ednr)[0]; + v2 = edge2vert.Get(ednr)[1]; +} + + +void MeshTopology :: GetFaceEdges (int fnr, ARRAY<int> & fedges, bool withorientation) const +{ + ArrayMem<int,4> pi(4); + ArrayMem<int,12> eledges; + + fedges.SetSize (0); + GetFaceVertices(fnr, pi); + + // Sort Edges according to global vertex numbers + // e1 = fmax, f2 + // e2 = fmax, f1 + // e3 = op e1(f2,f3) + // e4 = op e2(f1,f3) + + /* ArrayMem<int,4> fp; + fp[0] = pi[0]; + for(int k=1;k<pi.Size();k++) + if(fp[k]>fp[0]) swap(fp[k],fp[0]); + + fp[1] = fp[0]+ */ + + + // GetVertexElements (pi[0], els); + FlatArray<int> els= GetVertexElements (pi[0]); + + // find one element having all vertices of the face + for (int i = 0; i < els.Size(); i++) + { + const Element & el = mesh.VolumeElement(els[i]); + int nref_faces = GetNFaces (el.GetType()); + const ELEMENT_FACE * ref_faces = GetFaces (el.GetType()); + int nfa_ref_edges = GetNEdges (GetFaceType(fnr)); + + int cntv = 0,fa=-1; + for(int m=0;m<nref_faces;m++) + { + cntv=0; + for(int j=0;j<nfa_ref_edges && ref_faces[m][j]>0;j++) + for(int k=0;k<pi.Size();k++) + { + if(el[ref_faces[m][j]-1] == pi[k]) + cntv++; + } + if (cntv == pi.Size()) + { + fa=m; + break; + } + } + + if(fa>=0) + { + const ELEMENT_EDGE * fa_ref_edges = GetEdges(GetFaceType(fnr)); + fedges.SetSize(nfa_ref_edges); + GetElementEdges (els[i], eledges); + + for (int j = 0; j < eledges.Size(); j++) + { + int vi1, vi2; + GetEdgeVertices (eledges[j], vi1, vi2); + + bool has1 = 0; + bool has2 = 0; + for (int k = 0; k < pi.Size(); k++) + { + if (vi1 == pi[k]) has1 = 1; + if (vi2 == pi[k]) has2 = 1; + + } + + if (has1 && has2) // eledges[j] is on face + { + // fedges.Append (eledges[j]); + for(int k=0;k<nfa_ref_edges;k++) + { + int w1 = el[ref_faces[fa][fa_ref_edges[k][0]-1]-1]; + int w2 = el[ref_faces[fa][fa_ref_edges[k][1]-1]-1]; + + if(withorientation) + { + if(w1==vi1 && w2==vi2) + fedges[k] = eledges[j]; + if(w1==vi2 && w2==vi1) + fedges[k] = -eledges[j]; + } + else + if((w1==vi1 && w2==vi2) || (w1==vi2 && w2==vi1)) + fedges[k] = eledges[j]; + } + } + } + + // *testout << " Face " << fnr << endl; + // *testout << " GetFaceEdges " << fedges << endl; + + return; + } + } +} + + +ELEMENT_TYPE MeshTopology :: GetFaceType (int fnr) const +{ + if (face2vert.Get(fnr)[3] == 0) return TRIG; else return QUAD; +} + + +void MeshTopology :: GetVertexElements (int vnr, ARRAY<int> & elements) const +{ + if (vert2element) + { + int i; + int ne = vert2element->EntrySize(vnr); + elements.SetSize(ne); + for (i = 1; i <= ne; i++) + elements.Elem(i) = vert2element->Get(vnr, i); + } +} + + +FlatArray<int> MeshTopology :: GetVertexElements (int vnr) const +{ + if (vert2element) + return (*vert2element)[vnr]; + return FlatArray<int> (0,0); +} + +FlatArray<int> MeshTopology :: GetVertexSurfaceElements (int vnr) const +{ + if (vert2surfelement) + return (*vert2surfelement)[vnr]; + return FlatArray<int> (0,0); +} + + +void MeshTopology :: GetVertexSurfaceElements( int vnr, + ARRAY<int>& elements ) const +{ + if (vert2surfelement) + { + int i; + int ne = vert2surfelement->EntrySize(vnr); + elements.SetSize(ne); + for (i = 1; i <= ne; i++) + elements.Elem(i) = vert2surfelement->Get(vnr, i); + } +} + + +int MeshTopology :: GetVerticesEdge ( int v1, int v2 ) const +{ + ARRAY<int> elements_v1, elementedges; + GetVertexElements ( v1, elements_v1); + int edv1, edv2; + + for ( int i = 0; i < elements_v1.Size(); i++ ) + { + GetElementEdges( elements_v1[i], elementedges ); + for ( int ed = 0; ed < elementedges.Size(); ed ++) + { + GetEdgeVertices( elementedges[ed], edv1, edv2 ); + if ( ( edv1 == v1 && edv2 == v2 ) || ( edv1 == v2 && edv2 == v1 ) ) + return elementedges[ed]; + } + } + + return -1; +} + + + +void MeshTopology :: GetSegmentVolumeElements ( int segnr, ARRAY<int> & volels ) const +{ + int v1, v2; + GetEdgeVertices ( GetSegmentEdge (segnr), v1, v2 ); + ARRAY<int> volels1, volels2; + GetVertexElements ( v1, volels1 ); + GetVertexElements ( v2, volels2 ); + volels.SetSize(0); + + for ( int eli1=1; eli1 <= volels1.Size(); eli1++) + if ( volels2.Contains( volels1.Elem(eli1) ) ) + volels.Append ( volels1.Elem(eli1) ); + +} +} diff --git a/contrib/Netgen/libsrc/meshing/topology.hpp b/contrib/Netgen/libsrc/meshing/topology.hpp new file mode 100644 index 0000000000000000000000000000000000000000..be1a3456dcfc099a441a4d3de907a9c724b404ac --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/topology.hpp @@ -0,0 +1,325 @@ +#ifndef TOPOLOGY +#define TOPOLOGY + +/**************************************************************************/ +/* File: topology.hh */ +/* Author: Joachim Schoeberl */ +/* Date: 27. Apr. 01 */ +/**************************************************************************/ + +/* + Mesh topology + (Elements, Faces, Edges, Vertices +*/ + + +class MeshTopology +{ + const Mesh & mesh; + bool buildedges; + bool buildfaces; + + MoveableArray<INDEX_2> edge2vert; + MoveableArray<INDEX_4> face2vert; + MoveableArray<int[12]> edges; + MoveableArray<int[6]> faces; + MoveableArray<int[4]> surfedges; + MoveableArray<int> segedges; + MoveableArray<int> surffaces; + MoveableArray<INDEX_2> surf2volelement; + MoveableArray<int> face2surfel; + TABLE<int,PointIndex::BASE> *vert2element; + TABLE<int,PointIndex::BASE> *vert2surfelement; + TABLE<int,PointIndex::BASE> *vert2segment; + int timestamp; +public: + int GetNSurfedges() const {return surfedges.Size();} + + MeshTopology (const Mesh & amesh); + ~MeshTopology (); + + void SetBuildEdges (bool be) + { buildedges = be; } + void SetBuildFaces (bool bf) + { buildfaces = bf; } + + bool HasEdges () const + { return buildedges; } + bool HasFaces () const + { return buildfaces; } + + void Update(); + + + int GetNEdges () const + { return edge2vert.Size(); } + int GetNFaces () const + { return face2vert.Size(); } + + static int GetNVertices (ELEMENT_TYPE et); + static int GetNEdges (ELEMENT_TYPE et); + static int GetNFaces (ELEMENT_TYPE et); + + static const Point3d * GetVertices (ELEMENT_TYPE et); + inline static const ELEMENT_EDGE * GetEdges (ELEMENT_TYPE et); + inline static const ELEMENT_FACE * GetFaces (ELEMENT_TYPE et); + + + int GetSegmentEdge (int segnr) const { return abs(segedges[segnr-1]); } + int GetSegmentEdgeOrientation (int segnr) const { return sgn(segedges[segnr-1]); } + + void GetSegmentEdge (int segnr, int & enr, int & orient) const + { + enr = abs(segedges.Get(segnr)); + orient = segedges.Get(segnr) > 0 ? 1 : -1; + } + + void GetElementEdges (int elnr, ARRAY<int> & edges) const; + void GetElementFaces (int elnr, ARRAY<int> & faces, bool withorientation = false) const; + void GetElementEdgeOrientations (int elnr, ARRAY<int> & eorient) const; + void GetElementFaceOrientations (int elnr, ARRAY<int> & forient) const; + + int GetElementEdges (int elnr, int * edges, int * orient) const; + int GetElementFaces (int elnr, int * faces, int * orient) const; + + void GetFaceVertices (int fnr, ARRAY<int> & vertices) const; + void GetFaceVertices (int fnr, int * vertices) const; + void GetEdgeVertices (int fnr, int & v1, int & v2) const; + void GetFaceEdges (int fnr, ARRAY<int> & edges, bool withorientation = false) const; + + ELEMENT_TYPE GetFaceType (int fnr) const; + + void GetSurfaceElementEdges (int elnr, ARRAY<int> & edges) const; + int GetSurfaceElementFace (int elnr) const; + void GetSurfaceElementEdgeOrientations (int elnr, ARRAY<int> & eorient) const; + int GetSurfaceElementFaceOrientation (int elnr) const; + + int GetSurfaceElementEdges (int elnr, int * edges, int * orient) const; + + void GetSurface2VolumeElement (int selnr, int & elnr1, int & elnr2) const + { + elnr1 = surf2volelement.Get(selnr)[0]; + elnr2 = surf2volelement.Get(selnr)[1]; + } + + int GetFace2SurfaceElement (int fnr) const { return face2surfel[fnr-1]; } + + void GetVertexElements (int vnr, ARRAY<int> & elements) const; + FlatArray<int> GetVertexElements (int vnr) const; + + void GetVertexSurfaceElements( int vnr, ARRAY<int>& elements ) const; + FlatArray<int> GetVertexSurfaceElements (int vnr) const; + + + + int GetVerticesEdge ( int v1, int v2) const; + void GetSegmentVolumeElements ( int segnr, ARRAY<int> & surfels ) const; +}; + + + + + + + + + + + + + +const ELEMENT_EDGE * MeshTopology :: GetEdges (ELEMENT_TYPE et) +{ + static int segm_edges[1][2] = + { { 1, 2 }}; + + static int trig_edges[3][2] = + { { 3, 1 }, + { 2, 3 }, + { 1, 2 }}; + + static int quad_edges[4][2] = + { { 1, 2 }, + { 3, 4 }, + { 4, 1 }, + { 2, 3 }}; + + + static int tet_edges[6][2] = + { { 4, 1 }, + { 4, 2 }, + { 4, 3 }, + { 1, 2 }, + { 1, 3 }, + { 2, 3 }}; + + static int prism_edges[9][2] = + { { 3, 1 }, + { 1, 2 }, + { 3, 2 }, + { 6, 4 }, + { 4, 5 }, + { 6, 5 }, + { 3, 6 }, + { 1, 4 }, + { 2, 5 }}; + + static int pyramid_edges[8][2] = + { { 1, 2 }, + { 2, 3 }, + { 1, 4 }, + { 4, 3 }, + { 1, 5 }, + { 2, 5 }, + { 3, 5 }, + { 4, 5 }}; + + static int hex_edges[12][2] = + { + { 1, 2 }, + { 3, 4 }, + { 4, 1 }, + { 2, 3 }, + { 5, 6 }, + { 7, 8 }, + { 8, 5 }, + { 6, 7 }, + { 1, 5 }, + { 2, 6 }, + { 3, 7 }, + { 4, 8 }, + }; + + switch (et) + { + case SEGMENT: + case SEGMENT3: + return segm_edges; + + case TRIG: + case TRIG6: + return trig_edges; + + case QUAD: + case QUAD6: + case QUAD8: + return quad_edges; + + case TET: + case TET10: + return tet_edges; + + case PYRAMID: + return pyramid_edges; + + case PRISM: + case PRISM12: + return prism_edges; + + case HEX: + return hex_edges; + default: + cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; + } + return 0; +} + + +const ELEMENT_FACE * MeshTopology :: GetFaces (ELEMENT_TYPE et) +{ + static const int trig_faces[1][4] = + { { 1, 2, 3, 0 } }; + static const int quad_faces[1][4] = + { { 1, 2, 3, 4 } }; + + static const int tet_faces[4][4] = + { { 4, 2, 3, 0 }, + { 4, 3, 1, 0 }, + { 4, 1, 2, 0 }, + { 1, 3, 2, 0 } }; + + static const int prism_faces[5][4] = + { + { 1, 3, 2, 0 }, + { 4, 5, 6, 0 }, + { 3, 1, 4, 6 }, + { 1, 2, 5, 4 }, + { 2, 3, 6, 5 } + }; + + static const int pyramid_faces[5][4] = + { + { 1, 2, 5, 0 }, + { 2, 3, 5, 0 }, + { 3, 4, 5, 0 }, + { 4, 1, 5, 0 }, + { 1, 4, 3, 2 } + }; + + static const int hex_faces[6][4] = + { + { 1, 4, 3, 2 }, + { 5, 6, 7, 8 }, + { 1, 2, 6, 5 }, + { 2, 3, 7, 6 }, + { 3, 4, 8, 7 }, + { 4, 1, 5, 8 } + }; + + + + switch (et) + { + case TRIG: + case TRIG6: + return trig_faces; + + case QUAD: + case QUAD6: + case QUAD8: + return quad_faces; + + + case TET: + case TET10: + return tet_faces; + + case PRISM: + case PRISM12: + return prism_faces; + + case PYRAMID: + return pyramid_faces; + + case SEGMENT: + case SEGMENT3: + + case HEX: + return hex_faces; + + default: + cerr << "Ng_ME_GetVertices, illegal element type " << et << endl; + } + return 0; +} + + + + + + + + + + + + + + + + + + + + +#endif diff --git a/contrib/Netgen/libsrc/meshing/triarls.cpp b/contrib/Netgen/libsrc/meshing/triarls.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d82806e9bcbd9cf9f5b8a90306e1cee23c0bf4bc --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/triarls.cpp @@ -0,0 +1,468 @@ +namespace netgen +{ +const char * triarules[] = { +"rule \"Free Triangle (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0) { 1.0, 0, 1.0 };\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 0.5 X2 } { };\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.7) { 0.5 X2 } { };\n",\ +"(0.5, 1.5) { 0.5 X2 } { };\n",\ +"(-0.5, 0.7) { 0.5 X2 } { };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.866) { 0.5 X2 } { };\n",\ +"(0.5, 0.866) { 0.5 X2 } { };\n",\ +"(0.5, 0.866) { 0.5 X2 } { };\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"Free Triangle (5)\"\n",\ +"\n",\ +"quality 5\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0) { 1.0, 0, 1.0 };\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.5) { 0.5 X2 } { };\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.7) { 1 X2 } { };\n",\ +"(0, 0.7) { } { };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.5) { 0.5 X2 } { };\n",\ +"(0.5, 0.5) { 0.5 X2 } { };\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Free Triangle (10)\"\n",\ +"\n",\ +"quality 10\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0) { 1.0, 0, 1.0 };\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.3) { 0.5 X2 } { };\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.5) { 1 X2 } { };\n",\ +"(0, 0.5) { } { };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.3) { 0.5 X2 } { };\n",\ +"(0.5, 0.3) { 0.5 X2 } { };\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Free Triangle (20)\"\n",\ +"\n",\ +"quality 20\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0) { 1.0, 0, 1.0 };\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.1) { 0.5 X2 } { };\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1, 0.2) { 1 X2 } { };\n",\ +"(0, 0.2) { } { };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.1) { 0.5 X2 } { };\n",\ +"(0.5, 0.1) { 0.5 X2 } { };\n",\ +"\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Right 60 (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0) { 0.5, 0, 1.0 };\n",\ +"(0.5, 0.866) { 0.6, 0, 0.8 };\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(-0.125, 0.6495) { -0.5 X2, 0.75 X3 } { -0.5 Y2, 0.75 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left 60 (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.125, 0.6495) { 0.75 X2, 0.75 X3 } { 0.75 Y3 };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Right 120 (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 1 X3, -1 X2 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 4);\n",\ +"(4, 3);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(1, 1.732) { -2 X2, 2 X3 } { 2 Y3 };\n",\ +"(0, 1.732) { -3 X2, 2 X3 } { 2 Y3 };\n",\ +"(-0.5, 0.866) { -2 X2, 1 X3 } {1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4);\n",\ +"(2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left 120 (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(-0.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 1 X3, 1 X2 } { 1 Y3 };\n",\ +"\n",\ +"newlines\n",\ +"(3, 4);\n",\ +"(4, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.866) { 2 X2, 1 X3 } { 1 Y3 };\n",\ +"(1, 1.732) { 2 X2, 2 X3 } { 2 Y3 };\n",\ +"(0, 1.732) { -1 X2, 2 X3 } { 2 Y3 };\n",\ +"(-0.5, 0.866) { 1 X3 } {1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 4);\n",\ +"(2, 3, 4);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Left Right 120 (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(-0.5, 0.866);\n",\ +"(1.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 1) del;\n",\ +"(2, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 0.5 X3, 0.5 X4 } { 0.5 Y3, 0.5 Y4 };\n",\ +"\n",\ +"newlines\n",\ +"(3, 5);\n",\ +"(5, 4);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.5, 0.866) { 1 X4 } { 1 Y4 };\n",\ +"(1, 1.299) { -0.5 X2, 0.375 X3, 1.125 X4 } { -0.5 Y2, 0.375 Y3, 1.125 Y4 };\n",\ +"(0, 1.299) { 1.125 X3, 0.375 X4 } { 1.125 Y3, 0.375 Y4 };\n",\ +"(-0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 5);\n",\ +"(3, 1, 5);\n",\ +"(2, 4, 5);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"rule \"Fill Triangle\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(2, 3) del;\n",\ +"(3, 1) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { 1 Y2 };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"Vis A Vis (1)\"\n",\ +"\n",\ +"quality 1\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(0.5, 0.866);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"\n",\ +"newpoints\n",\ +"\n",\ +"newlines\n",\ +"(1, 3);\n",\ +"(3, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(1.2, 0.693) { 0.8 X2, 0.8 X3 } { 0.8 Y2, 0.8 Y3 };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(-0.2, 0.693) { -0.6 X2, 0.8 X3 } { -0.6 Y2, 0.8 Y3 };\n",\ +"\n",\ +"freearea2\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { };\n",\ +"(0.75, 0.433) { 0.5 X2, 0.5 X3 } { 0.5 Y2, 0.5 Y3 };\n",\ +"(0.5, 0.866) { 1 X3 } { 1 Y3 };\n",\ +"(0.25, 0.433) { 0.5 X3 } { 0.5 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 3);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"rule \"2 h Vis A Vis (1)\"\n",\ +"\n",\ +"quality 3\n",\ +"\n",\ +"mappoints\n",\ +"(0, 0);\n",\ +"(1, 0);\n",\ +"(1, 1.732);\n",\ +"(0, 1.732);\n",\ +"\n",\ +"maplines\n",\ +"(1, 2) del;\n",\ +"(3, 4) del;\n",\ +"\n",\ +"newpoints\n",\ +"(0.5, 0.866) { 0.25 X2, 0.25 X3, 0.25 X4 } { 0.25 Y2, 0.25 Y3, 0.25 Y4 };\n",\ +"\n",\ +"newlines\n",\ +"(1, 5);\n",\ +"(5, 4);\n",\ +"(3, 5);\n",\ +"(5, 2);\n",\ +"\n",\ +"freearea\n",\ +"(0, 0);\n",\ +"(1, 0) { 1 X2 } { 1 Y2 };\n",\ +"(1.5, 0.866) { 0.75 X2, 0.75 X3, -0.25 X4 } { 0.75 Y2, 0.75 Y3, -0.25 Y4 };\n",\ +"(1, 1.732) { 1 X3 } { 1 Y3 };\n",\ +"(0, 1.732) { 1 X4 } { 1 Y4 };\n",\ +"(-0.5, 0.866) { 0.75 X4, -0.25 X2, -0.25 X3 } { 0.75 Y4, -0.25 Y3 };\n",\ +"\n",\ +"elements\n",\ +"(1, 2, 5);\n",\ +"(3, 4, 5);\n",\ +"\n",\ +"endrule\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +"\n",\ +0}; +} diff --git a/contrib/Netgen/libsrc/meshing/validate.cpp b/contrib/Netgen/libsrc/meshing/validate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d519e27c25d58a8779a7e9a00b2784b5624f30f6 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/validate.cpp @@ -0,0 +1,587 @@ + +#include <mystdlib.h> +#include "meshing.hpp" + + +namespace netgen +{ + void GetPureBadness(Mesh & mesh, ARRAY<double> & pure_badness, + const BitArray & isnewpoint) + { + //const int ne = mesh.GetNE(); + const int np = mesh.GetNP(); + + pure_badness.SetSize(np+PointIndex::BASE+1); + pure_badness = -1; + + ARRAY< Point<3>* > backup(np); + + for(int i=0; i<np; i++) + { + backup[i] = new Point<3>(mesh.Point(i+1)); + + if(isnewpoint.Test(i+PointIndex::BASE) && + mesh.mlbetweennodes[i+PointIndex::BASE][0] > 0) + { + mesh.Point(i+1) = Center(mesh.Point(mesh.mlbetweennodes[i+PointIndex::BASE][0]), + mesh.Point(mesh.mlbetweennodes[i+PointIndex::BASE][1])); + } + } + for (ElementIndex i = 0; i < mesh.GetNE(); i++) + { + double bad = mesh[i].CalcJacobianBadness (mesh.Points()); + for(int j=0; j<mesh[i].GetNP(); j++) + if(bad > pure_badness[mesh[i][j]]) + pure_badness[mesh[i][j]] = bad; + + // save maximum + if(bad > pure_badness.Last()) + pure_badness.Last() = bad; + } + + for(int i=0; i<np; i++) + { + mesh.Point(i+1) = *backup[i]; + delete backup[i]; + } + } + + + double Validate(const Mesh & mesh, ARRAY<ElementIndex> & bad_elements, + const ARRAY<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + ARRAY<double> * quality_loss) + { + PrintMessage(3,"!!!! Validating !!!!"); + //if(max_worsening > 0) + // (*testout) << "badness " << counter++ << endl; + + bad_elements.SetSize(0); + + double loc_pure_badness = -1; + + if(!uselocalworsening) + loc_pure_badness = pure_badness.Last(); // maximum is saved at last position + + + double worsening = -1; + ElementIndex ind; + + if(quality_loss != NULL) + quality_loss->SetSize(mesh.GetNE()); + + for (ElementIndex i = 0; i < mesh.GetNE(); i++) + { + if(uselocalworsening) + { + loc_pure_badness = -1; + for(int j=0; j<mesh[i].GetNP(); j++) + if(pure_badness[mesh[i][j]] > loc_pure_badness) + loc_pure_badness = pure_badness[mesh[i][j]]; + } + + + double bad = mesh[i].CalcJacobianBadness (mesh.Points()); + if (bad > 1e10 || + (max_worsening > 0 && bad > loc_pure_badness*max_worsening)) + bad_elements.Append(i); + + + if(max_worsening > 0) + { + double actw = bad/loc_pure_badness; + if(quality_loss != NULL) + (*quality_loss)[i] = actw; + + if(actw > worsening) + { + worsening = actw; + ind = i; + } + } + } + return worsening; + } + + + void GetWorkingArea(BitArray & working_elements, BitArray & working_points, + const Mesh & mesh, const ARRAY<ElementIndex> & bad_elements, + const int width) + { + working_elements.Clear(); + working_points.Clear(); + + for(int i=0; i<bad_elements.Size(); i++) + { + working_elements.Set(bad_elements[i]); + const Element & el = mesh[bad_elements[i]]; + for(int j=1; j<=el.GetNP(); j++) + working_points.Set(el.PNum(j)); + } + + + for(int i=0; i<width; i++) + { + for(ElementIndex j=0; j<mesh.GetNE(); j++) + { + if(!working_elements.Test(j)) + { + const Element & el = mesh[j]; + bool set_active = false; + + for(int k=1; !set_active && k<=el.GetNP(); k++) + set_active = working_points.Test(el.PNum(k)); + + if(set_active) + working_elements.Set(j); + } + } + + for(ElementIndex j=0; j<mesh.GetNE(); j++) + { + if(working_elements.Test(j)) + { + const Element & el = mesh[j]; + for(int k=1; k<=el.GetNP(); k++) + working_points.Set(el.PNum(k)); + } + } + } + } + + + + void RepairBisection(Mesh & mesh, ARRAY<ElementIndex> & bad_elements, + const BitArray & isnewpoint, Refinement & refinement, + const ARRAY<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + const ARRAY< ARRAY<int,PointIndex::BASE>* > & idmaps) + { + ostringstream ostrstr; + + const int maxtrials = 100; + + //bool doit; + //cout << "DOIT: " << flush; + //cin >> doit; + + int ne = mesh.GetNE(); + int np = mesh.GetNP(); + + int numbadneighbours = 3; + const int numtopimprove = 3; + + PrintMessage(1,"repairing"); + + PushStatus("Repair Bisection"); + + ARRAY<Point<3>* > should(np); + ARRAY<Point<3>* > can(np); + ARRAY<Vec<3>* > nv(np); + for(int i=0; i<np; i++) + { + nv[i] = new Vec<3>; + should[i] = new Point<3>; + can[i] = new Point<3>; + } + + BitArray isboundarypoint(np),isedgepoint(np); + isboundarypoint.Clear(); + isedgepoint.Clear(); + + for(int i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + isedgepoint.Set(seg.p1); + isedgepoint.Set(seg.p2); + } + + ARRAY<int> surfaceindex(np); + surfaceindex = -1; + + for (int i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + for (int j = 1; j <= sel.GetNP(); j++) + if(!isedgepoint.Test(sel.PNum(j))) + { + isboundarypoint.Set(sel.PNum(j)); + surfaceindex[sel.PNum(j) - PointIndex::BASE] = + mesh.GetFaceDescriptor(sel.GetIndex()).SurfNr(); + } + } + + + + Validate(mesh,bad_elements,pure_badness, + ((uselocalworsening) ? (0.8*(max_worsening-1.) + 1.) : (0.1*(max_worsening-1.) + 1.)), + uselocalworsening); // -> larger working area + BitArray working_elements(ne); + BitArray working_points(np); + + GetWorkingArea(working_elements,working_points,mesh,bad_elements,numbadneighbours); + //working_elements.Set(); + //working_points.Set(); + + ostrstr.str(""); + ostrstr << "worsening: " << + Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); + PrintMessage(4,ostrstr.str()); + + + + int auxnum=0; + for(int i=1; i<=np; i++) + if(working_points.Test(i)) + auxnum++; + + ostrstr.str(""); + ostrstr << "Percentage working points: " << 100.*double(auxnum)/np; + PrintMessage(5,ostrstr.str()); + + + BitArray isworkingboundary(np); + for(int i=1; i<=np; i++) + if(working_points.Test(i) && isboundarypoint.Test(i)) + isworkingboundary.Set(i); + else + isworkingboundary.Clear(i); + + + for(int i=0; i<np; i++) + *should[i] = mesh.Point(i+1); + + + for(int i=0; i<np; i++) + { + if(isnewpoint.Test(i+PointIndex::BASE) && + //working_points.Test(i+PointIndex::BASE) && + mesh.mlbetweennodes[i+PointIndex::BASE][0] > 0) + *can[i] = Center(*can[mesh.mlbetweennodes[i+PointIndex::BASE][0]-PointIndex::BASE], + *can[mesh.mlbetweennodes[i+PointIndex::BASE][1]-PointIndex::BASE]); + else + *can[i] = mesh.Point(i+1); + } + + + int cnttrials = 1; + + double lamedge = 0.5; + double lamface = 0.5; + + double facokedge = 0; + double facokface = 0; + double factryedge; + double factryface = 0; + + double oldlamedge,oldlamface; + + MeshOptimize2d * optimizer2d = refinement.Get2dOptimizer(); + if(!optimizer2d) + { + cerr << "No 2D Optimizer!" << endl; + return; + } + + while ((facokedge < 1.-1e-8 || facokface < 1.-1e-8) && + cnttrials < maxtrials && + multithread.terminate != 1) + { + (*testout) << " facokedge " << facokedge << " facokface " << facokface << " cnttrials " << cnttrials << endl + << " perc. " << 95. * max2( min2(facokedge,facokface), + double(cnttrials)/double(maxtrials)) << endl; + + SetThreadPercent(95. * max2( min2(facokedge,facokface), + double(cnttrials)/double(maxtrials))); + + ostrstr.str(""); + ostrstr << "max. worsening " << max_worsening; + PrintMessage(5,ostrstr.str()); + oldlamedge = lamedge; + lamedge *= 6; + if (lamedge > 2) + lamedge = 2; + + if(1==1 || facokedge < 1.-1e-8) + { + for(int i=0; i<nv.Size(); i++) + *nv[i] = Vec<3>(0,0,0); + for (int i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + Vec<3> auxvec = Cross(mesh.Point(sel.PNum(2))-mesh.Point(sel.PNum(1)), + mesh.Point(sel.PNum(3))-mesh.Point(sel.PNum(1))); + auxvec.Normalize(); + for (int j = 1; j <= sel.GetNP(); j++) + if(!isedgepoint.Test(sel.PNum(j))) + *nv[sel.PNum(j) - PointIndex::BASE] += auxvec; + } + for(int i=0; i<nv.Size(); i++) + nv[i]->Normalize(); + + + do // move edges + { + lamedge *= 0.5; + cnttrials++; + if(cnttrials % 10 == 0) + max_worsening *= 1.1; + + + factryedge = lamedge + (1.-lamedge) * facokedge; + + ostrstr.str(""); + ostrstr << "lamedge = " << lamedge << ", trying: " << factryedge; + PrintMessage(5,ostrstr.str()); + + + for (int i = 1; i <= np; i++) + { + if (isedgepoint.Test(i)) + { + for (int j = 0; j < 3; j++) + mesh.Point(i)(j) = + lamedge * (*should.Get(i))(j) + + (1.-lamedge) * (*can.Get(i))(j); + } + else + mesh.Point(i) = *can.Get(i); + } + if(facokedge < 1.-1e-8) + { + ostrstr.str(""); + ostrstr << "worsening: " << + Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); + + PrintMessage(5,ostrstr.str()); + } + else + Validate(mesh,bad_elements,pure_badness,-1,uselocalworsening); + + + ostrstr.str(""); + ostrstr << bad_elements.Size() << " bad elements"; + PrintMessage(5,ostrstr.str()); + } + while (bad_elements.Size() > 0 && + cnttrials < maxtrials && + multithread.terminate != 1); + } + + if(cnttrials < maxtrials && + multithread.terminate != 1) + { + facokedge = factryedge; + + // smooth faces + mesh.CalcSurfacesOfNode(); + + mesh.ImproveMeshJacobianOnSurface(isworkingboundary,nv,OPT_QUALITY,&idmaps); + + for (int i = 1; i <= np; i++) + *can.Elem(i) = mesh.Point(i); + + if(optimizer2d) + optimizer2d->ProjectBoundaryPoints(surfaceindex,can,should); + } + + + oldlamface = lamface; + lamface *= 6; + if (lamface > 2) + lamface = 2; + + + if(cnttrials < maxtrials && + multithread.terminate != 1) + { + + do // move faces + { + lamface *= 0.5; + cnttrials++; + if(cnttrials % 10 == 0) + max_worsening *= 1.1; + factryface = lamface + (1.-lamface) * facokface; + + ostrstr.str(""); + ostrstr << "lamface = " << lamface << ", trying: " << factryface; + PrintMessage(5,ostrstr.str()); + + + for (int i = 1; i <= np; i++) + { + if (isboundarypoint.Test(i)) + { + for (int j = 0; j < 3; j++) + mesh.Point(i)(j) = + lamface * (*should.Get(i))(j) + + (1.-lamface) * (*can.Get(i))(j); + } + else + mesh.Point(i) = *can.Get(i); + } + + ostrstr.str(""); + ostrstr << "worsening: " << + Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); + PrintMessage(5,ostrstr.str()); + + + ostrstr.str(""); + ostrstr << bad_elements.Size() << " bad elements"; + PrintMessage(5,ostrstr.str()); + } + while (bad_elements.Size() > 0 && + cnttrials < maxtrials && + multithread.terminate != 1); + } + + + + if(cnttrials < maxtrials && + multithread.terminate != 1) + { + facokface = factryface; + // smooth interior + + mesh.CalcSurfacesOfNode(); + + mesh.ImproveMeshJacobian (OPT_QUALITY,&working_points); + //mesh.ImproveMeshJacobian (OPT_WORSTCASE,&working_points); + + + for (int i = 1; i <= np; i++) + *can.Elem(i) = mesh.Point(i); + } + + //! + if((facokedge < 1.-1e-8 || facokface < 1.-1e-8) && + cnttrials < maxtrials && + multithread.terminate != 1) + { + MeshOptimize3d optmesh; + for(int i=0; i<numtopimprove; i++) + { + optmesh.SwapImproveSurface(mesh,OPT_QUALITY,&working_elements,&idmaps); + optmesh.SwapImprove(mesh,OPT_QUALITY,&working_elements); + + } + + // mesh.mglevels = 1; + + + ne = mesh.GetNE(); + working_elements.SetSize(ne); + + + for (int i = 1; i <= np; i++) + mesh.Point(i) = *should.Elem(i); + + Validate(mesh,bad_elements,pure_badness, + ((uselocalworsening) ? (0.8*(max_worsening-1.) + 1.) : (0.1*(max_worsening-1.) + 1.)), + uselocalworsening); + + if(lamedge < oldlamedge || lamface < oldlamface) + numbadneighbours++; + GetWorkingArea(working_elements,working_points,mesh,bad_elements,numbadneighbours); + for(int i=1; i<=np; i++) + if(working_points.Test(i) && isboundarypoint.Test(i)) + isworkingboundary.Set(i); + else + isworkingboundary.Clear(i); + auxnum=0; + for(int i=1; i<=np; i++) + if(working_points.Test(i)) + auxnum++; + + + ostrstr.str(""); + ostrstr << "Percentage working points: " << 100.*double(auxnum)/np; + PrintMessage(5,ostrstr.str()); + + for (int i = 1; i <= np; i++) + mesh.Point(i) = *can.Elem(i); + } + //! + + } + + MeshOptimize3d optmesh; + for(int i=0; i<numtopimprove && multithread.terminate != 1; i++) + { + optmesh.SwapImproveSurface(mesh,OPT_QUALITY,NULL,&idmaps); + optmesh.SwapImprove(mesh,OPT_QUALITY); + //mesh.UpdateTopology(); + } + mesh.UpdateTopology(); + /* + if(cnttrials < 100) + { + nv = Vec3d(0,0,0); + for (int i = 1; i <= mesh.GetNSE(); i++) + { + const Element2d & sel = mesh.SurfaceElement(i); + Vec3d auxvec = Cross(mesh.Point(sel.PNum(2))-mesh.Point(sel.PNum(1)), + mesh.Point(sel.PNum(3))-mesh.Point(sel.PNum(1))); + auxvec.Normalize(); + for (int j = 1; j <= sel.GetNP(); j++) + if(!isedgepoint.Test(sel.PNum(j))) + nv[sel.PNum(j) - PointIndex::BASE] += auxvec; + } + for(int i=0; i<nv.Size(); i++) + nv[i].Normalize(); + + + mesh.ImproveMeshJacobianOnSurface(isboundarypoint,nv,OPT_QUALITY); + mesh.CalcSurfacesOfNode(); + // smooth interior + + + for (int i = 1; i <= np; i++) + if(isboundarypoint.Test(i)) + can.Elem(i) = mesh.Point(i); + + if(optimizer2d) + optimizer2d->ProjectBoundaryPoints(surfaceindex,can,should); + + + for (int i = 1; i <= np; i++) + if(isboundarypoint.Test(i)) + for(int j=1; j<=3; j++) + mesh.Point(i).X(j) = should.Get(i).X(j); + } + */ + + + if(cnttrials == maxtrials) + { + for (int i = 1; i <= np; i++) + mesh.Point(i) = *should.Get(i); + + Validate(mesh,bad_elements,pure_badness,max_worsening,uselocalworsening); + + for(int i=0; i<bad_elements.Size(); i++) + { + ostrstr.str(""); + ostrstr << "bad element:" << endl + << mesh[bad_elements[i]][0] << ": " << mesh.Point(mesh[bad_elements[i]][0]) << endl + << mesh[bad_elements[i]][1] << ": " << mesh.Point(mesh[bad_elements[i]][1]) << endl + << mesh[bad_elements[i]][2] << ": " << mesh.Point(mesh[bad_elements[i]][2]) << endl + << mesh[bad_elements[i]][3] << ": " << mesh.Point(mesh[bad_elements[i]][3]); + PrintMessage(5,ostrstr.str()); + } + for (int i = 1; i <= np; i++) + mesh.Point(i) = *can.Get(i); + } + + for(int i=0; i<np; i++) + { + delete nv[i]; + delete can[i]; + delete should[i]; + } + + PopStatus(); + } +} diff --git a/contrib/Netgen/libsrc/meshing/validate.hpp b/contrib/Netgen/libsrc/meshing/validate.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5f898c179db6cb9105660b4cf637c8982eec9320 --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/validate.hpp @@ -0,0 +1,17 @@ +#ifndef VALIDATE_HPP +#define VALIDATE_HPP + + + +void GetPureBadness(Mesh & mesh, ARRAY<double> & pure_badness, + const BitArray & isnewpoint); +double Validate(const Mesh & mesh, ARRAY<ElementIndex> & bad_elements, + const ARRAY<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + ARRAY<double> * quality_loss = NULL); +void RepairBisection(Mesh & mesh, ARRAY<ElementIndex> & bad_elements, const BitArray & isnewpoint, Refinement & refinement, + const ARRAY<double> & pure_badness, + double max_worsening, const bool uselocalworsening, + const ARRAY< ARRAY<int,PointIndex::BASE>* > & idmaps); + +#endif // VALIDATE_HPP diff --git a/contrib/Netgen/libsrc/meshing/zrefine.cpp b/contrib/Netgen/libsrc/meshing/zrefine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13e02bbaf955b4ce5a1b084a10f01d261c6435be --- /dev/null +++ b/contrib/Netgen/libsrc/meshing/zrefine.cpp @@ -0,0 +1,742 @@ +#include <mystdlib.h> +#include "meshing.hpp" + +#include <csg.hpp> + + +namespace netgen +{ + + // find singular edges + void SelectSingularEdges (const Mesh & mesh, const CSGeometry & geom, + INDEX_2_HASHTABLE<int> & singedges, + ZRefinementOptions & opt) + { + int i, j; + + // edges selected in csg input file + for (i = 1; i <= geom.singedges.Size(); i++) + { + //if(geom.singedges.Get(i)->maxhinit > 0) + // continue; //!!!! + + const SingularEdge & se = *geom.singedges.Get(i); + for (j = 1; j <= se.segms.Size(); j++) + { + INDEX_2 i2 = se.segms.Get(j); + singedges.Set (i2, 1); + } + } + + // edges interactively selected + for (i = 1; i <= mesh.GetNSeg(); i++) + { + const Segment & seg = mesh.LineSegment(i); + if (seg.singedge_left || seg.singedge_right) + { + INDEX_2 i2(seg.p1, seg.p2); + i2.Sort(); + singedges.Set (i2, 1); + } + } + } + + + /** + Convert elements (vol-tets, surf-trigs) into prisms/quads + */ + void MakePrismsSingEdge (Mesh & mesh, INDEX_2_HASHTABLE<int> & singedges) + { + int i, j, k; + + // volume elements + for (i = 1; i <= mesh.GetNE(); i++) + { + Element & el = mesh.VolumeElement(i); + if (el.GetType() != TET) continue; + + for (j = 1; j <= 3; j++) + for (k = j+1; k <= 4; k++) + { + INDEX_2 edge(el.PNum(j), el.PNum(k)); + edge.Sort(); + if (singedges.Used (edge)) + { + int pi3 = 1, pi4 = 1; + while (pi3 == j || pi3 == k) pi3++; + pi4 = 10 - j - k - pi3; + + int p3 = el.PNum(pi3); + int p4 = el.PNum(pi4); + + el.SetType(PRISM); + el.PNum(1) = edge.I1(); + el.PNum(2) = p3; + el.PNum(3) = p4; + el.PNum(4) = edge.I2(); + el.PNum(5) = p3; + el.PNum(6) = p4; + } + } + } + + // surface elements + for (i = 1; i <= mesh.GetNSE(); i++) + { + Element2d & el = mesh.SurfaceElement(i); + if (el.GetType() != TRIG) continue; + + for (j = 1; j <= 3; j++) + { + k = (j % 3) + 1; + INDEX_2 edge(el.PNum(j), el.PNum(k)); + edge.Sort(); + + if (singedges.Used (edge)) + { + int pi3 = 6-j-k; + int p3 = el.PNum(pi3); + int p1 = el.PNum(j); + int p2 = el.PNum(k); + + el.SetType(QUAD); + el.PNum(1) = p2; + el.PNum(2) = p3; + el.PNum(3) = p3; + el.PNum(4) = p1; + } + } + } + } + + + /* + Convert tets and pyramids next to close (identified) points into prisms + */ + void MakePrismsClosePoints (Mesh & mesh) + { + int i, j, k; + for (i = 1; i <= mesh.GetNE(); i++) + { + Element & el = mesh.VolumeElement(i); + if (el.GetType() == TET) + { + for (j = 1; j <= 3; j++) + for (k = j+1; k <= 4; k++) + { + INDEX_2 edge(el.PNum(j), el.PNum(k)); + edge.Sort(); + if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k))) + { + int pi3 = 1, pi4 = 1; + while (pi3 == j || pi3 == k) pi3++; + pi4 = 10 - j - k - pi3; + + int p3 = el.PNum(pi3); + int p4 = el.PNum(pi4); + + el.SetType(PRISM); + el.PNum(1) = edge.I1(); + el.PNum(2) = p3; + el.PNum(3) = p4; + el.PNum(4) = edge.I2(); + el.PNum(5) = p3; + el.PNum(6) = p4; + } + } + } + + if (el.GetType() == PYRAMID) + { + // pyramid, base face = 1,2,3,4 + + for (j = 0; j <= 1; j++) + { + int pi1 = el.PNum( (j+0) % 4 + 1); + int pi2 = el.PNum( (j+1) % 4 + 1); + int pi3 = el.PNum( (j+2) % 4 + 1); + int pi4 = el.PNum( (j+3) % 4 + 1); + int pi5 = el.PNum(5); + + INDEX_2 edge1(pi1, pi4); + INDEX_2 edge2(pi2, pi3); + edge1.Sort(); + edge2.Sort(); + if (mesh.GetIdentifications().GetSymmetric (pi1, pi4) && + mesh.GetIdentifications().GetSymmetric (pi2, pi3)) + { + //int p3 = el.PNum(pi3); + //int p4 = el.PNum(pi4); + + el.SetType(PRISM); + el.PNum(1) = pi1; + el.PNum(2) = pi2; + el.PNum(3) = pi5; + el.PNum(4) = pi4; + el.PNum(5) = pi3; + el.PNum(6) = pi5; + } + } + } + } + + for (i = 1; i <= mesh.GetNSE(); i++) + { + Element2d & el = mesh.SurfaceElement(i); + if (el.GetType() != TRIG) continue; + + for (j = 1; j <= 3; j++) + { + k = (j % 3) + 1; + INDEX_2 edge(el.PNum(j), el.PNum(k)); + edge.Sort(); + + if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k))) + { + int pi3 = 6-j-k; + int p3 = el.PNum(pi3); + int p1 = el.PNum(j); + int p2 = el.PNum(k); + + el.SetType(QUAD); + el.PNum(1) = p2; + el.PNum(2) = p3; + el.PNum(3) = p3; + el.PNum(4) = p1; + } + } + } + } + + + +#ifdef OLD + void MakeCornerNodes (Mesh & mesh, + INDEX_HASHTABLE<int> & cornernodes) + { + int i, j; + int nseg = mesh.GetNSeg(); + ARRAY<int> edgesonpoint(mesh.GetNP()); + for (i = 1; i <= mesh.GetNP(); i++) + edgesonpoint.Elem(i) = 0; + + for (i = 1; i <= nseg; i++) + { + for (j = 1; j <= 2; j++) + { + int pi = (j == 1) ? + mesh.LineSegment(i).p1 : + mesh.LineSegment(i).p2; + edgesonpoint.Elem(pi)++; + } + } + + /* + cout << "cornernodes: "; + for (i = 1; i <= edgesonpoint.Size(); i++) + if (edgesonpoint.Get(i) >= 6) + { + cornernodes.Set (i, 1); + cout << i << " "; + } + cout << endl; + */ + // cornernodes.Set (5, 1); + } +#endif + + + void RefinePrisms (Mesh & mesh, const CSGeometry * geom, + ZRefinementOptions & opt) + { + int i, j; + bool found, change; + int cnt = 0; + + + // markers for z-refinement: p1, p2, levels + // p1-p2 is an edge to be refined + ARRAY<INDEX_3> ref_uniform; + ARRAY<INDEX_3> ref_singular; + ARRAY<INDEX_4 > ref_slices; + + BitArray first_id(geom->identifications.Size()); + first_id.Set(); + + + INDEX_2_HASHTABLE<int> & identpts = + mesh.GetIdentifications().GetIdentifiedPoints (); + + if (&identpts) + { + for (i = 1; i <= identpts.GetNBags(); i++) + for (j = 1; j <= identpts.GetBagSize(i); j++) + { + INDEX_2 pair; + int idnr; + identpts.GetData(i, j, pair, idnr); + const CloseSurfaceIdentification * csid = + dynamic_cast<const CloseSurfaceIdentification*> + (geom->identifications.Get(idnr)); + if (csid) + { + if (!csid->GetSlices().Size()) + { + if (first_id.Test (idnr)) + { + first_id.Clear(idnr); + ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels())); + ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1())); + ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2())); + } + } + else + { + //const ARRAY<double> & slices = csid->GetSlices(); + INDEX_4 i4; + i4[0] = pair.I1(); + i4[1] = pair.I2(); + i4[2] = idnr; + i4[3] = csid->GetSlices().Size(); + ref_slices.Append (i4); + } + } + } + } + + + + ARRAY<EdgePointGeomInfo> epgi; + + while (1) + { + cnt++; + PrintMessage (3, "Z-Refinement, level = ", cnt); + INDEX_2_HASHTABLE<int> refedges(mesh.GetNSE()+1); + + + found = 0; + // mark prisms due to close surface flags: + int oldsize = ref_uniform.Size(); + for (i = 1; i <= oldsize; i++) + { + int pi1 = ref_uniform.Get(i).I1(); + int pi2 = ref_uniform.Get(i).I2(); + int levels = ref_uniform.Get(i).I3(); + + if (levels > 0) + { + const Point3d & p1 = mesh.Point(pi1); + const Point3d & p2 = mesh.Point(pi2); + int npi(0); + + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (!refedges.Used(edge)) + { + Point3d np = Center (p1, p2); + npi = mesh.AddPoint (np); + refedges.Set (edge, npi); + found = 1; + } + + ref_uniform.Elem(i) = INDEX_3(pi1, npi, levels-1); + ref_uniform.Append (INDEX_3(pi2, npi, levels-1)); + } + } + for (i = 1; i <= ref_singular.Size(); i++) + { + int pi1 = ref_singular.Get(i).I1(); + int pi2 = ref_singular.Get(i).I2(); + int levels = ref_singular.Get(i).I3(); + + if (levels > 0) + { + const Point3d & p1 = mesh.Point(pi1); + const Point3d & p2 = mesh.Point(pi2); + int npi; + + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (!refedges.Used(edge)) + { + Point3d np = Center (p1, p2); + npi = mesh.AddPoint (np); + refedges.Set (edge, npi); + found = 1; + } + else + npi = refedges.Get (edge); + + ref_singular.Elem(i) = INDEX_3(pi1, npi, levels-1); + } + } + + for (i = 1; i <= ref_slices.Size(); i++) + { + int pi1 = ref_slices.Get(i)[0]; + int pi2 = ref_slices.Get(i)[1]; + int idnr = ref_slices.Get(i)[2]; + int slicenr = ref_slices.Get(i)[3]; + + if (slicenr > 0) + { + const Point3d & p1 = mesh.Point(pi1); + const Point3d & p2 = mesh.Point(pi2); + int npi; + + const CloseSurfaceIdentification * csid = + dynamic_cast<const CloseSurfaceIdentification*> + (geom->identifications.Get(idnr)); + + + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (!refedges.Used(edge)) + { + const ARRAY<double> & slices = csid->GetSlices(); + //(*testout) << "idnr " << idnr << " i " << i << endl; + //(*testout) << "slices " << slices << endl; + double slicefac = slices.Get(slicenr); + double slicefaclast = + (slicenr == slices.Size()) ? 1 : slices.Get(slicenr+1); + + Point3d np = p1 + (slicefac / slicefaclast) * (p2-p1); + //(*testout) << "slicenr " << slicenr << " slicefac " << slicefac << " quot " << (slicefac / slicefaclast) << " np " << np << endl; + npi = mesh.AddPoint (np); + refedges.Set (edge, npi); + found = 1; + } + else + npi = refedges.Get (edge); + + ref_slices.Elem(i)[1] = npi; + ref_slices.Elem(i)[3] --; + } + } + + + + + for (i = 1; i <= mesh.GetNE(); i++) + { + Element & el = mesh.VolumeElement (i); + if (el.GetType() != PRISM) + continue; + + for (j = 1; j <= 3; j++) + { + int pi1 = el.PNum(j); + int pi2 = el.PNum(j+3); + const Point3d & p1 = mesh.Point(pi1); + const Point3d & p2 = mesh.Point(pi2); + + bool ref = 0; + + /* + if (Dist (p1, p2) > mesh.GetH (Center (p1, p2))) + ref = 1; + */ + + /* + if (cnt <= opt.minref) + ref = 1; + */ + + /* + if ((pi1 == 460 || pi2 == 460 || + pi1 == 461 || pi2 == 461) && cnt <= 8) ref = 1; + */ + if (ref == 1) + { + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (!refedges.Used(edge)) + { + Point3d np = Center (p1, p2); + int npi = mesh.AddPoint (np); + refedges.Set (edge, npi); + found = 1; + } + } + } + } + + if (!found) break; + + // build closure: + PrintMessage (5, "start closure"); + do + { + PrintMessage (5, "start loop"); + change = 0; + for (i = 1; i <= mesh.GetNE(); i++) + { + Element & el = mesh.VolumeElement (i); + if (el.GetType() != PRISM) + continue; + + bool hasref = 0, hasnonref = 0; + for (j = 1; j <= 3; j++) + { + int pi1 = el.PNum(j); + int pi2 = el.PNum(j+3); + if (pi1 != pi2) + { + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (refedges.Used(edge)) + hasref = 1; + else + hasnonref = 1; + } + } + + if (hasref && hasnonref) + { + // cout << "el " << i << " in closure" << endl; + change = 1; + for (j = 1; j <= 3; j++) + { + int pi1 = el.PNum(j); + int pi2 = el.PNum(j+3); + const Point3d & p1 = mesh.Point(pi1); + const Point3d & p2 = mesh.Point(pi2); + + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (!refedges.Used(edge)) + { + Point3d np = Center (p1, p2); + int npi = mesh.AddPoint (np); + refedges.Set (edge, npi); + } + } + } + } + } + while (change); + + PrintMessage (5, "Do segments"); + + // (*testout) << "closure formed, np = " << mesh.GetNP() << endl; + + int oldns = mesh.GetNSeg(); + + for (i = 1; i <= oldns; i++) + { + const Segment & el = mesh.LineSegment(i); + + INDEX_2 i2(el.p1, el.p2); + i2.Sort(); + + int pnew; + EdgePointGeomInfo ngi; + + if (refedges.Used(i2)) + { + pnew = refedges.Get(i2); + // ngi = epgi.Get(pnew); + } + else + { + continue; + + // Point3d pb; + + // /* + // geom->PointBetween (mesh.Point (el.p1), + // mesh.Point (el.p2), + // el.surfnr1, el.surfnr2, + // el.epgeominfo[0], el.epgeominfo[1], + // pb, ngi); + // */ + // pb = Center (mesh.Point (el.p1), mesh.Point (el.p2)); + + // pnew = mesh.AddPoint (pb); + + // refedges.Set (i2, pnew); + + // if (pnew > epgi.Size()) + // epgi.SetSize (pnew); + // epgi.Elem(pnew) = ngi; + } + + Segment ns1 = el; + Segment ns2 = el; + ns1.p2 = pnew; + ns1.epgeominfo[1] = ngi; + ns2.p1 = pnew; + ns2.epgeominfo[0] = ngi; + + mesh.LineSegment(i) = ns1; + mesh.AddSegment (ns2); + } + + PrintMessage (5, "Segments done, NSeg = ", mesh.GetNSeg()); + + // do refinement + int oldne = mesh.GetNE(); + for (i = 1; i <= oldne; i++) + { + Element & el = mesh.VolumeElement (i); + if (el.GetNP() != 6) + continue; + + int npi[3]; + for (j = 1; j <= 3; j++) + { + int pi1 = el.PNum(j); + int pi2 = el.PNum(j+3); + + if (pi1 == pi2) + npi[j-1] = pi1; + else + { + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (refedges.Used (edge)) + npi[j-1] = refedges.Get(edge); + else + { + /* + (*testout) << "ERROR: prism " << i << " has hanging node !!" + << ", edge = " << edge << endl; + cerr << "ERROR: prism " << i << " has hanging node !!" << endl; + */ + npi[j-1] = 0; + } + } + } + + if (npi[0]) + { + Element nel1(6), nel2(6); + for (j = 1; j <= 3; j++) + { + nel1.PNum(j) = el.PNum(j); + nel1.PNum(j+3) = npi[j-1]; + nel2.PNum(j) = npi[j-1]; + nel2.PNum(j+3) = el.PNum(j+3); + } + nel1.SetIndex (el.GetIndex()); + nel2.SetIndex (el.GetIndex()); + mesh.VolumeElement (i) = nel1; + mesh.AddVolumeElement (nel2); + } + } + + + PrintMessage (5, "Elements done, NE = ", mesh.GetNE()); + + + // do surface elements + int oldnse = mesh.GetNSE(); + // cout << "oldnse = " << oldnse << endl; + for (i = 1; i <= oldnse; i++) + { + Element2d & el = mesh.SurfaceElement (i); + if (el.GetType() != QUAD) + continue; + + int index = el.GetIndex(); + int npi[2]; + for (j = 1; j <= 2; j++) + { + int pi1, pi2; + + if (j == 1) + { + pi1 = el.PNum(1); + pi2 = el.PNum(4); + } + else + { + pi1 = el.PNum(2); + pi2 = el.PNum(3); + } + + if (pi1 == pi2) + npi[j-1] = pi1; + else + { + INDEX_2 edge(pi1, pi2); + edge.Sort(); + if (refedges.Used (edge)) + npi[j-1] = refedges.Get(edge); + else + { + npi[j-1] = 0; + } + } + } + + if (npi[0]) + { + Element2d nel1(QUAD), nel2(QUAD); + for (j = 1; j <= 4; j++) + { + nel1.PNum(j) = el.PNum(j); + nel2.PNum(j) = el.PNum(j); + } + nel1.PNum(3) = npi[1]; + nel1.PNum(4) = npi[0]; + nel2.PNum(1) = npi[0]; + nel2.PNum(2) = npi[1]; + /* + for (j = 1; j <= 2; j++) + { + nel1.PNum(j) = el.PNum(j); + nel1.PNum(j+2) = npi[j-1]; + nel2.PNum(j) = npi[j-1]; + nel2.PNum(j+2) = el.PNum(j+2); + } + */ + nel1.SetIndex (el.GetIndex()); + nel2.SetIndex (el.GetIndex()); + + mesh.SurfaceElement (i) = nel1; + mesh.AddSurfaceElement (nel2); + + int si = mesh.GetFaceDescriptor (index).SurfNr(); + + Point<3> hp = mesh.Point(npi[0]); + geom->GetSurface(si)->Project (hp); + mesh.Point (npi[0]).SetPoint (hp); + + hp = mesh.Point(npi[1]); + geom->GetSurface(si)->Project (hp); + mesh.Point (npi[1]).SetPoint (hp); + + // geom->GetSurface(si)->Project (mesh.Point(npi[0])); + // geom->GetSurface(si)->Project (mesh.Point(npi[1])); + } + } + + PrintMessage (5, "Surface elements done, NSE = ", mesh.GetNSE()); + + } + } + + + + void ZRefinement (Mesh & mesh, const CSGeometry * geom, + ZRefinementOptions & opt) + { + INDEX_2_HASHTABLE<int> singedges(mesh.GetNSeg()); + + SelectSingularEdges (mesh, *geom, singedges, opt); + //MakePrismsSingEdge (mesh, singedges); + MakePrismsClosePoints (mesh); + + RefinePrisms (mesh, geom, opt); + } + + + + ZRefinementOptions :: ZRefinementOptions() + { + minref = 0; + } + +} diff --git a/contrib/Netgen/libsrc/opti/Makefile b/contrib/Netgen/libsrc/opti/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d73441553f5d206679559512e4d7c50af8b21e15 --- /dev/null +++ b/contrib/Netgen/libsrc/opti/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for optimisation library +# +src = bfgs.cpp linsearch.cpp linopt.cpp +# +lib = opti +libpath = libsrc/opti +# +# +include ../makefile.inc diff --git a/contrib/Netgen/libsrc/opti/bfgs.cpp b/contrib/Netgen/libsrc/opti/bfgs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d106b6f1c0421d5fde9ae5068ee7468d22aafd24 --- /dev/null +++ b/contrib/Netgen/libsrc/opti/bfgs.cpp @@ -0,0 +1,410 @@ +/***************************************************************************/ +/* */ +/* Vorlesung Optimierung I, Gfrerer, WS94/95 */ +/* BFGS-Verfahren zur L�sung freier nichtlinearer Optimierungsprobleme */ +/* */ +/* Programmautor: Joachim Sch�berl */ +/* Matrikelnummer: 9155284 */ +/* */ +/***************************************************************************/ + +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include "opti.hpp" + + +namespace netgen +{ + +void Cholesky (const DenseMatrix & a, + DenseMatrix & l, Vector & d) +{ + // Factors A = L D L^T + + double x; + + int i, j, k; + int n = a.Height(); + + // (*testout) << "a = " << a << endl; + + l = a; + + for (i = 1; i <= n; i++) + { + for (j = i; j <= n; j++) + { + x = l.Get(i, j); + + for (k = 1; k < i; k++) + x -= l.Get(i, k) * l.Get(j, k) * d.Get(k); + + if (i == j) + { + d.Elem(i) = x; + } + else + { + l.Elem(j, i) = x / d.Get(k); + } + } + } + + for (i = 1; i <= n; i++) + { + l.Elem(i, i) = 1; + for (j = i+1; j <= n; j++) + l.Elem(i, j) = 0; + } + + /* + // Multiply: + (*testout) << "multiplied factors: " << endl; + for (i = 1; i <= n; i++) + for (j = 1; j <= n; j++) + { + x = 0; + for (k = 1; k <= n; k++) + x += l.Get(i, k) * l.Get(j, k) * d.Get(k); + (*testout) << x << " "; + } + (*testout) << endl; + */ +} + + +void MultLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p) +{ + /* + int i, j, n; + double val; + + n = l.Height(); + p = g; + for (i = 1; i <= n; i++) + { + val = 0; + for (j = i; j <= n; j++) + val += p.Get(j) * l.Get(j, i); + p.Set(i, val); + } + for (i = 1; i <= n; i++) + p.Elem(i) *= d.Get(i); + + for (i = n; i >= 1; i--) + { + val = 0; + for (j = 1; j <= i; j++) + val += p.Get(j) * l.Get(i, j); + p.Set(i, val); + } + */ + + + + double val; + + int n = l.Height(); + p = g; + + for (int i = 0; i < n; i++) + { + val = 0; + for (int j = i; j < n; j++) + val += p(j) * l(j, i); + p(i) = val; + } + + for (int i = 0; i < n; i++) + p(i) *= d(i); + + for (int i = n-1; i >= 0; i--) + { + val = 0; + for (int j = 0; j <= i; j++) + val += p(j) * l(i, j); + p(i) = val; + } +} + +void SolveLDLt (const DenseMatrix & l, const Vector & d, const Vector & g, Vector & p) +{ + double val; + + int n = l.Height(); + p = g; + + for (int i = 0; i < n; i++) + { + val = 0; + for (int j = 0; j < i; j++) + val += p(j) * l(i,j); + p(i) -= val; + } + + for (int i = 0; i < n; i++) + p(i) /= d(i); + + for (int i = n-1; i >= 0; i--) + { + val = 0; + for (int j = i+1; j < n; j++) + val += p(j) * l(j, i); + p(i) -= val; + } +} + +int LDLtUpdate (DenseMatrix & l, Vector & d, double a, const Vector & u) +{ + // Bemerkung: Es wird a aus R erlaubt + // Rueckgabewert: 0 .. D bleibt positiv definit + // 1 .. sonst + + int i, j, n; + + n = l.Height(); + + Vector v(n); + double t, told, xi; + + told = 1; + v = u; + + for (j = 1; j <= n; j++) + { + t = told + a * sqr (v.Elem(j)) / d.Get(j); + + if (t <= 0) + { + (*testout) << "update err, t = " << t << endl; + return 1; + } + + xi = a * v.Elem(j) / (d.Get(j) * t); + + d.Elem(j) *= t / told; + + for (i = j + 1; i <= n; i++) + { + v.Elem(i) -= v.Elem(j) * l.Elem(i, j); + l.Elem(i, j) += xi * v.Elem(i); + } + + told = t; + } + + return 0; +} + + +double BFGS ( + Vector & x, // i: Startwert + // o: Loesung, falls IFAIL = 0 + const MinFunction & fun, + const OptiParameters & par, + double eps + ) + + +{ + int i, j, n = x.Size(); + long it; + char a1crit, a3acrit; + + + Vector d(n), g(n), p(n), temp(n), bs(n), xneu(n), y(n), s(n), x0(n); + DenseMatrix l(n); + DenseMatrix hesse(n); + + double /* normg, */ alphahat, hd, fold; + double a1, a2; + const double mu1 = 0.1, sigma = 0.1, xi1 = 1, xi2 = 10; + const double tau = 0.1, tau1 = 0.1, tau2 = 0.6; + + Vector typx(x.Size()); // i: typische Groessenordnung der Komponenten + double f, f0; + double typf; // i: typische Groessenordnung der Loesung + double fmin = -1e5; // i: untere Schranke fuer Funktionswert + // double eps = 1e-8; // i: Abbruchschranke fuer relativen Gradienten + double tauf = 0.1; // i: Abbruchschranke fuer die relative Aenderung der + // Funktionswerte + int ifail; // o: 0 .. Erfolg + // -1 .. Unterschreitung von fmin + // 1 .. kein Erfolg bei Liniensuche + // 2 .. �berschreitung von itmax + + typx = par.typx; + typf = par.typf; + + + l = 0; + for (i = 1; i <= n; i++) + l.Elem(i, i) = 1; + + f = fun.FuncGrad (x, g); + f0 = f; + x0 = x; + + it = 0; + do + { + // Restart + + if (it % (5 * n) == 0) + { + + for (i = 1; i <= n; i++) + d.Elem(i) = typf/ sqr (typx.Get(i)); // 1; + for (i = 2; i <= n; i++) + for (j = 1; j < i; j++) + l.Elem(i, j) = 0; + + /* + hesse = 0; + for (i = 1; i <= n; i++) + hesse.Elem(i, i) = typf / sqr (typx.Get(i)); + + fun.ApproximateHesse (x, hesse); + + Cholesky (hesse, l, d); + */ + } + + it++; + if (it > par.maxit_bfgs) + { + ifail = 2; + break; + } + + + // Solve with factorized B + + SolveLDLt (l, d, g, p); + + // (*testout) << "l " << l << endl +// << "d " << d << endl +// << "g " << g << endl +// << "p " << p << endl; + + + p *= -1; + y = g; + + fold = f; + + // line search + + alphahat = 1; + lines (x, xneu, p, f, g, fun, par, alphahat, fmin, + mu1, sigma, xi1, xi2, tau, tau1, tau2, ifail); + + if(ifail == 1) + (*testout) << "no success with linesearch" << endl; + + /* + // if (it > par.maxit_bfgs/2) + { + (*testout) << "x = " << x << endl; + (*testout) << "xneu = " << xneu << endl; + (*testout) << "f = " << f << endl; + (*testout) << "g = " << g << endl; + } + */ + + // (*testout) << "it = " << it << " f = " << f << endl; + // if (ifail != 0) break; + + s.Set2 (1, xneu, -1, x); + y *= -1; + y.Add (1,g); // y += g; + + x = xneu; + + // BFGS Update + + MultLDLt (l, d, s, bs); + + a1 = y * s; + a2 = s * bs; + + if (a1 > 0 && a2 > 0) + { + if (LDLtUpdate (l, d, 1 / a1, y) != 0) + { + cerr << "BFGS update error1" << endl; + (*testout) << "BFGS update error1" << endl; + (*testout) << "l " << endl << l << endl + << "d " << d << endl; + ifail = 1; + break; + } + + if (LDLtUpdate (l, d, -1 / a2, bs) != 0) + { + cerr << "BFGS update error2" << endl; + (*testout) << "BFGS update error2" << endl; + (*testout) << "l " << endl << l << endl + << "d " << d << endl; + ifail = 1; + break; + } + } + + // Calculate stop conditions + + hd = eps * max2 (typf, fabs (f)); + a1crit = 1; + for (i = 1; i <= n; i++) + if ( fabs (g.Elem(i)) * max2 (typx.Elem(i), fabs (x.Elem(i))) > hd) + a1crit = 0; + + + a3acrit = (fold - f <= tauf * max2 (typf, fabs (f))); + + // testout << "g = " << g << endl; + // testout << "a1crit, a3crit = " << int(a1crit) << ", " << int(a3acrit) << endl; + + /* + // Output for tests + + normg = sqrt (g * g); + + testout << "it =" << setw (5) << it + << " f =" << setw (12) << setprecision (5) << f + << " |g| =" << setw (12) << setprecision (5) << normg; + + testout << " x = (" << setw (12) << setprecision (5) << x.Elem(1); + for (i = 2; i <= n; i++) + testout << "," << setw (12) << setprecision (5) << x.Elem(i); + testout << ")" << endl; + */ + + //(*testout) << "it = " << it << " f = " << f << " x = " << x << endl + // << " g = " << g << " p = " << p << endl << endl; + + // (*testout) << "|g| = " << g.L2Norm() << endl; + + if (g.L2Norm() < fun.GradStopping (x)) break; + + } + while (!a1crit || !a3acrit); + + /* + (*testout) << "it = " << it << " g = " << g << " f = " << f + << " fail = " << ifail << endl; + */ + if (f0 < f || (ifail == 1)) + { + (*testout) << "fail, f = " << f << " f0 = " << f0 << endl; + f = f0; + x = x0; + } + + // (*testout) << "x = " << x << ", x0 = " << x0 << endl; + return f; +} + +} diff --git a/contrib/Netgen/libsrc/opti/linopt.cpp b/contrib/Netgen/libsrc/opti/linopt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5d381e6b7b56b610e6255914a1f749188cc38b1 --- /dev/null +++ b/contrib/Netgen/libsrc/opti/linopt.cpp @@ -0,0 +1,73 @@ +#include <mystdlib.h> +#include <myadt.hpp> + +#include <linalg.hpp> +#include "opti.hpp" + +namespace netgen +{ + +void LinearOptimize (const DenseMatrix & a, const Vector & b, + const Vector & c, Vector & x) + + { + int i1, i2, i3, j; + DenseMatrix m(3), inv(3); + Vector rs(3), hx(3), res(a.Height()), res2(3); + double f, fmin; + int nrest; + + if (a.Width() != 3) + { + cerr << "LinearOptimize only implemented for 3 unknowns" << endl; + return; + } + + fmin = 1e10; + x = 0; + nrest = a.Height(); + for (i1 = 1; i1 <= nrest; i1++) + for (i2 = i1 + 1; i2 <= nrest; i2++) + for (i3 = i2 + 1; i3 <= nrest; i3++) + { + for (j = 1; j <= 3; j++) + { + m.Elem(1, j) = a.Get(i1, j); + m.Elem(2, j) = a.Get(i2, j); + m.Elem(3, j) = a.Get(i3, j); + } + + rs.Elem(1) = b.Get(i1); + rs.Elem(2) = b.Get(i2); + rs.Elem(3) = b.Get(i3); + + if (fabs (m.Det()) < 1e-12) continue; + + CalcInverse (m, inv); + inv.Mult (rs, hx); + + a.Residuum (hx, b, res); +// m.Residuum (hx, rs, res2); + f = c * hx; + +/* + testout -> precision(12); + (*testout) << "i = (" << i1 << "," << i2 << "," << i3 + << "), f = " << f << " x = " << x << " res = " << res + << " resmin = " << res.Min() + << " res2 = " << res2 << " prod = " << prod << endl; +*/ + + + double rmin = res.Elem(1); + for (int hi = 2; hi <= res.Size(); hi++) + if (res.Elem(hi) < rmin) rmin = res.Elem(hi); + + if ( (f < fmin) && rmin >= -1e-8) + { + fmin = f; + x = hx; + } + } + } +} diff --git a/contrib/Netgen/libsrc/opti/linsearch.cpp b/contrib/Netgen/libsrc/opti/linsearch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c297fd92c8dc0b6b8007297c213a3a2dae5cf55 --- /dev/null +++ b/contrib/Netgen/libsrc/opti/linsearch.cpp @@ -0,0 +1,351 @@ +/***************************************************************************/ +/* */ +/* Problem: Liniensuche */ +/* */ +/* Programmautor: Joachim Sch�berl */ +/* Matrikelnummer: 9155284 */ +/* */ +/* Algorithmus nach: */ +/* */ +/* Optimierung I, Gfrerer, WS94/95 */ +/* Algorithmus 2.1: Liniensuche Problem (ii) */ +/* */ +/***************************************************************************/ + + + +#include <mystdlib.h> + +#include <myadt.hpp> // min, max, sqr + +#include <linalg.hpp> +#include "opti.hpp" + + +namespace netgen +{ +const double eps0 = 1E-15; + +// Liniensuche + + +double MinFunction :: Func (const Vector & /* x */) const +{ + cerr << "Func of MinFunction called" << endl; + return 0; +} + +void MinFunction :: Grad (const Vector & /* x */, Vector & /* g */) const +{ + cerr << "Grad of MinFunction called" << endl; +} + +double MinFunction :: FuncGrad (const Vector & x, Vector & g) const +{ + cerr << "Grad of MinFunction called" << endl; + return 0; + /* + int n = x.Size(); + + static Vector xr; + static Vector xl; + xr.SetSize(n); + xl.SetSize(n); + + double eps = 1e-6; + double fl, fr; + + for (int i = 1; i <= n; i++) + { + xr.Set (1, x); + xl.Set (1, x); + + xr.Elem(i) += eps; + fr = Func (xr); + + xl.Elem(i) -= eps; + fl = Func (xl); + + g.Elem(i) = (fr - fl) / (2 * eps); + } + + double f = Func(x); + // (*testout) << "f = " << f << " grad = " << g << endl; + return f; + */ +} + + +double MinFunction :: FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const +{ + Vector g(x.Size()); + double f = FuncGrad (x, g); + deriv = (g * dir); + + // (*testout) << "g = " << g << ", dir = " << dir << ", deriv = " << deriv << endl; + return f; +} + +void MinFunction :: ApproximateHesse (const Vector & x, + DenseMatrix & hesse) const +{ + int n = x.Size(); + int i, j; + + static Vector hx; + hx.SetSize(n); + + double eps = 1e-6; + double f, f11, f12, f21, f22; + + for (i = 1; i <= n; i++) + { + for (j = 1; j < i; j++) + { + hx = x; + hx.Elem(i) = x.Get(i) + eps; + hx.Elem(j) = x.Get(j) + eps; + f11 = Func(hx); + hx.Elem(i) = x.Get(i) + eps; + hx.Elem(j) = x.Get(j) - eps; + f12 = Func(hx); + hx.Elem(i) = x.Get(i) - eps; + hx.Elem(j) = x.Get(j) + eps; + f21 = Func(hx); + hx.Elem(i) = x.Get(i) - eps; + hx.Elem(j) = x.Get(j) - eps; + f22 = Func(hx); + + hesse.Elem(i, j) = hesse.Elem(j, i) = + (f11 + f22 - f12 - f21) / (2 * eps * eps); + } + + hx = x; + f = Func(x); + hx.Elem(i) = x.Get(i) + eps; + f11 = Func(hx); + hx.Elem(i) = x.Get(i) - eps; + f22 = Func(hx); + + hesse.Elem(i, i) = (f11 + f22 - 2 * f) / (eps * eps); + } + // (*testout) << "hesse = " << hesse << endl; +} + + + + + + + +/// Line search, modified Mangasarien conditions +void lines (Vector & x, // i: initial point of line-search + Vector & xneu, // o: solution, if successful + Vector & p, // i: search direction + double & f, // i: function-value at x + // o: function-value at xneu, iff ifail = 0 + Vector & g, // i: gradient at x + // o: gradient at xneu, iff ifail = 0 + const MinFunction & fun, // function to minimize + const OptiParameters & par, + double & alphahat, // i: initial value for alpha_hat + // o: solution alpha iff ifail = 0 + double fmin, // i: lower bound for f + double mu1, // i: Parameter mu_1 of Alg.2.1 + double sigma, // i: Parameter sigma of Alg.2.1 + double xi1, // i: Parameter xi_1 of Alg.2.1 + double xi2, // i: Parameter xi_1 of Alg.2.1 + double tau, // i: Parameter tau of Alg.2.1 + double tau1, // i: Parameter tau_1 of Alg.2.1 + double tau2, // i: Parameter tau_2 of Alg.2.1 + int & ifail) // o: 0 on success + // -1 bei termination because lower limit fmin + // 1 bei illegal termination due to different reasons + +{ + double phi0, phi0prime, phi1, phi1prime, phihatprime; + double alpha1, alpha2, alphaincr, c; + char flag = 1; + long it; + + alpha1 = 0; + alpha2 = 1e50; + phi0 = phi1 = f; + + phi0prime = g * p; + + if (phi0prime > 0) + { + ifail = 1; + return; + } + + ifail = 1; // Markus + + phi1prime = phi0prime; + + // (*testout) << "phi0prime = " << phi0prime << endl; + + // it = 100000l; + it = 0; + + while (it++ <= par.maxit_linsearch) + { + + xneu.Set2 (1, x, alphahat, p); + + + // f = fun.FuncGrad (xneu, g); + // f = fun.Func (xneu); + f = fun.FuncDeriv (xneu, p, phihatprime); + + // (*testout) << "lines, f = " << f << " phip = " << phihatprime << endl; + + if (f < fmin) + { + ifail = -1; + break; + } + + + if (alpha2 - alpha1 < eps0 * alpha2) + { + ifail = 0; + break; + } + + // (*testout) << "i = " << it << " al = " << alphahat << " f = " << f << " fprime " << phihatprime << endl;; + + if (f - phi0 > mu1 * alphahat * phi1prime + eps0 * fabs (phi0)) + + { + + flag = 0; + alpha2 = alphahat; + + c = + (f - phi1 - phi1prime * (alphahat-alpha1)) / + sqr (alphahat-alpha1); + + alphahat = alpha1 - 0.5 * phi1prime / c; + + if (alphahat > alpha2) + alphahat = alpha1 + 1/(4*c) * + ( (sigma+mu1) * phi0prime - 2*phi1prime + + sqrt (sqr(phi1prime - mu1 * phi0prime) - + 4 * (phi1 - phi0 - mu1 * alpha1 * phi0prime) * c)); + + alphahat = max2 (alphahat, alpha1 + tau * (alpha2 - alpha1)); + alphahat = min2 (alphahat, alpha2 - tau * (alpha2 - alpha1)); + + // (*testout) << " if-branch" << endl; + + } + + else + + { + /* + f = fun.FuncGrad (xneu, g); + phihatprime = g * p; + */ + f = fun.FuncDeriv (xneu, p, phihatprime); + + if (phihatprime < sigma * phi0prime * (1 + eps0)) + + { + if (phi1prime < phihatprime) + // Approximationsfunktion ist konvex + + alphaincr = (alphahat - alpha1) * phihatprime / + (phi1prime - phihatprime); + + else + alphaincr = 1e99; // MAXDOUBLE; + + if (flag) + { + alphaincr = max2 (alphaincr, xi1 * (alphahat-alpha1)); + alphaincr = min2 (alphaincr, xi2 * (alphahat-alpha1)); + } + else + { + alphaincr = max2 (alphaincr, tau1 * (alpha2 - alphahat)); + alphaincr = min2 (alphaincr, tau2 * (alpha2 - alphahat)); + } + + alpha1 = alphahat; + alphahat += alphaincr; + phi1 = f; + phi1prime = phihatprime; + } + + else + + { + ifail = 0; // Erfolg !! + break; + } + + // (*testout) << " else, " << endl; + + } + + } + + // (*testout) << "linsearch: it = " << it << " ifail = " << ifail << endl; + + fun.FuncGrad (xneu, g); + + + if (it < 0) + ifail = 1; + + // (*testout) << "fail = " << ifail << endl; +} + + + + + + + + + + + + + + + + + + + +void SteepestDescent (Vector & x, const MinFunction & fun, + const OptiParameters & par) +{ + int it, n = x.Size(); + Vector xnew(n), p(n), g(n), g2(n); + double val, alphahat; + int fail; + + val = fun.FuncGrad(x, g); + + alphahat = 1; + // testout << "f = "; + for (it = 0; it < 10; it++) + { + // testout << val << " "; + + // p = -g; + p.Set (-1, g); + + lines (x, xnew, p, val, g, fun, par, alphahat, -1e5, + 0.1, 0.1, 1, 10, 0.1, 0.1, 0.6, fail); + + x = xnew; + } + // testout << endl; +} +} diff --git a/contrib/Netgen/libsrc/opti/opti.hpp b/contrib/Netgen/libsrc/opti/opti.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9875786900ea8cba360c04149ff4c57c5e0aa66e --- /dev/null +++ b/contrib/Netgen/libsrc/opti/opti.hpp @@ -0,0 +1,142 @@ +#ifndef FILE_OPTI +#define FILE_OPTI + +/**************************************************************************/ +/* File: opti.hpp */ +/* Author: Joachim Schoeberl */ +/* Date: 01. Jun. 95 */ +/**************************************************************************/ + + + +namespace netgen +{ + + /** + Function to be minimized. + */ + class MinFunction + { + public: + /// + virtual double Func (const Vector & x) const; + /// + virtual void Grad (const Vector & x, Vector & g) const; + /// function and gradient + virtual double FuncGrad (const Vector & x, Vector & g) const; + /// directional derivative + virtual double FuncDeriv (const Vector & x, const Vector & dir, double & deriv) const; + /// if |g| < gradaccuray, then stop bfgs + virtual double GradStopping (const Vector & /* x */) const { return 0; } + + /// + virtual void ApproximateHesse (const Vector & /* x */, + DenseMatrix & /* hesse */) const; + }; + + + class OptiParameters + { + public: + int maxit_linsearch; + int maxit_bfgs; + double typf; + double typx; + + OptiParameters () + { + maxit_linsearch = 100; + maxit_bfgs = 100; + typf = 1; + typx = 1; + } + }; + + + /** Implementation of BFGS method. + Efficient method for non-linear minimiztion problems. + @param x initial value and solution + @param fun function to be minimized + */ + extern double BFGS (Vector & x, const MinFunction & fun, + const OptiParameters & par, + double eps = 1e-8); + + /** Steepest descent method. + Simple method for non-linear minimization problems. + @param x initial value and solution + @param fun function to be minimized + */ + void SteepestDescent (Vector & x, const MinFunction & fun, + const OptiParameters & par); + + + extern void lines ( + Vector & x, // i: Ausgangspunkt der Liniensuche + Vector & xneu, // o: Loesung der Liniensuche bei Erfolg + Vector & p, // i: Suchrichtung + double & f, // i: Funktionswert an der Stelle x + // o: Funktionswert an der Stelle xneu, falls ifail = 0 + Vector & g, // i: Gradient an der Stelle x + // o: Gradient an der Stelle xneu, falls ifail = 0 + + const MinFunction & fun, // function to minmize + const OptiParameters & par, // parameters + double & alphahat, // i: Startwert f�r alpha_hat + // o: Loesung falls ifail = 0 + double fmin, // i: untere Schranke f�r f + double mu1, // i: Parameter mu_1 aus Alg.2.1 + double sigma, // i: Parameter sigma aus Alg.2.1 + double xi1, // i: Parameter xi_1 aus Alg.2.1 + double xi2, // i: Parameter xi_1 aus Alg.2.1 + double tau, // i: Parameter tau aus Alg.2.1 + double tau1, // i: Parameter tau_1 aus Alg.2.1 + double tau2, // i: Parameter tau_2 aus Alg.2.1 + int & ifail); // o: 0 bei erfolgreicher Liniensuche + // -1 bei Abbruch wegen Unterschreiten von fmin + // 1 bei Abbruch, aus sonstigen Gr�nden + + + + + /** + Solver for linear programming problem. + + \begin{verbatim} + min c^t x + A x <= b + \end{verbatim} + */ + extern void LinearOptimize (const DenseMatrix & a, const Vector & b, + const Vector & c, Vector & x); + + +#ifdef NONE + + /** + Simple projection iteration. + + find $u = argmin_{v >= 0} 0.5 u A u - f u$ + */ + extern void ApproxProject (const BaseMatrix & a, Vector & u, + const Vector & f, + double tau, int its); + + + /** + CG Algorithm for quadratic programming problem. + See: Dostal ... + + d ... diag(A) ^{-1} + */ + extern void ApproxProjectCG (const BaseMatrix & a, Vector & x, + const Vector & b, const class DiagMatrix & d, + double gamma, int & steps, int & changes); + +#endif + + +} + +#endif +