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

move Examples/Octree* to INMOST-Graphics repository

parent 3d77088a
......@@ -21,10 +21,6 @@ if (USE_AUTODIFF AND USE_SOLVER AND USE_MESH)
add_subdirectory(ADVDIFF)
add_subdirectory(MFD-ES)
endif (USE_AUTODIFF AND USE_SOLVER AND USE_MESH)
#add_subdirectory(OctreeCutcell)
if (USE_MESH AND USE_PARTITIONER)
#add_subdirectory(Octree)
endif (USE_MESH AND USE_PARTITIONER)
if (USE_ANI_INMOST_EXAMPLES)
if (DEFINED ENV{ANI_DIR})
message("ANI_DIR is defined")
......
project(Octree)
set(SOURCE main.cpp
rotate.cpp
rotate.h
octgrid.cpp
octgrid.h
my_glut.h)
set(SOURCE_LIGHT main_light.cpp
octgrid.cpp
octgrid.h)
set(SOURCE_TEST main_test.cpp
octgrid.cpp
octgrid.h)
add_executable(Octree ${SOURCE})
add_executable(Octree_light ${SOURCE_LIGHT})
add_executable(Octree_test ${SOURCE_TEST})
set(TARGETS Octree Octree_light Octree_test)
foreach(vtarget ${TARGETS})
target_link_libraries(${vtarget} inmost)
#target_link_libraries(${vtarget} lapack blas)
if(USE_MPI)
message("linking ${vtarget} with mpi")
target_link_libraries(${vtarget} ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
message("adding link flags to ${vtarget}")
set_target_properties(${vtarget} PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
find_package(OpenGL)
find_package(GLUT)
if(OPENGL_FOUND)
if(GLUT_FOUND)
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${GLUT_INCLUDE_DIR})
add_definitions(-D__GRAPHICS__)
target_link_libraries(${vtarget} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES})
else(GLUT_FOUND)
message("GLUT not found for ${vtarget}")
endif(GLUT_FOUND)
else(OPENGL_FOUND)
message("OpenGL not found for ${vtarget}")
endif(OPENGL_FOUND)
if(USE_PARTITIONER_ZOLTAN)
message("linking ${vtarget} with Zoltan")
target_link_libraries(${vtarget} ${ZOLTAN_LIBRARIES})
endif()
if(USE_PARTITIONER_PARMETIS)
message("linking ${vtarget} with ParMETIS")
target_link_libraries(${vtarget} ${PARMETIS_LIBRARIES})
endif()
endforeach(vtarget ${TARGETS})
if(NOT GLUT_FOUND)
set_target_properties(Octree PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
endif(NOT GLUT_FOUND)
This diff is collapsed.
#include "octgrid.h"
#include "my_glut.h"
#include "rotate.h"
#include <math.h>
#include "inmost.h"
#include <iomanip>
#include <iostream>
#define LOG(level,msg) { if (log_level >= level) cout << msg << endl; }
#define BARRIER MPI_Barrier(MPI_COMM_WORLD);
using namespace std;
struct grid thegrid;
// Variables for refine and coarse
int refine_depth = 1;
double mx = 0.75, my = 0.5;
double base_radius = 0.02;
int log_level = 3;
// Variables for MPI
int rank;
int size;
int counter = 0; // Count number of steps
/// Dump mesh to vtk file in folder "grids"
void dump_to_vtk()
{
//thegrid.mesh->ResolveShared(); // Resolve duplicate nodes
//thegrid.mesh->ExchangeGhost(2,NODE); // Construct Ghost cells in 2 layers connected via nodes
std::stringstream filename;
filename << "grids/grid_";
filename << size;
if( size == 1 )
filename << ".vtk";
else
filename << ".pvtk";
thegrid.mesh->Save(filename.str());
cout << "Process " << ::rank << ": dumped mesh to file" << endl;
}
/// Function provided to octgrid algorithm. Defines transformation from grid to grid for draw.
void transformation(double xyz[3])
{
double tmp[3];
tmp[0] = xyz[0];
tmp[1] = xyz[1];
tmp[2] = xyz[2];
tmp[0] -= 0.5;
tmp[0] *= 100.0;
tmp[1] -= 0.5;
tmp[1] *= 100.0;
xyz[0] = tmp[0];
xyz[1] = tmp[1];
//xyz[2] = 4010.0 + 10.0 * (tmp[2]-0.5);
xyz[2] = 4010.0 + 10.0 * (tmp[2]-0.5);
}
/// Function provided to octgrid algorithm. Defines transformation from grid for draw to grid.
void rev_transformation(double xyz[3])
{
double tmp[3];
tmp[0] = xyz[0];
tmp[1] = xyz[1];
tmp[2] = xyz[2];
tmp[0] /= 100.0;
tmp[0] += 0.5;
tmp[1] /= 100.0;
tmp[1] += 0.5;
xyz[0] = tmp[0];
xyz[1] = tmp[1];
xyz[2] = 4010.0 + 10.0 * (tmp[2]-0.5);
xyz[2] = (tmp[2] - 4010.0) / 10.0 + 0.5;
}
/// Function provided to octgrid algorithm.
/// Defines that cell should be unite. Returns 1 for unite else returns 0.
int cell_should_unite(struct grid * g, Cell cell)
{
const double r = base_radius;
int test = 1;
double x = cell.RealArrayDF(g->c_tags.center)[0];
double y = cell.RealArrayDF(g->c_tags.center)[1];
test &= (x-mx)*(x-mx)+(y-my)*(y-my) > r;
return test;
}
/// Function provided to octgrid algorithm.
/// Defines that cell should be split. Returns 1 for split else returns 0.
int cell_should_split(struct grid * g, Cell cell)
{
double r = base_radius;
double x = cell.RealArrayDF(g->c_tags.center)[0];
double y = cell.RealArrayDF(g->c_tags.center)[1];
int c_level = cell.Integer(g->c_tags.level);
if ((x-mx)*(x-mx)+(y-my)*(y-my) < r)
{
if (c_level < refine_depth) return 1;
}
for (int level = 2; level <= refine_depth; level++)
{
if ((x-mx)*(x-mx)+(y-my)*(y-my) < r*5*(level-1))
if (c_level < refine_depth - level + 1) return 1;
}
return 0;
}
void prepare_to_correct_brothers()
{
correct_brothers(&thegrid,size,::rank, 0);
thegrid.mesh->RemoveGhost();
thegrid.mesh->Redistribute();
thegrid.mesh->ReorderEmpty(CELL|FACE|EDGE|NODE);
//thegrid.mesh->AssignGlobalID(CELL | EDGE | FACE | NODE);
}
/// Redistribute grid by partitioner
void redistribute(int type)
{
//std::stringstream str1;
//str1 << "startredist" << ::rank << ".xml";
//thegrid.mesh->Save(str1.str());
//thegrid.mesh->Save("startredist.pmf");
thegrid.mesh->ResolveShared();
//thegrid.mesh->Save("resolveshared.pmf");
//std::stringstream str2;
//str2 << "resolveshared" << ::rank << ".xml";
//thegrid.mesh->Save(str2.str());
LOG(2,"Process " << ::rank << ": redistribute. Cells: " << thegrid.mesh->NumberOfCells())
if( type == 3 )
{
TagInteger r = thegrid.mesh->RedistributeTag();
TagInteger o = thegrid.mesh->OwnerTag();
for(Mesh::iteratorCell it = thegrid.mesh->BeginCell(); it != thegrid.mesh->EndCell(); ++it)
r[it->self()] = (o[it->self()]+1)%size;
}
else
{
Partitioner * part = new Partitioner(thegrid.mesh);
// Specify the partitioner
if (type == 0) part->SetMethod(Partitioner::Parmetis, Partitioner::Partition);
if (type == 1) part->SetMethod(Partitioner::Parmetis, Partitioner::Repartition);
if (type == 2) part->SetMethod(Partitioner::Parmetis, Partitioner::Refine);
try
{
part->Evaluate();
}
catch (INMOST::ErrorType er)
{
cout << "Exception: " << er << endl;
}
delete part;
}
//thegrid.mesh->Save("parmetis.pmf");
correct_brothers(&thegrid,size,::rank, 2);
//thegrid.mesh->Save("brothers.pmf");
try
{
thegrid.mesh->Redistribute();
}
catch (INMOST::ErrorType er)
{
cout << "Exception: " << er << endl;
}
//thegrid.mesh->Save("redistribute.pmf");
thegrid.mesh->RemoveGhost();
//thegrid.mesh->Save("removeghost.pmf");
thegrid.mesh->ReorderEmpty(CELL|FACE|EDGE|NODE);
//thegrid.mesh->Save("reorderempty.pmf");
thegrid.mesh->AssignGlobalID(CELL | EDGE | FACE | NODE);
//thegrid.mesh->Save("assigngid.pmf");
LOG(2,"Process " << ::rank << ": redistribute completed")
}
int main(int argc, char ** argv)
{
int i;
int n[3] = {20,40,1};
thegrid.transformation = transformation;
thegrid.rev_transformation = rev_transformation;
thegrid.cell_should_split = cell_should_split;
thegrid.cell_should_unite = cell_should_unite;
Mesh::Initialize(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &::rank);
gridInit(&thegrid,n);
Partitioner::Initialize(&argc,&argv);
::size = thegrid.mesh->GetProcessorsNumber();
::rank = thegrid.mesh->GetProcessorRank();
std::cout << "rank " << ::rank << " size " << ::size << std::endl;
//dump_to_vtk();
std::cout << "gridAMR" << std::endl;
gridAMR(&thegrid, 0);
std::cout << "redistribute" << std::endl;
redistribute(1);
std::cout << "after redistribute " << thegrid.mesh->NumberOfCells() << std::endl;
thegrid.mesh->Save("end.pvtk");
Partitioner::Finalize();
Mesh::Finalize();
return 0;
}
//make all && mpirun -np 1 ./Octree_test -log=3 -l=2 -n=50x50x2
#include "octgrid.h"
#include <math.h>
#include "inmost.h"
#include <iomanip>
#include <iostream>
#include <sstream>
#define LOG(level,msg) { if (log_level >= level) cout << msg << endl; }
#define BARRIER MPI_Barrier(MPI_COMM_WORLD);
using namespace std;
const int MAX_PROCESSORS_COUNT = 10;
struct grid thegrid;
int refine_depth = 2;
double mx = 0, my = 0;
double rmx = 0, rmy = 0;
double base_radius = 0.01;
int action = 0;
int log_level = 0;
int all_cells_count;
int rank;
int size;
int counter = 0; // Count number of steps
/// Function provided to octgrid algorithm. Defines transformation from grid to grid for draw.
void transformation(double xyz[3])
{
double tmp[3];
tmp[0] = xyz[0];
tmp[1] = xyz[1];
tmp[2] = xyz[2];
tmp[0] -= 0.5;
tmp[0] *= 100.0;
tmp[1] -= 0.5;
tmp[1] *= 100.0;
xyz[0] = tmp[0];
xyz[1] = tmp[1];
//xyz[2] = 4010.0 + 10.0 * (tmp[2]-0.5);
xyz[2] = 4010.0 + 10.0 * (tmp[2]-0.5);
}
/// Function provided to octgrid algorithm. Defines transformation from grid for draw to grid.
void rev_transformation(double xyz[3])
{
double tmp[3];
tmp[0] = xyz[0];
tmp[1] = xyz[1];
tmp[2] = xyz[2];
tmp[0] /= 100.0;
tmp[0] += 0.5;
tmp[1] /= 100.0;
tmp[1] += 0.5;
xyz[0] = tmp[0];
xyz[1] = tmp[1];
xyz[2] = 4010.0 + 10.0 * (tmp[2]-0.5);
xyz[2] = (tmp[2] - 4010.0) / 10.0 + 0.5;
}
void pre_redistribute(int type)
{
redistribute(&thegrid, type);
}
/// Function provided to octgrid algorithm.
/// Defines that cell should be unite. Returns 1 for unite else returns 0.
int cell_should_unite(struct grid * g, Cell cell)
{
// return !cell_should_split(g,cell);
const double r = base_radius;
double x = cell.RealArrayDF(g->c_tags.center)[0];
double y = cell.RealArrayDF(g->c_tags.center)[1];
int c_level = cell.Integer(g->c_tags.level);
if (c_level == refine_depth)
{
if ((x-mx)*(x-mx)+(y-my)*(y-my) > r) return 1;
}
else
{
double R = (refine_depth - c_level)*5*r;
if ((x-mx)*(x-mx)+(y-my)*(y-my) > R) return 1;
}
return 0;
}
/// Function provided to octgrid algorithm.
/// Defines that cell should be split. Returns 1 for split else returns 0.
int cell_should_split(struct grid * g, Cell cell)
{
double r = base_radius;
double x = cell.RealArrayDF(g->c_tags.center)[0];
double y = cell.RealArrayDF(g->c_tags.center)[1];
int c_level = cell.Integer(g->c_tags.level);
if ((x-mx)*(x-mx)+(y-my)*(y-my) < r)
{
if (c_level < refine_depth) return 1;
}
for (int level = 2; level <= refine_depth; level++)
{
if ((x-mx)*(x-mx)+(y-my)*(y-my) < r*5*(level-1))
if (c_level < refine_depth - level + 1) return 1;
}
return 0;
}
/// Main loop for not main process
void NotMainProcess()
{
char buff[256];
MPI_Status status;
int length;
int iteration = 0;
while (1)
{
MPI_Recv(buff, 256, MPI_CHAR, 0,0, INMOST_MPI_COMM_WORLD, &status);
LOG(2, "Process " << ::rank << ": received message '" << buff[0] << "'")
if (buff[0] == 'q') // Need to refine, mouse coordinates come
{
break;
}
if (buff[0] == 'm') // Need to refine, mouse coordinates come
{
mx = *((double*)(buff + 1));
my = *((double*)(buff + 1 + sizeof(double)));
int action = *((int*)(buff + 1 + 2*sizeof(double)));
gridAMR(&thegrid, action);
//thegrid.mesh->AssignGlobalID(CELL | EDGE | FACE | NODE);
}
if (buff[0] == 'x') // Need to redistribute
{
char type_C = buff[1];
int type = type_C - '0';
//redistribute(&thegrid,type);
pre_redistribute(type);
cout << ::rank << ": iteration " << iteration++ << " complete. Cells: " << thegrid.mesh->NumberOfCells() << endl;
}
if (buff[0] == 'u') // Need remove ghosts
{
thegrid.mesh->RemoveGhost();
}
if (buff[0] == 'c') // Need command
{
command(&thegrid);
}
if (buff[0] == 'f') // Dump mesh to file
{
dump_to_vtk(&thegrid);
}
}
}
void send_dump_command()
{
char buff[10][2];
MPI_Request req[10];
for (int i = 1; i < size; i++)
{
buff[i][0] = 'f'; // Special key, means dump file
MPI_Isend(buff[i], 1, MPI_CHAR, i, 0, INMOST_MPI_COMM_WORLD, req + i);
}
}
void send_quit_command()
{
char buff[10][2];
MPI_Request req[10];
for (int i = 1; i < size; i++)
{
buff[i][0] = 'q'; // Special key, means dump file
MPI_Isend(buff[i], 1, MPI_CHAR, i, 0, INMOST_MPI_COMM_WORLD, req + i);
}
}
/// Send mpuse coordinates to slaves. Slaves receive the message 'm', execute "refine" with received coordinates.
void send_coordinates_to_slaves(int action)
{
char buff[MAX_PROCESSORS_COUNT][10];
MPI_Request req[MAX_PROCESSORS_COUNT];
for (int i = 1; i < size; i++)
{
LOG(2,"Main process: send coordinates to " << i)
buff[i][0] = 'm'; // Special key, means refine
*((double*)(buff[i] + 1)) = mx;
*((double*)(buff[i] + 1 + sizeof(double))) = my;
*((int*)(buff[i] + 1 + 2*sizeof(double))) = action;
MPI_Isend(buff[i], 1 + 2 * sizeof(double) + sizeof(int), MPI_CHAR, i, 0, INMOST_MPI_COMM_WORLD, req + i);
}
}
/// Prepare to redistribute. Master sends special command to slaves which means redistribute
void redistribute_command()
{
char buff[MAX_PROCESSORS_COUNT][10];
MPI_Request req[MAX_PROCESSORS_COUNT];
int type = 2;
if (counter == 5)
{
counter = 0;
type = 1;
}
for (int i = 1; i < size; i++)
{
LOG(3,"Master: send redistribute command to slave " << ::rank)
buff[i][0] = 'x'; // Special key, means redistribute
buff[i][1] = type + '0'; // Special key, means redistribute
MPI_Isend(buff[i], 2, MPI_CHAR, i, 0, INMOST_MPI_COMM_WORLD, req + i);
}
// redistribute(&thegrid, type);
pre_redistribute(type);
counter++;
}
void print_help()
{
cout << "Example of Octree refine on redistributed grid" << endl;
cout << "Command arguments:" << endl;
cout << " -n=10x10x1 - grid size" << endl;
cout << " -r=0.01 - refine radius" << endl;
cout << " -l=2 - refine level" << endl;
cout << " -log=1 - log level" << endl;
cout << endl;
cout << "Hotkeys:" << endl;
cout << " Space - refine grid around mouse cursor" << endl;
//cout << " r - redraw grid" << endl;
cout << " f - dump grid to file (see grids folder)" << endl;
cout << " x - redistribute grid" << endl;
}
void parse_arguments(int argc, char** argv, int* n, double* R, int* L, int* log, int* iters_count, double* h)
{
if (argc < 2) return;
string str;
string str1, str2;
for (int i = 1; i < argc; i++)
{
str = argv[i];
size_t pos = str.find('=');
if (pos == string::npos)
{
cout << "Invalid argument: " << str << endl;
continue;
}
str1 = str.substr(0, pos);
str2 = str.substr(pos + 1);
if (str1 == "-n")
{
for (int j = 0; j < 3; j++)
{
pos = str2.find('x');
if (j < 2 && pos == string::npos)
{
cout << "Invalid command: " << str2 << endl;
break;
}
str1 = str2.substr(0, pos);
n[j] = atoi(str1.c_str());
str2 = str2.substr(pos + 1);
}
}
else if (str1 == "-r")
{
*R = atof(str2.c_str());
}
else if (str1 == "-l")
{