Commit f52d6054 authored by Kirill Terekhov's avatar Kirill Terekhov

Updates and fixes

Examples/AdaptiveMesh do not inherit Mesh anymore - easier to work with
the method

Examples/Fracture got the option to not to fill the space

SearchKDTree class to search for elements by coordinates in mesh (some
rearrangements and improvements may follow)

Code to support mesh adaptation in models

Fix boundary condition in TestSuite/cavity
parent 9b984278
Pipeline #170 failed with stages
in 10 minutes and 9 seconds
......@@ -35,9 +35,9 @@ namespace INMOST
void AdaptiveMesh::ClearData()
{
level = DeleteTag(level);
hanging_nodes = DeleteTag(hanging_nodes);
parent_set = DeleteTag(parent_set);
level = m->DeleteTag(level);
hanging_nodes = m->DeleteTag(hanging_nodes);
parent_set = m->DeleteTag(parent_set);
root.DeleteSetTree();
}
......@@ -46,29 +46,30 @@ namespace INMOST
//retrive set for coarsening, initialize set if is not present
if( !root.isValid() )
{
root = GetSet("ROOT_SET");
root = m->GetSet("ROOT_SET");
if( root == InvalidElement() )
{
root = CreateSetUnique("ROOT_SET").first;
root = m->CreateSetUnique("ROOT_SET").first;
level[root] = 0;
for(iteratorCell it = BeginCell(); it != EndCell(); ++it)
for(Mesh::iteratorCell it = m->BeginCell(); it != m->EndCell(); ++it)
{
root.PutElement(it->self());
parent_set[it->self()] = root.GetHandle();
}
}
}
if( !HaveGlobalID(CELL) ) AssignGlobalID(CELL); //for unique set names
if( !m->HaveGlobalID(CELL) ) m->AssignGlobalID(CELL); //for unique set names
}
AdaptiveMesh::AdaptiveMesh() : Mesh()
AdaptiveMesh::AdaptiveMesh(Mesh & _m) : m(&_m)
{
model = NULL;
//create a tag that stores maximal refinement level of each element
level = CreateTag("REFINEMENT_LEVEL",DATA_INTEGER,CELL|FACE|EDGE|NODE|ESET,NONE,1);
level = m->CreateTag("REFINEMENT_LEVEL",DATA_INTEGER,CELL|FACE|EDGE|NODE|ESET,NONE,1);
//create a tag that stores links to all the hanging nodes of the cell
hanging_nodes = CreateTag("HANGING_NODES",DATA_REFERENCE,CELL|FACE,NONE);
hanging_nodes = m->CreateTag("HANGING_NODES",DATA_REFERENCE,CELL|FACE,NONE);
//create a tag that stores links to sets
parent_set = CreateTag("PARENT_SET",DATA_REFERENCE,CELL,NONE,1);
parent_set = m->CreateTag("PARENT_SET",DATA_REFERENCE,CELL,NONE,1);
}
AdaptiveMesh::~AdaptiveMesh()
......@@ -79,6 +80,7 @@ namespace INMOST
bool AdaptiveMesh::Refine(TagInteger & indicator)
{
//std::cout << __FUNCTION__ << std::endl;
static int call_counter = 0;
int ret = 0; //return number of refined cells
//initialize tree structure
......@@ -86,16 +88,16 @@ namespace INMOST
int schedule_counter = 1; //indicates order in which refinement will be scheduled
int scheduled = 1; //indicates that at least one element was scheduled on current sweep
//0. Extend indicator for edges and faces
indicator = CreateTag(indicator.GetTagName(),DATA_INTEGER,FACE|EDGE,NONE,1);
indicator = m->CreateTag(indicator.GetTagName(),DATA_INTEGER,FACE|EDGE,NONE,1);
while(scheduled)
{
//1.Communicate indicator - it may be not synced
ExchangeData(indicator,CELL,0);
m->ExchangeData(indicator,CELL,0);
//2.Propogate indicator down to the faces,edges
// select schedule for them
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
if( indicator[c] == schedule_counter )
{
ElementArray<Element> adj = c.getAdjElements(FACE|EDGE);
......@@ -107,14 +109,14 @@ namespace INMOST
}
}
//3.Communicate indicator on faces and edges
ExchangeData(indicator,FACE|EDGE,0);
m->ExchangeData(indicator,FACE|EDGE,0);
//4.Check for each cell if there is
// any hanging node with adjacent in a need to refine,
// schedule for refinement earlier.
scheduled = 0;
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
//already scheduled cells may be required to be refined first
//if( indicator[c] == 0 ) //some optimization
{
......@@ -137,43 +139,43 @@ namespace INMOST
}
}
//5.Go back to 1 until no new elements scheduled
scheduled = Integrate(scheduled);
scheduled = m->Integrate(scheduled);
if( scheduled ) schedule_counter++;
}
//6.Refine
BeginModification();
m->BeginModification();
while(schedule_counter)
{
Storage::real xyz[3] = {0,0,0};
//7.split all edges of the current schedule
for(Storage::integer it = 0; it < EdgeLastLocalID(); ++it) if( isValidEdge(it) )
for(Storage::integer it = 0; it < m->EdgeLastLocalID(); ++it) if( m->isValidEdge(it) )
{
Edge e = EdgeByLocalID(it);
Edge e = m->EdgeByLocalID(it);
if( !e.Hidden() && indicator[e] == schedule_counter )
{
//remember adjacent faces that should get information about new hanging node
ElementArray<Face> edge_faces = e.getFaces();
//location on the center of the edge
for(Storage::integer d = 0; d < GetDimensions(); ++d)
for(Storage::integer d = 0; d < m->GetDimensions(); ++d)
xyz[d] = (e.getBeg().Coords()[d]+e.getEnd().Coords()[d])*0.5;
//todo: request transformation of node location according to geometrical model
//create middle node
Node n = CreateNode(xyz);
Node n = m->CreateNode(xyz);
//set increased level for new node
level[n] = level[e.getBeg()] = level[e.getEnd()] = level[e]+1;
//for each face provide link to a new hanging node
for(ElementArray<Face>::size_type kt = 0; kt < edge_faces.size(); ++kt)
hanging_nodes[edge_faces[kt]].push_back(n);
//split the edge by the middle node
ElementArray<Edge> new_edges = Edge::SplitEdge(e,ElementArray<Node>(this,1,n.GetHandle()),0);
ElementArray<Edge> new_edges = Edge::SplitEdge(e,ElementArray<Node>(m,1,n.GetHandle()),0);
//set increased level for new edges
level[new_edges[0]] = level[new_edges[1]] = level[e]+1;
}
}
//8.split all faces of the current schedule, using hanging nodes on edges
for(Storage::integer it = 0; it < FaceLastLocalID(); ++it) if( isValidFace(it) )
for(Storage::integer it = 0; it < m->FaceLastLocalID(); ++it) if( m->isValidFace(it) )
{
Face f = FaceByLocalID(it);
Face f = m->FaceByLocalID(it);
if( !f.Hidden() && indicator[f] == schedule_counter )
{
//connect face center to hanging nodes of the face
......@@ -189,19 +191,19 @@ namespace INMOST
for(int d = 0; d < 3; ++d) xyz[d] /= (Storage::real)face_hanging_nodes.size();
//todo: request transformation of node location according to geometrical model
//create middle node
Node n = CreateNode(xyz);
Node n = m->CreateNode(xyz);
//set increased level for the new node
level[n] = level[f]+1;
//for each cell provide link to new hanging node
for(ElementArray<Face>::size_type kt = 0; kt < face_cells.size(); ++kt)
hanging_nodes[face_cells[kt]].push_back(n);
ElementArray<Node> edge_nodes(this,2); //to create new edges
ElementArray<Edge> hanging_edges(this,face_hanging_nodes.size());
ElementArray<Node> edge_nodes(m,2); //to create new edges
ElementArray<Edge> hanging_edges(m,face_hanging_nodes.size());
edge_nodes[0] = n;
for(Storage::reference_array::size_type kt = 0; kt < face_hanging_nodes.size(); ++kt)
{
edge_nodes[1] = face_hanging_nodes[kt].getAsNode();
hanging_edges[kt] = CreateEdge(edge_nodes).first;
hanging_edges[kt] = m->CreateEdge(edge_nodes).first;
//set increased level for new edges
level[hanging_edges[kt]] = level[f]+1;
}
......@@ -213,15 +215,15 @@ namespace INMOST
}
}
//this tag helps recreate internal face
TagReferenceArray internal_face_edges = CreateTag("INTERNAL_FACE_EDGES",DATA_REFERENCE,NODE,NODE,4);
TagReferenceArray internal_face_edges = m->CreateTag("INTERNAL_FACE_EDGES",DATA_REFERENCE,NODE,NODE,4);
//this marker helps detect edges of current cell only
MarkerType mark_cell_edges = CreateMarker();
MarkerType mark_cell_edges = m->CreateMarker();
//this marker helps detect nodes hanging on edges of unrefined cell
MarkerType mark_hanging_nodes = CreateMarker();
MarkerType mark_hanging_nodes = m->CreateMarker();
//9.split all cells of the current schedule
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
if( !c.Hidden() && indicator[c] == schedule_counter )
{
Storage::reference_array cell_hanging_nodes = hanging_nodes[c]; //nodes to be connected
......@@ -233,7 +235,7 @@ namespace INMOST
//c->Centroid(xyz);
//todo: request transformation of node location according to geometrical model
//create middle node
Node n = CreateNode(xyz);
Node n = m->CreateNode(xyz);
//set increased level for the new node
level[n] = level[c]+1;
//retrive all edges of current face to mark them
......@@ -241,15 +243,15 @@ namespace INMOST
//mark all edges so that we can retive them later
cell_edges.SetMarker(mark_cell_edges);
//connect face center to centers of faces by edges
ElementArray<Node> edge_nodes(this,2);
ElementArray<Edge> edges_to_faces(this,cell_hanging_nodes.size());
ElementArray<Node> edge_nodes(m,2);
ElementArray<Edge> edges_to_faces(m,cell_hanging_nodes.size());
edge_nodes[0] = n;
for(Storage::reference_array::size_type kt = 0; kt < cell_hanging_nodes.size(); ++kt)
{
assert(cell_hanging_nodes[kt].isValid());
//todo: unmark hanging node on edge if no more cells depend on it
edge_nodes[1] = cell_hanging_nodes[kt].getAsNode();
edges_to_faces[kt] = CreateEdge(edge_nodes).first;
edges_to_faces[kt] = m->CreateEdge(edge_nodes).first;
//set increased level for new edges
level[edges_to_faces[kt]] = level[c]+1;
//for each node other then the hanging node of the face
......@@ -285,7 +287,7 @@ namespace INMOST
cell_edges.RemMarker(mark_cell_edges);
//now we have to create internal faces
ElementArray<Node> edge_hanging_nodes = c.getNodes(mark_hanging_nodes,0);
ElementArray<Face> internal_faces(this,edge_hanging_nodes.size());
ElementArray<Face> internal_faces(m,edge_hanging_nodes.size());
//unmark hanging nodes on edges
edge_hanging_nodes.RemMarker(mark_hanging_nodes);
for(ElementArray<Node>::size_type kt = 0; kt < edge_hanging_nodes.size(); ++kt)
......@@ -296,7 +298,7 @@ namespace INMOST
assert(face_edges[1].isValid());
assert(face_edges[2].isValid());
assert(face_edges[3].isValid());
internal_faces[kt] = CreateFace(ElementArray<Edge>(this,face_edges.begin(),face_edges.end())).first;
internal_faces[kt] = m->CreateFace(ElementArray<Edge>(m,face_edges.begin(),face_edges.end())).first;
//set increased level
level[internal_faces[kt]] = level[c]+1;
//clean up structure, so that other cells can use it
......@@ -305,11 +307,11 @@ namespace INMOST
//split the cell
ElementArray<Cell> new_cells = Cell::SplitCell(c,internal_faces,0);
//retrive parent set
ElementSet parent(this,parent_set[c]);
ElementSet parent(m,parent_set[c]);
//create set corresponding to old coarse cell
std::stringstream set_name;
set_name << parent.GetName() << "_C" << c.GlobalID(); //rand may be unsafe
ElementSet cell_set = CreateSetUnique(set_name.str()).first;
ElementSet cell_set = m->CreateSetUnique(set_name.str()).first;
level[cell_set] = level[c]+1;
//set up increased level for the new cells
for(ElementArray<Cell>::size_type kt = 0; kt < new_cells.size(); ++kt)
......@@ -323,26 +325,27 @@ namespace INMOST
ret++;
}
}
ReleaseMarker(mark_hanging_nodes);
ReleaseMarker(mark_cell_edges);
DeleteTag(internal_face_edges);
m->ReleaseMarker(mark_hanging_nodes);
m->ReleaseMarker(mark_cell_edges);
m->DeleteTag(internal_face_edges);
//10.jump to later schedule, and go to 7.
schedule_counter--;
}
//free created tag
DeleteTag(indicator,FACE|EDGE);
m->DeleteTag(indicator,FACE|EDGE);
//11. Restore parallel connectivity, global ids
//ResolveShared(true);
//ResolveModification();
//12. Let the user update their data
//todo: call back function for New() cells
if( model ) model->Adaptation(*m);
//13. Delete old elements of the mesh
ApplyModification();
m->ApplyModification();
//14. Done
EndModification();
m->EndModification();
//ExchangeData(hanging_nodes,CELL | FACE,0);
//reorder element's data to free up space
ReorderEmpty(CELL|FACE|EDGE|NODE);
m->ReorderEmpty(CELL|FACE|EDGE|NODE);
//return number of refined cells
call_counter++;
return ret != 0;
......@@ -355,6 +358,7 @@ namespace INMOST
bool AdaptiveMesh::Coarse(TagInteger & indicator)
{
//std::cout << __FUNCTION__ << std::endl;
static int call_counter = 0;
//return number of coarsened cells
int ret = 0;
......@@ -363,9 +367,9 @@ namespace INMOST
int schedule_counter = 1; //indicates order in which refinement will be scheduled
int scheduled = 1, unscheduled = 0; //indicates that at least one element was scheduled on current sweep
//TagInteger coarsened = CreateTag("COARSENED",DATA_INTEGER,CELL,NONE,1);
TagInteger coarse_indicator = CreateTag("COARSE_INDICATOR",DATA_INTEGER,EDGE,NONE,1); //used to find on fine cells indicator on coarse cells
TagInteger coarse_indicator = m->CreateTag("COARSE_INDICATOR",DATA_INTEGER,EDGE,NONE,1); //used to find on fine cells indicator on coarse cells
//0. Extend indicator for sets, edges and faces
indicator = CreateTag(indicator.GetTagName(),DATA_INTEGER,FACE|EDGE,NONE,1);
indicator = m->CreateTag(indicator.GetTagName(),DATA_INTEGER,FACE|EDGE,NONE,1);
while(scheduled || unscheduled)
{
// rules
......@@ -374,7 +378,7 @@ namespace INMOST
// b) If there is adjacent coarser cell, then this cell should be coarsened
// first
//0.Communicate indicator - it may be not synced
ExchangeData(indicator,CELL,0);
m->ExchangeData(indicator,CELL,0);
//1. Mark each adjacent face/edge for coarsement schedule
// problem: should mark so that if every adjacent cell is coarsened
// then adjacent face/edge are also coarsened
......@@ -382,9 +386,9 @@ namespace INMOST
{
//for(Storage::integer it = 0; it < LastLocalID(etype); ++it) if( isValidElement(etype,it) )
// indicator[ElementByLocalID(etype,it)] = 0;
for(Storage::integer it = 0; it < LastLocalID(etype); ++it) if( isValidElement(etype,it) )
for(Storage::integer it = 0; it < m->LastLocalID(etype); ++it) if( m->isValidElement(etype,it) )
{
Element e = ElementByLocalID(etype,it);
Element e = m->ElementByLocalID(etype,it);
ElementArray<Cell> adj = e.getCells();
indicator[e] = INT_MAX;
for(ElementArray<Element>::size_type kt = 0; kt < adj.size(); ++kt)
......@@ -393,13 +397,13 @@ namespace INMOST
}
}
//2.Communicate indicator on faces and edges
ReduceData(indicator,FACE|EDGE,0,ReduceMin);
m->ReduceData(indicator,FACE|EDGE,0,ReduceMin);
//3.If there is adjacent finer edge that are not marked for coarsening
// then this cell should not be coarsened
unscheduled = scheduled = 0;
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
if( indicator[c] )
{
ElementArray<Edge> edges = c.getEdges();
......@@ -418,12 +422,12 @@ namespace INMOST
// of the set are marked for coarsening, then mark the set for coarsement
// otherwise unmark.
// Unmark all cells that are not to be coarsened
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
if( indicator[c] )
{
ElementSet parent(this,parent_set[c]);
ElementSet parent(m,parent_set[c]);
//intermediate cell may not be coarsened
//root set may not have coarsening cells
if( parent.HaveChild() || !parent.HaveParent() )
......@@ -457,12 +461,12 @@ namespace INMOST
//5.If there is an adjacent coarser element to be refined, then
// this one should be scheduled to be refined first
//a) clean up coarse indicator tag
for(Storage::integer it = 0; it < EdgeLastLocalID(); ++it) if( isValidEdge(it) )
coarse_indicator[EdgeByLocalID(it)] = 0;
for(Storage::integer it = 0; it < m->EdgeLastLocalID(); ++it) if( m->isValidEdge(it) )
coarse_indicator[m->EdgeByLocalID(it)] = 0;
//b) each cell mark it's finer edges with cell's schedule
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
if( indicator[c] )
{
ElementArray<Element> adj = c.getAdjElements(EDGE);
......@@ -474,11 +478,11 @@ namespace INMOST
}
}
//c) data reduction to get maximum over mesh partition
ReduceData(coarse_indicator,EDGE,0,ReduceMax);
m->ReduceData(coarse_indicator,EDGE,0,ReduceMax);
//d) look from cells if any edge is coarsened earlier
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
if( indicator[c] )
{
ElementArray<Element> adj = c.getAdjElements(EDGE);
......@@ -494,28 +498,28 @@ namespace INMOST
}
}
//5.Go back to 1 until no new elements scheduled
scheduled = Integrate(scheduled);
unscheduled = Integrate(unscheduled);
scheduled = m->Integrate(scheduled);
unscheduled = m->Integrate(unscheduled);
if( scheduled ) schedule_counter++;
}
//cleanup
coarse_indicator = DeleteTag(coarse_indicator);
coarse_indicator = m->DeleteTag(coarse_indicator);
//Make schedule which elements should be refined earlier.
BeginModification();
m->BeginModification();
while(schedule_counter)
{
//unite cells
//should find and set hanging nodes on faces
//find single node at the center, all other nodes,
//adjacent over edge are hanging nodes
for(Storage::integer it = 0; it < CellLastLocalID(); ++it) if( isValidCell(it) )
for(Storage::integer it = 0; it < m->CellLastLocalID(); ++it) if( m->isValidCell(it) )
{
Cell c = CellByLocalID(it);
Cell c = m->CellByLocalID(it);
if( !c.Hidden() && indicator[c] == schedule_counter )
{
//this set contains all the cells to be united
ElementSet parent(this,parent_set[c]);
ElementArray<Cell> unite_cells(this,parent.Size());
ElementSet parent(m,parent_set[c]);
ElementArray<Cell> unite_cells(m,parent.Size());
//unmark indicator to prevent coarsement with next element
Storage::integer kt = 0;
for(ElementSet::iterator jt = parent.Begin(); jt != parent.End(); ++jt)
......@@ -538,7 +542,7 @@ namespace INMOST
//set new parent
parent_set[v] = parent.GetParent().GetHandle();
//add cell to parent set
ElementSet(this,parent_set[v]).PutElement(v);
ElementSet(m,parent_set[v]).PutElement(v);
//set level for new cell
level[v] = level[c]-1;
//delete set that contained cells
......@@ -553,9 +557,9 @@ namespace INMOST
//find single node at the center, all other nodes,
//adjacent over edge of the face are hanging nodes
int numcoarsened = 0;
for(Storage::integer it = 0; it < FaceLastLocalID(); ++it) if( isValidFace(it) )
for(Storage::integer it = 0; it < m->FaceLastLocalID(); ++it) if( m->isValidFace(it) )
{
Face f = FaceByLocalID(it);
Face f = m->FaceByLocalID(it);
if( !f.Hidden() && indicator[f] == schedule_counter )
{
//one (or both) of the adjacent cells were coarsened and has lower level
......@@ -601,9 +605,9 @@ namespace INMOST
}
}
//unite edges
for(Storage::integer it = 0; it < EdgeLastLocalID(); ++it) if( isValidEdge(it) )
for(Storage::integer it = 0; it < m->EdgeLastLocalID(); ++it) if( m->isValidEdge(it) )
{
Edge e = EdgeByLocalID(it);
Edge e = m->EdgeByLocalID(it);
if( !e.Hidden() && indicator[e] == schedule_counter )
{
//at least one face must have lower level
......@@ -640,22 +644,23 @@ namespace INMOST
schedule_counter--;
}
//free created tag
DeleteTag(indicator,FACE|EDGE);
m->DeleteTag(indicator,FACE|EDGE);
//todo:
//ResolveShared(true);
//ResolveModification();
//todo:
//let the user update their data
ApplyModification();
if( model ) model->Adaptation(*m);
m->ApplyModification();
//done
EndModification();
m->EndModification();
//ExchangeData(hanging_nodes,CELL | FACE,0);
//cleanup null links to hanging nodes
for(ElementType etype = FACE; etype <= CELL; etype = NextElementType(etype))
{
for(Storage::integer it = 0; it < LastLocalID(etype); ++it) if( isValidElement(etype,it) )
for(Storage::integer it = 0; it < m->LastLocalID(etype); ++it) if( m->isValidElement(etype,it) )
{
Storage::reference_array arr = hanging_nodes[ElementByLocalID(etype,it)];
Storage::reference_array arr = hanging_nodes[m->ElementByLocalID(etype,it)];
Storage::reference_array::size_type jt = 0;
for(Storage::reference_array::size_type kt = 0; kt < arr.size(); ++kt)
if( arr[kt] != InvalidElement() ) arr[jt++] = arr[kt];
......@@ -665,7 +670,7 @@ namespace INMOST
//cleanup null links in sets
CleanupSets(root);
//reorder element's data to free up space
ReorderEmpty(CELL|FACE|EDGE|NODE|ESET);
m->ReorderEmpty(CELL|FACE|EDGE|NODE|ESET);
call_counter++;
return ret != 0;
......
......@@ -4,8 +4,10 @@
namespace INMOST
{
class AdaptiveMesh : public Mesh
class AdaptiveMesh
{
Mesh * m;
Model * model;
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.
......@@ -15,7 +17,7 @@ namespace INMOST
void PrepareSet();
public:
Storage::integer GetLevel(const Storage & e) {return level[e];}
AdaptiveMesh();
AdaptiveMesh(Mesh & m);
~AdaptiveMesh();
/// Indicator must be 1 on cells to be refined
/// and 0 on all other cells
......@@ -23,6 +25,7 @@ namespace INMOST
bool Coarse(TagInteger & indicator);
/// Delete all data related to mesh refinement-coarsement.
void ClearData();
void SetModel(Model * mm) {model = mm;}
};
}
......
......@@ -8,9 +8,10 @@ int main(int argc, char ** argv)
if( argc > 1 )
{
AdaptiveMesh m;
Mesh m;
m.SetCommunicator(INMOST_MPI_COMM_WORLD);
m.Load(argv[1]);
AdaptiveMesh am(m);
//m.SetTopologyCheck(NEED_TEST_CLOSURE);
//m.SetTopologyCheck(PROHIBIT_MULTILINE);
//m.SetTopologyCheck(PROHIBIT_MULTIPOLYGON);
......@@ -56,7 +57,7 @@ int main(int argc, char ** argv)
do
{
numref = 0;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) if( m.GetLevel(it->self()) < max_levels )
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) if( am.GetLevel(it->self()) < max_levels )
{
it->Barycenter(xyz);
//refine a circle
......@@ -82,7 +83,7 @@ int main(int argc, char ** argv)
m.Save(file.str());
}
*/
if( !m.Refine(indicator) ) break;
if( !am.Refine(indicator) ) break;
{
std::stringstream file;
......@@ -100,7 +101,7 @@ int main(int argc, char ** argv)
do
{
numref = 0;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) if( m.GetLevel(it->self()) > 0 )
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) if( am.GetLevel(it->self()) > 0 )
{
it->Barycenter(xyz);
//refine a circle
......@@ -125,7 +126,7 @@ int main(int argc, char ** argv)
m.Save(file.str());
}
*/
if( !m.Coarse(indicator) ) break;
if( !am.Coarse(indicator) ) break;
{
std::stringstream file;
......
......@@ -8,9 +8,10 @@ int main(int argc, char ** argv)
if( argc > 1 )
{
AdaptiveMesh m;
m.Load(argv[1]);
TagInteger indicator = m.CreateTag("INDICATOR",DATA_INTEGER,CELL,NONE,1);
Mesh mm;
mm.Load(argv[1]);
TagInteger indicator = mm.CreateTag("INDICATOR",DATA_INTEGER,CELL,NONE,1);
AdaptiveMesh m(mm);
int max_levels = 2;
if( argc > 2 ) max_levels = atoi(argv[2]);
......@@ -19,7 +20,7 @@ int main(int argc, char ** argv)
do
{
numref = 0;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
for(Mesh::iteratorCell it = mm.BeginCell(); it != mm.EndCell(); ++it)
if( m.GetLevel(it->self()) < max_levels )
{
double x[3];
......@@ -33,13 +34,13 @@ int main(int argc, char ** argv)
if( numref )
{
if( !m.Refine(indicator) ) break;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) indicator[it->self()] = 0;
for(Mesh::iteratorCell it = mm.BeginCell(); it != mm.EndCell(); ++it) indicator[it->self()] = 0;
}
}
while(numref);
std::string file = "out.vtk";
if( argc > 3 ) file = std::string(argv[3]);
m.Save(file);
mm.Save(file);
}
else std::cout << "Usage: " << argv[0] << " mesh_file [max_levels=2] [mesh_out=out.vtk]" << std::endl;
}
\ No newline at end of file
}
......@@ -8,9 +8,10 @@ int main(int argc, char ** argv)
if( argc > 1 )
{
AdaptiveMesh m;
Mesh m;
m.Load(argv[1]);
TagInteger indicator = m.CreateTag("INDICATOR",DATA_INTEGER,CELL,NONE,1);
AdaptiveMesh am(m);
int max_levels = 2;
if( argc > 2 ) max_levels = atoi(argv[2]);
......@@ -20,7 +21,7 @@ int main(int argc, char ** argv)
{
numref = 0;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
if( m.GetLevel(it->self()) < max_levels )
if( am.GetLevel(it->self()) < max_levels )
{
double x[3];
it->Centroid(x);
......@@ -32,7 +33,7 @@ int main(int argc, char ** argv)
}
if( numref )
{
if( !m.Refine(indicator) ) break;
if( !am.Refine(indicator) ) break;
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) indicator[it->self()] = 0;
}
}
......@@ -42,4 +43,4 @@ int main(int argc, char ** argv)
m.Save(file);
}
else std::cout << "Usage: " << argv[0] << " mesh_file [max_levels=2] [mesh_out=out.vtk]" << std::endl;
}
\ No newline at end of file
}
......@@ -29,9 +29,22 @@ add_executable(shestakov_mesh shestakov_grid.cpp)
add_executable(sinusoidal_mesh sinusoidal_grid.cpp)
add_executable(split_faces split_faces.cpp)
add_executable(glue_faces glue_faces.cpp)
add_executable(check_collapse check_collapse.cpp)
add_executable(check_collapse check_collapse.cpp)
add_executable(test_fracture test_fracture.cpp)
add_library(FractureLib fracture.cpp fracture.h)
target_link_libraries(test_fracture inmost)
target_link_libraries(test_fracture FractureLib)
if(USE_MPI)
message("linking test_fracture with MPI")
target_link_libraries(test_fracture ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(test_fracture PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
install(TARGETS test_fracture EXPORT inmost-targets RUNTIME DESTINATION bin/GridTools)
target_link_libraries(FixTinyCollapse inmost)
if(USE_MPI)
......
......@@ -72,11 +72,13 @@ void Fracture::FaceCenter(Face f, INMOST_DATA_REAL_TYPE cnt[3]) const
else f->Centroid(cnt);
}
void Fracture::Open(Tag aperture)
void Fracture::Open(Tag aperture, bool fill_fracture)
{
fracture_aperture = aperture;
m->BeginModification();
fracture_marker = m->CreateMarker();
for(Mesh::iteratorFace f = m->BeginFace(); f != m->EndFace(); ++f)
if( f->HaveData(aperture) ) f->SetMarker(fracture_marker);
m->self()->Integer(m->CreateTag("FRACTURE_MARKER",DATA_INTEGER,MESH,NONE,1)) = fracture_marker;
//break up all the faces with fractures into volumes?
fracture_volume = m->CreateTag("VOLUME_FRACTURE",DATA_REAL,CELL,CELL,1);
......@@ -213,7 +215,7 @@ void Fracture::Open(Tag aperture)
Tag centroid_tag;
if( m->HaveTag("GEOM_UTIL_CENTROID") )
centroid_tag = m->GetTag("GEOM_UTIL_CENTROID");
if( !centroid_tag.isDefined(FACE) )
if( centroid_tag.isValid() && !centroid_tag.isDefined(FACE) )
centroid_tag = Tag();
////////
std::vector<Tag> transfer_face_real_tags;
......@@ -620,7 +622,7 @@ void Fracture::Open(Tag aperture)