Commit 199f5aaa authored by Kirill Terekhov's avatar Kirill Terekhov

Fixes and lib for general adaptive mesh

Fixes for mesh modification algorithms

A lib for general adaptive mesh
parent d02be56a
#include "agrid.h"
#include <math.h>
Storage::integer min_nonzero(Storage::integer a, Storage::integer b)
{
Storage::integer get_max = std::max(a,b);
Storage::integer get_min = std::min(a,b);
if( get_min == 0 ) return get_max; else return get_min;
}
void AdaptiveGrid
void AdaptiveGrid::Refine(const TagInteger & indicator)
{
int schedule_counter = 1;
bool scheduled = true;
//0. Extend indicator for edges and faces
indicator = CreateTag(indicator.GetTagName(),DATA_INTEGER,FACE|EDGE,NONE,1);
while(scheduled)
{
//1.Communicate indicator - it may be not synced
ExchangeTag(indicator,0,CELL);
//2.Propogate indicator down to the faces,edges
// select latest schedule for them
//
//possible problem - a cell needs all it's elements to be splitted in the same schedule
//so the cell must mark all it's elements without hanging nodes into the same schedule,
//unless there is an even earlier cell
//
//should we select earliest possible for elements without hanging nodes and
//latest possible for elements with hanging nodes?
//
//with loop over cells we would mark elements without hanging nodes of the cells
//in current schedule
for(ElementType etype = FACE; etype >= EDGE; etype = PrevElementType(etype))
{
#if defined(USE_OMP)
#pragma omp parallel for
#endif
for(Storage::integer it = 0; it < LastLocalID(etype); ++it) if( isValidElement(etype,it) )
{
Element e = ElementByLocalID(etype,it);
ElementArray<Element> adj = f.getAdjElements(NextElementType(etype));
//here latest schedule is selected
if( e->nbAdjElements(NODE,hanging_node,0) > 0 ) //latest possible schedule
{
for(ElementArray<Element>::size_type kt = 0; kt < adj.size(); ++kt)
if( indicator[adj[kt]] )
indicator[f] = indicator[f] ? std::min(indicator[f],indicator[adj[kt]]) : indicator[adj[kt]];
}
else //earliest possible schedule
{
for(ElementArray<Element>::size_type kt = 0; kt < adj.size(); ++kt)
indicator[f] = std::max(indicator[f],indicator[adj[kt]]);
}
}
}
//3.Communicate indicator on faces and edges
ExchangeTag(indicator,0,FACE|EDGE);
//4.Check for each cell without indicator if there is
// any hanging node with adjacent in a need to refine,
// schedule for refinement earlier.
scheduled = false;
#if defined(USE_OMP)
#pragma omp parallel for
#endif
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
{
Cell c = CellByLocalID(it);
if( indicator[c] == 0 )
{
bool scheduled_c = false;
//retrive only hanging nodes, this may be empty
ElementArray<Node> hanging = c->getNodes(hanging_node,0);
for(ElementArray<Node>::size_type kt = 0; kt < hanging.size() && !scheduled_c; ++kt)
{
//adjacent edges may be scheduled for refinement
ElementArray<Edge> adj = hanging[kt].getEdges();
for(ElementArray<Edge>::size_type lt = 0; lt < adj.size() && !scheduled_c; ++lt)
if( indicator[adj[lt]] != 0 )
{
indicator[c] = schedulde_counter+1;
scheduled = scheduled_c = true;
}
}
}
}
//5.Go back to 1 until no new elements scheduled
if( scheduled ) schedulde_counter++;
}
//5.Refine
BeginModification();
while(scheduled_counter)
{
scheduled_counter--;
}
ResolveModification();
//Let the user update their data
ApplyModification();
EndModification();
}
void AdaptiveGrid::Coarse(const TagInteger & indicator)
{
}
#ifndef _AGRID_H
#define _AGRID_H
#include "inmost.h"
class AdaptiveMesh : public Mesh
{
MarkerType hanging_node;
void SplitFace();
public:
AdaptiveMesh() : Mesh() {}
~AdaptiveMesh() {}
/// Indicator must be 1 on cells to be refined
/// and 0 on all other cells
void Refine(const TagInteger & indicator);
void Coarse(const TagInteger & indicator);
};
#endif //_AGRID_H
project(AdaptiveMesh)
set(LIBSOURCE amesh.cpp amesh.h)
set(SOURCE main.cpp)
add_library(AdaptiveMeshLib ${LIBSOURCE})
add_executable(AdaptiveMesh ${SOURCE})
target_link_libraries(AdaptiveMesh inmost AdaptiveMeshLib)
if(USE_MPI)
message("linking AdaptiveMesh with MPI")
target_link_libraries(AdaptiveMesh ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(AdaptiveMesh PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
set_property(TARGET AdaptiveMeshLib PROPERTY PUBLIC_HEADER "${PROJECT_BINARY_DIR}/Examples/AdaptiveMesh/amesh.h")
install(TARGETS AdaptiveMeshLib EXPORT inmost-targets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include)
install(TARGETS AdaptiveMesh EXPORT inmost-targets RUNTIME DESTINATION bin)
\ No newline at end of file
This diff is collapsed.
#ifndef _AMESH_H
#define _AMESH_H
#include "inmost.h"
namespace INMOST
{
class AdaptiveMesh : public Mesh
{
ElementSet root; //< Root set that links all the other sets for coarsements
TagInteger level; //< Refinement level of the cell
TagReference parent_set; //<Link to the set that contains an element.
TagReferenceArray hanging_nodes; //< Link to current hanging nodes of the cell.
/// Prepare sets for coarsements.
/// Do not do this in constructor, since mesh may contain no cells.
void PrepareSet();
public:
Storage::integer GetLevel(const Storage & e) {return level[e];}
AdaptiveMesh();
~AdaptiveMesh();
/// Indicator must be 1 on cells to be refined
/// and 0 on all other cells
bool Refine(TagInteger & indicator);
bool Coarse(TagInteger & indicator);
/// Delete all data related to mesh refinement-coarsement.
void ClearData();
};
}
#endif //_AMESH_H
#include "amesh.h"
using namespace INMOST;
int main(int argc, char ** argv)
{
Mesh::Initialize(&argc,&argv);
if( argc > 1 )
{
AdaptiveMesh m;
m.Load(argv[1]);
//m.SetTopologyCheck(NEED_TEST_CLOSURE);
//m.SetTopologyCheck(PROHIBIT_MULTILINE);
//m.SetTopologyCheck(PROHIBIT_MULTIPOLYGON);
TagInteger indicator = m.CreateTag("INDICATOR",DATA_INTEGER,CELL,NONE,1);
int max_levels = 2;
if( argc > 2 ) max_levels = atoi(argv[2]);
//bounding box around mesh
Storage::real cmax[3] = {-1.0e20,-1.0e20,-1.0e20};
Storage::real cmin[3] = {+1.0e20,+1.0e20,+1.0e20};
Storage::real xyz[3], r, q, cnt[3];
//find bounding box around mesh
for(Mesh::iteratorNode it = m.BeginNode(); it != m.EndNode(); ++it)
{
for(int d = 0; d < 3; ++d)
{
if( it->Coords()[d] > cmax[d] ) cmax[d] = it->Coords()[d];
if( it->Coords()[d] < cmin[d] ) cmin[d] = it->Coords()[d];
}
}
r = 1;
for(int d = 0; d < 3; ++d)
{
r *= cmax[d]-cmin[d];
cnt[d] = (cmax[d]+cmin[d])*0.5;
}
r = pow(r,1.0/3.0)/20.0;
for(int k = 0; k < 16; ++k)
{
int numref;
int refcnt = 0;
do
{
numref = 0;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) if( m.GetLevel(it->self()) < max_levels )
{
it->Centroid(xyz);
//refine a circle
q = 0;
for(int d = 0; d < 3; ++d)
q += (xyz[d]-cnt[d])*(xyz[d]-cnt[d]);
q = sqrt(q);
if( q < r*(k+1) && q > r*k)
{
indicator[it->self()] = 1;
numref++;
}
}
if( numref )
{
std::cout << "k " << k << " refcnt " << refcnt << " " << r*k << " < r < " << r*(k+1) << " numref " << numref << " cells " << m.NumberOfCells() << std::endl;
/*
{
std::stringstream file;
file << "indicator_" << k << "_" << refcnt << "r.pmf";
m.Save(file.str());
}
*/
if( !m.Refine(indicator) ) break;
{
std::stringstream file;
file << "dump_" << k << "_" << refcnt << "r.pmf";
m.Save(file.str());
}
//cleanup indicator
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) indicator[it->self()] = 0;
}
refcnt++;
}
while(numref);
refcnt = 0;
do
{
numref = 0;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) if( m.GetLevel(it->self()) > 0 )
{
it->Centroid(xyz);
//refine a circle
q = 0;
for(int d = 0; d < 3; ++d)
q += (xyz[d]-cnt[d])*(xyz[d]-cnt[d]);
q = sqrt(q);
if( q < r*k)
{
indicator[it->self()] = 1;
numref++;
}
}
if( numref )
{
std::cout << "k " << k << " crscnt " << refcnt << " " << r*k << " < r < " << r*(k+1) << " numcrs " << numref << " cells " << m.NumberOfCells() << std::endl;
/*
{
std::stringstream file;
file << "indicator_" << k << "_" << refcnt << "c.pmf";
m.Save(file.str());
}
*/
if( !m.Coarse(indicator) ) break;
{
std::stringstream file;
file << "dump_" << k << "_" << refcnt << "c.pmf";
m.Save(file.str());
}
//cleanup indicator
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) indicator[it->self()] = 0;
}
//return -1;
refcnt++;
}
while(numref);
{
std::stringstream file;
file << "step_" << k << ".vtk";
m.Save(file.str());
}
{
std::stringstream file;
file << "step_" << k << ".pmf";
m.Save(file.str());
}
}
}
else std::cout << "Usage: " << argv[0] << " mesh_file [max_levels=2]" << std::endl;
}
\ No newline at end of file
if(USE_MESH) if(USE_MESH)
add_subdirectory(AdaptiveMesh)
add_subdirectory(DrawGrid) add_subdirectory(DrawGrid)
add_subdirectory(OldDrawGrid) add_subdirectory(OldDrawGrid)
add_subdirectory(GridGen) add_subdirectory(GridGen)
......
...@@ -106,7 +106,7 @@ void printtext(const char * fmt, ... ) ...@@ -106,7 +106,7 @@ void printtext(const char * fmt, ... )
{ {
unsigned int i; unsigned int i;
char stext[4096]; char stext[1048576];
va_list ap; va_list ap;
if ( fmt == NULL ) return; if ( fmt == NULL ) return;
va_start(ap,fmt); va_start(ap,fmt);
...@@ -4102,13 +4102,14 @@ double display_elem_info(Element e, double top, double left, double interval) ...@@ -4102,13 +4102,14 @@ double display_elem_info(Element e, double top, double left, double interval)
top -= interval; top -= interval;
glRasterPos2f(left,top); glRasterPos2f(left,top);
printtext("%s %d",ElementTypeName(e->GetElementType()),e->LocalID()); printtext("%s %d",ElementTypeName(e->GetElementType()),e->LocalID());
if( e->GetElementType() == ESET ) printtext(" size %d",e->getAsSet().Size());
glColor3f(0.2,0.2,0.2); glColor3f(0.2,0.2,0.2);
for(Mesh::iteratorTag t = mesh->BeginTag(); t != mesh->EndTag(); ++t) if( t->isDefined(e->GetElementType()) ) for(Mesh::iteratorTag t = mesh->BeginTag(); t != mesh->EndTag(); ++t) if( t->isDefined(e->GetElementType()) )
{ {
if( e->HaveData(*t) ) if( e->HaveData(*t) )
{ {
char str[4096]; char str[1048576];
char temp[4096]; char temp[1048576];
str[0] = '\0'; str[0] = '\0';
int dsize; int dsize;
switch(t->GetDataType()) switch(t->GetDataType())
...@@ -4475,7 +4476,7 @@ void draw_screen() ...@@ -4475,7 +4476,7 @@ void draw_screen()
for(int k = 0; k < (int)orphans.size(); ++k) for(int k = 0; k < (int)orphans.size(); ++k)
DrawElement(orphans[k],color_t(1,0,1),color_t(0,1,1),color_t(0,0,1)); DrawElement(orphans[k],color_t(1,0,1),color_t(0,1,1),color_t(0,0,1));
if( disp_e.isValid() ) if( disp_e.isValid() && disp_e.GetElementType() != ESET)
DrawElement(disp_e,color_t(1,1,0),color_t(1,0,0),color_t(0,0,1)); DrawElement(disp_e,color_t(1,1,0),color_t(1,0,0),color_t(0,0,1));
...@@ -4588,6 +4589,7 @@ void draw_screen() ...@@ -4588,6 +4589,7 @@ void draw_screen()
else if ( stype == "edge" ) visualization_type = EDGE; else if ( stype == "edge" ) visualization_type = EDGE;
else if ( stype == "face" ) visualization_type = FACE; else if ( stype == "face" ) visualization_type = FACE;
else if ( stype == "cell" ) visualization_type = CELL; else if ( stype == "cell" ) visualization_type = CELL;
else if ( stype == "eset" ) visualization_type = ESET;
if( visualization_type == NONE ) if( visualization_type == NONE )
printf("unknown element type %s\n",typen); printf("unknown element type %s\n",typen);
if( !mesh->isValidElement(visualization_type,comp) ) if( !mesh->isValidElement(visualization_type,comp) )
...@@ -4596,9 +4598,12 @@ void draw_screen() ...@@ -4596,9 +4598,12 @@ void draw_screen()
if( mesh->isValidElement(visualization_type,comp) ) if( mesh->isValidElement(visualization_type,comp) )
{ {
disp_e = mesh->ElementByLocalID(visualization_type,comp); disp_e = mesh->ElementByLocalID(visualization_type,comp);
disp_e->Centroid(shift); if( disp_e.GetElementType() != ESET )
for(int r = 0; r < 3; ++r) {
shift[r] = -shift[r]; disp_e->Centroid(shift);
for(int r = 0; r < 3; ++r)
shift[r] = -shift[r];
}
} }
} }
......
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
// a very expensive check for debug purposes, // a very expensive check for debug purposes,
// when you release marker checks all the elements // when you release marker checks all the elements
// that no element is marked by released marker // that no element is marked by released marker
// in Mesh::Init function change two variables:
// check_shared_mrk - check shared markers.
// check_private_mrk - check private markers.
//#define CHECKS_MARKERS //#define CHECKS_MARKERS
// use additional sets to store elements for parallel // use additional sets to store elements for parallel
......
...@@ -622,7 +622,8 @@ namespace INMOST ...@@ -622,7 +622,8 @@ namespace INMOST
TagReal(const Tag & b) : Tag(b) {} TagReal(const Tag & b) : Tag(b) {}
TagReal & operator = (TagReal const & b) {Tag::operator =(b); return *this;} TagReal & operator = (TagReal const & b) {Tag::operator =(b); return *this;}
TagReal & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagReal & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::real & operator [](const Storage & arg) const {return arg.Real(*static_cast<const Tag*>(this));} __INLINE Storage::real & operator [](const Storage & arg) const {return arg.Real(*static_cast<const Tag*>(this));}
__INLINE Storage::real & operator [](HandleType h) const;
}; };
class TagInteger : public Tag class TagInteger : public Tag
...@@ -633,7 +634,8 @@ namespace INMOST ...@@ -633,7 +634,8 @@ namespace INMOST
TagInteger(const Tag & b) : Tag(b) {} TagInteger(const Tag & b) : Tag(b) {}
TagInteger & operator = (TagInteger const & b) {Tag::operator =(b); return *this;} TagInteger & operator = (TagInteger const & b) {Tag::operator =(b); return *this;}
TagInteger & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagInteger & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::integer & operator [](const Storage & arg) const {return arg.Integer(*static_cast<const Tag*>(this));} __INLINE Storage::integer & operator [](const Storage & arg) const {return arg.Integer(*static_cast<const Tag*>(this));}
__INLINE Storage::integer & operator [](HandleType h) const;
}; };
class TagBulk : public Tag class TagBulk : public Tag
...@@ -644,7 +646,8 @@ namespace INMOST ...@@ -644,7 +646,8 @@ namespace INMOST
TagBulk(const Tag & b) : Tag(b) {} TagBulk(const Tag & b) : Tag(b) {}
TagBulk & operator = (TagBulk const & b) {Tag::operator =(b); return *this;} TagBulk & operator = (TagBulk const & b) {Tag::operator =(b); return *this;}
TagBulk & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagBulk & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::bulk & operator [](const Storage & arg) const {return arg.Bulk(*static_cast<const Tag*>(this));} __INLINE Storage::bulk & operator [](const Storage & arg) const {return arg.Bulk(*static_cast<const Tag*>(this));}
__INLINE Storage::bulk & operator [](HandleType h) const;
}; };
class TagReference : public Tag class TagReference : public Tag
...@@ -655,7 +658,8 @@ namespace INMOST ...@@ -655,7 +658,8 @@ namespace INMOST
TagReference(const Tag & b) : Tag(b) {} TagReference(const Tag & b) : Tag(b) {}
TagReference & operator = (TagReference const & b) {Tag::operator =(b); return *this;} TagReference & operator = (TagReference const & b) {Tag::operator =(b); return *this;}
TagReference & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagReference & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::reference & operator [](const Storage & arg) const {return arg.Reference(*static_cast<const Tag*>(this));} __INLINE Storage::reference & operator [](const Storage & arg) const {return arg.Reference(*static_cast<const Tag*>(this));}
__INLINE Storage::reference & operator [](HandleType h) const;
}; };
...@@ -667,7 +671,8 @@ namespace INMOST ...@@ -667,7 +671,8 @@ namespace INMOST
TagRealArray(const Tag & b) : Tag(b) {} TagRealArray(const Tag & b) : Tag(b) {}
TagRealArray & operator = (TagRealArray const & b) {Tag::operator =(b); return *this;} TagRealArray & operator = (TagRealArray const & b) {Tag::operator =(b); return *this;}
TagRealArray & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagRealArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::real_array operator [](const Storage & arg) const {return arg.RealArray(*static_cast<const Tag*>(this));} __INLINE Storage::real_array operator [](const Storage & arg) const {return arg.RealArray(*static_cast<const Tag*>(this));}
__INLINE Storage::real_array operator [](HandleType h) const;
}; };
class TagIntegerArray : public Tag class TagIntegerArray : public Tag
...@@ -678,7 +683,8 @@ namespace INMOST ...@@ -678,7 +683,8 @@ namespace INMOST
TagIntegerArray(const Tag & b) : Tag(b) {} TagIntegerArray(const Tag & b) : Tag(b) {}
TagIntegerArray & operator = (TagIntegerArray const & b) {Tag::operator =(b); return *this;} TagIntegerArray & operator = (TagIntegerArray const & b) {Tag::operator =(b); return *this;}
TagIntegerArray & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagIntegerArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::integer_array operator [](const Storage & arg) const {return arg.IntegerArray(*static_cast<const Tag*>(this));} __INLINE Storage::integer_array operator [](const Storage & arg) const {return arg.IntegerArray(*static_cast<const Tag*>(this));}
__INLINE Storage::integer_array operator [](HandleType h) const;
}; };
class TagBulkArray : public Tag class TagBulkArray : public Tag
...@@ -689,7 +695,8 @@ namespace INMOST ...@@ -689,7 +695,8 @@ namespace INMOST
TagBulkArray(const Tag & b) : Tag(b) {} TagBulkArray(const Tag & b) : Tag(b) {}
TagBulkArray & operator = (TagBulkArray const & b) {Tag::operator =(b); return *this;} TagBulkArray & operator = (TagBulkArray const & b) {Tag::operator =(b); return *this;}
TagBulkArray & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagBulkArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::bulk_array operator [](const Storage & arg) const {return arg.BulkArray(*static_cast<const Tag*>(this));} __INLINE Storage::bulk_array operator [](const Storage & arg) const {return arg.BulkArray(*static_cast<const Tag*>(this));}
__INLINE Storage::bulk_array operator [](HandleType h) const;
}; };
class TagReferenceArray : public Tag class TagReferenceArray : public Tag
...@@ -700,7 +707,8 @@ namespace INMOST ...@@ -700,7 +707,8 @@ namespace INMOST
TagReferenceArray(const Tag & b) : Tag(b) {} TagReferenceArray(const Tag & b) : Tag(b) {}
TagReferenceArray & operator = (TagReferenceArray const & b) {Tag::operator =(b); return *this;} TagReferenceArray & operator = (TagReferenceArray const & b) {Tag::operator =(b); return *this;}
TagReferenceArray & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagReferenceArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::reference_array operator [](const Storage & arg) const {return arg.ReferenceArray(*static_cast<const Tag*>(this));} __INLINE Storage::reference_array operator [](const Storage & arg) const {return arg.ReferenceArray(*static_cast<const Tag*>(this));}
__INLINE Storage::reference_array operator [](HandleType h) const;
}; };
#if defined(USE_AUTODIFF) #if defined(USE_AUTODIFF)
...@@ -712,7 +720,8 @@ namespace INMOST ...@@ -712,7 +720,8 @@ namespace INMOST
TagVariable(const Tag & b) : Tag(b) {} TagVariable(const Tag & b) : Tag(b) {}
TagVariable & operator = (TagVariable const & b) {Tag::operator =(b); return *this;} TagVariable & operator = (TagVariable const & b) {Tag::operator =(b); return *this;}
TagVariable & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagVariable & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::var & operator [](const Storage & arg) const {return arg.Variable(*static_cast<const Tag*>(this));} __INLINE Storage::var & operator [](const Storage & arg) const {return arg.Variable(*static_cast<const Tag*>(this));}
__INLINE Storage::var & operator [](HandleType h) const;
}; };
class TagVariableArray : public Tag class TagVariableArray : public Tag
...@@ -723,7 +732,8 @@ namespace INMOST ...@@ -723,7 +732,8 @@ namespace INMOST
TagVariableArray(const Tag & b) : Tag(b) {} TagVariableArray(const Tag & b) : Tag(b) {}
TagVariableArray & operator = (TagVariableArray const & b) {Tag::operator =(b); return *this;} TagVariableArray & operator = (TagVariableArray const & b) {Tag::operator =(b); return *this;}
TagVariableArray & operator = (Tag const & b) {Tag::operator =(b); return *this;} TagVariableArray & operator = (Tag const & b) {Tag::operator =(b); return *this;}
Storage::var_array operator [](const Storage & arg) const {return arg.VariableArray(*static_cast<const Tag*>(this));} __INLINE Storage::var_array operator [](const Storage & arg) const {return arg.VariableArray(*static_cast<const Tag*>(this));}
__INLINE Storage::var_array operator [](HandleType h) const;
}; };
#endif //USE_AUTODIFF #endif //USE_AUTODIFF
......
...@@ -1310,6 +1310,9 @@ namespace INMOST ...@@ -1310,6 +1310,9 @@ namespace INMOST
void AllocateSparseData (void * & q, const Tag & t); void AllocateSparseData (void * & q, const Tag & t);
void Init (std::string name); void Init (std::string name);
public: public:
/// Go through all elements and detect presence of prescribed element in
/// any reference data tag.
void ReportConnection(HandleType h);
/// Test whether global identificator was set on certain type of elements. /// Test whether global identificator was set on certain type of elements.
/// This function does not validate correctness of global identificators. /// This function does not validate correctness of global identificators.
/// @param type Single type of elements on which to test presence of global identificators. /// @param type Single type of elements on which to test presence of global identificators.
...@@ -1318,8 +1321,6 @@ namespace INMOST ...@@ -1318,8 +1321,6 @@ namespace INMOST
/// Remove all data and all elements from the mesh /// Remove all data and all elements from the mesh
/// Reset geometry service and topology check flags /// Reset geometry service and topology check flags
void Clear (); void Clear ();
/// For debug purposes
integer HandleDataPos (HandleType h) {return links[GetHandleElementNum(h)][GetHandleID(h)];}
/// For parmetis /// For parmetis
/// return total number in bytes of occupied memory by element and its data /// return total number in bytes of occupied memory by element and its data
enumerator MemoryUsage (HandleType h); enumerator MemoryUsage (HandleType h);
...@@ -1459,7 +1460,7 @@ namespace INMOST ...@@ -1459,7 +1460,7 @@ namespace INMOST
bool isValidEdge (integer lid) const {return links[ElementNum(EDGE)][lid] != -1;} bool isValidEdge (integer lid) const {return links[ElementNum(EDGE)][lid] != -1;}
bool isValidNode (integer lid) const {return links[ElementNum(NODE)][lid] != -1;} bool isValidNode (integer lid) const {return links[ElementNum(NODE)][lid] != -1;}
bool isValidElementSet (integer lid) const {return links[ElementNum(ESET)][lid] != -1;} bool isValidElementSet (integer lid) const {return links[ElementNum(ESET)][lid] != -1;}
bool isValidElement (HandleType h) const {return isValidHandle(h) && isValidElementNum(GetHandleElementNum(h),GetHandleID(h));} bool isValidElement (HandleType h) const {return isValidHandleRange(h) && isValidElementNum(GetHandleElementNum(h),GetHandleID(h));}
/// Retrieve upper adjacent that is shared by multiple lower adjacencies. /// Retrieve upper adjacent that is shared by multiple lower adjacencies.
/// @return handle of found element or InvalidHandle() /// @return handle of found element or InvalidHandle()
HandleType FindSharedAdjacency(const HandleType * arr, enumerator num) const; HandleType FindSharedAdjacency(const HandleType * arr, enumerator num) const;
...@@ -3438,6 +3439,38 @@ namespace INMOST ...@@ -3438,6 +3439,38 @@ namespace INMOST
{ {
return GetMeshLink()->RemoteReferenceDV(GetHandle(),tag); return GetMeshLink()->RemoteReferenceDV(GetHandle(),tag);
} }
__INLINE Storage::real & TagReal::operator [](HandleType h) const
{
return GetMeshLink()->Real(h,*static_cast<const Tag*>(this));
}
__INLINE Storage::integer & TagInteger::operator [](HandleType h) const
{
return GetMeshLink()->Integer(h,*static_cast<const Tag*>(this));
}
__INLINE Storage::bulk & TagBulk::operator [](HandleType h) const
{
return GetMeshLink()->Bulk(h,*static_cast<const Tag*>(this));
}
__INLINE Storage::reference & TagReference::operator [](HandleType h) const
{
return GetMeshLink()->Reference(h,*static_cast<const Tag*>(this));
}
__INLINE Storage::real_array TagRealArray::operator [](HandleType h) const
{
return GetMeshLink()->RealArray(h,*static_cast<const Tag*>(this));
}
__INLINE Storage::integer_array TagIntegerArray::operator [](HandleType h) const
{
return GetMeshLink()->IntegerArray(h,*static_cast<const Tag*>(this));
}
__INLINE Storage::bulk_array TagBulkArray::operator [](HandleType h) const
{
return GetMeshLink()->BulkArray(h,*static_cast<const Tag*>(this));
}
__INLINE Storage::reference_array TagReferenceArray::operator [](HandleType h) const
{
return GetMeshLink()->ReferenceArray(h,*static_cast<const Tag*>(this));
}
#if defined(USE_AUTODIFF) #if defined(USE_AUTODIFF)
__INLINE Storage::var & Storage::Variable(const Tag & tag) const __INLINE Storage::var & Storage::Variable(const Tag & tag) const
{ {
...@@ -3463,17 +3496,25 @@ namespace INMOST ...@@ -3463,17 +3496,25 @@ namespace INMOST
{ {
return GetMeshLink()->VariableArrayDV(GetHandle(),tag); return GetMeshLink()->VariableArrayDV(GetHandle(),tag);
} }
__INLINE Storage::var & TagVariable::operator [](HandleType h) const
{
return GetMeshLink()->Variable(h,