Commit af0abfe3 authored by jannick.wolters's avatar jannick.wolters
Browse files

includes changes from #44 ; closes #45

parent 5077c09a
......@@ -5,7 +5,7 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON )
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -march=native -Wno-dev" )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -march=native -pg -no-pie" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -Wall -Werror" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -Wall" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin" )
......@@ -13,6 +13,10 @@ file( GLOB_RECURSE SRCS RELATIVE ${CMAKE_SOURCE_DIR} "src/*.cpp" "include/*.h" )
include_directories( ${CMAKE_SOURCE_DIR}/include )
add_executable( ${CMAKE_PROJECT_NAME} ${SRCS} )
find_package( Python3 COMPONENTS Interpreter Development NumPy REQUIRED )
include_directories( ${Python3_INCLUDE_DIRS} ${Python3_NumPy_INCLUDE_DIRS} )
add_compile_definitions( RTSN_PYTHON_PATH="${CMAKE_SOURCE_DIR}/python" )
find_package( OpenMP REQUIRED )
if( OPENMP_FOUND )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" )
......@@ -130,7 +134,7 @@ execute_process(
)
add_compile_definitions( GIT_HASH="${GIT_HASH}" )
set( CORE_LIBRARIES ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} ${MPI_LIBRARIES} ${VTK_LIBRARIES} parmetis -lstdc++fs )
set( CORE_LIBRARIES ${Python3_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} ${MPI_LIBRARIES} ${VTK_LIBRARIES} parmetis -lstdc++fs )
target_link_libraries( ${CMAKE_PROJECT_NAME} ${CORE_LIBRARIES} )
......
......@@ -6,7 +6,6 @@
#include <iostream>
#include <string>
#include "cpptoml.h"
#include <mpi.h>
#include <omp.h>
#include <vtkCellArray.h>
......@@ -21,6 +20,10 @@
#include <vtkUnstructuredGrid.h>
#include <vtkUnstructuredGridWriter.h>
#include <Python.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>
#include "mesh.h"
#include "settings/config.h"
......@@ -44,4 +47,6 @@ std::string ParseArguments( int argc, char* argv[] );
void PrintLogHeader( std::string inputFile );
Matrix createSU2MeshFromImage( std::string imageName, std::string SU2Filename );
#endif // IO_H
......@@ -41,6 +41,7 @@ class Config
std::string _outputFile; /*!< @brief Name of output file*/
std::string _logDir; /*!< @brief Directory of log file*/
std::string _meshFile; /*!< @brief Name of mesh file*/
std::string _ctFile; /*!< @brief Name of CT file*/
// Quadrature
QUAD_NAME _quadName; /*!< @brief Quadrature Name*/
......@@ -190,6 +191,7 @@ class Config
std::string inline GetOutputDir() const { return std::filesystem::path( _outputDir ).lexically_normal(); }
std::string inline GetOutputFile() const { return std::filesystem::path( _outputFile ).lexically_normal(); }
std::string inline GetLogDir() const { return std::filesystem::path( _logDir ).lexically_normal(); }
std::string inline GetCTFile() const { return std::filesystem::path( _ctFile ).lexically_normal(); }
// Quadrature Structure
QUAD_NAME inline GetQuadName() const { return _quadName; }
......
# importing PIL
from PIL import Image
import numpy as np
def extract(image_name):
img = Image.open(image_name).convert('L') #image data
I = np.asarray(img) # image as greyscale
I = I/255; # rescale values to [0,1]
dimensions = (1,1) # [cm]
return I , dimensions
\ No newline at end of file
import numpy as np
import pygmsh as pg
import os
import extract_grayscale_image as egs
def add_rectangle(x0,y0,width,height,char_length,geom):
coords = np.array([
[x0, y0, 0.0],
[x0+width, y0, 0.0],
[x0+width, y0+height, 0.0],
[x0, y0+height, 0.0]
])
return geom.add_polygon(coords, char_length)
def generate(image_name, mesh_name):
if mesh_name.endswith('.su2'):
mesh_name = os.path.splitext(mesh_name)[0]
gsImage, dimensions = egs.extract(image_name)
char_length = 1.0#np.min(1.0, np.min(dimensions)/10.0) #arbitrary
geom = pg.opencascade.Geometry()
domain = add_rectangle(0.0, 0.0, dimensions[0], dimensions[1], char_length, geom)
geom.add_physical(domain.lines, label="void")
mesh_code = geom.get_code()
with open(mesh_name+".geo","w") as mesh_file:
mesh_file.write(mesh_code,)
os.system('gmsh '+mesh_name+'.geo -2 -format su2 -save_all > /dev/null')
os.system('rm '+mesh_name+'.geo > /dev/null')
return gsImage
......@@ -314,3 +314,61 @@ void PrintLogHeader( std::string inputFile ) {
}
MPI_Barrier( MPI_COMM_WORLD );
}
Matrix createSU2MeshFromImage( std::string imageName, std::string SU2Filename ) {
auto log = spdlog::get( "event" );
if( !std::filesystem::exists( imageName ) ) {
ErrorMessages::Error( "Can not open image '" + imageName + "'!", CURRENT_FUNCTION );
exit( EXIT_FAILURE );
}
std::filesystem::path outDir( std::filesystem::path( SU2Filename ).parent_path() );
if( !std::filesystem::exists( outDir ) ) {
ErrorMessages::Error( "Output directory '" + outDir.string() + "' does not exists!", CURRENT_FUNCTION );
exit( EXIT_FAILURE );
}
setenv( "PYTHONPATH", RTSN_PYTHON_PATH, 1 );
Py_Initialize();
PyObject *pArgs, *pReturn, *pModule, *pFunc;
PyArrayObject* np_ret;
auto image = PyUnicode_FromString( imageName.c_str() );
auto su2 = PyUnicode_FromString( SU2Filename.c_str() );
PyObject* pName = PyUnicode_FromString( "mesh_from_image" );
pModule = PyImport_Import( pName );
Py_DECREF( pName );
if( !pModule ) {
ErrorMessages::Error( "'mesh_from_image.py' can not be imported!", CURRENT_FUNCTION );
exit( EXIT_FAILURE );
}
pFunc = PyObject_GetAttrString( pModule, "generate" );
if( !pFunc || !PyCallable_Check( pFunc ) ) {
Py_DECREF( pModule );
Py_XDECREF( pFunc );
ErrorMessages::Error( "'generate' is null or not callable!", CURRENT_FUNCTION );
exit( EXIT_FAILURE );
}
pArgs = PyTuple_New( 2 );
PyTuple_SetItem( pArgs, 0, reinterpret_cast<PyObject*>( image ) );
PyTuple_SetItem( pArgs, 1, reinterpret_cast<PyObject*>( su2 ) );
pReturn = PyObject_CallObject( pFunc, pArgs );
np_ret = reinterpret_cast<PyArrayObject*>( pReturn );
size_t m{ static_cast<size_t>( PyArray_SHAPE( np_ret )[0] ) };
size_t n{ static_cast<size_t>( PyArray_SHAPE( np_ret )[1] ) };
double* c_out = reinterpret_cast<double*>( PyArray_DATA( np_ret ) );
Matrix gsImage( m, n, c_out );
// Finalizing
Py_DECREF( pFunc );
Py_DECREF( pModule );
Py_DECREF( np_ret );
Py_Finalize();
return gsImage;
}
......@@ -184,8 +184,10 @@ void Config::SetConfigOptions() {
AddStringOption( "OUTPUT_FILE", _outputFile, string( "output" ) );
/*! @brief LOG_DIR \n DESCRIPTION: Relative Directory of log files \n DEFAULT "/out" @ingroup Config.*/
AddStringOption( "LOG_DIR", _logDir, string( "/out" ) );
/*!\brief MESH_FILE \n DESCRIPTION: Name of mesh file \n DEFAULT "" \ingroup Config.*/
/*! @brief MESH_FILE \n DESCRIPTION: Name of mesh file \n DEFAULT "" \ingroup Config.*/
AddStringOption( "MESH_FILE", _meshFile, string( "mesh.su2" ) );
/*! @brief MESH_FILE \n DESCRIPTION: Name of mesh file \n DEFAULT "" \ingroup Config.*/
AddStringOption( "CT_FILE", _ctFile, string( "phantom.png" ) );
// Quadrature relatated options
/*! @brief QUAD_TYPE \n DESCRIPTION: Type of Quadrature rule \n Options: see @link QUAD_NAME \endlink \n DEFAULT: QUAD_MonteCarlo \ingroup
......@@ -314,6 +316,7 @@ void Config::SetPostprocessing() {
_outputDir = _inputDir + _outputDir;
_meshFile = _inputDir + _meshFile;
_outputFile = _outputDir + _outputFile;
_ctFile = _inputDir + _ctFile;
// create directories if they dont exist
if( !std::filesystem::exists( _outputDir ) ) std::filesystem::create_directory( _outputDir );
......
#include <numeric>
#include "catch.hpp"
#include "io.h"
TEST_CASE( "convert image to grayscale matrix and generate suitable mesh", "[image I/O]" ) {
std::string config_file_name = "../tests/input/linesource.cfg";
Config* config = new Config( config_file_name ); // just to setup the logger
std::string testImage = "../tests/input/phantom.png";
std::string testMesh = "../result/test.su2";
Matrix gsImage = createSU2MeshFromImage( testImage, testMesh );
REQUIRE( std::filesystem::exists( testMesh ) );
REQUIRE( blaze::max( gsImage ) > 0 );
REQUIRE( gsImage.rows() > 0 );
REQUIRE( gsImage.columns() > 0 );
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment