Commit c0016f0f authored by Kirill Terekhov's avatar Kirill Terekhov
Browse files

Adding GridTools examples

Various helpful tools for grids.
parent 85fedb59
......@@ -3,6 +3,7 @@ add_subdirectory(AdaptiveMesh)
add_subdirectory(DrawGrid)
add_subdirectory(OldDrawGrid)
add_subdirectory(GridGen)
add_subdirectory(GridTools)
endif(USE_MESH)
if(USE_SOLVER)
add_subdirectory(DrawMatrix)
......
project(GridGen)
add_executable(FixFaults fix_faults.cpp)
add_executable(FixTiny fix_tiny.cpp)
add_executable(UniteFaces unite_faces.cpp)
add_executable(Dual dual.cpp)
add_executable(Slice slice.cpp)
add_executable(SliceFunc slice_func.cpp)
target_link_libraries(FixFaults inmost)
if(USE_MPI)
message("linking FixFaults with MPI")
target_link_libraries(FixFaults ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(FixFaults PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
install(TARGETS FixFaults EXPORT inmost-targets RUNTIME DESTINATION bin)
target_link_libraries(FixTiny inmost)
if(USE_MPI)
message("linking FixTiny with MPI")
target_link_libraries(FixTiny ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(FixTiny PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
install(TARGETS FixTiny EXPORT inmost-targets RUNTIME DESTINATION bin)
target_link_libraries(UniteFaces inmost)
if(USE_MPI)
message("linking UniteFaces with MPI")
target_link_libraries(UniteFaces ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(UniteFaces PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
install(TARGETS UniteFaces EXPORT inmost-targets RUNTIME DESTINATION bin)
target_link_libraries(Dual inmost)
if(USE_MPI)
message("linking Dual with MPI")
target_link_libraries(Dual ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(Dual PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
install(TARGETS Dual EXPORT inmost-targets RUNTIME DESTINATION bin)
target_link_libraries(Slice inmost)
if(USE_MPI)
message("linking Slice with MPI")
target_link_libraries(Slice ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(Slice PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
install(TARGETS Slice EXPORT inmost-targets RUNTIME DESTINATION bin)
target_link_libraries(SliceFunc inmost)
if(USE_MPI)
message("linking SliceFunc with MPI")
target_link_libraries(SliceFunc ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(SliceFunc PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
install(TARGETS SliceFunc EXPORT inmost-targets RUNTIME DESTINATION bin)
#include <stdio.h>
#include "inmost.h"
using namespace INMOST;
typedef Storage::real real;
typedef Storage::real_array real_array;
int main(int argc, char ** argv)
{
if( argc < 2 )
{
printf("Usage: %s input_mesh [output_mesh]\n",argv[0]);
return -1;
}
Mesh A("orig"),B("voro");
A.Load(argv[1]);
Mesh::GeomParam table;
table[ORIENTATION] = FACE;
table[CENTROID] = FACE | CELL;
A.PrepareGeometricData(table);
//create nodes of the voronoi mesh
Tag cell2node = A.CreateTag("CELL2NODE",DATA_REMOTE_REFERENCE,CELL|FACE|EDGE|NODE,FACE|EDGE|NODE,1);
for(Mesh::iteratorCell it = A.BeginCell(); it != A.EndCell(); ++it)
{
real cnt[3];
it->Centroid(cnt);
it->RemoteReference(cell2node) = RemoteHandleType(&B,B.CreateNode(cnt).GetHandle());
}
for(Mesh::iteratorFace it = A.BeginFace(); it != A.EndFace(); ++it) if( it->Boundary() )
{
real cnt[3];
it->Centroid(cnt);
it->RemoteReference(cell2node) = RemoteHandleType(&B,B.CreateNode(cnt).GetHandle());
}
//add corner nodes
int corners = 0;
MarkerType corner = A.CreateMarker();
for(Mesh::iteratorEdge it = A.BeginEdge(); it != A.EndEdge(); ++it) if( it->Boundary() )
{
real nrm[2][3], dot, cnt[3];
int nbndfaces = 0;
ElementArray<Face> faces = it->getFaces();
for(ElementArray<Face>::iterator kt = faces.begin(); kt != faces.end(); ++kt) if( kt->Boundary() )
kt->UnitNormal(nrm[nbndfaces++]);
assert(nbndfaces==2);
dot = 0;
for(int k = 0; k < 3; ++k) dot += nrm[0][k]*nrm[1][k];
if( dot < 0.95 )
{
corners++;
it->SetMarker(corner);
it->Centroid(cnt);
it->RemoteReference(cell2node) = RemoteHandleType(&B,B.CreateNode(cnt).GetHandle());
}
}
for(Mesh::iteratorNode it = A.BeginNode(); it != A.EndNode(); ++it) if( it->Boundary() )
{
real cnt[3];
int ncorners = it->nbAdjElements(EDGE,corner);
if( ncorners > 2 )
{
corners++;
it->SetMarker(corner);
it->Centroid(cnt);
it->RemoteReference(cell2node) = RemoteHandleType(&B,B.CreateNode(cnt).GetHandle());
}
else if( ncorners == 2 )
{
ElementArray<Edge> edges = it->getEdges(corner);
Node n1 = edges[0]->getBeg() == it->self() ? edges[0]->getEnd() : edges[0]->getBeg();
Node n2 = edges[1]->getBeg() == it->self() ? edges[1]->getEnd() : edges[1]->getBeg();
real cnt1[3], cnt2[3], r1[3],r2[3], l, dot;
it->Centroid(cnt);
n1->Centroid(cnt1);
n2->Centroid(cnt2);
r1[0] = cnt[0] - cnt1[0];
r1[1] = cnt[1] - cnt1[1];
r1[2] = cnt[2] - cnt1[2];
l = sqrt(r1[0]*r1[0]+r1[1]*r1[1]+r1[2]*r1[2]);
r1[0] /= l;
r1[1] /= l;
r1[2] /= l;
r2[0] = cnt2[0] - cnt1[0];
r2[1] = cnt2[1] - cnt1[1];
r2[2] = cnt2[2] - cnt1[2];
l = sqrt(r2[0]*r2[0]+r2[1]*r2[1]+r2[2]*r2[2]);
r2[0] /= l;
r2[1] /= l;
r2[2] /= l;
dot = 0;
for(int k = 0; k < 3; ++k) dot += r1[k]*r2[k];
if( dot < 0.95 )
{
corners++;
it->SetMarker(corner);
it->Centroid(cnt);
it->RemoteReference(cell2node) = RemoteHandleType(&B,B.CreateNode(cnt).GetHandle());
}
}
}
std::cout << "corner nodes: " << corners << std::endl;
//create edges of the voronoi mesh
Tag face2edge = A.CreateTag("FACE2EDGE",DATA_REMOTE_REFERENCE,FACE|EDGE,EDGE,1);
Tag face2edge_corner = A.CreateTag("FACE2EDGE_CORNER",DATA_REMOTE_REFERENCE,EDGE,EDGE,2);
Tag face2edge_corner_node = A.CreateTag("FACE2EDGE_CORNER_NODE",DATA_REMOTE_REFERENCE,NODE,NODE);
ElementArray<Node> edgenodes(&B,2);
for(Mesh::iteratorFace it = A.BeginFace(); it != A.EndFace(); ++it)
{
Cell c1 = it->BackCell();
Cell c2 = it->FrontCell();
if( c2.isValid() )
{
edgenodes[0] = MakeElement(c1.RemoteReference(cell2node)).getAsNode();
edgenodes[1] = MakeElement(c2.RemoteReference(cell2node)).getAsNode();
}
else
{
edgenodes[0] = MakeElement(c1.RemoteReference(cell2node)).getAsNode();
edgenodes[1] = MakeElement(it->RemoteReference(cell2node)).getAsNode();
}
it->RemoteReference(face2edge) = RemoteHandleType(&B,B.CreateEdge(edgenodes).first.GetHandle());
}
int process_corners = 0;
for(Mesh::iteratorEdge it = A.BeginEdge(); it != A.EndEdge(); ++it) if( it->Boundary() )
{
ElementArray<Face> faces = it->getFaces();
ElementArray<Face> bndfaces(&A);
for(ElementArray<Face>::iterator kt = faces.begin(); kt != faces.end(); ++kt) if( kt->Boundary() )
bndfaces.push_back(kt->self());
assert(bndfaces.size() == 2);
if( it->GetMarker(corner) )
{
process_corners++;
edgenodes[0] = MakeElement(bndfaces[0].RemoteReference(cell2node)).getAsNode();
edgenodes[1] = MakeElement(it->RemoteReference(cell2node)).getAsNode();
it->RemoteReferenceArray(face2edge_corner).at(0) = RemoteHandleType(&B,B.CreateEdge(edgenodes).first.GetHandle());
edgenodes[0] = MakeElement(bndfaces[1].RemoteReference(cell2node)).getAsNode();
edgenodes[1] = MakeElement(it->RemoteReference(cell2node)).getAsNode();
it->RemoteReferenceArray(face2edge_corner).at(1) = RemoteHandleType(&B,B.CreateEdge(edgenodes).first.GetHandle());
}
else
{
edgenodes[0] = MakeElement(bndfaces[0].RemoteReference(cell2node)).getAsNode();
edgenodes[1] = MakeElement(bndfaces[1].RemoteReference(cell2node)).getAsNode();
it->RemoteReference(face2edge) = RemoteHandleType(&B,B.CreateEdge(edgenodes).first.GetHandle());
}
}
//add edges connecting corners
for(Mesh::iteratorNode it = A.BeginNode(); it != A.EndNode(); ++it) if( it->Boundary() )
{
ElementArray<Edge> edges = it->getEdges(corner);
if( it->GetMarker(corner) ) //connect each corner node
{
edgenodes[0] = MakeElement(it->RemoteReference(cell2node)).getAsNode();
for(ElementArray<Edge>::iterator kt = edges.begin(); kt != edges.end(); ++kt)
{
process_corners++;
edgenodes[1] = MakeElement(kt->RemoteReference(cell2node)).getAsNode();
it->RemoteReferenceArray(face2edge_corner_node).push_back(&B,B.CreateEdge(edgenodes).first.GetHandle());
}
}
else if( edges.size() == 2 ) //connect two corner nodes
{
process_corners++;
edgenodes[0] = MakeElement(edges[0]->RemoteReference(cell2node)).getAsNode();
edgenodes[1] = MakeElement(edges[1]->RemoteReference(cell2node)).getAsNode();
it->RemoteReferenceArray(face2edge_corner_node).push_back(&B,B.CreateEdge(edgenodes).first.GetHandle());
}
}
std::cout << "corners processed: " << process_corners << std::endl;
//create faces of the voronoi mesh
Tag edge2face = A.CreateTag("EDGE2FACE",DATA_REMOTE_REFERENCE,EDGE|NODE,NODE,1);
ElementArray<Edge> faceedges(&B);
process_corners = 0;
for(Mesh::iteratorEdge it = A.BeginEdge(); it != A.EndEdge(); ++it)
{
ElementArray<Face> faces = it->getFaces();
ElementArray<Node> nodes = it->getNodes();
for(ElementArray<Face>::iterator kt = faces.begin(); kt != faces.end(); ++kt)
faceedges.push_back(MakeElement(kt->RemoteReference(face2edge)));
if( it->GetMarker(corner) )
{
process_corners++;
faceedges.push_back(it->RemoteReferenceArray(face2edge_corner)[0]);
faceedges.push_back(it->RemoteReferenceArray(face2edge_corner)[1]);
}
else if( it->Boundary() )
faceedges.push_back(MakeElement(it->RemoteReference(face2edge)));
Face f = B.CreateFace(faceedges).first;
f.FixEdgeOrder();
it->RemoteReference(edge2face) = RemoteHandleType(&B,B.CreateFace(faceedges).first.GetHandle());
faceedges.clear();
}
//construct boundary faces without corner nodes
for(Mesh::iteratorNode it = A.BeginNode(); it != A.EndNode(); ++it) if( it->Boundary() )
{
ElementArray<Edge> edges = it->getEdges();
for(ElementArray<Edge>::iterator kt = edges.begin(); kt != edges.end(); ++kt) if( kt->Boundary() )
{
if( kt->GetMarker(corner) )
{
process_corners++;
faceedges.push_back(kt->RemoteReferenceArray(face2edge_corner)[0]);
faceedges.push_back(kt->RemoteReferenceArray(face2edge_corner)[1]);
}
else
faceedges.push_back(MakeElement(kt->RemoteReference(face2edge)));
}
Face f = B.CreateFace(faceedges).first;
f.FixEdgeOrder();
it->RemoteReference(edge2face) = RemoteHandleType(&B,B.CreateFace(faceedges).first.GetHandle());
faceedges.clear();
}
std::cout << "corners processed: " << process_corners << std::endl;
//construct cells
ElementArray<Face> cellfaces(&B);
for(Mesh::iteratorNode it = A.BeginNode(); it != A.EndNode(); ++it)
{
ElementArray<Edge> edges = it->getEdges();
for(ElementArray<Edge>::iterator kt = edges.begin(); kt != edges.end(); ++kt)
cellfaces.push_back(MakeElement(kt->RemoteReference(edge2face)));
if( it->Boundary() )
cellfaces.push_back(MakeElement(it->RemoteReference(edge2face)));
B.CreateCell(cellfaces);
cellfaces.clear();
}
//split corner faces by edges connected to corner nodes
process_corners= 0;
for(Mesh::iteratorNode it = A.BeginNode(); it != A.EndNode(); ++it) if( it->HaveData(face2edge_corner_node) )
{
process_corners++;
Storage::remote_reference_array arr = it->RemoteReferenceArray(face2edge_corner_node);
ElementArray<Edge> edges(&B);
for(Storage::remote_reference_array::iterator kt = arr.begin(); kt != arr.end(); ++kt)
edges.push_back(kt->GetHandle());
Face f = MakeElement(it->RemoteReference(edge2face)).getAsFace();
Face::SplitFace(f,edges,0);
}
std::cout << "corners splitted: " << process_corners << std::endl;
if( A.HaveTag("GRIDNAME") )
{
Storage::bulk_array nameA = A.self().BulkArray(A.GetTag("GRIDNAME"));
Storage::bulk_array nameB = B.self().BulkArray(B.CreateTag("GRIDNAME",DATA_BULK,MESH,NONE));
std::string ins = "_dual";
nameB.insert(nameB.end(),nameA.begin(),nameA.end());
nameB.insert(nameB.end(),ins.c_str(),ins.c_str()+ins.size());
}
if( argc > 2 )
{
std::cout << "Save to " << argv[2] << std::endl;
B.Save(argv[2]);
}
else
{
std::cout << "Save to out.vtk" << std::endl;
B.Save("out.vtk");
}
return 0;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
fix_faults - Intersects faces of the mesh along unresolved faults. Introduce a mesh with a set of blocks,
shifted against each other and this tool will introduce edges and matching faces along
faces of shifted blocks. Only for convex mesh elements.
mesh_input - general polyhedral grid with unresolved faults.
mesh_output - output general polyhedral grid with resolved faults, default grid.vtk
fix_tiny - Collapses small cells, faces and edges in the mesh.
Cells may collapse into face, edge or node, face into edge or node and edge into node.
Only for convex mesh elements.
Warning: cells are not implemented
mesh_input - general polyhedral grid
mesh_output - output general polyhedral grid with no tiny elements, default grid.vtk
unite_faces - Unite faces of the cell that share the same adjacent cell, some edges and are approximately
coplanar.
mesh_input - general polyhedral grid
mesh_output - output general polyhedral grid with united faces, default grid.vtk
#include "inmost.h"
using namespace INMOST;
int main(int argc, char ** argv)
{
double nx = 2.0/7.0, ny = 6.0/7.0, nz = 3.0/7.0;
double px = 0.5, py = 0.5, pz = 0.5;
if( argc < 2 )
{
std::cout << "Usage: " << argv[0] << " mesh [mesh_out=grid.pmf] [nx=0] [ny=0] [nz=1] [px=0.5] [py=0.5] [pz=0.5]" << std::endl;
return -1;
}
std::string grid_out = "grid.pmf";
if( argc > 2 ) grid_out = std::string(argv[2]);
if( argc > 3 ) nx = atof(argv[3]);
if( argc > 4 ) ny = atof(argv[4]);
if( argc > 5 ) nz = atof(argv[5]);
if( argc > 6 ) px = atof(argv[6]);
if( argc > 7 ) py = atof(argv[7]);
if( argc > 8 ) pz = atof(argv[8]);
double d = nx*px+ny*py+nz*pz;
Mesh m;
m.Load(argv[1]);
m.SetTopologyCheck(NEED_TEST_CLOSURE|PROHIBIT_MULTILINE|PROHIBIT_MULTIPOLYGON|GRID_CONFORMITY|DEGENERATE_EDGE|DEGENERATE_FACE|DEGENERATE_CELL | FACE_EDGES_ORDER);
//m.RemTopologyCheck(THROW_EXCEPTION);
Tag sliced = m.CreateTag("SLICED",DATA_BULK,FACE|EDGE|NODE,FACE|EDGE|NODE,1);
std::cout << "Cells: " << m.NumberOfCells() << std::endl;
std::cout << "Faces: " << m.NumberOfFaces() << std::endl;
MarkerType slice = m.CreateMarker();
int nslice = 0, nmark = 0;
for(Mesh::iteratorEdge it = m.BeginEdge(); it != m.EndEdge(); ++it)
{
double p[3];
Storage::real_array c0 = it->getBeg()->Coords();
Storage::real_array c1 = it->getEnd()->Coords();
double r0 = c0[0]*nx+c0[1]*ny+c0[2]*nz - d;
double r1 = c1[0]*nx+c1[1]*ny+c1[2]*nz - d;
//std::cout << "r0 " << r0 << " r1 " << r1 << std::endl;
if( r0*r1 < -1.0e-12 )
{
p[0] = (r0*c1[0] - r1*c0[0])/(r0-r1);
p[1] = (r0*c1[1] - r1*c0[1])/(r0-r1);
p[2] = (r0*c1[2] - r1*c0[2])/(r0-r1);
//std::cout << "p " << p[0] << " " << p[1] << " " << p[2] << std::endl;
Node n = m.CreateNode(p);
n.Bulk(sliced) = 1;
n.SetMarker(slice);
bool was_sliced = it->HaveData(sliced) ? true : false;
ElementArray<Edge> ret = Edge::SplitEdge(it->self(),ElementArray<Node>(&m,1,n.GetHandle()),0);
if( was_sliced ) for(int q = 0; q < ret.size(); ++q) ret[q]->Bulk(sliced) = 1;
nslice++;
}
else
{
if( fabs(r0) < 1.0e-6 )
{
it->getBeg()->SetMarker(slice);
nmark++;
}
if( fabs(r1) < 1.0e-6 )
{
it->getEnd()->SetMarker(slice);
nmark++;
}
}
}
std::cout << "sliced edges: " << nslice << " marked nodes: " << nmark << std::endl;
if( !Element::CheckConnectivity(&m) )
std::cout << "Connectivity is broken" << std::endl;
nslice = 0;
for(Mesh::iteratorFace it = m.BeginFace(); it != m.EndFace(); ++it)
{
ElementArray<Node> nodes = it->getNodes(slice); //those nodes should be ordered so that each pair forms an edge
if( nodes.size() > 1 ) // if there is 1, then only one vertex touches the plane
{
//if there is more then two, then original face is non-convex
if( nodes.size() > 2 ) std::cout << "Looks like face " << it->LocalID() << " is nonconvex" << std::endl;
else
{
Edge e = m.CreateEdge(nodes).first;
e.Bulk(sliced) = 1;
e.SetMarker(slice);
bool was_sliced = it->HaveData(sliced) ? true : false;
ElementArray<Face> ret = Face::SplitFace(it->self(),ElementArray<Edge>(&m,1,e.GetHandle()),0);
if( was_sliced ) for(int q = 0; q < ret.size(); ++q) ret[q]->Bulk(sliced) = 1;
nslice++;
}
}
//else std::cout << "Only one adjacent slice node, face " << it->LocalID() << std::endl;
}
nmark = 0;
for(Mesh::iteratorEdge it = m.BeginEdge(); it != m.EndEdge(); ++it)
if( !it->GetMarker(slice) && it->getBeg()->GetMarker(slice) && it->getEnd()->GetMarker(slice) )
{
it->SetMarker(slice);
nmark++;
}
std::cout << "sliced faces: " << nslice << " marked edges: " << nmark << std::endl;
if( !Element::CheckConnectivity(&m) )
std::cout << "Connectivity is broken" << std::endl;
nslice = 0;
MarkerType visited = m.CreateMarker();
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
{
ElementArray<Edge> edges = it->getEdges(slice);
if( edges.size() >= 3 ) //these should form a triangle
{
//order edges
ElementArray<Edge> order_edges(&m);
order_edges.push_back(edges[0]);
order_edges.SetMarker(visited);
while(order_edges.size() != edges.size() )
{
for(int k = 0; k < edges.size(); ++k) if( !edges[k]->GetMarker(visited) )
{
if( edges[k]->getBeg() == order_edges.back()->getBeg() || edges[k]->getBeg() == order_edges.back()->getEnd() ||
edges[k]->getEnd() == order_edges.back()->getBeg() || edges[k]->getEnd() == order_edges.back()->getEnd() )
{
order_edges.push_back(edges[k]);
order_edges.back().SetMarker(visited);
}
}
}
edges.RemMarker(visited);
Face f = m.CreateFace(order_edges).first;
f.Bulk(sliced) = 1;
Cell::SplitCell(it->self(),ElementArray<Face>(&m,1,f.GetHandle()),0);
nslice++;
}
}
m.ReleaseMarker(visited);
std::cout << "sliced cells: " << nslice << std::endl;
if( !Element::CheckConnectivity(&m) )
std::cout << "Connectivity is broken" << std::endl;
Tag material = m.CreateTag("MATERIAL",DATA_INTEGER,CELL,NONE,1);
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
{
double cnt[3];
it->Centroid(cnt);
double v = cnt[0]*nx+cnt[1]*ny+cnt[2]*nz-d;
if( v < 0.0 )
it->Integer(material) = 0;
else
it->Integer(material) = 1;
}
m.ReleaseMarker(slice,NODE|EDGE);
m.Save(grid_out);
return 0;
}
\ No newline at end of file
#include "inmost.h"
using namespace INMOST;
double func(double x, double y, double z, int n)
{
if( n == 0 )
return sqrt(x*x+y*y)-0.25;
else if( n == 1 )
return -(sqrt((x-0.5)*(x-0.5)+(y-0.5)*(y-0.5)+(z-0.5)*(z-0.5))-0.5);
return 1;
}
void search(double r0, double r1, double c0[3], double c1[3], double p[3],int type)
{
double rp;
do
{
p[0] = (r0*c1[0] - r1*c0[0])/(r0-r1);
p[1] = (r0*c1[1] - r1*c0[1])/(r0-r1);
p[2] = (r0*c1[2] - r1*c0[2])/(r0-r1);
rp = func(p[0],p[1],p[2],type);
if( rp*r0 < 0.0 )