diff --git a/CMakeLists.txt b/CMakeLists.txt index 60fa5d99d55311fd0854a6d5b40265fe493be9b6..3a68013136be86583b84fa315d12e1577cfef772 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,23 +182,6 @@ if( WITH_CUDA STREQUAL "yes" ) # TODO: this is necessary only due to a bug in cmake set( CUDA_ADD_LIBRARY_OPTIONS -shared ) - #### - # Check for cuBLAS - # - if( NOT WITH_CUBLAS STREQUAL "no" ) - find_path( CUBLAS_INCLUDE_DIR cublas_v2.h - /usr/local/cuda/include - ${CUDA_INCLUDE_DIRS} - DOC "CUBLAS headers." ) - if( ${CUBLAS_INCLUDE_DIR} STREQUAL "CUBLAS_INCLUDE_DIR-NOTFOUND" ) - message( "CUBLAS not found." ) - set( HAVE_CUBLAS "//#define HAVE_CUBLAS 1" ) - else() - message( "CUBLAS found. -- ${CUBLAS_INCLUDE_DIR}" ) - set( HAVE_CUBLAS "#define HAVE_CUBLAS 1" ) - endif() - endif( NOT WITH_CUBLAS STREQUAL "no" ) - #### # Check for CUSP # diff --git a/doc/pde-solvers.rst b/doc/pde-solvers.rst index 6f7eed46d377e19862f297d31ec6d70f3846ed56..d93e49e5a6901c091f1e6672bc91bb2451b75943 100644 --- a/doc/pde-solvers.rst +++ b/doc/pde-solvers.rst @@ -1,3 +1,9 @@ =========== PDE Solvers =========== + +Finite difference method + + Elliptic problems + + Parabolic problems \ No newline at end of file diff --git a/examples/heat-equation/HeatEquationBuildConfigTag.h b/examples/heat-equation/HeatEquationBuildConfigTag.h index 8579b7f473c6ab1a3472aaa8a11913758390a15a..0e0389ca74fa62367ec6d1facd07ac18c528ad9a 100644 --- a/examples/heat-equation/HeatEquationBuildConfigTag.h +++ b/examples/heat-equation/HeatEquationBuildConfigTag.h @@ -11,50 +11,57 @@ #pragma once #include <TNL/Solvers/BuildConfigTags.h> +#include <TNL/Meshes/BuildConfigTags.h> namespace TNL { -namespace Solvers { - -class HeatEquationBuildConfig -{ - public: - static void print() { std::cerr << "HeatEquationBuildConfig" << std::endl; } -}; +class HeatEquationBuildConfigTag{}; +namespace Solvers { + /**** * Turn off support for float and long double. */ -template<> struct ConfigTagReal< HeatEquationBuildConfig, float > { enum { enabled = false }; }; -template<> struct ConfigTagReal< HeatEquationBuildConfig, long double > { enum { enabled = false }; }; +template<> struct ConfigTagReal< HeatEquationBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct ConfigTagReal< HeatEquationBuildConfigTag, long double > { enum { enabled = false }; }; /**** * Turn off support for short int and long int indexing. */ -template<> struct ConfigTagIndex< HeatEquationBuildConfig, short int >{ enum { enabled = false }; }; -template<> struct ConfigTagIndex< HeatEquationBuildConfig, long int >{ enum { enabled = false }; }; - -/**** - * Use of Grid is enabled for allowed dimensions and Real, Device and Index types. - */ -template< int Dimension, typename Real, typename Device, typename Index > - struct ConfigTagMesh< HeatEquationBuildConfig, Meshes::Grid< Dimension, Real, Device, Index > > - { enum { enabled = ConfigTagDimension< HeatEquationBuildConfig, Dimension >::enabled && - ConfigTagReal< HeatEquationBuildConfig, Real >::enabled && - ConfigTagDevice< HeatEquationBuildConfig, Device >::enabled && - ConfigTagIndex< HeatEquationBuildConfig, Index >::enabled }; }; +template<> struct ConfigTagIndex< HeatEquationBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct ConfigTagIndex< HeatEquationBuildConfigTag, long int >{ enum { enabled = false }; }; /**** * Please, chose your preferred time discretization here. */ -template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfig, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; }; -template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfig, SemiImplicitTimeDiscretisationTag >{ enum { enabled = false }; }; -template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfig, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; }; +template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfigTag, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; }; +template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfigTag, SemiImplicitTimeDiscretisationTag >{ enum { enabled = false }; }; +template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfigTag, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; }; /**** * Only the Runge-Kutta-Merson solver is enabled by default. */ -template<> struct ConfigTagExplicitSolver< HeatEquationBuildConfig, ExplicitEulerSolverTag >{ enum { enabled = false }; }; +template<> struct ConfigTagExplicitSolver< HeatEquationBuildConfigTag, ExplicitEulerSolverTag >{ enum { enabled = false }; }; } // namespace Solvers + +namespace Meshes { +namespace BuildConfigTags { + +template< int Dimensions > struct GridDimensionTag< HeatEquationBuildConfigTag, Dimensions >{ enum { enabled = true }; }; + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< HeatEquationBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< HeatEquationBuildConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< HeatEquationBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< HeatEquationBuildConfigTag, long int >{ enum { enabled = false }; }; + +} // namespace BuildConfigTags +} // namespace Meshes } // namespace TNL diff --git a/examples/heat-equation/tnl-heat-equation-eoc.h b/examples/heat-equation/tnl-heat-equation-eoc.h index f9876fb9adf66479282f1223bd48fb10da759ae7..57ec6536fee8c43add54c4122a1c328ca489b508 100644 --- a/examples/heat-equation/tnl-heat-equation-eoc.h +++ b/examples/heat-equation/tnl-heat-equation-eoc.h @@ -24,8 +24,8 @@ using namespace TNL; using namespace TNL::Problems; -//typedef tnlDefaultBuildMeshConfig BuildConfig; -typedef Solvers::FastBuildConfig BuildConfig; +//typedef Solvers::DefaultBuildConfigTag BuildConfig; +typedef Solvers::FastBuildConfigTag BuildConfig; template< typename MeshConfig > class heatEquationEocConfig diff --git a/examples/heat-equation/tnl-heat-equation.h b/examples/heat-equation/tnl-heat-equation.h index 1a0041f93e3f6edeb73b8bfe9d632ed9538f9f41..048abb409ac0d4567a22d87817edca057120b328 100644 --- a/examples/heat-equation/tnl-heat-equation.h +++ b/examples/heat-equation/tnl-heat-equation.h @@ -26,9 +26,8 @@ using namespace TNL; using namespace TNL::Problems; -//typedef tnlDefaultBuildMeshConfig BuildConfig; -typedef Solvers::FastBuildConfig BuildConfig; -//typedef Solvers::HeatEquationBuildConfig BuildConfig; +//typedef Solvers::DefaultBuildConfigTag BuildConfig; +typedef Solvers::FastBuildConfigTag BuildConfig; template< typename MeshConfig > class heatEquationConfig diff --git a/examples/inviscid-flow/eulerBuildConfigTag.h b/examples/inviscid-flow/eulerBuildConfigTag.h index b219ba4ff58c0c6601f7393e93ee395fa18ce6f8..fec6d0fe721550c828cc475fafcd11d4c3496817 100644 --- a/examples/inviscid-flow/eulerBuildConfigTag.h +++ b/examples/inviscid-flow/eulerBuildConfigTag.h @@ -2,6 +2,7 @@ #define eulerBUILDCONFIGTAG_H_ #include <TNL/Solvers/BuildConfigTags.h> +#include <TNL/Meshes/BuildConfigTags.h> namespace TNL { @@ -21,18 +22,6 @@ template<> struct ConfigTagReal< eulerBuildConfigTag, long double > { enum { ena template<> struct ConfigTagIndex< eulerBuildConfigTag, short int >{ enum { enabled = false }; }; template<> struct ConfigTagIndex< eulerBuildConfigTag, long int >{ enum { enabled = false }; }; -template< int Dimension > struct ConfigTagDimension< eulerBuildConfigTag, Dimension >{ enum { enabled = ( Dimension == 1 ) }; }; - -/**** - * Use of Grid is enabled for allowed dimensions and Real, Device and Index types. - */ -template< int Dimension, typename Real, typename Device, typename Index > - struct ConfigTagMesh< eulerBuildConfigTag, Meshes::Grid< Dimension, Real, Device, Index > > - { enum { enabled = ConfigTagDimension< eulerBuildConfigTag, Dimension >::enabled && - ConfigTagReal< eulerBuildConfigTag, Real >::enabled && - ConfigTagDevice< eulerBuildConfigTag, Device >::enabled && - ConfigTagIndex< eulerBuildConfigTag, Index >::enabled }; }; - /**** * Please, chose your preferred time discretisation here. */ @@ -46,6 +35,26 @@ template<> struct ConfigTagTimeDiscretisation< eulerBuildConfigTag, ImplicitTime template<> struct ConfigTagExplicitSolver< eulerBuildConfigTag, ExplicitEulerSolverTag >{ enum { enabled = true }; }; } // namespace Solvers + +namespace Meshes { +namespace BuildConfigTags { + +template< int Dimensions > struct GridDimensionTag< eulerBuildConfigTag, Dimensions >{ enum { enabled = ( Dimensions == 1 ) }; }; + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< eulerBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< eulerBuildConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< eulerBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< eulerBuildConfigTag, long int >{ enum { enabled = false }; }; + +} // namespace BuildConfigTags +} // namespace Meshes } // namespace TNL #endif /* eulerBUILDCONFIGTAG_H_ */ diff --git a/examples/transport-equation/transportEquationBuildConfigTag.h b/examples/transport-equation/transportEquationBuildConfigTag.h index 884060fa2d973530f1b5fb926ee280aa11a4b7ed..0121ab2c00582a4b8f47a96d81b30d31b35f51bf 100644 --- a/examples/transport-equation/transportEquationBuildConfigTag.h +++ b/examples/transport-equation/transportEquationBuildConfigTag.h @@ -12,6 +12,7 @@ #pragma once #include <TNL/Solvers/BuildConfigTags.h> +#include <TNL/Meshes/BuildConfigTags.h> namespace TNL { @@ -31,17 +32,6 @@ template<> struct ConfigTagReal< transportEquationBuildConfigTag, long double > template<> struct ConfigTagIndex< transportEquationBuildConfigTag, short int >{ enum { enabled = false }; }; template<> struct ConfigTagIndex< transportEquationBuildConfigTag, long int >{ enum { enabled = false }; }; -/**** - * Use of Grid is enabled for allowed dimensions and Real, Device and Index types. - */ - -template< int Dimensions, typename Real, typename Device, typename Index > - struct ConfigTagMesh< transportEquationBuildConfigTag, Meshes::Grid< Dimensions, Real, Device, Index > > - { enum { enabled = ConfigTagDimension< transportEquationBuildConfigTag, Dimensions >::enabled && - ConfigTagReal< transportEquationBuildConfigTag, Real >::enabled && - ConfigTagDevice< transportEquationBuildConfigTag, Device >::enabled && - ConfigTagIndex< transportEquationBuildConfigTag, Index >::enabled }; }; - /**** * Please, chose your preferred time discretisation here. */ @@ -55,4 +45,24 @@ template<> struct ConfigTagTimeDiscretisation< transportEquationBuildConfigTag, template<> struct ConfigTagExplicitSolver< transportEquationBuildConfigTag, Solvers::ExplicitEulerSolverTag >{ enum { enabled = true }; }; } // namespace Solvers + +namespace Meshes { +namespace BuildConfigTags { + +template< int Dimensions > struct GridDimensionTag< transportEquationBuildConfigTag, Dimensions >{ enum { enabled = true }; }; + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< transportEquationBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< transportEquationBuildConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< transportEquationBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< transportEquationBuildConfigTag, long int >{ enum { enabled = false }; }; + +} // namespace BuildConfigTags +} // namespace Meshes } // namespace TNL diff --git a/src/Python/CMakeLists.txt b/src/Python/CMakeLists.txt index 6356af0046b95d4f5a61944324cdcf2827408270..598d9faf14446f4073daffccd4a9cc5f15beb7b7 100644 --- a/src/Python/CMakeLists.txt +++ b/src/Python/CMakeLists.txt @@ -1,8 +1,36 @@ find_package( PythonInterp 3 ) +find_package( PythonLibs 3 ) + +set( PYTHON_SITE_PACKAGES_DIR lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages ) if( PYTHONINTERP_FOUND ) CONFIGURE_FILE( "__init__.py.in" "${PROJECT_BUILD_PATH}/Python/__init__.py" ) INSTALL( FILES ${PROJECT_BUILD_PATH}/Python/__init__.py LogParser.py - DESTINATION lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/TNL ) + DESTINATION ${PYTHON_SITE_PACKAGES_DIR}/TNL ) +endif() + +if( PYTHONLIBS_FOUND ) + # download and build pybind11 at configure time + configure_file(pybind11.cmake.in ${CMAKE_BINARY_DIR}/pybind11-download/CMakeLists.txt) + execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pybind11-download ) + if(result) + message(FATAL_ERROR "CMake step for pybind11 failed: ${result}") + endif() + execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pybind11-download ) + if(result) + message(FATAL_ERROR "Build step for pybind11 failed: ${result}") + endif() + + # add the pybind11 subdirectory to provide the pybind11_add_module macro + add_subdirectory(${CMAKE_BINARY_DIR}/pybind11-src ${CMAKE_BINARY_DIR}/pybind11-build) + + # add the subdirectory with our bindings + add_subdirectory(pytnl) +else() + message( "The Python.h header file was not found, Python bindings will not be builg." ) endif() diff --git a/src/Python/pybind11.cmake.in b/src/Python/pybind11.cmake.in new file mode 100644 index 0000000000000000000000000000000000000000..18f1aeac607f719a067a8a61c1c3449cfd64687b --- /dev/null +++ b/src/Python/pybind11.cmake.in @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(pybind11-download) +include(ExternalProject) + +ExternalProject_Add(pybind11 + GIT_REPOSITORY https://github.com/pybind/pybind11.git + GIT_TAG master + SOURCE_DIR "${CMAKE_BINARY_DIR}/pybind11-src" + BINARY_DIR "${CMAKE_BINARY_DIR}/pybind11-build" + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DPYBIND11_TEST=FALSE +) diff --git a/src/Python/pytnl/CMakeLists.txt b/src/Python/pytnl/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..eecb2aeeb6c9abd9acce6650189df3c4129834ee --- /dev/null +++ b/src/Python/pytnl/CMakeLists.txt @@ -0,0 +1,13 @@ +add_subdirectory( tnl ) + +set( headers + exceptions.h + RawIterator.h + tnl_conversions.h + tnl_indexing.h + tnl_str_conversion.h + tnl_tuple_conversion.h + typedefs.h +) + +install( FILES ${headers} DESTINATION "include/pytnl" ) diff --git a/src/Python/pytnl/RawIterator.h b/src/Python/pytnl/RawIterator.h new file mode 100644 index 0000000000000000000000000000000000000000..6e9aa7b41cfb3f06c4630675062a5b9cbe77c848 --- /dev/null +++ b/src/Python/pytnl/RawIterator.h @@ -0,0 +1,51 @@ +#pragma once + +#include <iterator> + +template< typename DataType > +class RawIterator : public std::iterator<std::random_access_iterator_tag, + DataType, + ptrdiff_t, + DataType*, + DataType&> +{ +protected: + DataType* m_ptr; + +public: + RawIterator( DataType* ptr = nullptr ) { m_ptr = ptr; } + RawIterator( const RawIterator<DataType> & rawIterator ) = default; + ~RawIterator(){} + + RawIterator<DataType>& operator=( const RawIterator<DataType> & rawIterator ) = default; + RawIterator<DataType>& operator=( DataType* ptr ) { m_ptr = ptr; return (*this); } + + operator bool() const + { + if(m_ptr) + return true; + else + return false; + } + + bool operator==( const RawIterator<DataType> & rawIterator ) const { return ( m_ptr == rawIterator.getConstPtr() ); } + bool operator!=( const RawIterator<DataType> & rawIterator ) const { return ( m_ptr != rawIterator.getConstPtr() ); } + + RawIterator<DataType>& operator+=( const ptrdiff_t & movement ){ m_ptr += movement; return (*this); } + RawIterator<DataType>& operator-=( const ptrdiff_t & movement ){ m_ptr -= movement; return (*this); } + RawIterator<DataType>& operator++() { ++m_ptr; return (*this); } + RawIterator<DataType>& operator--() { --m_ptr; return (*this); } + RawIterator<DataType> operator++( int ) { auto temp(*this); ++m_ptr; return temp; } + RawIterator<DataType> operator--( int ) { auto temp(*this); --m_ptr; return temp; } + RawIterator<DataType> operator+( const ptrdiff_t & movement ) { auto oldPtr = m_ptr; m_ptr+=movement; auto temp(*this); m_ptr = oldPtr; return temp; } + RawIterator<DataType> operator-( const ptrdiff_t & movement ) { auto oldPtr = m_ptr; m_ptr-=movement; auto temp(*this); m_ptr = oldPtr; return temp; } + + ptrdiff_t operator-( const RawIterator<DataType>& rawIterator ) { return std::distance(rawIterator.getPtr(), this->getPtr()); } + + DataType& operator*() { return *m_ptr; } + const DataType& operator*() const { return *m_ptr; } + DataType* operator->() { return m_ptr; } + + DataType* getPtr() const { return m_ptr; } + const DataType* getConstPtr() const { return m_ptr; } +}; diff --git a/src/Python/pytnl/exceptions.h b/src/Python/pytnl/exceptions.h new file mode 100644 index 0000000000000000000000000000000000000000..669fb3214c9e6bfad69bd2a80cde79ede532f781 --- /dev/null +++ b/src/Python/pytnl/exceptions.h @@ -0,0 +1,35 @@ +#pragma once + +#include <stdexcept> + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +#include <TNL/Assert.h> + +struct NotImplementedError + : public std::runtime_error +{ + NotImplementedError( const char* msg ) + : std::runtime_error( msg ) + {} +}; + +static void register_exceptions( py::module & m ) +{ + py::register_exception_translator( + [](std::exception_ptr p) { + try { + if (p) std::rethrow_exception(p); + } + // translate exceptions used in the bindings + catch (const NotImplementedError & e) { + PyErr_SetString(PyExc_NotImplementedError, e.what()); + } + // translate TNL::Assert::AssertionError + catch (const TNL::Assert::AssertionError & e) { + PyErr_SetString(PyExc_AssertionError, e.what()); + } + } + ); +} diff --git a/src/Python/pytnl/tnl/Array.h b/src/Python/pytnl/tnl/Array.h new file mode 100644 index 0000000000000000000000000000000000000000..0d74acdccef35773616fb6b7e695caa32c767361 --- /dev/null +++ b/src/Python/pytnl/tnl/Array.h @@ -0,0 +1,63 @@ +#pragma once + +#include <pybind11/pybind11.h> +#include <pybind11/operators.h> +namespace py = pybind11; + +#include "../tnl_indexing.h" + +#include <TNL/Containers/Array.h> + +template< typename ArrayType > +void export_Array(py::module & m, const char* name) +{ + auto array = py::class_<ArrayType, TNL::Object>(m, name, py::buffer_protocol()) + .def(py::init<>()) + .def(py::init<int>()) + .def_static("getType", &ArrayType::getType) + .def("getTypeVirtual", &ArrayType::getTypeVirtual) + .def_static("getSerializationType", &ArrayType::getSerializationType) + .def("getSerializationTypeVirtual", &ArrayType::getSerializationTypeVirtual) + .def("setSize", &ArrayType::setSize) + .def("setLike", &ArrayType::template setLike<ArrayType>) + .def("swap", &ArrayType::swap) + .def("reset", &ArrayType::reset) + .def("getSize", &ArrayType::getSize) + .def("setElement", &ArrayType::setElement) + .def("getElement", &ArrayType::getElement) + // operator= + .def("assign", []( ArrayType& array, const ArrayType& other ) -> ArrayType& { + return array = other; + }) + .def(py::self == py::self) + .def(py::self != py::self) + .def("setValue", &ArrayType::setValue) + + .def("__str__", []( ArrayType & a ) { + std::stringstream ss; + ss << a; + return ss.str(); + } ) + + // Python buffer protocol: http://pybind11.readthedocs.io/en/master/advanced/pycpp/numpy.html + .def_buffer( [](ArrayType & a) -> py::buffer_info { + return py::buffer_info( + // Pointer to buffer + a.getData(), + // Size of one scalar + sizeof( typename ArrayType::ElementType ), + // Python struct-style format descriptor + py::format_descriptor< typename ArrayType::ElementType >::format(), + // Number of dimensions + 1, + // Buffer dimensions + { a.getSize() }, + // Strides (in bytes) for each index + { sizeof( typename ArrayType::ElementType ) } + ); + }) + ; + + tnl_indexing< ArrayType >( array ); + tnl_slice_indexing< ArrayType >( array ); +} diff --git a/src/Python/pytnl/tnl/CMakeLists.txt b/src/Python/pytnl/tnl/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9fa9bef04c181688e90cb8762608d9cf68e72d45 --- /dev/null +++ b/src/Python/pytnl/tnl/CMakeLists.txt @@ -0,0 +1,26 @@ +set( sources + Grid1D.cpp + Grid2D.cpp + Grid3D.cpp + Mesh.cpp + Object.cpp + SparseMatrix.cpp + String.cpp + tnl.cpp +) +pybind11_add_module( pytnl ${sources} ) + +# link against tnl.so +target_link_libraries( pytnl PRIVATE tnl ) + +# rename the shared library to tnl.cpython-XXm-x86_64-linux-gnu.so +set_target_properties( pytnl PROPERTIES LIBRARY_OUTPUT_NAME tnl ) + +# We have bindings for unsafe objects (e.g. Array::operator[]) where assertion +# is the only safeguard, so we need to translate the TNL::AssertionError to +# Python's AssertionError. +# NDEBUG is defined in the global CMAKE_CXX_FLAGS and cannot be easily removed +# per-target, so we need to undefine it by passing -U NDEBUG. +target_compile_options( pytnl PRIVATE -U NDEBUG -D TNL_THROW_ASSERTION_ERROR ) + +install( TARGETS pytnl DESTINATION ${PYTHON_SITE_PACKAGES_DIR} ) diff --git a/src/Python/pytnl/tnl/EntityTypes.h b/src/Python/pytnl/tnl/EntityTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..1f10e2827dd2cc24d006c88f509e6b8d5a5cbf90 --- /dev/null +++ b/src/Python/pytnl/tnl/EntityTypes.h @@ -0,0 +1,36 @@ +#pragma once + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +enum class EntityTypes { Cell, Face, Vertex }; + +inline void +export_EntityTypes( py::module & m ) +{ + // avoid duplicate conversion -> export only once + static bool exported = false; + if( ! exported ) { + // TODO: should be nested types instead + py::enum_< EntityTypes >( m, "EntityTypes" ) + .value("Cell", EntityTypes::Cell) + .value("Face", EntityTypes::Face) + .value("Vertex", EntityTypes::Vertex) + ; + exported = true; + } +} + +template< typename Mesh > +typename Mesh::GlobalIndexType +mesh_getEntitiesCount( const Mesh & self, const EntityTypes & entity ) +{ + if( entity == EntityTypes::Cell ) + return self.template getEntitiesCount< typename Mesh::Cell >(); + else if( entity == EntityTypes::Face ) + return self.template getEntitiesCount< typename Mesh::Face >(); + else if( entity == EntityTypes::Vertex ) + return self.template getEntitiesCount< typename Mesh::Vertex >(); + else + throw py::value_error("The entity parameter must be either Cell, Face or Vertex."); +} diff --git a/src/Python/pytnl/tnl/Grid.h b/src/Python/pytnl/tnl/Grid.h new file mode 100644 index 0000000000000000000000000000000000000000..afc5b39749362a08248befb7716c8f446e888dad --- /dev/null +++ b/src/Python/pytnl/tnl/Grid.h @@ -0,0 +1,98 @@ +#pragma once + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +#include "StaticVector.h" +#include "Grid_getSpaceStepsProducts.h" +#include "EntityTypes.h" + +#include <type_traits> + +template< typename GridEntity, typename PyGrid > +void export_GridEntity( PyGrid & scope, const char* name ) +{ + typename GridEntity::CoordinatesType const & (GridEntity::* _getCoordinates1)(void) const = &GridEntity::getCoordinates; + typename GridEntity::CoordinatesType & (GridEntity::* _getCoordinates2)(void) = &GridEntity::getCoordinates; + + py::class_< GridEntity >( scope, name ) + .def( py::init< typename GridEntity::GridType >(), + py::return_value_policy::reference_internal ) + .def( py::init< typename GridEntity::GridType, + typename GridEntity::CoordinatesType, + typename GridEntity::EntityOrientationType, + typename GridEntity::EntityBasisType >(), + py::return_value_policy::reference_internal ) + .def("getEntityDimension", &GridEntity::getEntityDimension) + .def("getMeshDimension", &GridEntity::getMeshDimension) + // TODO: constructors + .def("getCoordinates", _getCoordinates1, py::return_value_policy::reference_internal) + .def("getCoordinates", _getCoordinates2, py::return_value_policy::reference_internal) + .def("setCoordinates", &GridEntity::setCoordinates) + .def("refresh", &GridEntity::refresh) + .def("getIndex", &GridEntity::getIndex) + // FIXME: some templates return reference, others value +// .def("getOrientation", &GridEntity::getOrientation, py::return_internal_reference<>(), py::return_value_policy<py::copy_const_reference>()) + .def("setOrientation", &GridEntity::setOrientation) + // FIXME: some templates return reference, others value +// .def("getBasis", &GridEntity::getBasis, py::return_internal_reference<>(), py::return_value_policy<py::copy_const_reference>()) + .def("setBasis", &GridEntity::setBasis) + // TODO: getNeighbourEntities + .def("isBoundaryEntity", &GridEntity::isBoundaryEntity) + .def("getCenter", &GridEntity::getCenter) + // FIXME: some templates return reference, others value +// .def("getMeasure", &GridEntity::getMeasure, py::return_value_policy<py::copy_const_reference>()) + .def("getMesh", &GridEntity::getMesh, py::return_value_policy::reference_internal) + ; +} + +template< typename Grid > +void export_Grid( py::module & m, const char* name ) +{ + // function pointers for overloaded methods +// FIXME: number of parameters depends on the grid dimension +// void (Grid::* _setDimensions1)(const IndexType) = &Grid::setDimensions; + void (Grid::* _setDimensions2)(const typename Grid::CoordinatesType &) = &Grid::setDimensions; + + export_EntityTypes(m); + + auto grid = py::class_<Grid, TNL::Object>( m, name ) + .def(py::init<>()) + .def_static("getMeshDimension", &Grid::getMeshDimension) + .def_static("getType", &Grid::getType) + .def("getTypeVirtual", &Grid::getTypeVirtual) + .def_static("getSerializationType", &Grid::getSerializationType) + .def("getSerializationTypeVirtual", &Grid::getSerializationTypeVirtual) + // FIXME: number of parameters depends on the grid dimension +// .def("setDimensions", _setDimensions1) + .def("setDimensions", _setDimensions2) + .def("getDimensions", &Grid::getDimensions, py::return_value_policy::reference_internal) + .def("setDomain", &Grid::setDomain) + .def("getOrigin", &Grid::getOrigin, py::return_value_policy::reference_internal) + .def("getProportions", &Grid::getProportions, py::return_value_policy::reference_internal) + .def("getEntitiesCount", &mesh_getEntitiesCount< Grid >) + // TODO: if combined, the return type would depend on the runtime parameter (entity) + .def("getEntity_cell", &Grid::template getEntity<typename Grid::Cell>) + .def("getEntity_face", &Grid::template getEntity<typename Grid::Face>) + .def("getEntity_vertex", &Grid::template getEntity<typename Grid::Vertex>) + .def("getEntityIndex", &Grid::template getEntityIndex<typename Grid::Cell>) + .def("getEntityIndex", &Grid::template getEntityIndex<typename Grid::Face>) + .def("getEntityIndex", &Grid::template getEntityIndex<typename Grid::Vertex>) + .def("getCellMeasure", &Grid::getCellMeasure, py::return_value_policy::reference_internal) + .def("getSpaceSteps", &Grid::getSpaceSteps, py::return_value_policy::reference_internal) + .def("getSmallestSpaceStep", &Grid::getSmallestSpaceStep) + // TODO: writeProlog() + ; + + // complicated methods + SpaceStepsProductsGetter< Grid >::export_getSpaceSteps( grid ); + + // nested types + export_StaticVector< typename Grid::CoordinatesType >( grid, "CoordinatesType" ); + export_StaticVector< typename Grid::PointType >( grid, "PointType" ); + export_GridEntity< typename Grid::Cell >( grid, "Cell" ); + export_GridEntity< typename Grid::Face >( grid, "Face" ); + // avoid duplicate conversion if the type is the same + if( ! std::is_same< typename Grid::Face, typename Grid::Vertex >::value ) + export_GridEntity< typename Grid::Vertex >( grid, "Vertex" ); +} diff --git a/src/Python/pytnl/tnl/Grid1D.cpp b/src/Python/pytnl/tnl/Grid1D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d10952b713e89a8deab65c6fe321bfeea5a3b16f --- /dev/null +++ b/src/Python/pytnl/tnl/Grid1D.cpp @@ -0,0 +1,9 @@ +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include "Grid.h" + +void export_Grid1D( py::module & m ) +{ + export_Grid< Grid1D >( m, "Grid1D" ); +} diff --git a/src/Python/pytnl/tnl/Grid2D.cpp b/src/Python/pytnl/tnl/Grid2D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69b8683c10453d44ac415da95e83067ba4139376 --- /dev/null +++ b/src/Python/pytnl/tnl/Grid2D.cpp @@ -0,0 +1,9 @@ +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include "Grid.h" + +void export_Grid2D( py::module & m ) +{ + export_Grid< Grid2D >( m, "Grid2D" ); +} diff --git a/src/Python/pytnl/tnl/Grid3D.cpp b/src/Python/pytnl/tnl/Grid3D.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15d7dd48071ac310c78d7cf057f5e7d700f72ad2 --- /dev/null +++ b/src/Python/pytnl/tnl/Grid3D.cpp @@ -0,0 +1,9 @@ +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include "Grid.h" + +void export_Grid3D( py::module & m ) +{ + export_Grid< Grid3D >( m, "Grid3D" ); +} diff --git a/src/Python/pytnl/tnl/Grid_getSpaceStepsProducts.h b/src/Python/pytnl/tnl/Grid_getSpaceStepsProducts.h new file mode 100644 index 0000000000000000000000000000000000000000..f54b9eebc5a6dde5a373a00f57733aa7a15c1885 --- /dev/null +++ b/src/Python/pytnl/tnl/Grid_getSpaceStepsProducts.h @@ -0,0 +1,82 @@ +#pragma once + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +#include "../typedefs.h" + +template< typename Grid > +struct SpaceStepsProductsGetter +{}; + +template<> +struct SpaceStepsProductsGetter< Grid1D > +{ + static inline + typename Grid1D::RealType + get( const Grid1D & grid, const int & xPow ) + { + if( xPow == -2 ) return grid.template getSpaceStepsProducts< -2 >(); + if( xPow == -1 ) return grid.template getSpaceStepsProducts< -1 >(); + if( xPow == 0 ) return grid.template getSpaceStepsProducts< 0 >(); + if( xPow == 1 ) return grid.template getSpaceStepsProducts< 1 >(); + if( xPow == 2 ) return grid.template getSpaceStepsProducts< 2 >(); + const auto hx = grid.template getSpaceStepsProducts< 1 >(); + return pow( hx, xPow ); + } + + template< typename PyGrid > + static void + export_getSpaceSteps( PyGrid & scope, const char* name = "getSpaceSteps" ) + { + scope.def("getSpaceStepsProducts", get, py::arg("xPow") ); + } +}; + +template<> +struct SpaceStepsProductsGetter< Grid2D > +{ + static inline + typename Grid2D::RealType + get( const Grid2D & grid, const int & xPow, const int & yPow = 0 ) + { + if( xPow == 0 && yPow == 0 ) return grid.template getSpaceStepsProducts< 0, 0 >(); + auto hx = grid.template getSpaceStepsProducts< 1, 0 >(); + auto hy = grid.template getSpaceStepsProducts< 0, 1 >(); + if( xPow != 1 ) hx = pow( hx, xPow ); + if( yPow != 1 ) hy = pow( hy, yPow ); + return hx * hy; + } + + template< typename PyGrid > + static void + export_getSpaceSteps( PyGrid & scope, const char* name = "getSpaceSteps" ) + { + scope.def("getSpaceStepsProducts", get, py::arg("xPow"), py::arg("yPow")=0 ); + } +}; + +template<> +struct SpaceStepsProductsGetter< Grid3D > +{ + static inline + typename Grid3D::RealType + get( const Grid3D & grid, const int & xPow, const int & yPow = 0, const int & zPow = 0 ) + { + if( xPow == 0 && yPow == 0 && zPow == 0 ) return grid.template getSpaceStepsProducts< 0, 0, 0 >(); + auto hx = grid.template getSpaceStepsProducts< 1, 0, 0 >(); + auto hy = grid.template getSpaceStepsProducts< 0, 1, 0 >(); + auto hz = grid.template getSpaceStepsProducts< 0, 0, 1 >(); + if( xPow != 1 ) hx = pow( hx, xPow ); + if( yPow != 1 ) hy = pow( hy, yPow ); + if( zPow != 1 ) hz = pow( hz, zPow ); + return hx * hy * hz; + } + + template< typename PyGrid > + static void + export_getSpaceSteps( PyGrid & scope, const char* name = "getSpaceSteps" ) + { + scope.def("getSpaceStepsProducts", get, py::arg("xPow"), py::arg("yPow")=0, py::arg("zPow")=0 ); + } +}; diff --git a/src/Python/pytnl/tnl/Mesh.cpp b/src/Python/pytnl/tnl/Mesh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c267aeade67b136d2b425444bc4f010ce3acc12d --- /dev/null +++ b/src/Python/pytnl/tnl/Mesh.cpp @@ -0,0 +1,30 @@ +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include "Mesh.h" +#include <TNL/Meshes/Readers/VTKReader.h> + +void export_Meshes( py::module & m ) +{ + export_Mesh< MeshOfEdges >( m, "MeshOfEdges" ); + export_Mesh< MeshOfTriangles >( m, "MeshOfTriangles" ); + export_Mesh< MeshOfTetrahedrons >( m, "MeshOfTetrahedrons" ); + + using Reader = TNL::Meshes::Readers::VTKReader; + + py::class_< Reader >( m, "VTKReader" ) + .def(py::init<>()) + .def("readMesh", &Reader::template readMesh< MeshOfEdges >) + .def("readMesh", &Reader::template readMesh< MeshOfTriangles >) + .def("readMesh", &Reader::template readMesh< MeshOfTetrahedrons >) +// .def("readMesh", []( Reader& reader, const std::string& name, MeshOfEdges & mesh ) { +// return reader.readMesh( name.c_str(), mesh ); +// } ) +// .def("readMesh", []( Reader& reader, const std::string& name, MeshOfTriangles & mesh ) { +// return reader.readMesh( name.c_str(), mesh ); +// } ) +// .def("readMesh", []( Reader& reader, const std::string& name, MeshOfTetrahedrons & mesh ) { +// return reader.readMesh( name.c_str(), mesh ); +// } ) + ; +} diff --git a/src/Python/pytnl/tnl/Mesh.h b/src/Python/pytnl/tnl/Mesh.h new file mode 100644 index 0000000000000000000000000000000000000000..ee17a134804fc2fb71d69f5e81bd2838d57428e2 --- /dev/null +++ b/src/Python/pytnl/tnl/Mesh.h @@ -0,0 +1,145 @@ +#pragma once + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +#include "../typedefs.h" +#include "StaticVector.h" +#include "EntityTypes.h" + +#include <TNL/String.h> +#include <TNL/Meshes/Geometry/getEntityCenter.h> +#include <TNL/Meshes/Geometry/getEntityMeasure.h> + +#include <type_traits> + +template< typename MeshEntity > +typename MeshEntity::MeshTraitsType::GlobalIndexType +getIndex( const MeshEntity& entity ) +{ + return entity.getIndex(); +}; + +struct _general {}; +struct _special : _general {}; + +template< typename MeshEntity, + int Superdimension, + typename Scope, + typename = typename std::enable_if< Superdimension <= MeshEntity::MeshTraitsType::meshDimension >::type > +// && MeshEntity::template SuperentityTraits< Superdimension >::storageEnabled >::type > +void export_getSuperentityIndex( Scope & m, _special ) +{ + m.def("getSuperentityIndex", []( const MeshEntity& entity, const typename MeshEntity::LocalIndexType& i ) { + return entity.template getSuperentityIndex< Superdimension >( i ); + } + ); +} + +template< typename MeshEntity, + int Superdimension, + typename Scope > +void export_getSuperentityIndex( Scope &, _general ) +{ +} + + +template< typename MeshEntity, + int Subdimension, + typename Scope, + typename = typename std::enable_if< Subdimension <= MeshEntity::MeshTraitsType::meshDimension + && (Subdimension < MeshEntity::getEntityDimension()) >::type > +void export_getSubentityIndex( Scope & m, const char* name, _special ) +{ + m.def(name, []( const MeshEntity& entity, const typename MeshEntity::LocalIndexType& i ) { + return entity.template getSubentityIndex< Subdimension >( i ); + } + ); +} + +template< typename MeshEntity, + int Superdimension, + typename Scope > +void export_getSubentityIndex( Scope &, const char*, _general ) +{ +} + + +template< typename MeshEntity, + typename Scope, + typename = typename std::enable_if< MeshEntity::getEntityDimension() == 0 >::type > +void export_getPoint( Scope & scope, _special ) +{ + scope.def("getPoint", []( const MeshEntity& entity ) { + return entity.getPoint(); + } + ); +} + +template< typename MeshEntity, + typename Scope > +void export_getPoint( Scope &, _general ) +{ +} + + +template< typename MeshEntity, typename Scope > +void export_MeshEntity( Scope & scope, const char* name ) +{ + auto entity = py::class_< MeshEntity >( scope, name ) + .def_static("getEntityDimension", &MeshEntity::getEntityDimension) + // FIXME: boost chokes on this +// .def("getIndex", &MeshEntity::getIndex, py::return_internal_reference<>()) + .def("getIndex", getIndex< MeshEntity >) + // TODO + ; + + export_getSuperentityIndex< MeshEntity, MeshEntity::getEntityDimension() + 1 >( entity, _special() ); + export_getSubentityIndex< MeshEntity, 0 >( entity, "getSubvertexIndex", _special() ); + export_getPoint< MeshEntity >( entity, _special() ); +} + +template< typename Mesh > +void export_Mesh( py::module & m, const char* name ) +{ + // there are two templates - const and non-const - take only the const + auto (Mesh::* getEntity_cell)(const typename Mesh::GlobalIndexType&) const = &Mesh::template getEntity<typename Mesh::Cell>; + auto (Mesh::* getEntity_face)(const typename Mesh::GlobalIndexType&) const = &Mesh::template getEntity<typename Mesh::Face>; + auto (Mesh::* getEntity_vertex)(const typename Mesh::GlobalIndexType&) const = &Mesh::template getEntity<typename Mesh::Vertex>; + + export_EntityTypes(m); + + auto mesh = py::class_< Mesh, TNL::Object >( m, name ) + .def(py::init<>()) + .def_static("getMeshDimension", &Mesh::getMeshDimension) + .def_static("getType", &Mesh::getType) + .def("getTypeVirtual", &Mesh::getTypeVirtual) + .def_static("getSerializationType", &Mesh::getSerializationType) + .def("getSerializationTypeVirtual", &Mesh::getSerializationTypeVirtual) + .def("getEntitiesCount", &mesh_getEntitiesCount< Mesh >) + // TODO: if combined, the return type would depend on the runtime parameter (entity) + .def("getEntity_cell", getEntity_cell, py::return_value_policy::reference_internal) + .def("getEntity_face", getEntity_face, py::return_value_policy::reference_internal) + .def("getEntity_vertex", getEntity_vertex, py::return_value_policy::reference_internal) + .def("getEntityCenter", []( const Mesh& mesh, const typename Mesh::Cell& cell ){ return getEntityCenter( mesh, cell ); } ) + .def("getEntityCenter", []( const Mesh& mesh, const typename Mesh::Face& face ){ return getEntityCenter( mesh, face ); } ) + .def("getEntityCenter", []( const Mesh& mesh, const typename Mesh::Vertex& vertex ){ return getEntityCenter( mesh, vertex ); } ) + .def("getEntityMeasure", []( const Mesh& mesh, const typename Mesh::Cell& cell ){ return getEntityMeasure( mesh, cell ); } ) + .def("getEntityMeasure", []( const Mesh& mesh, const typename Mesh::Face& face ){ return getEntityMeasure( mesh, face ); } ) + .def("getEntityMeasure", []( const Mesh& mesh, const typename Mesh::Vertex& vertex ){ return getEntityMeasure( mesh, vertex ); } ) + .def("isBoundaryEntity", []( const Mesh& mesh, const typename Mesh::Cell& cell ){ + return mesh.template isBoundaryEntity< Mesh::Cell::getEntityDimension() >( cell.getIndex() ); } ) + .def("isBoundaryEntity", []( const Mesh& mesh, const typename Mesh::Face& face ){ + return mesh.template isBoundaryEntity< Mesh::Face::getEntityDimension() >( face.getIndex() ); } ) + .def("isBoundaryEntity", []( const Mesh& mesh, const typename Mesh::Vertex& vertex ){ + return mesh.template isBoundaryEntity< Mesh::Vertex::getEntityDimension() >( vertex.getIndex() ); } ) + // TODO: more? + ; + + // nested types + export_MeshEntity< typename Mesh::Cell >( mesh, "Cell" ); + export_MeshEntity< typename Mesh::Face >( mesh, "Face" ); + // avoid duplicate conversion if the type is the same + if( ! std::is_same< typename Mesh::Face, typename Mesh::Vertex >::value ) + export_MeshEntity< typename Mesh::Vertex >( mesh, "Vertex" ); +} diff --git a/src/Python/pytnl/tnl/Object.cpp b/src/Python/pytnl/tnl/Object.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd592a2c6ac8eb0e3cd24ce09c5e27110e92f8a2 --- /dev/null +++ b/src/Python/pytnl/tnl/Object.cpp @@ -0,0 +1,22 @@ +#include <pybind11/pybind11.h> +namespace py = pybind11; + +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include <TNL/Object.h> + +void export_Object( py::module & m ) +{ + py::class_< TNL::Object >( m, "Object" ) + // TODO: make it abstract class in Python + .def("save", (bool (TNL::Object::*)(const TNL::String &) const) &TNL::Object::save) + .def("load", (bool (TNL::Object::*)(const TNL::String &)) &TNL::Object::load) + .def("boundLoad", (bool (TNL::Object::*)(const TNL::String &)) &TNL::Object::boundLoad) + // FIXME: why does it not work? +// .def("save", py::overload_cast<TNL::File>(&TNL::Object::save, py::const_)) +// .def("load", py::overload_cast<TNL::File>(&TNL::Object::load)) + .def("save", (bool (TNL::Object::*)(TNL::File &) const) &TNL::Object::save) + .def("load", (bool (TNL::Object::*)(TNL::File &)) &TNL::Object::load) + ; +} diff --git a/src/Python/pytnl/tnl/SparseMatrix.cpp b/src/Python/pytnl/tnl/SparseMatrix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e6584998313fa9e3c1314c6f67b99267815cf0a8 --- /dev/null +++ b/src/Python/pytnl/tnl/SparseMatrix.cpp @@ -0,0 +1,29 @@ +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include "SparseMatrix.h" + +#include <TNL/Matrices/CSR.h> +#include <TNL/Matrices/Ellpack.h> +#include <TNL/Matrices/SlicedEllpack.h> + +using CSR_host = TNL::Matrices::CSR< double, TNL::Devices::Host, int >; +using CSR_cuda = TNL::Matrices::CSR< double, TNL::Devices::Cuda, int >; +using E_host = TNL::Matrices::Ellpack< double, TNL::Devices::Host, int >; +using E_cuda = TNL::Matrices::Ellpack< double, TNL::Devices::Cuda, int >; +using SE_host = TNL::Matrices::SlicedEllpack< double, TNL::Devices::Host, int >; +using SE_cuda = TNL::Matrices::SlicedEllpack< double, TNL::Devices::Cuda, int >; + +void export_SparseMatrices( py::module & m ) +{ + export_Matrix< CSR_host >( m, "CSR" ); + export_Matrix< E_host >( m, "Ellpack" ); + export_Matrix< SE_host >( m, "SlicedEllpack" ); + + m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< CSR_host, E_host >); + m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< E_host, CSR_host >); + m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< CSR_host, SE_host >); + m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< SE_host, CSR_host >); + m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< E_host, SE_host >); + m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< SE_host, E_host >); +} diff --git a/src/Python/pytnl/tnl/SparseMatrix.h b/src/Python/pytnl/tnl/SparseMatrix.h new file mode 100644 index 0000000000000000000000000000000000000000..5d278ae8a17fc204f51b39652cc5dfe735c28dca --- /dev/null +++ b/src/Python/pytnl/tnl/SparseMatrix.h @@ -0,0 +1,113 @@ +#pragma once + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +#include <TNL/String.h> +#include <TNL/Containers/Vector.h> +#include <TNL/Matrices/CSR.h> + +template< typename Matrix > +struct SpecificExports +{ + template< typename Scope > + static void exec( Scope & s ) {} +}; + +template< typename Real, typename Device, typename Index > +struct SpecificExports< TNL::Matrices::CSR< Real, Device, Index > > +{ + template< typename Scope > + static void exec( Scope & s ) + { + using Matrix = TNL::Matrices::CSR< Real, Device, Index >; + + s.def("getRowPointers", py::overload_cast<>(&Matrix::getRowPointers), py::return_value_policy::reference_internal); + s.def("getColumnIndexes", py::overload_cast<>(&Matrix::getColumnIndexes), py::return_value_policy::reference_internal); + s.def("getValues", py::overload_cast<>(&Matrix::getValues), py::return_value_policy::reference_internal); + } +}; + +template< typename MatrixRow > +void export_MatrixRow( py::module & m, const char* name ) +{ + // guard against duplicate to-Python converters for the same type + static bool defined = false; + if( ! defined ) { + py::class_< MatrixRow >( m, name ) + .def("setElement", &MatrixRow::setElement) + .def("getElementColumn", &MatrixRow::getElementColumn, py::return_value_policy::reference_internal) + .def("getElementValue", &MatrixRow::getElementValue, py::return_value_policy::reference_internal) +// .def(py::self_ns::str(py::self_ns::self)) + ; + defined = true; + } +} + +template< typename Matrix > +void export_Matrix( py::module & m, const char* name ) +{ + typename Matrix::MatrixRow (Matrix::* _getRow)(typename Matrix::IndexType) = &Matrix::getRow; + + using VectorType = TNL::Containers::Vector< typename Matrix::RealType, typename Matrix::DeviceType, typename Matrix::IndexType >; + + auto matrix = py::class_< Matrix, TNL::Object >( m, name ) + .def(py::init<>()) + // overloads (defined in Object) + .def_static("getType", &Matrix::getType) + .def("getTypeVirtual", &Matrix::getTypeVirtual) + .def_static("getSerializationType", &Matrix::getSerializationType) + .def("getSerializationTypeVirtual", &Matrix::getSerializationTypeVirtual) + .def("print", &Matrix::print) + .def("__str__", []( Matrix & m ) { + std::stringstream ss; + ss << m; + return ss.str(); + } ) + + // Matrix + .def("setDimensions", &Matrix::setDimensions) + .def("setCompressedRowLengths", &Matrix::setCompressedRowLengths) + .def("getRowLength", &Matrix::getRowLength) + .def("getCompressedRowLengths", &Matrix::getCompressedRowLengths) + // TODO: export for more types + .def("setLike", &Matrix::template setLike< typename Matrix::RealType, typename Matrix::DeviceType, typename Matrix::IndexType >) + .def("getNumberOfMatrixElements", &Matrix::getNumberOfMatrixElements) + .def("getNumberOfNonzeroMatrixElements", &Matrix::getNumberOfNonzeroMatrixElements) + .def("reset", &Matrix::reset) + .def("getRows", &Matrix::getRows) + .def("getColumns", &Matrix::getColumns) + .def("setElement", &Matrix::setElement) + .def("addElement", &Matrix::addElement) + // setRow and addRow operate on pointers + //.def("setRow", &Matrix::setRow) + //.def("addRow", &Matrix::addRow) + .def("getElement", &Matrix::getElement) + // TODO: operator== and operator!= are general and very slow + + // Sparse + .def("getMaxRowLength", &Matrix::getMaxRowLength) + .def("getPaddingIndex", &Matrix::getPaddingIndex) + // TODO: this one is empty in the C++ code +// .def("printStructure", &Matrix::printStructure) + + // specific to each format, but with common interface + .def("getRow", _getRow) + // TODO: export for more types + .def("rowVectorProduct", &Matrix::template rowVectorProduct< VectorType >) + .def("vectorProduct", &Matrix::template vectorProduct< VectorType, VectorType >) + // TODO: these two don't work + //.def("addMatrix", &Matrix::addMatrix) + //.def("getTransposition", &Matrix::getTransposition) + .def("performSORIteration", &Matrix::template performSORIteration< VectorType >) +// .def("assign", &Matrix::operator=) + .def("assign", []( Matrix& matrix, const Matrix& other ) -> Matrix& { + return matrix = other; + }) + ; + + // export format-specific methods + SpecificExports< Matrix >::exec( matrix ); + + export_MatrixRow< typename Matrix::MatrixRow >( m, "MatrixRow" ); +} diff --git a/src/Python/pytnl/tnl/StaticVector.h b/src/Python/pytnl/tnl/StaticVector.h new file mode 100644 index 0000000000000000000000000000000000000000..53197af56195fa0c22dceba6e05bcc7e3b6b9319 --- /dev/null +++ b/src/Python/pytnl/tnl/StaticVector.h @@ -0,0 +1,43 @@ +#pragma once + +#include <pybind11/pybind11.h> +#include <pybind11/operators.h> +namespace py = pybind11; + +#include "../tnl_indexing.h" + +// needed for discovery of operator<< for tnlStaticArray +#include <TNL/Containers/StaticArray.h> + +template< typename VectorType, typename Scope > +void export_StaticVector( Scope & scope, const char* name ) +{ + using RealType = typename VectorType::RealType; + + auto vector = py::class_<VectorType>(scope, name) + .def(py::init< typename VectorType::RealType >()) + .def(py::init< VectorType >()) + .def_static("getType", &VectorType::getType) + .def("getSize", &VectorType::getSize) + .def("assign", &VectorType::operator=) + .def(py::self == py::self) + .def(py::self != py::self) + .def("setValue", &VectorType::setValue) + // TODO: pybind11 + // explicit namespace resolution is necessary, see http://stackoverflow.com/a/3084341/4180822 +// .def(py::self_ns::str(py::self)) + .def(py::self += py::self) + .def(py::self -= py::self) + .def(py::self *= typename VectorType::RealType()) + .def(py::self + py::self) + .def(py::self - py::self) + .def(py::self * typename VectorType::RealType()) + .def(py::self * py::self) + .def(py::self < py::self) + .def(py::self > py::self) + .def(py::self <= py::self) + .def(py::self >= py::self) + ; + + tnl_indexing< VectorType >( vector ); +} diff --git a/src/Python/pytnl/tnl/String.cpp b/src/Python/pytnl/tnl/String.cpp new file mode 100644 index 0000000000000000000000000000000000000000..309a6fe25fdafae45c672cd321ad851a55f57056 --- /dev/null +++ b/src/Python/pytnl/tnl/String.cpp @@ -0,0 +1,41 @@ +#include <pybind11/pybind11.h> +#include <pybind11/operators.h> +namespace py = pybind11; + +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include <TNL/String.h> +#include <TNL/File.h> + +void export_String( py::module & m ) +{ + // function pointers for overloaded methods +// const char* (TNL::String::* _String_getString)() const = &TNL::String::getString; + bool (TNL::String::* _String_save)(TNL::File &) const = &TNL::String::save; + bool (TNL::String::* _String_load)(TNL::File &) = &TNL::String::load; + + py::class_<TNL::String>(m, "String") + .def(py::init<const char*>()) + .def(py::init<const char*, int>()) + .def(py::init<const char*, int, int>()) + .def(py::init<int>()) + .def(py::init<double>()) + .def_static("getType", &TNL::String::getType) + // __str__ (uses operator<<) + // explicit namespace resolution is necessary, see http://stackoverflow.com/a/3084341/4180822 +// .def(py::self_ns::str(py::self_ns::self)) + // TODO: operator[] +// .def(vector_indexing_suite<TNL::String>()) + .def(py::self + py::self) + .def(py::self += py::self) + .def(py::self == py::self) + .def(py::self != py::self) + .def("getLength", &TNL::String::getLength) + .def("__len__", &TNL::String::getLength) + // FIXME +// .def("replace", &TNL::String::replace) + .def("save", _String_save) + .def("load", _String_load) + ; +} diff --git a/src/Python/pytnl/tnl/Vector.h b/src/Python/pytnl/tnl/Vector.h new file mode 100644 index 0000000000000000000000000000000000000000..7f4232e1bc48954750bacf7c47f4da5b23301dee --- /dev/null +++ b/src/Python/pytnl/tnl/Vector.h @@ -0,0 +1,52 @@ +#pragma once + +#include <pybind11/pybind11.h> +#include <pybind11/operators.h> +namespace py = pybind11; + +#include <TNL/Containers/Vector.h> + +template< typename ArrayType, typename VectorType > +void export_Vector(py::module & m, const char* name) +{ + // function pointers for overloaded methods + void (VectorType::* _addElement1)(const typename VectorType::IndexType, + const typename VectorType::RealType &) + = &VectorType::addElement; + void (VectorType::* _addElement2)(const typename VectorType::IndexType, + const typename VectorType::RealType &, + const typename VectorType::RealType &) + = &VectorType::addElement; + + py::class_<VectorType, ArrayType>(m, name) + .def(py::init<>()) + .def(py::init<int>()) + .def_static("getType", &VectorType::getType) + .def("getTypeVirtual", &VectorType::getTypeVirtual) + .def_static("getSerializationType", &VectorType::getSerializationType) + .def("getSerializationTypeVirtual", &VectorType::getSerializationTypeVirtual) + .def("addElement", _addElement1) + .def("addElement", _addElement2) + .def(py::self == py::self) + .def(py::self != py::self) + .def(py::self += py::self) + .def(py::self -= py::self) + .def(py::self *= typename VectorType::RealType()) + .def(py::self /= typename VectorType::RealType()) + .def("max", &VectorType::max) + .def("min", &VectorType::min) + .def("absMax", &VectorType::absMax) + .def("absMin", &VectorType::absMin) + .def("lpNorm", &VectorType::template lpNorm<double, double>) + .def("sum", &VectorType::template sum<double>) + .def("differenceMax", &VectorType::template differenceMax<VectorType>) + .def("differenceMin", &VectorType::template differenceMin<VectorType>) + .def("differenceAbsMax", &VectorType::template differenceAbsMax<VectorType>) + .def("differenceAbsMin", &VectorType::template differenceAbsMin<VectorType>) + .def("differenceLpNorm", &VectorType::template differenceLpNorm<double, VectorType, double>) + .def("differenceSum", &VectorType::template differenceSum<double, VectorType>) + .def("scalarProduct", &VectorType::template scalarProduct<VectorType>) + .def("addVector", &VectorType::template addVector<VectorType>) + .def("addVectors", &VectorType::template addVectors<VectorType>) + ; +} diff --git a/src/Python/pytnl/tnl/tnl.cpp b/src/Python/pytnl/tnl/tnl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0eb7c3e8b0aee48791a546e36291f4790c9ca8a9 --- /dev/null +++ b/src/Python/pytnl/tnl/tnl.cpp @@ -0,0 +1,47 @@ +#include "../exceptions.h" +#include "../typedefs.h" + +// conversions have to be registered for each object file +#include "../tnl_conversions.h" + +#include "Array.h" +#include "Vector.h" + +// external functions +void export_Object( py::module & m ); +void export_String( py::module & m ); +void export_Grid1D( py::module & m ); +void export_Grid2D( py::module & m ); +void export_Grid3D( py::module & m ); +void export_Meshes( py::module & m ); +void export_SparseMatrices( py::module & m ); + +template< typename T > +using _array = TNL::Containers::Array< T, TNL::Devices::Host, IndexType >; + +template< typename T > +using _vector = TNL::Containers::Vector< T, TNL::Devices::Host, IndexType >; + +// Python module definition +PYBIND11_MODULE(tnl, m) +{ + register_exceptions(m); + + export_Object(m); + // TODO: TNL::File + export_String(m); + + export_Array< _array<double> >(m, "Array"); + export_Vector< _array<double>, _vector<double> >(m, "Vector"); + export_Array< _array<int> >(m, "Array_int"); + export_Vector< _array<int>, _vector<int> >(m, "Vector_int"); + export_Array< _array<bool> >(m, "Array_bool"); + + export_Grid1D(m); + export_Grid2D(m); + export_Grid3D(m); + + export_Meshes(m); + + export_SparseMatrices(m); +} diff --git a/src/Python/pytnl/tnl_conversions.h b/src/Python/pytnl/tnl_conversions.h new file mode 100644 index 0000000000000000000000000000000000000000..602d1cffd1ccd32660b72630c023f2d913f1da19 --- /dev/null +++ b/src/Python/pytnl/tnl_conversions.h @@ -0,0 +1,3 @@ +// conversion has to be registered for each object file +#include "tnl_str_conversion.h" +#include "tnl_tuple_conversion.h" diff --git a/src/Python/pytnl/tnl_indexing.h b/src/Python/pytnl/tnl_indexing.h new file mode 100644 index 0000000000000000000000000000000000000000..29663d66b553d8095ca0a67f980b346fac04e712 --- /dev/null +++ b/src/Python/pytnl/tnl_indexing.h @@ -0,0 +1,81 @@ +#pragma once + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +#include "RawIterator.h" + +template< typename Array, typename Scope > +void tnl_indexing( Scope & scope ) +{ + using Index = typename Array::IndexType; + using Element = typename Array::ElementType; + + scope.def("__len__", &Array::getSize); + + scope.def("__iter__", + []( Array& array ) { + return py::make_iterator( + RawIterator<Element>(array.getData()), + RawIterator<Element>(array.getData() + array.getSize()) ); + }, + py::keep_alive<0, 1>() // keep array alive while iterator is used + ); + + scope.def("__getitem__", + [](Array &a, Index i) { + if (i >= a.getSize()) + throw py::index_error(); + return a[i]; + } + ); + + scope.def("__setitem__", + [](Array &a, Index i, const Element& e) { + if (i >= a.getSize()) + throw py::index_error(); + a[i] = e; + } + ); +} + +template< typename Array, typename Scope > +void tnl_slice_indexing( Scope & scope ) +{ + /// Slicing protocol + scope.def("__getitem__", + [](const Array& a, py::slice slice) -> Array* { + size_t start, stop, step, slicelength; + + if (!slice.compute(a.getSize(), &start, &stop, &step, &slicelength)) + throw py::error_already_set(); + + Array* seq = new Array(); + seq->setSize(slicelength); + + for (size_t i = 0; i < slicelength; ++i) { + seq->operator[](i) = a[start]; + start += step; + } + return seq; + }, + "Retrieve list elements using a slice object" + ); + + scope.def("__setitem__", + [](Array& a, py::slice slice, const Array& value) { + size_t start, stop, step, slicelength; + if (!slice.compute(a.getSize(), &start, &stop, &step, &slicelength)) + throw py::error_already_set(); + + if (slicelength != value.getSize()) + throw std::runtime_error("Left and right hand size of slice assignment have different sizes!"); + + for (size_t i = 0; i < slicelength; ++i) { + a[start] = value[i]; + start += step; + } + }, + "Assign list elements using a slice object" + ); +} diff --git a/src/Python/pytnl/tnl_str_conversion.h b/src/Python/pytnl/tnl_str_conversion.h new file mode 100644 index 0000000000000000000000000000000000000000..b62886e58a201d30b8d52abba5e3306d203bbd31 --- /dev/null +++ b/src/Python/pytnl/tnl_str_conversion.h @@ -0,0 +1,51 @@ +#pragma once + +#include <pybind11/pybind11.h> +namespace py = pybind11; + +#include <TNL/String.h> + +namespace pybind11 { namespace detail { + + template <> + struct type_caster<TNL::String> + { + using StdStringCaster = type_caster<std::string>; + StdStringCaster _caster; + + public: + /** + * This macro establishes the name 'TNL::String' in + * function signatures and declares a local variable + * 'value' of type TNL::String + */ + PYBIND11_TYPE_CASTER(TNL::String, _("TNL::String")); + + /** + * Conversion part 1 (Python->C++): convert a PyObject into a TNL::String + * instance or return false upon failure. The second argument + * indicates whether implicit conversions should be applied. + */ + bool load(handle src, bool implicit) + { + if( ! _caster.load(src, implicit) ) + return false; + const std::string& str = (std::string&) _caster; + value = TNL::String(str.c_str()); + return true; + } + + /** + * Conversion part 2 (C++ -> Python): convert an TNL::String instance into + * a Python object. The second and third arguments are used to + * indicate the return value policy and parent object (for + * ``return_value_policy::reference_internal``) and are generally + * ignored by implicit casters. + */ + static handle cast(TNL::String src, return_value_policy policy, handle parent) + { + return StdStringCaster::cast( src.getString(), policy, parent ); + } + }; + +}} // namespace pybind11::detail diff --git a/src/Python/pytnl/tnl_tuple_conversion.h b/src/Python/pytnl/tnl_tuple_conversion.h new file mode 100644 index 0000000000000000000000000000000000000000..f4ca8045ea18bfd7e9d40a75d3201533628e662f --- /dev/null +++ b/src/Python/pytnl/tnl_tuple_conversion.h @@ -0,0 +1,79 @@ +#pragma once + +#include <pybind11/pybind11.h> +#include <pybind11/stl.h> +namespace py = pybind11; + +#include <TNL/Containers/StaticArray.h> +#include <TNL/Containers/StaticVector.h> + +namespace pybind11 { namespace detail { + + template< typename ArrayType > + struct _tnl_tuple_caster + { + using Value = typename std::remove_reference< decltype(ArrayType()[0]) >::type; + using StdArray = std::array< Value, ArrayType::size >; + using StdArrayCaster = type_caster< StdArray >; +// StdArrayCaster _caster; + using value_conv = make_caster<Value>; + + public: +// PYBIND11_TYPE_CASTER(ArrayType, StdArrayCaster::name); + PYBIND11_TYPE_CASTER(ArrayType, _("Tuple[") + value_conv::name + _<false>(_(""), _("[") + _<ArrayType::size>() + _("]")) + _("]")); + + /** + * Conversion part 1 (Python -> C++): convert a PyObject into an ArrayType + * instance or return false upon failure. The second argument indicates + * whether implicit conversions should be applied. + */ + bool load(handle src, bool implicit) + { + // we don't use StdArrayCaster here because we want to convert Python tuples, not lists +// if( ! _caster.load(src, implicit) ) +// return false; +// const StdArray& arr = (StdArray&) _caster; +// for( int i = 0; i < ArrayType::size; i++ ) +// value[ i ] = arr[ i ]; +// return true; + + if (!isinstance<tuple>(src)) + return false; + auto t = reinterpret_borrow<tuple>(src); + if (t.size() != ArrayType::size) + return false; + size_t ctr = 0; + for (auto it : t) { + value_conv conv; + if (!conv.load(it, implicit)) + return false; + value[ctr++] = cast_op<Value &&>(std::move(conv)); + } + return true; + } + + /** + * Conversion part 2 (C++ -> Python): convert an ArrayType instance into + * a Python object. The second and third arguments are used to + * indicate the return value policy and parent object (for + * ``return_value_policy::reference_internal``) and are generally + * ignored by implicit casters. + */ + static handle cast(const ArrayType& src, return_value_policy policy, handle parent) + { + StdArray arr; + for( int i = 0; i < ArrayType::size; i++ ) + arr[ i ] = src[ i ]; + return StdArrayCaster::cast( arr, policy, parent ); + } + }; + + template< typename T, int Size > + struct type_caster< TNL::Containers::StaticArray< Size, T > > + : _tnl_tuple_caster< TNL::Containers::StaticArray< Size, T > > {}; + + template< typename T, int Size > + struct type_caster< TNL::Containers::StaticVector< Size, T > > + : _tnl_tuple_caster< TNL::Containers::StaticVector< Size, T > > {}; + +}} // namespace pybind11::detail diff --git a/src/Python/pytnl/typedefs.h b/src/Python/pytnl/typedefs.h new file mode 100644 index 0000000000000000000000000000000000000000..b06693ab66ee0afb901aea469a347231bf68beae --- /dev/null +++ b/src/Python/pytnl/typedefs.h @@ -0,0 +1,42 @@ +#pragma once + +#include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/DefaultConfig.h> +#include <TNL/Meshes/Topologies/Edge.h> +#include <TNL/Meshes/Topologies/Triangle.h> +#include <TNL/Meshes/Topologies/Tetrahedron.h> + +using RealType = double; +using DeviceType = TNL::Devices::Host; +using IndexType = int; + +using Grid1D = TNL::Meshes::Grid<1, RealType, DeviceType, IndexType>; +using Grid2D = TNL::Meshes::Grid<2, RealType, DeviceType, IndexType>; +using Grid3D = TNL::Meshes::Grid<3, RealType, DeviceType, IndexType>; + +using LocalIndexType = short int; +using EdgeTopology = TNL::Meshes::Topologies::Edge; +using TriangleTopology = TNL::Meshes::Topologies::Triangle; +using TetrahedronTopology = TNL::Meshes::Topologies::Tetrahedron; +using MeshOfEdges = TNL::Meshes::Mesh< TNL::Meshes::DefaultConfig< + EdgeTopology, + EdgeTopology::dimension, + RealType, + IndexType, + LocalIndexType, + IndexType > >; +using MeshOfTriangles = TNL::Meshes::Mesh< TNL::Meshes::DefaultConfig< + TriangleTopology, + TriangleTopology::dimension, + RealType, + IndexType, + LocalIndexType, + IndexType > >; +using MeshOfTetrahedrons = TNL::Meshes::Mesh< TNL::Meshes::DefaultConfig< + TetrahedronTopology, + TetrahedronTopology::dimension, + RealType, + IndexType, + LocalIndexType, + IndexType > >; diff --git a/src/TNL/CMakeLists.txt b/src/TNL/CMakeLists.txt index b2b23f89251dfe02bd21797818d74bdc0c4b1ff9..13113f9c3fa6b04c3e485eb836e149f48a1c91d7 100644 --- a/src/TNL/CMakeLists.txt +++ b/src/TNL/CMakeLists.txt @@ -18,7 +18,7 @@ ADD_SUBDIRECTORY( legacy ) SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL ) -set( headers +set( headers Assert.h Constants.h CudaSharedMemory.h @@ -42,7 +42,7 @@ set( headers Timer.h UniquePointer.h ) -set( common_SOURCES +set( common_SOURCES File.cpp FileName.cpp Object.cpp @@ -50,7 +50,7 @@ set( common_SOURCES SmartPointersRegister.cpp String.cpp Timer.cpp ) - + set( tnl_SOURCES ${tnl_config_SOURCES} ${tnl_containers_SOURCES} ${tnl_devices_SOURCES} @@ -63,8 +63,8 @@ set( tnl_SOURCES ${tnl_config_SOURCES} ${tnl_solvers_SOURCES} ${tnl_core_SOURCES} - ${tnl_legacy_SOURCES} - + ${tnl_legacy_SOURCES} + ${common_SOURCES} ) set( tnl_CUDA__SOURCES ${tnl_config_CUDA__SOURCES} @@ -82,52 +82,56 @@ set( tnl_CUDA__SOURCES ${tnl_config_CUDA__SOURCES} ${tnl_core_CUDA__SOURCES} ${tnl_legacy_CUDA__SOURCES} ${common_SOURCES} ) - - + + +ADD_LIBRARY( tnl_static STATIC ${tnl_SOURCES} ) +INSTALL( TARGETS tnl_static DESTINATION lib ) + if( BUILD_CUDA ) CUDA_ADD_LIBRARY( tnl SHARED ${tnl_CUDA__SOURCES} - OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} ) - if( HAVE_CUBLAS ) - CUDA_ADD_CUBLAS_TO_TARGET( tnl ) - endif( HAVE_CUBLAS ) + OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} ) + # the static library with CUDA support has to be built separately + CUDA_ADD_LIBRARY( tnl-cuda_static STATIC ${tnl_CUDA__SOURCES} ) + INSTALL( TARGETS tnl-cuda_static DESTINATION lib ) else( BUILD_CUDA ) - ADD_LIBRARY( tnl SHARED - ${tnl_SOURCES} ) + ADD_LIBRARY( tnl SHARED ${tnl_SOURCES} ) #ifMIC #TARGET_COMPILE_DEFINITIONS( tnl PUBLIC -DHAVE_MIC ) -endif( BUILD_CUDA ) - -SET_TARGET_PROPERTIES( tnl PROPERTIES +endif( BUILD_CUDA ) + +SET_TARGET_PROPERTIES( tnl PROPERTIES VERSION ${tnlVersion} ) -TARGET_LINK_LIBRARIES( tnl - ${DCMTK_LIBRARIES}) +TARGET_LINK_LIBRARIES( tnl + ${DCMTK_LIBRARIES} ) INSTALL( TARGETS tnl DESTINATION lib ) IF( BUILD_MPI ) - + + ADD_LIBRARY( tnl-mpi_static STATIC ${tnl_SOURCES} ) + INSTALL( TARGETS tnl-mpi_static DESTINATION lib ) + if( BUILD_CUDA ) - CUDA_ADD_LIBRARY( tnl-mpi-${tnlVersion} SHARED ${tnl_CUDA__SOURCES} - OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} ) - if( HAVE_CUBLAS ) - CUDA_ADD_CUBLAS_TO_TARGET( tnl-mpi-${tnlVersion} ) - endif( HAVE_CUBLAS ) + CUDA_ADD_LIBRARY( tnl-mpi SHARED ${tnl_CUDA__SOURCES} + OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} ) + # the static library with CUDA support has to be built separately + CUDA_ADD_LIBRARY( tnl-mpi-cuda_static STATIC ${tnl_CUDA__SOURCES} ) + INSTALL( TARGETS tnl-mpi-cuda_static DESTINATION lib ) else( BUILD_CUDA ) - ADD_LIBRARY( tnl-mpi-${tnlVersion} SHARED - ${tnl_SOURCES} ) - endif( BUILD_CUDA ) - - SET_TARGET_PROPERTIES( tnl-mpi-${tnlVersion} PROPERTIES - VERSION ${tnlVersion} ) -# SET_TARGET_PROPERTIES( tnl-mpi-${tnlVersion} + ADD_LIBRARY( tnl-mpi SHARED ${tnl_SOURCES} ) + endif( BUILD_CUDA ) + + SET_TARGET_PROPERTIES( tnl-mpi PROPERTIES + VERSION ${tnlVersion} ) +# SET_TARGET_PROPERTIES( tnl-mpi # LINK_INTERFACE_LIBRARIES "") - - TARGET_LINK_LIBRARIES( tnl-mpi-${tnlVersion} + + TARGET_LINK_LIBRARIES( tnl-mpi ${MPI_LIBRARIES} ) - INSTALL( TARGETS tnl-mpi-${tnlVersion} DESTINATION lib ) - -ENDIF() + INSTALL( TARGETS tnl-mpi DESTINATION lib ) + +endif() INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY} ) diff --git a/src/TNL/Containers/Algorithms/CMakeLists.txt b/src/TNL/Containers/Algorithms/CMakeLists.txt index 49e5a36567c973cbd8543b31ddccad085558bd3c..a8c9bf7699f129c21c4930df090af5c7d5910325 100644 --- a/src/TNL/Containers/Algorithms/CMakeLists.txt +++ b/src/TNL/Containers/Algorithms/CMakeLists.txt @@ -6,7 +6,6 @@ set( headers ArrayOperations.h ArrayOperationsMIC_impl.h cuda-prefix-sum.h cuda-prefix-sum_impl.h - CublasWrapper.h CudaMultireductionKernel.h CudaReductionBuffer.h CudaReductionKernel.h diff --git a/src/TNL/Containers/Algorithms/CublasWrapper.h b/src/TNL/Containers/Algorithms/CublasWrapper.h deleted file mode 100644 index bb6572c93b6d37a938646d9bd7d9943952b1e768..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/Algorithms/CublasWrapper.h +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - CublasWraper.h - description - ------------------- - begin : Apr 7, 2015 - copyright : (C) 2015 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#if defined HAVE_CUBLAS && defined HAVE_CUDA -#include <cublas_v2.h> -#endif - -namespace TNL { -namespace Containers { -namespace Algorithms { - -template< typename Real1, - typename Real2, - typename Index > -class CublasWraper -{ - public: - static bool dot( const Real1* v1, const Real2* v2, const Index size, Real1& result) - { - return false; - } -}; - -#if defined HAVE_CUBLAS && defined HAVE_CUDA - -template< typename Index > -class CublasWraper< float, float, Index > -{ - public: - static bool dot( const float* v1, const float* v2, const Index size, float& result) - { - - cublasHandle_t handle; - cublasCreate( &handle ); - cublasSdot( handle, size, v1, 1, v2, 1, &result ); - cublasDestroy( handle ); - return false; - } -}; - -template< typename Index > -class CublasWraper< double, double, Index > -{ - public: - static bool dot( const double* v1, const double* v2, const Index size, double& result) - { - cublasHandle_t handle; - cublasCreate( &handle ); - cublasDdot( handle, size, v1, 1, v2, 1, &result ); - cublasDestroy( handle ); - return false; - } -}; -#endif - -} // namespace Algorithms -} // namespace Containers -} // namespace TNL - diff --git a/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h b/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h index e5c21b232a6946710e9ab3e69ec1dcbd40687abe..64846317c486f6f852e2abeeef79c184b7fb0b76 100644 --- a/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h +++ b/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h @@ -14,7 +14,6 @@ #include <TNL/Exceptions/CudaSupportMissing.h> #include <TNL/Containers/Algorithms/VectorOperations.h> #include <TNL/Containers/Algorithms/cuda-prefix-sum.h> -#include <TNL/Containers/Algorithms/CublasWrapper.h> namespace TNL { namespace Containers { @@ -426,12 +425,6 @@ getScalarProduct( const Vector1& v1, TNL_ASSERT_EQ( v1.getSize(), v2.getSize(), "The vector sizes must be the same." ); Real result( 0 ); -/*#if defined HAVE_CUBLAS && defined HAVE_CUDA - if( CublasWraper< typename Vector1::RealType, - typename Vector2::RealType, - typename Vector1::IndexType >::dot( v1.getData(), v1.getData(), v1.getSize(), result ) ) - return result; -#endif*/ Algorithms::ParallelReductionScalarProduct< typename Vector1::RealType, typename Vector2::RealType > operation; Reduction< Devices::Cuda >::reduce( operation, v1.getSize(), diff --git a/src/TNL/Containers/ArrayIO.h b/src/TNL/Containers/ArrayIO.h index 0c0ea62eead463311bb2843bbbe42de1ba9f2127..0b79cf9d1db0444f81dea124ca61b7d5f1e41f3e 100644 --- a/src/TNL/Containers/ArrayIO.h +++ b/src/TNL/Containers/ArrayIO.h @@ -10,7 +10,9 @@ #pragma once -#include <TNL/Containers/DynamicTypeTag.h> +#include <type_traits> + +#include <TNL/Object.h> #include <TNL/File.h> namespace TNL { @@ -19,7 +21,7 @@ namespace Containers { template< typename Element, typename Device, typename Index, - bool DynamicType = DynamicTypeTag< Element >::value > + bool Elementwise = std::is_base_of< Object, Element >::value > class ArrayIO {}; diff --git a/src/TNL/Containers/CMakeLists.txt b/src/TNL/Containers/CMakeLists.txt index 4beb1159a8eed5eefce3cd1dedd7c4d2f37af4e5..83991f2456b97146284701ab82d5a8927b3e9ab5 100644 --- a/src/TNL/Containers/CMakeLists.txt +++ b/src/TNL/Containers/CMakeLists.txt @@ -1,24 +1,25 @@ ADD_SUBDIRECTORY( Algorithms ) +ADD_SUBDIRECTORY( Multimaps ) set( headers Array.h Array_impl.h ArrayIO.h - DynamicTypeTag.h IndexedMap.h IndexedMap_impl.h IndexedSet.h IndexedSet_impl.h + UnorderedIndexedSet.h + UnorderedIndexedSet_impl.h List.h List_impl.h MultiArray.h MultiArray1D_impl.h MultiArray2D_impl.h MultiArray3D_impl.h - MultiArray4D_impl.h + MultiArray4D_impl.h SharedArray.h SharedArray_impl.h - ConstSharedArray.h - StaticArray.h + StaticArray.h StaticArray_impl.h StaticArray1D_impl.h StaticArray2D_impl.h @@ -32,23 +33,23 @@ set( headers Array.h MultiVector4D_impl.h SharedVector.h SharedVector_impl.h - StaticVector.h + StaticVector.h StaticVector_impl.h StaticVector1D_impl.h StaticVector2D_impl.h StaticVector3D_impl.h ) SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Containers ) -set( common_SOURCES +set( common_SOURCES ${CURRENT_DIR}/SharedArray_impl.cpp ${CURRENT_DIR}/MultiArray_impl.cpp ${CURRENT_DIR}/Array_impl.cpp - ${CURRENT_DIR}/StaticArray_impl.cpp + ${CURRENT_DIR}/StaticArray_impl.cpp ${CURRENT_DIR}/MultiVector_impl.cpp ${CURRENT_DIR}/SharedVector_impl.cpp ${CURRENT_DIR}/Vector_impl.cpp ${CURRENT_DIR}/StaticVector_impl.cpp -) +) IF( BUILD_CUDA ) set( tnl_containers_CUDA__SOURCES @@ -58,12 +59,12 @@ IF( BUILD_CUDA ) ${CURRENT_DIR}/MultiArray_impl.cu ${CURRENT_DIR}/StaticArray_impl.cu ${CURRENT_DIR}/Vector_impl.cu - ${CURRENT_DIR}/StaticVector_impl.cu + ${CURRENT_DIR}/StaticVector_impl.cu PARENT_SCOPE ) -ENDIF() +ENDIF() -set( tnl_containers_SOURCES +set( tnl_containers_SOURCES ${common_SOURCES} PARENT_SCOPE ) - + INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Containers ) diff --git a/src/TNL/Containers/ConstSharedArray.h b/src/TNL/Containers/ConstSharedArray.h deleted file mode 100644 index ec719634f604e95ac92f06ca2259f6990972ba2e..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/ConstSharedArray.h +++ /dev/null @@ -1,119 +0,0 @@ -/*************************************************************************** - tnlConstSharedArray.h - description - ------------------- - begin : Feb 13, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/Object.h> - -// Forward declarations -namespace TNL { - class File; - -namespace Devices -{ - class Host; -} - -namespace Containers { - - -template< typename Element, typename Device, typename Index > -class Array; - -template< typename Element, - typename Device = Devices::Host, - typename Index = int > -class tnlConstSharedArray : public Object -{ - public: - - typedef Element ElementType; - typedef Device DeviceType; - typedef Index IndexType; - typedef tnlConstSharedArray< Element, Devices::Host, Index > HostType; - typedef tnlConstSharedArray< Element, Devices::Cuda, Index > CudaType; - - tnlConstSharedArray(); - - static String getType(); - - String getTypeVirtual() const; - - static String getSerializationType(); - - virtual String getSerializationTypeVirtual() const; - - void bind( const Element* _data, - const Index _size ); - - template< typename Array > - void bind( const Array& array, - IndexType index = 0, - IndexType size = 0 ); - - void swap( tnlConstSharedArray< Element, Device, Index >& array ); - - void reset(); - - __cuda_callable__ Index getSize() const; - - Element getElement( Index i ) const; - - __cuda_callable__ const Element& operator[] ( Index i ) const; - - tnlConstSharedArray< Element, Device, Index >& operator = ( const tnlConstSharedArray< Element, Device, Index >& array ); - - template< typename Array > - tnlConstSharedArray< Element, Device, Index >& operator = ( const Array& array ); - - template< typename Array > - bool operator == ( const Array& array ) const; - - template< typename Array > - bool operator != ( const Array& array ) const; - - __cuda_callable__ const Element* getData() const; - - /**** - * Returns true if non-zero size is set. - */ - operator bool() const; - - //! This method measures data transfers done by this vector. - /*! - * Every time one touches this grid touches * size * sizeof( Real ) bytes are added - * to transfered bytes in tnlStatistics. - */ - template< typename IndexType2 = Index > - void touch( IndexType2 touches = 1 ) const; - - //! Method for saving the object to a file as a binary data. - bool save( File& file ) const; - - bool save( const String& fileName ) const; - - protected: - - //!Number of allocated elements - Index size; - - //! Pointer to allocated data - const Element* data; -}; - -template< typename Element, typename Device, typename Index > -std::ostream& operator << ( std::ostream& str, const tnlConstSharedArray< Element, Device, Index >& v ); - -} // namespace Containers -} // namespace TNL - -#include <TNL/Containers/ConstSharedArray_impl.h> - - diff --git a/src/TNL/Containers/ConstSharedArray_impl.h b/src/TNL/Containers/ConstSharedArray_impl.h deleted file mode 100644 index fde53b35807267d85495f34d0d90ca38f69ba358..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/ConstSharedArray_impl.h +++ /dev/null @@ -1,312 +0,0 @@ -/*************************************************************************** - tnlConstSharedArray_impl.h - description - ------------------- - begin : Feb 13, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <iostream> -#include <TNL/File.h> -#include <TNL/Containers/Array.h> -#include <TNL/Containers/Algorithms/ArrayOperations.h> -#include <TNL/Math.h> -#include <TNL/param-types.h> - -namespace TNL { -namespace Containers { - -template< typename Element, - typename Device, - typename Index > -tnlConstSharedArray< Element, Device, Index > :: tnlConstSharedArray() -: size( 0 ), data( 0 ) -{ -}; - -template< typename Element, - typename Device, - typename Index > -String tnlConstSharedArray< Element, Device, Index > :: getType() -{ - return String( "tnlConstSharedArray< " ) + ", " + - TNL::getType< Element >() + ", " + - Device::getDeviceType() + ", " + - TNL::getType< Index >() + " >"; -}; - -template< typename Element, - typename Device, - typename Index > -String tnlConstSharedArray< Element, Device, Index > :: getTypeVirtual() const -{ - return this->getType(); -}; - -template< typename Element, - typename Device, - typename Index > -String tnlConstSharedArray< Element, Device, Index > :: getSerializationType() -{ - return Array< Element, Device, Index >::getSerializationType(); -}; - -template< typename Element, - typename Device, - typename Index > -String tnlConstSharedArray< Element, Device, Index > :: getSerializationTypeVirtual() const -{ - return this->getSerializationType(); -}; - -template< typename Element, - typename Device, - typename Index > -void tnlConstSharedArray< Element, Device, Index > :: bind( const Element* data, - const Index size ) -{ - TNL_ASSERT( size >= 0, - std::cerr << "You try to set size of tnlConstSharedArray to negative value." - << "New size: " << size << std::endl ); - TNL_ASSERT( data != 0, - std::cerr << "You try to use null pointer to data for tnlConstSharedArray." ); - - this->size = size; - this->data = data; -}; - -template< typename Element, - typename Device, - typename Index > - template< typename Array > -void tnlConstSharedArray< Element, Device, Index > :: bind( const Array& array, - IndexType index, - IndexType size ) -{ - // TODO: This does not work for static arrays. - //tnlStaticTNL_ASSERT( Array::DeviceType::DeviceType == DeviceType::DeviceType, - // "Attempt to bind arrays between different devices." ); - this->data = &( array. getData()[ index ] ); - if( ! size ) - this->size = array. getSize(); - else - this->size = size; - -}; - -template< typename Element, - typename Device, - typename Index > -void tnlConstSharedArray< Element, Device, Index > :: swap( tnlConstSharedArray< Element, Device, Index >& array ) -{ - swap( this->size, array. size ); - swap( this->data, array. data ); -}; - -template< typename Element, - typename Device, - typename Index > -void tnlConstSharedArray< Element, Device, Index > :: reset() -{ - this->size = 0; - this->data = 0; -}; - -template< typename Element, - typename Device, - typename Index > -__cuda_callable__ -Index tnlConstSharedArray< Element, Device, Index > :: getSize() const -{ - return this->size; -} - -template< typename Element, - typename Device, - typename Index > -Element tnlConstSharedArray< Element, Device, Index > :: getElement( Index i ) const -{ - TNL_ASSERT( 0 <= i && i < this->getSize(), - std::cerr << "Wrong index for getElement method in tnlConstSharedArray with name " - << " index is " << i - << " and array size is " << this->getSize() ); - return Algorithms::ArrayOperations< Device >::getMemoryElement( &( this->data[ i ] ) ); -}; - -template< typename Element, - typename Device, - typename Index > -__cuda_callable__ -const Element& tnlConstSharedArray< Element, Device, Index > :: operator[] ( Index i ) const -{ - TNL_ASSERT( 0 <= i && i < this->getSize(), - std::cerr << "Wrong index for operator[] in tnlConstSharedArray with name " - << " index is " << i - << " and array size is " << this->getSize() ); - // TODO: add static assert - this does not make sense for Devices::CudaDevice - return Algorithms::ArrayOperations< Device >::getArrayElementReference( this->data, i ); -}; - -template< typename Element, - typename Device, - typename Index > -tnlConstSharedArray< Element, Device, Index >& - tnlConstSharedArray< Element, Device, Index > :: operator = ( const tnlConstSharedArray< Element, Device, Index >& array ) -{ - this->bind( array ); - return ( *this ); -}; - -template< typename Element, - typename Device, - typename Index > - template< typename Array > -tnlConstSharedArray< Element, Device, Index >& tnlConstSharedArray< Element, Device, Index > :: operator = ( const Array& array ) -{ - this->bind( array ); - return ( *this ); -}; - -template< typename Element, - typename Device, - typename Index > - template< typename Array > -bool tnlConstSharedArray< Element, Device, Index > :: operator == ( const Array& array ) const -{ - if( array. getSize() != this->getSize() ) - return false; - return Algorithms::ArrayOperations< Device, typename Array :: DeviceType >:: - template compareMemory< typename Array :: ElementType, - Element, - typename Array :: IndexType > - ( this->getData(), - array. getData(), - array. getSize() ); -} - -template< typename Element, - typename Device, - typename Index > - template< typename Array > -bool tnlConstSharedArray< Element, Device, Index > :: operator != ( const Array& array ) const -{ - return ! ( ( *this ) == array ); -} - -template< typename Element, - typename Device, - typename Index > -const Element* tnlConstSharedArray< Element, Device, Index > :: getData() const -{ - return this->data; -} - -template< typename Element, - typename Device, - typename Index > -tnlConstSharedArray< Element, Device, Index > :: operator bool() const -{ - return data != 0; -}; - - -template< typename Element, - typename Device, - typename Index > - template< typename IndexType2 > -void tnlConstSharedArray< Element, Device, Index > :: touch( IndexType2 touches ) const -{ - //TODO: implement -}; - -template< typename Element, - typename Device, - typename Index > -bool tnlConstSharedArray< Element, Device, Index > :: save( File& file ) const -{ - TNL_ASSERT( this->size != 0, - std::cerr << "You try to save empty array." ); - if( ! Object :: save( file ) ) - return false; - if( ! file. write( &this->size ) ) - return false; - if( ! file. write< Element, Device, Index >( this->data, this->size ) ) - { - std::cerr << "I was not able to WRITE tnlConstSharedArray " - << " with size " << this->getSize() << std::endl; - return false; - } - return true; -}; - -template< typename Element, - typename Device, - typename Index > -bool tnlConstSharedArray< Element, Device, Index > :: save( const String& fileName ) const -{ - return Object :: save( fileName ); -}; - -template< typename Element, typename Device, typename Index > -std::ostream& operator << ( std::ostream& str, const tnlConstSharedArray< Element, Device, Index >& v ) -{ - str << "[ "; - if( v.getSize() > 0 ) - { - str << v.getElement( 0 ); - for( Index i = 1; i < v.getSize(); i++ ) - str << ", " << v. getElement( i ); - } - str << " ]"; - return str; -} - -#ifdef TEMPLATE_EXPLICIT_INSTANTIATION - -#ifdef INSTANTIATE_FLOAT -extern template class tnlConstSharedArray< float, Devices::Host, int >; -#endif -extern template class tnlConstSharedArray< double, Devices::Host, int >; -#ifdef INSTANTIATE_LONG_DOUBLE -extern template class tnlConstSharedArray< long double, Devices::Host, int >; -#endif - -#ifdef INSTANTIATE_LONG_INT -#ifdef INSTANTIATE_FLOAT -extern template class tnlConstSharedArray< float, Devices::Host, long int >; -#endif -extern template class tnlConstSharedArray< double, Devices::Host, long int >; -#ifdef INSTANTIATE_LONG_DOUBLE -extern template class tnlConstSharedArray< long double, Devices::Host, long int >; -#endif -#endif - -#ifdef HAVE_CUDA -#ifdef INSTANTIATE_FLOAT -extern template class tnlConstSharedArray< float, Devices::Cuda, int >; -#endif -extern template class tnlConstSharedArray< double, Devices::Cuda, int >; -#ifdef INSTANTIATE_LONG_DOUBLE -extern template class tnlConstSharedArray< long double, Devices::Cuda, int >; -#endif - -#ifdef INSTANTIATE_LONG_INT -#ifdef INSTANTIATE_FLOAT -extern template class tnlConstSharedArray< float, Devices::Cuda, long int >; -#endif -extern template class tnlConstSharedArray< double, Devices::Cuda, long int >; -#ifdef INSTANTIATE_LONG_DOUBLE -extern template class tnlConstSharedArray< long double, Devices::Cuda, long int >; -#endif - -#endif -#endif - -#endif - -} // namespace Containers -} // namespace TNL diff --git a/src/TNL/Containers/DynamicTypeTag.h b/src/TNL/Containers/DynamicTypeTag.h deleted file mode 100644 index 40b7bbee35f853fbbb13033b270d8e800ad9112f..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/DynamicTypeTag.h +++ /dev/null @@ -1,23 +0,0 @@ -/*************************************************************************** - DynamicTypeTag.h - description - ------------------- - begin : Mar 13, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -namespace TNL { -namespace Containers { - -template< typename Element > -struct DynamicTypeTag -{ - enum { value = false }; -}; - -} // namespace Containers -} // namespace TNL diff --git a/src/TNL/Containers/IndexedMap_impl.h b/src/TNL/Containers/IndexedMap_impl.h index 2adb8872cd488d1ea2448024cff3521928b531a4..488b3b93bcc4716bec28375232130f21d62a58a2 100644 --- a/src/TNL/Containers/IndexedMap_impl.h +++ b/src/TNL/Containers/IndexedMap_impl.h @@ -57,9 +57,9 @@ template< typename Element, template<typename ArrayType> void IndexedMap< Element, Index, Key >::toArray( ArrayType& array ) const { - Assert( array.getSize() == getSize(), - std::cerr << "array.getSize() = " << array.getSize() - << " getSize() = " << getSize() ); + TNL_ASSERT( array.getSize() == getSize(), + std::cerr << "array.getSize() = " << array.getSize() + << " getSize() = " << getSize() ); for( STDMapIteratorType iter = map.begin(); iter != map.end(); diff --git a/src/TNL/Containers/Multimaps/CMakeLists.txt b/src/TNL/Containers/Multimaps/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..921c735f7bb71c2aca64027f0b70aecde34cf7c6 --- /dev/null +++ b/src/TNL/Containers/Multimaps/CMakeLists.txt @@ -0,0 +1,11 @@ +SET( headers EllpackIndexMultimap.h + EllpackIndexMultimap_impl.h + EllpackIndexMultimapValues.h + EllpackIndexMultimapValues_impl.h + StaticEllpackIndexMultimap.h + StaticEllpackIndexMultimap_impl.h + StaticEllpackIndexMultimapValues.h + StaticEllpackIndexMultimapValues_impl.h + MultimapPermutationApplier.h ) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Containers/Multimaps ) diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h new file mode 100644 index 0000000000000000000000000000000000000000..3cc3b365969fceef76cf23e197d522c12ea9eef2 --- /dev/null +++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h @@ -0,0 +1,111 @@ +/*************************************************************************** + EllpackIndexMultimap.h - description + ------------------- + begin : Sep 9, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Containers/Vector.h> +#include <TNL/Containers/Multimaps/EllpackIndexMultimapValues.h> + +namespace TNL { + +template< typename Device > +struct EllpackIndexMultimapSliceSizeGetter +{ + static constexpr int SliceSize = 1; +}; + +template<> +struct EllpackIndexMultimapSliceSizeGetter< Devices::Cuda > +{ + static constexpr int SliceSize = 32; +}; + +template< typename Index = int, + typename Device = Devices::Host, + typename LocalIndex = Index, + int SliceSize = EllpackIndexMultimapSliceSizeGetter< Device >::SliceSize > +class EllpackIndexMultimap + : public Object +{ + public: + using DeviceType = Device; + using IndexType = Index; + using LocalIndexType = LocalIndex; + using ValuesAccessorType = EllpackIndexMultimapValues< IndexType, DeviceType, LocalIndexType, SliceSize >; + using ConstValuesAccessorType = EllpackIndexMultimapValues< const IndexType, DeviceType, LocalIndexType, SliceSize >; + using ValuesAllocationVectorType = Containers::Vector< LocalIndexType, DeviceType, IndexType >; + + EllpackIndexMultimap() = default; + + template< typename Device_ > + EllpackIndexMultimap( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other ); + + template< typename Device_ > + EllpackIndexMultimap& operator=( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other ); + + static String getType(); + + String getTypeVirtual() const; + + void setKeysRange( const IndexType& keysRange ); + + __cuda_callable__ + const IndexType getKeysRange() const; + + void allocate( const LocalIndexType& maxValuesCount ); + + void allocate( const ValuesAllocationVectorType& valuesCounts ); + + template< typename Device_, int SliceSize_ > + void setLike( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize_ >& other ); + + __cuda_callable__ + ValuesAccessorType getValues( const IndexType& inputIndex ); + + __cuda_callable__ + ConstValuesAccessorType getValues( const IndexType& inputIndex ) const; + + bool operator==( const EllpackIndexMultimap& other ) const; + + bool save( File& file ) const; + + bool load( File& file ); + + using Object::load; + + using Object::save; + + void print( std::ostream& str ) const; + + protected: + Containers::Vector< IndexType, DeviceType, IndexType > values; + ValuesAllocationVectorType valuesCounts; + + IndexType keysRange = 0; + LocalIndexType maxValuesCount = 0; + + __cuda_callable__ + IndexType getAllocationKeysRange( IndexType keysRange ) const; + + // friend class is needed for templated assignment operators + template< typename Index_, typename Device_, typename LocalIndex_, int SliceSize_ > + friend class EllpackIndexMultimap; +}; + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >& multimap ); + +} // namespace TNL + +#include <TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h> + diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h new file mode 100644 index 0000000000000000000000000000000000000000..87364c5f79d6b3ffcbbfe744b72cd53a0ab17dbd --- /dev/null +++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h @@ -0,0 +1,118 @@ +/*************************************************************************** + EllpackIndexMultimapValues.h - description + ------------------- + begin : Sep 10, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <type_traits> +#include <ostream> + +#include <TNL/Devices/Cuda.h> + +namespace TNL { + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +class EllpackIndexMultimap; + +template< typename Index, + typename Device, + typename LocalIndex, + int step = 1 > +class EllpackIndexMultimapValues +{ + public: + using DeviceType = Device; + using IndexType = Index; + using LocalIndexType = LocalIndex; + using NetworkType = EllpackIndexMultimap< IndexType, DeviceType, LocalIndexType, step >; + + __cuda_callable__ + EllpackIndexMultimapValues(); + + __cuda_callable__ + EllpackIndexMultimapValues( EllpackIndexMultimapValues&& other ); + + __cuda_callable__ + EllpackIndexMultimapValues& operator=( const EllpackIndexMultimapValues& ); + + // converting assignment, needed for 'const int' -> 'int' etc. + template< typename Index_, typename LocalIndex_, int step_ > + __cuda_callable__ + EllpackIndexMultimapValues& operator=( const EllpackIndexMultimapValues< Index_, Device, LocalIndex_, step_ >& other ); + + __cuda_callable__ + EllpackIndexMultimapValues& operator=( EllpackIndexMultimapValues&& other ); + + __cuda_callable__ + void bind( const EllpackIndexMultimapValues& other ); + + __cuda_callable__ + void setSize( const LocalIndexType& portsCount ); + + __cuda_callable__ + LocalIndexType getSize() const; + + __cuda_callable__ + LocalIndexType getAllocatedSize() const; + + __cuda_callable__ + void setValue( const LocalIndexType& portIndex, + const IndexType& value ); + + __cuda_callable__ + IndexType getValue( const LocalIndexType& portIndex ) const; + + __cuda_callable__ + IndexType& operator[]( const LocalIndexType& portIndex ); + + __cuda_callable__ + const IndexType& operator[]( const LocalIndexType& portIndex ) const; + + __cuda_callable__ + bool operator==( const EllpackIndexMultimapValues& other ) const; + + __cuda_callable__ + bool operator!=( const EllpackIndexMultimapValues& other ) const; + + void print( std::ostream& str ) const; + + protected: + using ValuesCountType = typename std::conditional< std::is_const< IndexType >::value, + typename std::add_const< LocalIndexType >::type, + LocalIndexType >::type; + + __cuda_callable__ + EllpackIndexMultimapValues( IndexType* values, + ValuesCountType* valuesCount, + const LocalIndexType& allocatedSize ); + + IndexType* values; + + ValuesCountType* valuesCount; + + // TODO: this is useless for a const-accessor (without setSize etc.) + LocalIndexType allocatedSize; + + friend EllpackIndexMultimap< IndexType, DeviceType, LocalIndexType, step >; + friend EllpackIndexMultimap< typename std::remove_const< IndexType >::type, DeviceType, LocalIndexType, step >; +}; + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device, LocalIndex, step >& ports ); + +} // namespace TNL + +#include <TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h> + diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..9585741513a212d91d28c027f440752655eac07c --- /dev/null +++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h @@ -0,0 +1,290 @@ +/*************************************************************************** + EllpackIndexMultimapValues_impl.h - description + ------------------- + begin : Sep 10, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include "EllpackIndexMultimapValues.h" + +#include <TNL/Assert.h> + +namespace TNL { + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +EllpackIndexMultimapValues() +: values( nullptr ), valuesCount( nullptr ), allocatedSize( 0 ) +{ +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +EllpackIndexMultimapValues( EllpackIndexMultimapValues&& other ) +: values( other.values ), valuesCount( other.valuesCount ), allocatedSize( other.allocatedSize ) +{ + other.values = nullptr; + other.valuesCount = nullptr; + other.allocatedSize = 0; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +EllpackIndexMultimapValues( IndexType* values, + ValuesCountType* valuesCount, + const LocalIndexType& allocatedSize ) +: values( values ), valuesCount( valuesCount ), allocatedSize( allocatedSize ) +{ + TNL_ASSERT( *(this->valuesCount) <= allocatedSize, ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >& +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +operator=( const EllpackIndexMultimapValues& other ) +{ + TNL_ASSERT( this->getAllocatedSize() >= other.getSize(), ); + this->setSize( other.getSize() ); + if( this->values != other.values ) { + for( LocalIndexType i = 0; i < this->getSize(); i++ ) + this->setValue( i, other[ i ] ); + } + return *this; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > + template< typename Index_, typename LocalIndex_, int step_ > +__cuda_callable__ +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >& +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +operator=( const EllpackIndexMultimapValues< Index_, Device, LocalIndex_, step_ >& other ) +{ + TNL_ASSERT( this->getAllocatedSize() >= other.getSize(), ); + this->setSize( other.getSize() ); + for( LocalIndexType i = 0; i < this->getSize(); i++ ) + this->setValue( i, other[ i ] ); + return *this; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >& +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +operator=( EllpackIndexMultimapValues&& other ) +{ + this->values = other.values; + this->valuesCount = other.valuesCount; + this->allocatedSize = other.allocatedSize; + other.values = nullptr; + other.valuesCount = nullptr; + other.allocatedSize = 0; + return *this; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +void +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +bind( const EllpackIndexMultimapValues& other ) +{ + this->values = other.values; + this->valuesCount = other.valuesCount; + this->allocatedSize = other.allocatedSize; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +void +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +setSize( const LocalIndexType& size ) +{ + TNL_ASSERT( this->valuesCount, + std::cerr << "Uninitialized 'valuesCount' pointer in EllpackIndexMultimapValues." << std::endl; ); + TNL_ASSERT( size >= 0 && size <= this->allocatedSize, + std::cerr << "size = " << size << ", allocatedSize = " << this->allocatedSize << std::endl; ); + *valuesCount = size; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +LocalIndex +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +getSize() const +{ + if( ! valuesCount ) + return 0; + return *valuesCount; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +LocalIndex +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +getAllocatedSize() const +{ + return this->allocatedSize; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +void +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +setValue( const LocalIndexType& portIndex, + const IndexType& value ) +{ + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + this->values[ portIndex * step ] = value; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +Index +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +getValue( const LocalIndexType& portIndex ) const +{ + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + return this->values[ portIndex * step ]; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +Index& +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +operator[]( const LocalIndexType& portIndex ) +{ + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + return this->values[ portIndex * step ]; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +const Index& +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +operator[]( const LocalIndexType& portIndex ) const +{ + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + return this->values[ portIndex * step ]; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +bool +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +operator==( const EllpackIndexMultimapValues& other ) const +{ + if( this->getSize() != other.getSize() ) + return false; + for( LocalIndexType i = 0; i < this->getSize(); i++ ) + if( this->operator[]( i ) != other[ i ] ) + return false; + return true; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +bool +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +operator!=( const EllpackIndexMultimapValues& other ) const +{ + return ! ( *this == other ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +void +EllpackIndexMultimapValues< Index, Device, LocalIndex, step >:: +print( std::ostream& str ) const +{ + str << "[ "; + if( this->getSize() > 0 ) + { + str << this->getValue( 0 ); + for( typename std::remove_const< Index >::type i = 1; i < this->getSize(); i++ ) + str << ", " << this->getValue( i ); + } + str << " ]"; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int step > +std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device, LocalIndex, step >& ports ) +{ + ports.print( str ); + return str; +} + +} // namespace TNL + diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..5c10152a7dabf7bb3dca6ce11578fdbe8d3509ac --- /dev/null +++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h @@ -0,0 +1,319 @@ +/*************************************************************************** + EllpackIndexMultimap_impl.h - description + ------------------- + begin : Sep 9, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h> + +namespace TNL { + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > + template< typename Device_ > +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +EllpackIndexMultimap( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other ) +{ + operator=( other ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > + template< typename Device_ > +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >& +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +operator=( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other ) +{ + values = other.values; + valuesCounts = other.valuesCounts; + keysRange = other.keysRange; + maxValuesCount = other.maxValuesCount; + return *this; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +String +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +getType() +{ + return String( "EllpackIndexMultimap< ") + + String( TNL::getType< Index >() ) + + String( ", " ) + + Device :: getDeviceType() + + String( ", " ) + + String( TNL::getType< LocalIndexType >() ) + + String( " >" ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +String +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +getTypeVirtual() const +{ + return this->getType(); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +void +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +setKeysRange( const IndexType& keysRange ) +{ + TNL_ASSERT( keysRange >= 0, ); + this->keysRange = keysRange; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +const Index +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +getKeysRange() const +{ + return this->keysRange; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +void +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +allocate( const LocalIndexType& maxValuesCount ) +{ + TNL_ASSERT( maxValuesCount >= 0, ); + this->maxValuesCount = maxValuesCount; + const IndexType ldSize = getAllocationKeysRange( this->getKeysRange() ); + this->values.setSize( ldSize * this->maxValuesCount ); + this->valuesCounts.setSize( this->getKeysRange() ); + this->valuesCounts.setValue( maxValuesCount ); + + // extra cost at initialization, which allows to have much simpler operator== + values.setValue( 0 ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +void +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +allocate( const ValuesAllocationVectorType& valuesCounts ) +{ + TNL_ASSERT( valuesCounts.getSize() == this->keysRange, + std::cerr << "valuesCounts.getSize() = " << valuesCounts.getSize() + << "this->keysRange = " << this->keysRange + << std::endl; ); + this->maxValuesCount = valuesCounts.max(); + + TNL_ASSERT( this->maxValuesCount >= 0, + std::cerr << "this->maxValuesCount = " << this->maxValuesCount << std::endl; ); + const IndexType ldSize = getAllocationKeysRange( this->getKeysRange() ); + this->values.setSize( ldSize * this->maxValuesCount ); + this->valuesCounts.setSize( this->getKeysRange() ); + this->valuesCounts = valuesCounts; + + // extra cost at initialization, which allows to have much simpler operator== + values.setValue( 0 ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > + template< typename Device_, int SliceSize_ > +void +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +setLike( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize_ >& other ) +{ + const IndexType ldSize = getAllocationKeysRange( other.getKeysRange() ); + values.setSize( ldSize * other.maxValuesCount ); + valuesCounts.setLike( other.valuesCounts ); + valuesCounts = other.valuesCounts; + keysRange = other.keysRange; + maxValuesCount = other.maxValuesCount; + + // extra cost at initialization, which allows to have much simpler operator== + values.setValue( 0 ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +typename EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::ValuesAccessorType +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +getValues( const IndexType& inputIndex ) +{ + TNL_ASSERT( inputIndex < this->getKeysRange(), + std::cerr << "inputIndex = " << inputIndex << std::endl + << "this->getKeysRange() = " << this->getKeysRange() + << std::endl; ); + TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * this->maxValuesCount == this->values.getSize() && this->getKeysRange() == this->valuesCounts.getSize(), + std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl + << "this->getKeysRange() = " << this->getKeysRange() << std::endl + << "this->maxValuesCount = " << this->maxValuesCount << std::endl + << "this->values.getSize() = " << this->values.getSize() << std::endl + << "this->valuesCounts.getSize() = " << this->valuesCounts.getSize() << std::endl; ); + const IndexType sliceIdx = inputIndex / SliceSize; + const IndexType sliceOffset = sliceIdx * SliceSize * this->maxValuesCount; + const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize; + return ValuesAccessorType( &this->values[ offset ], &this->valuesCounts[ inputIndex ], this->maxValuesCount ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +typename EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::ConstValuesAccessorType +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +getValues( const IndexType& inputIndex ) const +{ + TNL_ASSERT( inputIndex < this->getKeysRange(), + std::cerr << "inputIndex = " << inputIndex << std::endl + << "this->getKeysRange() = " << this->getKeysRange() + << std::endl; ); + TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * this->maxValuesCount == this->values.getSize() && this->getKeysRange() == this->valuesCounts.getSize(), + std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl + << "this->getKeysRange() = " << this->getKeysRange() << std::endl + << "this->maxValuesCount = " << this->maxValuesCount << std::endl + << "this->values.getSize() = " << this->values.getSize() << std::endl + << "this->valuesCounts.getSize() = " << this->valuesCounts.getSize() << std::endl; ); + const IndexType sliceIdx = inputIndex / SliceSize; + const IndexType sliceOffset = sliceIdx * SliceSize * this->maxValuesCount; + const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize; + return ConstValuesAccessorType( &this->values[ offset ], &this->valuesCounts[ inputIndex ], this->maxValuesCount ); +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +bool +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +operator==( const EllpackIndexMultimap& other ) const +{ +// if( ! ( this->keysRange == other.keysRange && +// this->maxValuesCount == other.maxValuesCount && +// this->valuesCounts == other.valuesCounts ) ) +// return false; +// // compare values for each key separately - the sizes may vary +// for( IndexType i = 0; i < this->keysRange; i++ ) +// if( this->getValues( i ) != other.getValues( i ) ) +// return false; +// return true; + + // we assume that invalid entries in the ellpack format are always 0 + return this->keysRange == other.keysRange && + this->maxValuesCount == other.maxValuesCount && + this->valuesCounts == other.valuesCounts && + this->values == other.values; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +bool +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +save( File& file ) const +{ + if( ! Object::save( file ) ) + return false; + if( ! file.write( &this->keysRange ) ) + return false; + if( ! file.write( &this->maxValuesCount ) ) + return false; + if( ! this->values.save( file ) ) + return false; + if( ! this->valuesCounts.save( file ) ) + return false; + return true; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +bool +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +load( File& file ) +{ + if( ! Object::load( file ) ) + return false; + if( ! file.read( &this->keysRange ) ) + return false; + if( ! file.read( &this->maxValuesCount ) ) + return false; + if( ! this->values.load( file ) ) + return false; + if( ! this->valuesCounts.load( file ) ) + return false; + return true; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +void +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +print( std::ostream& str ) const +{ + str << "[ "; + if( this->getKeysRange() > 0 ) + { + str << this->getValues( 0 ); + for( Index i = 1; i < this->getKeysRange(); i++ ) + str << ",\n " << this->getValues( i ); + } + str << " ]"; +} + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +Index +EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >:: +getAllocationKeysRange( IndexType keysRange ) const +{ + return SliceSize * roundUpDivision( keysRange, SliceSize ); +} + + +template< typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >& multimap ) +{ + multimap.print( str ); + return str; +} + +} // namespace TNL + diff --git a/src/TNL/Containers/Multimaps/MultimapPermutationApplier.h b/src/TNL/Containers/Multimaps/MultimapPermutationApplier.h new file mode 100644 index 0000000000000000000000000000000000000000..b459b660d9303a7d66c81dc3aa17a6df74a0466c --- /dev/null +++ b/src/TNL/Containers/Multimaps/MultimapPermutationApplier.h @@ -0,0 +1,86 @@ +/*************************************************************************** + IndexPermutationApplier.h - description + ------------------- + begin : Mar 10, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/DevicePointer.h> +#include <TNL/ParallelFor.h> + +namespace TNL { + +template< typename Multimap, + typename PermutationVector > +void permuteMultimapKeys( Multimap& multimap, const PermutationVector& perm ) +{ + static_assert( std::is_same< typename Multimap::DeviceType, typename PermutationVector::DeviceType >::value, + "The multimap and permutation vector must be stored on the same device." ); + using IndexType = typename Multimap::IndexType; + using DeviceType = typename Multimap::DeviceType; + TNL_ASSERT( multimap.getKeysRange() == perm.getSize(), + std::cerr << "multimap keys range is " << multimap.getKeysRange() + << ", permutation size is " << perm.getSize() << std::endl; ); + + // create temporary multimap for the permuted data + Multimap multimapCopy; + multimapCopy.setLike( multimap ); + + // kernel to permute the rows of multimap into multimapCopy + auto kernel = [] __cuda_callable__ + ( IndexType i, + const Multimap* multimap, + Multimap* multimapCopy, + const typename PermutationVector::RealType* perm ) + { + const auto srcValues = multimap->getValues( perm[ i ] ); + auto destValues = multimapCopy->getValues( i ); + destValues = srcValues; + }; + + DevicePointer< Multimap > multimapPointer( multimap ); + DevicePointer< Multimap > multimapCopyPointer( multimapCopy ); + + ParallelFor< DeviceType >::exec( (IndexType) 0, multimap.getKeysRange(), + kernel, + &multimapPointer.template getData< DeviceType >(), + &multimapCopyPointer.template modifyData< DeviceType >(), + perm.getData() ); + + // copy the permuted data back into the multimap + multimap = multimapCopy; +} + +template< typename Multimap, + typename PermutationVector > +void permuteMultimapValues( Multimap& multimap, const PermutationVector& iperm ) +{ + static_assert( std::is_same< typename Multimap::DeviceType, typename PermutationVector::DeviceType >::value, + "The multimap and permutation vector must be stored on the same device." ); + using IndexType = typename Multimap::IndexType; + using DeviceType = typename Multimap::DeviceType; + + // kernel to permute the multimap values + auto kernel = [] __cuda_callable__ + ( IndexType i, + Multimap* multimap, + const typename PermutationVector::RealType* iperm ) + { + auto values = multimap->getValues( i ); + for( typename Multimap::LocalIndexType v = 0; v < values.getSize(); v++ ) + values[ v ] = iperm[ values[ v ] ]; + }; + + DevicePointer< Multimap > multimapPointer( multimap ); + ParallelFor< DeviceType >::exec( (IndexType) 0, multimap.getKeysRange(), + kernel, + &multimapPointer.template modifyData< DeviceType >(), + iperm.getData() ); +} + +} // namespace TNL diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h new file mode 100644 index 0000000000000000000000000000000000000000..85f013369828b60098efab5e5653797ec823757a --- /dev/null +++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h @@ -0,0 +1,108 @@ +/*************************************************************************** + StaticEllpackIndexMultimap.h - description + ------------------- + begin : Sep 9, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Containers/Vector.h> +#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h> + +namespace TNL { + +template< typename Device > +struct StaticEllpackIndexMultimapSliceSizeGetter +{ + static constexpr int SliceSize = 1; +}; + +template<> +struct StaticEllpackIndexMultimapSliceSizeGetter< Devices::Cuda > +{ + static constexpr int SliceSize = 32; +}; + +template< int ValuesCount, + typename Index = int, + typename Device = Devices::Host, + typename LocalIndex = Index, + int SliceSize = StaticEllpackIndexMultimapSliceSizeGetter< Device >::SliceSize > +class StaticEllpackIndexMultimap + : public Object +{ + public: + using DeviceType = Device; + using IndexType = Index; + using LocalIndexType = LocalIndex; + using ValuesAccessorType = StaticEllpackIndexMultimapValues< ValuesCount, IndexType, DeviceType, LocalIndexType, SliceSize >; + using ConstValuesAccessorType = StaticEllpackIndexMultimapValues< ValuesCount, const IndexType, DeviceType, LocalIndexType, SliceSize >; + + StaticEllpackIndexMultimap() = default; + + template< typename Device_ > + StaticEllpackIndexMultimap( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other ); + + template< typename Device_ > + StaticEllpackIndexMultimap& operator=( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other ); + + static String getType(); + + String getTypeVirtual() const; + + void setKeysRange( const IndexType& keysRange ); + + __cuda_callable__ + const IndexType getKeysRange() const; + + void allocate(); + + template< typename Device_ > + void setLike( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other ); + + __cuda_callable__ + ValuesAccessorType getValues( const IndexType& inputIndex ); + + __cuda_callable__ + ConstValuesAccessorType getValues( const IndexType& inputIndex ) const; + + bool operator==( const StaticEllpackIndexMultimap& other ) const; + + bool save( File& file ) const; + + bool load( File& file ); + + using Object::load; + + using Object::save; + + void print( std::ostream& str ) const; + + protected: + Containers::Vector< IndexType, DeviceType, IndexType > values; + + IndexType keysRange = 0; + + __cuda_callable__ + IndexType getAllocationKeysRange( IndexType keysRange ) const; + + // friend class is needed for templated assignment operators + template< int ValuesCount_, typename Index_, typename Device_, typename LocalIndex_, int SliceSize_ > + friend class StaticEllpackIndexMultimap; +}; + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >& multimap ); + +} // namespace TNL + +#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h> + diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h new file mode 100644 index 0000000000000000000000000000000000000000..5b69861c18d63f4fdfa60a0022ee5d145fdd306a --- /dev/null +++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h @@ -0,0 +1,105 @@ +/*************************************************************************** + StaticEllpackIndexMultimapValues.h - description + ------------------- + begin : Sep 10, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <type_traits> +#include <ostream> + +#include <TNL/Devices/Cuda.h> + +namespace TNL { + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +class StaticEllpackIndexMultimap; + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +class StaticEllpackIndexMultimapValues +{ + public: + using DeviceType = Device; + using IndexType = Index; + using LocalIndexType = LocalIndex; + using NetworkType = StaticEllpackIndexMultimap< ValuesCount, IndexType, DeviceType, LocalIndexType, step >; + + __cuda_callable__ + StaticEllpackIndexMultimapValues(); + + __cuda_callable__ + StaticEllpackIndexMultimapValues( StaticEllpackIndexMultimapValues&& other ); + + __cuda_callable__ + StaticEllpackIndexMultimapValues& operator=( const StaticEllpackIndexMultimapValues& other ); + + // converting assignment, needed for 'const int' -> 'int' etc. + template< typename Index_, typename LocalIndex_, int step_ > + __cuda_callable__ + StaticEllpackIndexMultimapValues& operator=( const StaticEllpackIndexMultimapValues< ValuesCount, Index_, Device, LocalIndex_, step_ >& other ); + + __cuda_callable__ + StaticEllpackIndexMultimapValues& operator=( StaticEllpackIndexMultimapValues&& other ); + + __cuda_callable__ + void bind( const StaticEllpackIndexMultimapValues& other ); + + constexpr LocalIndexType getSize() const; + + constexpr LocalIndexType getAllocatedSize() const; + + __cuda_callable__ + void setValue( const LocalIndexType& portIndex, + const IndexType& value ); + + __cuda_callable__ + IndexType getValue( const LocalIndexType& portIndex ) const; + + __cuda_callable__ + IndexType& operator[]( const LocalIndexType& portIndex ); + + __cuda_callable__ + const IndexType& operator[]( const LocalIndexType& portIndex ) const; + + __cuda_callable__ + bool operator==( const StaticEllpackIndexMultimapValues& other ) const; + + __cuda_callable__ + bool operator!=( const StaticEllpackIndexMultimapValues& other ) const; + + void print( std::ostream& str ) const; + + protected: + __cuda_callable__ + StaticEllpackIndexMultimapValues( IndexType* values ); + + IndexType* values; + + friend StaticEllpackIndexMultimap< ValuesCount, IndexType, DeviceType, LocalIndexType, step >; + friend StaticEllpackIndexMultimap< ValuesCount, typename std::remove_const< IndexType >::type, DeviceType, LocalIndexType, step >; +}; + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >& ports ); + +} // namespace TNL + +#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h> + diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..32ed4b137b94fae57e858e935dc42dd6f1333c1b --- /dev/null +++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h @@ -0,0 +1,282 @@ +/*************************************************************************** + StaticEllpackIndexMultimapValues_impl.h - description + ------------------- + begin : Sep 10, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include "StaticEllpackIndexMultimapValues.h" + +#include <TNL/Assert.h> + +namespace TNL { + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +StaticEllpackIndexMultimapValues() +: values( nullptr ) +{ +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +StaticEllpackIndexMultimapValues( StaticEllpackIndexMultimapValues&& other ) +: values( other.values ) +{ + other.values = nullptr; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +StaticEllpackIndexMultimapValues( IndexType* values ) +: values( values ) +{ +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >& +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +operator=( const StaticEllpackIndexMultimapValues& other ) +{ + if( this->values != other.values ) { + for( LocalIndexType i = 0; i < this->getSize(); i++ ) + this->setValue( i, other[ i ] ); + } + return *this; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > + template< typename Index_, typename LocalIndex_, int step_ > +__cuda_callable__ +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >& +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +operator=( const StaticEllpackIndexMultimapValues< ValuesCount, Index_, Device, LocalIndex_, step_ >& other ) +{ + for( LocalIndexType i = 0; i < this->getSize(); i++ ) + this->setValue( i, other[ i ] ); + return *this; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >& +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +operator=( StaticEllpackIndexMultimapValues&& other ) +{ + this->values = other.values; + other.values = nullptr; + return *this; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +void +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +bind( const StaticEllpackIndexMultimapValues& other ) +{ + this->values = other.values; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +constexpr LocalIndex +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +getSize() const +{ + return ValuesCount; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +constexpr LocalIndex +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +getAllocatedSize() const +{ + return ValuesCount; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +void +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +setValue( const LocalIndexType& portIndex, + const IndexType& value ) +{ + TNL_ASSERT( this->values, + std::cerr << "This instance is not bound to any multimap." << std::endl; ); + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + this->values[ portIndex * step ] = value; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +Index +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +getValue( const LocalIndexType& portIndex ) const +{ + TNL_ASSERT( this->values, + std::cerr << "This instance is not bound to any multimap." << std::endl; ); + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + return this->values[ portIndex * step ]; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +Index& +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +operator[]( const LocalIndexType& portIndex ) +{ + TNL_ASSERT( this->values, + std::cerr << "This instance is not bound to any multimap." << std::endl; ); + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + return this->values[ portIndex * step ]; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +const Index& +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +operator[]( const LocalIndexType& portIndex ) const +{ + TNL_ASSERT( this->values, + std::cerr << "This instance is not bound to any multimap." << std::endl; ); + TNL_ASSERT( portIndex < this->getSize(), + std::cerr << " portIndex = " << portIndex + << " getSize() = " << this->getSize() + << std::endl ); + return this->values[ portIndex * step ]; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +bool +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +operator==( const StaticEllpackIndexMultimapValues& other ) const +{ + if( this->values == other.values ) + return true; + if( ! this->values || ! other.values ) + return false; + for( LocalIndexType i = 0; i < this->getSize(); i++ ) + if( this->operator[]( i ) != other[ i ] ) + return false; + return true; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +__cuda_callable__ +bool +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +operator!=( const StaticEllpackIndexMultimapValues& other ) const +{ + return ! ( *this == other ); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +void +StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >:: +print( std::ostream& str ) const +{ + str << "[ "; + if( this->getSize() > 0 ) + { + str << this->getValue( 0 ); + for( typename std::remove_const< Index >::type i = 1; i < this->getSize(); i++ ) + str << ", " << this->getValue( i ); + } + str << " ]"; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int step > +std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >& ports ) +{ + ports.print( str ); + return str; +} + +} // namespace TNL + diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..a0c61fa08b508f1f5d75e46f77d7f085232fa032 --- /dev/null +++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h @@ -0,0 +1,274 @@ +/*************************************************************************** + StaticEllpackIndexMultimap_impl.h - description + ------------------- + begin : Sep 9, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h> + +namespace TNL { + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > + template< typename Device_ > +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +StaticEllpackIndexMultimap( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other ) +{ + operator=( other ); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > + template< typename Device_ > +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >& +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +operator=( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other ) +{ + values = other.values; + keysRange = other.keysRange; + return *this; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +String +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +getType() +{ + return String( "StaticEllpackIndexMultimap< ") + + String( TNL::getType< Index >() ) + + String( ", " ) + + Device :: getDeviceType() + + String( ", " ) + + String( TNL::getType< LocalIndexType >() ) + + String( " >" ); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +String +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +getTypeVirtual() const +{ + return this->getType(); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +void +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +setKeysRange( const IndexType& keysRange ) +{ + TNL_ASSERT( keysRange >= 0, ); + this->keysRange = keysRange; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +const Index +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +getKeysRange() const +{ + return this->keysRange; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +void +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +allocate() +{ + const IndexType ldSize = getAllocationKeysRange( this->getKeysRange() ); + values.setSize( ldSize * ValuesCount ); + + // extra cost at initialization, which allows to have much simpler operator== + values.setValue( 0 ); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > + template< typename Device_ > +void +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +setLike( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other ) +{ + const IndexType ldSize = getAllocationKeysRange( other.getKeysRange() ); + values.setSize( ldSize * ValuesCount ); + + // extra cost at initialization, which allows to have much simpler operator== + values.setValue( 0 ); + + keysRange = other.keysRange; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +typename StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::ValuesAccessorType +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +getValues( const IndexType& inputIndex ) +{ + TNL_ASSERT( inputIndex < this->getKeysRange(), + std::cerr << "inputIndex = " << inputIndex << std::endl + << "this->getKeysRange() = " << this->getKeysRange() << std::endl; ); + TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * ValuesCount == this->values.getSize(), + std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl + << "this->getKeysRange() = " << this->getKeysRange() << std::endl + << "this->values.getSize() = " << this->values.getSize() << std::endl; ); + const IndexType sliceIdx = inputIndex / SliceSize; + const IndexType sliceOffset = sliceIdx * SliceSize * ValuesCount; + const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize; + return ValuesAccessorType( &this->values[ offset ] ); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +typename StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::ConstValuesAccessorType +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +getValues( const IndexType& inputIndex ) const +{ + TNL_ASSERT( inputIndex < this->getKeysRange(), + std::cerr << "inputIndex = " << inputIndex << std::endl + << "this->getKeysRange() = " << this->getKeysRange() << std::endl; ); + TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * ValuesCount == this->values.getSize(), + std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl + << "this->getKeysRange() = " << this->getKeysRange() << std::endl + << "this->values.getSize() = " << this->values.getSize() << std::endl; ); + const IndexType sliceIdx = inputIndex / SliceSize; + const IndexType sliceOffset = sliceIdx * SliceSize * ValuesCount; + const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize; + return ConstValuesAccessorType( &this->values[ offset ] ); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +bool +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +operator==( const StaticEllpackIndexMultimap& other ) const +{ + return ( this->keysRange == other.keysRange && this->values == other.values ); +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +bool +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +save( File& file ) const +{ + if( ! Object::save( file ) ) + return false; + if( ! file.write( &this->keysRange ) ) + return false; + if( ! this->values.save( file ) ) + return false; + return true; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +bool +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +load( File& file ) +{ + if( ! Object::load( file ) ) + return false; + if( ! file.read( &this->keysRange ) ) + return false; + if( ! this->values.load( file ) ) + return false; + return true; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +void +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +print( std::ostream& str ) const +{ + str << "[ "; + if( this->getKeysRange() > 0 ) + { + str << this->getValues( 0 ); + for( Index i = 1; i < this->getKeysRange(); i++ ) + str << ",\n " << this->getValues( i ); + } + str << " ]"; +} + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +__cuda_callable__ +Index +StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >:: +getAllocationKeysRange( IndexType keysRange ) const +{ + return SliceSize * roundUpDivision( keysRange, SliceSize ); +} + + +template< int ValuesCount, + typename Index, + typename Device, + typename LocalIndex, + int SliceSize > +std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >& multimap ) +{ + multimap.print( str ); + return str; +} + +} // namespace TNL + diff --git a/src/TNL/Containers/UnorderedIndexedSet.h b/src/TNL/Containers/UnorderedIndexedSet.h new file mode 100644 index 0000000000000000000000000000000000000000..38a1e53937fabb7ca3de9e7e4c9f31a41b5adbe3 --- /dev/null +++ b/src/TNL/Containers/UnorderedIndexedSet.h @@ -0,0 +1,62 @@ +/*************************************************************************** + UnorderedIndexedSet.h - description + ------------------- + begin : Dec 12, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <unordered_map> +#include <ostream> + +namespace TNL { +namespace Containers { + +template< class Key, + class Index, + class Hash = std::hash< Key >, + class KeyEqual = std::equal_to< Key >, + class Allocator = std::allocator< std::pair<const Key, Index> > > +class UnorderedIndexedSet +{ +protected: + using map_type = std::unordered_map< Key, Index, Hash, KeyEqual, Allocator >; + map_type map; + +public: + using key_type = Key; + using index_type = Index; + using value_type = typename map_type::value_type; + using size_type = typename map_type::size_type; + using hasher = Hash; + using key_equal = KeyEqual; + + void clear(); + + size_type size() const; + + Index insert( const Key& key ); + + std::pair< Index, bool > try_insert( const Key& key ); + + bool find( const Key& key, Index& index ) const; + + size_type count( const Key& key ) const; + + size_type erase( const Key& key ); + + void print( std::ostream& str ) const; +}; + +template< typename Element, + typename Index > +std::ostream& operator <<( std::ostream& str, UnorderedIndexedSet< Element, Index >& set ); + +} // namespace Containers +} // namespace TNL + +#include <TNL/Containers/UnorderedIndexedSet_impl.h> diff --git a/src/TNL/Containers/UnorderedIndexedSet_impl.h b/src/TNL/Containers/UnorderedIndexedSet_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..4402ab55cca466c2c31f5c9f4704d94c33873395 --- /dev/null +++ b/src/TNL/Containers/UnorderedIndexedSet_impl.h @@ -0,0 +1,130 @@ +/*************************************************************************** + UnorderedIndexedSet_impl.h - description + ------------------- + begin : Feb 15, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Containers/UnorderedIndexedSet.h> + +namespace TNL { +namespace Containers { + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +void +UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::clear() +{ + map.clear(); +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type +UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size() const +{ + return map.size(); +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +Index +UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::insert( const Key& key ) +{ + auto iter = map.insert( value_type( key, size() ) ).first; + return iter->second; +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +std::pair< Index, bool > +UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::try_insert( const Key& key ) +{ + auto pair = map.insert( value_type( key, size() ) ); + return std::pair< Index, bool >{ pair.first->second, pair.second }; +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +bool +UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::find( const Key& key, Index& index ) const +{ + auto iter = map.find( Key( key ) ); + if( iter == map.end() ) + return false; + index = iter->second.index; + return true; +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type +UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::count( const Key& key ) const +{ + return map.count( key ); +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type +UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::erase( const Key& key ) +{ + return map.erase( key ); +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +void UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::print( std::ostream& str ) const +{ + auto iter = map.begin(); + str << iter->second.data; + iter++; + while( iter != map.end() ) + { + str << ", " << iter->second.data; + iter++; + } +} + +template< class Key, + class Index, + class Hash, + class KeyEqual, + class Allocator > +std::ostream& operator<<( std::ostream& str, UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >& set ) +{ + set.print( str ); + return str; +} + +} // namespace Containers +} // namespace TNL diff --git a/src/TNL/Debugging/FPE.h b/src/TNL/Debugging/FPE.h index 09011e8953205089db602357ad9840965dc95ede..5f6c18d3214ac1da58376a77dc647fc8f234d865 100644 --- a/src/TNL/Debugging/FPE.h +++ b/src/TNL/Debugging/FPE.h @@ -1,5 +1,5 @@ /*************************************************************************** - MeshConfigBase.h - description + FPE.h - description ------------------- begin : Nov 6, 2016 copyright : (C) 2016 by Tomas Oberhuber et al. diff --git a/src/TNL/Debugging/MemoryUsage.h b/src/TNL/Debugging/MemoryUsage.h index 03ea3fe4d3db40f566ce82762521da1596e45dd5..a657976130faef71f4e592e8a10752767cc04363 100644 --- a/src/TNL/Debugging/MemoryUsage.h +++ b/src/TNL/Debugging/MemoryUsage.h @@ -1,5 +1,5 @@ /*************************************************************************** - MeshConfigBase.h - description + MemoryUsage.h - description ------------------- begin : Nov 6, 2016 copyright : (C) 2016 by Tomas Oberhuber et al. diff --git a/src/TNL/Debugging/StackBacktrace.h b/src/TNL/Debugging/StackBacktrace.h index ee419922637899c7187e25d187abc6a427ebff68..99949eabaaa8c516fcf42ee8671971e5e530153f 100644 --- a/src/TNL/Debugging/StackBacktrace.h +++ b/src/TNL/Debugging/StackBacktrace.h @@ -1,5 +1,5 @@ /*************************************************************************** - MeshConfigBase.h - description + StackBacktrace.h - description ------------------- begin : Nov 6, 2016 copyright : (C) 2016 by Tomas Oberhuber et al. diff --git a/src/TNL/Experimental/CMakeLists.txt b/src/TNL/Experimental/CMakeLists.txt index 47fc9efa44f92699b64e247af1778ad83e6cebfa..fea80728f261adbdaa6519a3efea912f253de31e 100644 --- a/src/TNL/Experimental/CMakeLists.txt +++ b/src/TNL/Experimental/CMakeLists.txt @@ -1,3 +1,2 @@ ADD_SUBDIRECTORY( Arithmetics ) -ADD_SUBDIRECTORY( Multimaps ) ADD_SUBDIRECTORY( Hamilton-Jacobi ) diff --git a/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h b/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h index 225ce04b9851b93dd00d37644a7c042f563a3b9d..c4055d95df7afe453337e592de0f9ef224226b52 100644 --- a/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h +++ b/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h @@ -24,7 +24,7 @@ using namespace TNL; //typedef tnlDefaultBuildMeshConfig BuildConfig; -typedef Solvers::FastBuildConfig BuildConfig; +typedef Solvers::FastBuildConfigTag BuildConfig; template< typename MeshConfig > class tnlDirectEikonalSolverConfig diff --git a/src/TNL/Experimental/Multimaps/CMakeLists.txt b/src/TNL/Experimental/Multimaps/CMakeLists.txt deleted file mode 100644 index fc23d168ee5c5d8212f0e761834eff6421933215..0000000000000000000000000000000000000000 --- a/src/TNL/Experimental/Multimaps/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -SET( headers EllpackIndexMultimap.h - EllpackIndexMultimap_impl.h - EllpackIndexMultimapValues.h - EllpackIndexMultimapValues_impl.h ) - -SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/core/multimaps ) -set( common_SOURCES - ) - -IF( BUILD_CUDA ) - set( tnl_core_multimaps_CUDA__SOURCES - ${common_SOURCES} - PARENT_SCOPE ) -ENDIF() - -set( tnl_core_multimaps_SOURCES - ${common_SOURCES} - PARENT_SCOPE ) - -INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/core/multimaps ) diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimap.h deleted file mode 100644 index e5879c7937a7c00a611bbe2676cab08c19d73562..0000000000000000000000000000000000000000 --- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap.h +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************** - EllpackIndexMultimap.h - description - ------------------- - begin : Sep 9, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/Containers/Vector.h> - -namespace TNL { - -template< typename Index = int, - typename Device = Devices::Host > -class EllpackIndexMultimapValues; - -template< typename Index = int, - typename Device = Devices::Host > -class EllpackIndexMultimapConstValues; - -template< typename Index = int, - typename Device = Devices::Host > -class EllpackIndexMultimap -{ - public: - - typedef Device DeviceType; - typedef Index IndexType; - typedef EllpackIndexMultimapValues< IndexType, DeviceType > ValuesAccessorType; - typedef EllpackIndexMultimapConstValues< IndexType, DeviceType > ConstValuesAccessorType; - typedef Containers::Vector< IndexType, DeviceType, IndexType > ValuesAllocationVectorType; - - EllpackIndexMultimap(); - - static String getType(); - - String getTypeVirtual() const; - - void setRanges( const IndexType keysRange, - const IndexType valuesRange ); - - const IndexType getKeysRange() const; - - const IndexType getValuesRange() const; - - void allocate( const ValuesAllocationVectorType& portsCount ); - - ValuesAccessorType getValues( const IndexType& inputIndex ); - - ConstValuesAccessorType getValues( const IndexType& inputIndex ) const; - - protected: - - Containers::Vector< IndexType, DeviceType, IndexType > values; - - IndexType keysRange, valuesRange, valuesMaxCount; -}; - -} // namespace TNL - -#include <TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h> - diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h deleted file mode 100644 index fd297f030899ca4e3389925ed39c4c2dbd33dcae..0000000000000000000000000000000000000000 --- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - EllpackIndexMultimapValues.h - description - ------------------- - begin : Sep 10, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <ostream> -#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h> - -namespace TNL { - -template< typename Index, - typename Device > -class EllpackIndexMultimapValues -{ - public: - - typedef Device DeviceType; - typedef Index IndexType; - typedef EllpackIndexMultimap< IndexType, DeviceType > NetworkType; - - EllpackIndexMultimapValues(); - - IndexType getPortsCount() const; - - void setOutput( const IndexType portIndex, - const IndexType output ); - - IndexType getOutput( const IndexType portIndex ) const; - - IndexType& operator[]( const IndexType portIndex ); - - const IndexType& operator[]( const IndexType portIndex ) const; - - void print( std::ostream& str ) const; - - protected: - - EllpackIndexMultimapValues( IndexType* ports, - const IndexType input, - const IndexType portsMaxCount ); - - IndexType* ports; - - IndexType step, portsMaxCount; - - friend EllpackIndexMultimap< IndexType, DeviceType >; -}; - -template< typename Index, - typename Device > -std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device>& ports ); - -} // namespace TNL - -#include <TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h> - diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h deleted file mode 100644 index 612d0c5d6770e50e8f568f6a7bcb5a0842d4548e..0000000000000000000000000000000000000000 --- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h +++ /dev/null @@ -1,107 +0,0 @@ -/*************************************************************************** - EllpackIndexMultimapValues_impl.h - description - ------------------- - begin : Sep 10, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include "EllpackIndexMultimapValues.h" - -namespace TNL { - -template< typename Index, - typename Device > -EllpackIndexMultimapValues< Index, Device >:: -EllpackIndexMultimapValues() -{ -} - -template< typename Index, - typename Device > -EllpackIndexMultimapValues< Index, Device >:: -EllpackIndexMultimapValues( IndexType* networkPorts, - const IndexType input, - const IndexType portsMaxCount ) -{ - this->ports = &networkPorts[ input * portsMaxCount ]; - this->portsMaxCount = portsMaxCount; -} - -template< typename Index, - typename Device > -Index -EllpackIndexMultimapValues< Index, Device >:: -getPortsCount() const -{ - return this->portsMaxCount; -} - -template< typename Index, - typename Device > -void -EllpackIndexMultimapValues< Index, Device >:: -setOutput( const IndexType portIndex, - const IndexType output ) -{ - this->ports[ portIndex ] = output; -} - -template< typename Index, - typename Device > -Index -EllpackIndexMultimapValues< Index, Device >:: -getOutput( const IndexType portIndex ) const -{ - return this->ports[ portIndex ]; -} - -template< typename Index, - typename Device > -Index& -EllpackIndexMultimapValues< Index, Device >:: -operator[]( const IndexType portIndex ) -{ - return this->ports[ portIndex ]; -} - -template< typename Index, - typename Device > -const Index& -EllpackIndexMultimapValues< Index, Device >:: -operator[]( const IndexType portIndex ) const -{ - return this->ports[ portIndex ]; -} - -template< typename Index, - typename Device > -void -EllpackIndexMultimapValues< Index, Device >:: -print( std::ostream& str ) const -{ - if( this->getPortsCount() == 0 ) - { - str << "[]"; - return; - } - str << "[ " << this->getOutput( 0 ); - for( Index i = 1; i < this->getPortsCount(); i++ ) - str << ", " << this->getOutput( i ); - str << " ]"; -} - -template< typename Index, - typename Device > -std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device>& ports ) -{ - ports.print( str ); - return str; -} - -} // namespace TNL - diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h deleted file mode 100644 index 1b7c41a937f3fd5b9cd92c600364f09d5b4f28e3..0000000000000000000000000000000000000000 --- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h +++ /dev/null @@ -1,109 +0,0 @@ -/*************************************************************************** - EllpackIndexMultimap_impl.h - description - ------------------- - begin : Sep 9, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h> -#include <TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h> - -namespace TNL { - -template< typename Index, - typename Device > -EllpackIndexMultimap< Index, Device >:: -EllpackIndexMultimap() -: keysRange( 0 ), valuesRange( 0 ), valuesMaxCount( 0 ) -{ -} - -template< typename Index, - typename Device > -String EllpackIndexMultimap< Index, Device > :: getType() -{ - return String( "EllpackIndexMultimap< ") + - Device :: getDeviceType() + - String( ", " ) + - String( TNL::getType< Index >() ) + - String( " >" ); -} - -template< typename Index, - typename Device > -String EllpackIndexMultimap< Index, Device >::getTypeVirtual() const -{ - return this->getType(); -} - -template< typename Index, - typename Device > -void -EllpackIndexMultimap< Index, Device >:: -setRanges( const IndexType inputs, - const IndexType outputs ) -{ - this->keysRange = inputs; - this->valuesRange = outputs; -} - -template< typename Index, - typename Device > -const Index -EllpackIndexMultimap< Index, Device >:: -getKeysRange() const -{ - return this->keysRange; -} - -template< typename Index, - typename Device > -const Index -EllpackIndexMultimap< Index, Device >:: -getValuesRange() const -{ - return this->valuesRange; -} - -template< typename Index, - typename Device > -void -EllpackIndexMultimap< Index, Device >:: -allocate( const ValuesAllocationVectorType& portsCount ) -{ - TNL_ASSERT( portsCount.getSize() == this->keysRange, - std::cerr << "portsCount.getSize() = " << portsCount.getSize() - << "this->inputs = " << this->keysRange ); - this->valuesMaxCount = portsCount.max(); - - TNL_ASSERT( this->valuesMaxCount >= 0 && this->valuesMaxCount <= this->valuesRange, - std::cerr << "this->portsMaxCount = " << this->valuesMaxCount - << " this->outputs = " << this->valuesRange ); - this->values.setSize( this->keysRange * this->valuesMaxCount ); -} - -template< typename Index, - typename Device > -typename EllpackIndexMultimap< Index, Device >::ValuesAccessorType -EllpackIndexMultimap< Index, Device >:: -getValues( const IndexType& inputIndex ) -{ - return ValuesAccessorType( this->values.getData(), inputIndex, this->valuesMaxCount ); -} - -template< typename Index, - typename Device > -typename EllpackIndexMultimap< Index, Device >::ConstValuesAccessorType -EllpackIndexMultimap< Index, Device >:: -getValues( const IndexType& inputIndex ) const -{ - return ConstPortsType( this->values.getData(), inputIndex, this->valuesMaxCount ); -} - -} // namespace TNL - diff --git a/src/TNL/Functions/Analytic/Constant_impl.h b/src/TNL/Functions/Analytic/Constant_impl.h index bbd46853dc3cbe98448819876ffc8fc17940cc1a..80102ddf3817248fb3702aa902505f260dad8786 100644 --- a/src/TNL/Functions/Analytic/Constant_impl.h +++ b/src/TNL/Functions/Analytic/Constant_impl.h @@ -67,6 +67,7 @@ template< int Dimension, template< int XDiffOrder, int YDiffOrder, int ZDiffOrder > +__cuda_callable__ Real Constant< Dimension, Real >:: getPartialDerivative( const PointType& v, diff --git a/src/TNL/Functions/CMakeLists.txt b/src/TNL/Functions/CMakeLists.txt index 75a34d3181a6aab9db291407cc73f793549e0e3e..92359a15bf92d3255f9f1d97495cd7efc45725d0 100644 --- a/src/TNL/Functions/CMakeLists.txt +++ b/src/TNL/Functions/CMakeLists.txt @@ -8,10 +8,8 @@ SET( headers Domain.h MeshFunctionEvaluator.h MeshFunctionEvaluator_impl.h MeshFunctionGnuplotWriter.h - MeshFunctionGnuplotWriter_impl.h MeshFunctionNormGetter.h MeshFunctionVTKWriter.h - MeshFunctionVTKWriter_impl.h OperatorFunction.h TestFunction.h TestFunction_impl.h diff --git a/src/TNL/Functions/MeshFunctionGnuplotWriter.h b/src/TNL/Functions/MeshFunctionGnuplotWriter.h index 2c21a10328d4bd49bb6f3501246ce476cca83bd2..4b9b6d085ff7a69c0139fce319d3e3cb4d540f78 100644 --- a/src/TNL/Functions/MeshFunctionGnuplotWriter.h +++ b/src/TNL/Functions/MeshFunctionGnuplotWriter.h @@ -13,175 +13,73 @@ #include <TNL/Meshes/Grid.h> namespace TNL { -namespace Functions { -template< typename, int, typename > class MeshFunction; +namespace Meshes { + template< typename, typename, typename > class MeshEntity; +} + +namespace Functions { template< typename MeshFunction > class MeshFunctionGnuplotWriter { - public: - - static bool write( const MeshFunction& function, - std::ostream& str, - const double& scale ); -}; - -/*** - * 1D grids cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > > -{ - public: - typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); -}; - -/*** - * 1D grids vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > > -{ - public: - typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); -}; - - -/*** - * 2D grids cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > > -{ - public: - typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); -}; - -/*** - * 2D grids faces - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > > -{ - public: - typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); -}; - -/*** - * 2D grids vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > > -{ - public: - typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); -}; - - -/*** - * 3D grids cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > > -{ - public: - typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 3, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); -}; - -/*** - * 3D grids faces - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > > -{ - public: - typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); -}; - -/*** - * 3D grids vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > > -{ - public: - typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); + using MeshType = typename MeshFunction::MeshType; + using EntityType = typename MeshType::template EntityType< MeshFunction::getEntitiesDimension() >; + using GlobalIndex = typename MeshType::GlobalIndexType; + + template< typename Entity, int dim = Entity::getEntityDimension() > + struct center + { + static auto get( const Entity& entity ) -> decltype(entity.getCenter()) + { + return entity.getCenter(); + } + }; + + template< typename Entity > + struct center< Entity, 0 > + { + static auto get( const Entity& entity ) -> decltype(entity.getPoint()) + { + return entity.getPoint(); + } + }; + + template< typename MeshConfig, typename Device, typename Topology, int dim > + struct center< TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >, dim > + { + static int get( const TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >& entity ) + { + throw "not implemented"; + } + }; + + template< typename MeshConfig, typename Device, typename Topology > + struct center< TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >, 0 > + { + static int get( const TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >& entity ) + { + throw "not implemented"; + } + }; + +public: + static bool write( const MeshFunction& function, + std::ostream& str, + const double& scale = 1.0 ) + { + const MeshType& mesh = function.getMesh(); + const GlobalIndex entitiesCount = mesh.template getEntitiesCount< EntityType >(); + for( GlobalIndex i = 0; i < entitiesCount; i++ ) { + const EntityType& entity = mesh.template getEntity< EntityType >( i ); + typename MeshType::PointType v = center< EntityType >::get( entity ); + for( int j = 0; j < v.getSize(); j++ ) + str << v[ j ] << " "; + str << scale * function.getData().getElement( i ) << "\n"; + } + return true; + } }; } // namespace Functions } // namespace TNL - -#include <TNL/Functions/MeshFunctionGnuplotWriter_impl.h> diff --git a/src/TNL/Functions/MeshFunctionGnuplotWriter_impl.h b/src/TNL/Functions/MeshFunctionGnuplotWriter_impl.h deleted file mode 100644 index 13c8fa1cb0da1c280a7eb605a0f31f0f7c2a13e8..0000000000000000000000000000000000000000 --- a/src/TNL/Functions/MeshFunctionGnuplotWriter_impl.h +++ /dev/null @@ -1,363 +0,0 @@ -/*************************************************************************** - MeshFunctionGnuplotWriter.h - description - ------------------- - begin : Jan 28, 2016 - copyright : (C) 2016 by oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/Functions/MeshFunctionGnuplotWriter.h> - -namespace TNL { -namespace Functions { - -template< typename MeshFunction > -bool -MeshFunctionGnuplotWriter< MeshFunction >:: -write( const MeshFunction& function, - std::ostream& str, - const double& scale ) -{ - std::cerr << "Gnuplot writer for mesh functions defined on mesh type " << MeshFunction::MeshType::getType() << " is not (yet) implemented." << std::endl; - return false; -} - -/**** - * 1D grid, cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typename MeshType::Cell entity( mesh ); - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() < mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - return true; -} - -/**** - * 1D grid, vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typename MeshType::Vertex entity( mesh ); - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() <= mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - return true; -} - - -/**** - * 2D grid, cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typename MeshType::Cell entity( mesh ); - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() < mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() < mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - return true; -} - -/**** - * 2D grid, faces - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typedef typename MeshType::Face EntityType; - typedef typename EntityType::EntityOrientationType EntityOrientation; - EntityType entity( mesh ); - - entity.setOrientation( EntityOrientation( 1.0, 0.0 ) ); - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() < mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() <= mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - - entity.setOrientation( EntityOrientation( 0.0, 1.0 ) ); - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() < mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - - { - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() <= mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - return true; -} - - -/**** - * 2D grid, vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typename MeshType::Vertex entity( mesh ); - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() <= mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() <= mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - return true; -} - - -/**** - * 3D grid, cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typename MeshType::Cell entity( mesh ); - for( entity.getCoordinates().z() = 0; - entity.getCoordinates().z() < mesh.getDimensions().z(); - entity.getCoordinates().z() ++ ) - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() < mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() < mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " << v.z() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - return true; -} - -/**** - * 3D grid, faces - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typedef typename MeshType::Face EntityType; - typedef typename EntityType::EntityOrientationType EntityOrientation; - EntityType entity( mesh ); - - entity.setOrientation( EntityOrientation( 1.0, 0.0, 0.0 ) ); - for( entity.getCoordinates().z() = 0; - entity.getCoordinates().z() < mesh.getDimensions().z(); - entity.getCoordinates().z() ++ ) - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() < mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() <= mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " << v.z() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - - entity.setOrientation( EntityOrientation( 0.0, 1.0, 0.0 ) ); - for( entity.getCoordinates().z() = 0; - entity.getCoordinates().z() < mesh.getDimensions().z(); - entity.getCoordinates().z() ++ ) - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() < mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() <= mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " << v.z() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - - entity.setOrientation( EntityOrientation( 0.0, 0.0, 1.0 ) ); - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() < mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() <= mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - for( entity.getCoordinates().z() = 0; - entity.getCoordinates().z() < mesh.getDimensions().z(); - entity.getCoordinates().z() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " << v.z() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - return true; -} - - -/**** - * 3D grid, vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - const MeshType& mesh = function.getMesh(); - typename MeshType::Vertex entity( mesh ); - for( entity.getCoordinates().z() = 0; - entity.getCoordinates().z() <= mesh.getDimensions().z(); - entity.getCoordinates().z() ++ ) - for( entity.getCoordinates().y() = 0; - entity.getCoordinates().y() <= mesh.getDimensions().y(); - entity.getCoordinates().y() ++ ) - { - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() <= mesh.getDimensions().x(); - entity.getCoordinates().x() ++ ) - { - entity.refresh(); - typename MeshType::PointType v = entity.getCenter(); - str << v.x() << " " << v.y() << " " << v.z() << " " - << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - str << std::endl; - } - return true; -} - -} // namespace Functions -} // namespace TNL - diff --git a/src/TNL/Functions/MeshFunctionVTKWriter.h b/src/TNL/Functions/MeshFunctionVTKWriter.h index b4d18e4490901c2824ff922fe10f18607198e780..78608de7461dc5510d280d29b9f7c329836e3eb8 100644 --- a/src/TNL/Functions/MeshFunctionVTKWriter.h +++ b/src/TNL/Functions/MeshFunctionVTKWriter.h @@ -2,7 +2,7 @@ MeshFunctionVTKWriter.h - description ------------------- begin : Jan 28, 2016 - copyright : (C) 2016 by oberhuber + copyright : (C) 2016 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,225 +10,49 @@ #pragma once -#include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/Writers/VTKWriter.h> namespace TNL { namespace Functions { -template< typename, int, typename > class MeshFunction; - template< typename MeshFunction > class MeshFunctionVTKWriter { - public: - - static bool write( const MeshFunction& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunction& function, - std::ostream& str ){} -}; - -/*** - * 1D grid, cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > > -{ - public: - typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 1D grid, vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > > -{ - public: - typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 2D grid, cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > > -{ - public: - typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 2D grid, faces - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > > -{ - public: - typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 2D grid, vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > > -{ - public: - typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 3D grid, cells - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > > -{ - public: - typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 3, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 3D grid, faces - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > > -{ - public: - typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 3D grid, edges - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1, Real > > -{ - public: - typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); -}; - -/*** - * 3D grid, vertices - */ -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > > -{ - public: - typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; - typedef Real RealType; - typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType; - - static bool write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ); - - static void writeHeader(const MeshFunctionType& function, - std::ostream& str ); + using MeshType = typename MeshFunction::MeshType; + using MeshWriter = Meshes::Writers::VTKWriter< MeshType >; + using EntityType = typename MeshType::template EntityType< MeshFunction::getEntitiesDimension() >; + using GlobalIndex = typename MeshType::GlobalIndexType; + +public: + static bool write( const MeshFunction& function, + std::ostream& str, + const double& scale = 1.0, + const String& functionName = "cellFunctionValues" ) + { + const MeshType& mesh = function.getMesh(); + MeshWriter::template writeEntities< MeshFunction::getEntitiesDimension() >( mesh, str ); + appendFunction( function, str, functionName, scale ); + return true; + } + + // VTK supports writing multiple functions into the same file. + // You can call this after 'write', which initializes the mesh entities, + // with different function name. + static void appendFunction( const MeshFunction& function, + std::ostream& str, + const String& functionName, + const double& scale = 1.0 ) + { + const MeshType& mesh = function.getMesh(); + const GlobalIndex entitiesCount = mesh.template getEntitiesCount< EntityType >(); + str << std::endl << "CELL_DATA " << entitiesCount << std::endl; + str << "SCALARS " << functionName << " " << getType< typename MeshFunction::RealType >() << " 1" << std::endl; + str << "LOOKUP_TABLE default" << std::endl; + for( GlobalIndex i = 0; i < entitiesCount; i++ ) { + str << scale * function.getData().getElement( i ) << "\n"; + } + } }; } // namespace Functions } // namespace TNL - -#include <TNL/Functions/MeshFunctionVTKWriter_impl.h> diff --git a/src/TNL/Functions/MeshFunctionVTKWriter_impl.h b/src/TNL/Functions/MeshFunctionVTKWriter_impl.h deleted file mode 100644 index 606eac9ce348e2260109845af0bb05cea064a3e8..0000000000000000000000000000000000000000 --- a/src/TNL/Functions/MeshFunctionVTKWriter_impl.h +++ /dev/null @@ -1,841 +0,0 @@ -/*************************************************************************** - MeshFunctionVTKWriter_impl.h - description - ------------------- - begin : Jan 28, 2016 - copyright : (C) 2016 by oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/Functions/MeshFunctionVTKWriter.h> - -namespace TNL { -namespace Functions { - -template< typename MeshFunction > -bool -MeshFunctionVTKWriter< MeshFunction >:: -write( const MeshFunction& function, - std::ostream& str, - const double& scale ) -{ - std::cerr << "VTK writer for mesh functions defined on mesh type " << MeshFunction::MeshType::getType() << " is not (yet) implemented." << std::endl; - return false; -} - -/**** - * 1D grid, cells - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType origin = mesh.getOrigin().x(); - const RealType spaceStep = mesh.getSpaceSteps().x(); - - str << "POINTS " << mesh.getDimensions().x() + 1 << " float" << std::endl; - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << origin + i * spaceStep << " 0 0" << std::endl; - } - - str << std::endl << "CELLS " << mesh.getDimensions().x() << " " << mesh.getDimensions().x() * 3 << std::endl; - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "2 " << i << " " << i+1 << std::endl; - } - - str << std::endl << "CELL_TYPES " << mesh.getDimensions().x() << std::endl; - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "3 " << std::endl; - } - - str << std::endl << "CELL_DATA " << mesh.getDimensions().x() << std::endl; - str << "SCALARS cellFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < mesh.template getEntitiesCount< typename MeshType::Cell >(); i++ ) - { - typename MeshType::Cell entity = mesh.template getEntity< typename MeshType::Cell >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 1D grid, vertices - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType origin = mesh.getOrigin().x(); - const RealType spaceStep = mesh.getSpaceSteps().x(); - - str << "POINTS " << mesh.getDimensions().x() + 1 << " float" << std::endl; - for (int i = 0; i < mesh.getDimensions().x() + 1; i++) - { - str << origin + i * spaceStep << " 0 0" << std::endl; - } - - str << std::endl << "CELLS " << mesh.getDimensions().x() + 1 << " " << ( mesh.getDimensions().x() + 1 ) * 2 << std::endl; - for (int i = 0; i < mesh.getDimensions().x() + 1; i++) - { - str << "1 " << i << std::endl; - } - - str << std::endl << "CELL_TYPES " << mesh.getDimensions().x() + 1 << std::endl; - for (int i = 0; i < mesh.getDimensions().x() + 1; i++) - { - str << "1 " << std::endl; - } - - str << std::endl << "CELL_DATA " << mesh.getDimensions().x() + 1 << std::endl; - str << "SCALARS VerticesFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < mesh.template getEntitiesCount< typename MeshType::Vertex >(); i++ ) - { - typename MeshType::Vertex entity = mesh.template getEntity< typename MeshType::Vertex >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 2D grid, cells - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType originX = mesh.getOrigin().x(); - const RealType spaceStepX = mesh.getSpaceSteps().x(); - const RealType originY = mesh.getOrigin().y(); - const RealType spaceStepY = mesh.getSpaceSteps().y(); - const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >(); - const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Cell >(); - - str << "POINTS " << verticesCount << " float" << std::endl; - for (int j = 0; j < mesh.getDimensions().y() + 1; j++) - { - for (int i = 0; i < mesh.getDimensions().x() + 1; i++) - { - str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " 0" << std::endl; - } - } - - str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 5 << std::endl; - for (int j = 0; j < mesh.getDimensions().y(); j++) - { - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "4 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " << j * ( mesh.getDimensions().x() + 1 )+ i + 1 << - " " << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " << (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl; - } - } - - str << std::endl << "CELL_TYPES " << mesh.getDimensions().x() * mesh.getDimensions().y() << std::endl; - for (int i = 0; i < mesh.getDimensions().x()*mesh.getDimensions().y(); i++) - { - str << "8 " << std::endl; - } - - str << std::endl << "CELL_DATA " << entitiesCount << std::endl; - str << "SCALARS cellFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < entitiesCount; i++ ) - { - typename MeshType::Cell entity = mesh.template getEntity< typename MeshType::Cell >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 2D grid, faces - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - typedef typename MeshType::template EntityType< 0 > Vertex; - typedef typename MeshType::template EntityType< 1 > Face; - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType originX = mesh.getOrigin().x(); - const RealType spaceStepX = mesh.getSpaceSteps().x(); - const RealType originY = mesh.getOrigin().y(); - const RealType spaceStepY = mesh.getSpaceSteps().y(); - const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >(); - const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Face >(); - - str << "POINTS " << verticesCount << " float" << std::endl; - for (int j = 0; j < ( mesh.getDimensions().y() + 1); j++) - { - for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++) - { - str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " 0" << std::endl; - } - } - - str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 3 << std::endl; - for (int j = 0; j < mesh.getDimensions().y(); j++) - { - for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++) - { - str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << std::endl; - } - } - - for (int j = 0; j < (mesh.getDimensions().y()+1); j++) - { - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " <<j * ( mesh.getDimensions().x() + 1 ) + i + 1<< std::endl; - } - } - - str << std::endl << "CELL_TYPES " << entitiesCount << std::endl; - for (int i = 0; i < entitiesCount; i++) - { - str << "3" << std::endl; - } - - str << std::endl << "CELL_DATA " << entitiesCount << std::endl; - str << "SCALARS FaceslFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < entitiesCount; i++ ) - { - typename MeshType::Face entity = mesh.template getEntity< typename MeshType::Face >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 2D grid, vertices - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - typedef typename MeshType::template EntityType< 0 > Vertex; - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType originX = mesh.getOrigin().x(); - const RealType spaceStepX = mesh.getSpaceSteps().x(); - const RealType originY = mesh.getOrigin().y(); - const RealType spaceStepY = mesh.getSpaceSteps().y(); - const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >(); - - str << "POINTS " << verticesCount << " float" << std::endl; - for (int j = 0; j < ( mesh.getDimensions().y() + 1); j++) - { - for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++) - { - str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " 0" << std::endl; - } - } - - str << std::endl << "CELLS " << verticesCount << " " << verticesCount * 2 << std::endl; - for (int j = 0; j < ( mesh.getDimensions().y() + 1 ); j++) - { - for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++) - { - str << "1 " << j * mesh.getDimensions().x() + i << std::endl; - } - } - - str << std::endl << "CELL_TYPES " << verticesCount << std::endl; - for (int i = 0; i < verticesCount; i++) - { - str << "1" << std::endl; - } - - str << std::endl << "CELL_DATA " << verticesCount << std::endl; - str << "SCALARS VerticesFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < verticesCount; i++ ) - { - typename MeshType::Vertex entity = mesh.template getEntity< typename MeshType::Vertex >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 3D grid, cells - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType originX = mesh.getOrigin().x(); - const RealType spaceStepX = mesh.getSpaceSteps().x(); - const RealType originY = mesh.getOrigin().y(); - const RealType spaceStepY = mesh.getSpaceSteps().y(); - const RealType originZ = mesh.getOrigin().z(); - const RealType spaceStepZ = mesh.getSpaceSteps().z(); - const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >(); - const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Cell >(); - - str << "POINTS " << verticesCount << " float" << std::endl; - for (int k = 0; k <= mesh.getDimensions().y(); k++) - { - for (int j = 0; j <= mesh.getDimensions().y(); j++) - { - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " << - originZ + k * spaceStepZ << std::endl; - } - } - } - - str << std::endl << "CELLS " << entitiesCount << " " << - entitiesCount * 9 << std::endl; - for (int k = 0; k < mesh.getDimensions().z(); k++) - { - for (int j = 0; j < mesh.getDimensions().y(); j++) - { - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "8 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl; - } - } - } - - str << std::endl << "CELL_TYPES " << entitiesCount << std::endl; - for (int i = 0; i < entitiesCount; i++) - { - str << "11" << std::endl; - } - - str << std::endl << "CELL_DATA " << entitiesCount << std::endl; - str << "SCALARS cellFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < entitiesCount; i++ ) - { - typename MeshType::Cell entity = mesh.template getEntity< typename MeshType::Cell >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 3D grid, faces - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType originX = mesh.getOrigin().x(); - const RealType spaceStepX = mesh.getSpaceSteps().x(); - const RealType originY = mesh.getOrigin().y(); - const RealType spaceStepY = mesh.getSpaceSteps().y(); - const RealType originZ = mesh.getOrigin().z(); - const RealType spaceStepZ = mesh.getSpaceSteps().z(); - const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >(); - const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Face >(); - - str << "POINTS " << verticesCount << " float" << std::endl; - for (int k = 0; k <= mesh.getDimensions().y(); k++) - { - for (int j = 0; j <= mesh.getDimensions().y(); j++) - { - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " << - originZ + k * spaceStepZ << std::endl; - } - } - } - - str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 5 << std::endl; - for (int k = 0; k < mesh.getDimensions().z(); k++) - { - for (int j = 0; j < mesh.getDimensions().y(); j++) - { - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << std::endl; - } - } - } - - for (int k = 0; k < mesh.getDimensions().z(); k++) - { - for (int j = 0; j <= mesh.getDimensions().y(); j++) - { - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl; - } - } - } - - for (int k = 0; k <= mesh.getDimensions().z(); k++) - { - for (int j = 0; j < mesh.getDimensions().y(); j++) - { - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1<< std::endl; - } - } - } - - str << std::endl << "CELL_TYPES " << entitiesCount << std::endl; - for (int i = 0; i < entitiesCount; i++) - { - str << "8" << std::endl; - } - - str << std::endl << "CELL_DATA " << entitiesCount << std::endl; - str << "SCALARS facesFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < entitiesCount; i++ ) - { - typename MeshType::Face entity = mesh.template getEntity< typename MeshType::Face >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 3D grid, edges - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType originX = mesh.getOrigin().x(); - const RealType spaceStepX = mesh.getSpaceSteps().x(); - const RealType originY = mesh.getOrigin().y(); - const RealType spaceStepY = mesh.getSpaceSteps().y(); - const RealType originZ = mesh.getOrigin().z(); - const RealType spaceStepZ = mesh.getSpaceSteps().z(); - const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >(); - const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Edge >(); - - str << "POINTS " << verticesCount << " float" << std::endl; - for (int k = 0; k <= mesh.getDimensions().y(); k++) - { - for (int j = 0; j <= mesh.getDimensions().y(); j++) - { - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " << - originZ + k * spaceStepZ << std::endl; - } - } - } - - str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 3 << std::endl; - for (int k = 0; k <= mesh.getDimensions().z(); k++) - { - for (int j = 0; j <= mesh.getDimensions().y(); j++) - { - for (int i = 0; i < mesh.getDimensions().x(); i++) - { - str << "3 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl; - } - } - } - - for (int k = 0; k <= mesh.getDimensions().z(); k++) - { - for (int j = 0; j < mesh.getDimensions().y(); j++) - { - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << "3 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << std::endl; - } - } - } - - for (int k = 0; k < mesh.getDimensions().z(); k++) - { - for (int j = 0; j <= mesh.getDimensions().y(); j++) - { - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << "3 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " - << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << std::endl; - } - } - } - - str << std::endl << "CELL_TYPES " << entitiesCount << std::endl; - for (int i = 0; i < entitiesCount; i++) - { - str << "3" << std::endl; - } - - str << std::endl << "CELL_DATA " << entitiesCount << std::endl; - str << "SCALARS edgesFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < entitiesCount; i++ ) - { - typename MeshType::Edge entity = mesh.template getEntity< typename MeshType::Edge >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -/**** - * 3D grid, vertices - */ - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -void -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >:: -writeHeader( const MeshFunctionType& function, - std::ostream& str ) -{ - const MeshType& mesh = function.getMesh(); - const typename MeshType::PointType& origin = mesh.getOrigin(); - const typename MeshType::PointType& proportions = mesh.getProportions(); - str << "# vtk DataFile Version 2.0" << std::endl; - str << "TNL DATA" << std::endl; - str << "ASCII" << std::endl; - str << "DATASET UNSTRUCTURED_GRID" << std::endl; -} - -template< typename MeshReal, - typename Device, - typename MeshIndex, - typename Real > -bool -MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >:: -write( const MeshFunctionType& function, - std::ostream& str, - const double& scale ) -{ - writeHeader(function, str); - - const MeshType& mesh = function.getMesh(); - const RealType originX = mesh.getOrigin().x(); - const RealType spaceStepX = mesh.getSpaceSteps().x(); - const RealType originY = mesh.getOrigin().y(); - const RealType spaceStepY = mesh.getSpaceSteps().y(); - const RealType originZ = mesh.getOrigin().z(); - const RealType spaceStepZ = mesh.getSpaceSteps().z(); - const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >(); - - str << "POINTS " << verticesCount << " float" << std::endl; - for (int k = 0; k <= mesh.getDimensions().y(); k++) - { - for (int j = 0; j <= mesh.getDimensions().y(); j++) - { - for (int i = 0; i <= mesh.getDimensions().x(); i++) - { - str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " << - originZ + k * spaceStepZ << std::endl; - } - } - } - - str << std::endl << "CELLS " << verticesCount << " " << verticesCount * 2 << std::endl; - for (int k = 0; k < ( mesh.getDimensions().z() + 1 ); k++) - { - for (int j = 0; j < ( mesh.getDimensions().y() + 1 ); j++) - { - for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++) - { - str << "1 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << std::endl; - } - } - } - - str << std::endl << "CELL_TYPES " << verticesCount << std::endl; - for (int i = 0; i < verticesCount; i++) - { - str << "1" << std::endl; - } - - str << std::endl << "CELL_DATA " << verticesCount << std::endl; - str << "SCALARS verticesFunctionValues float 1" << std::endl; - str << "LOOKUP_TABLE default" << std::endl; - - for( MeshIndex i = 0; i < verticesCount; i++ ) - { - typename MeshType::Vertex entity = mesh.template getEntity< typename MeshType::Vertex >( i ); - entity.refresh(); - str << scale * function.getData().getElement( entity.getIndex() ) << std::endl; - } - - return true; -} - -} // namespace Functions -} // namespace TNL - diff --git a/src/TNL/Functions/VectorField.h b/src/TNL/Functions/VectorField.h index 2fe085e750c931d5d81cd1dbdf2c49fd9af38ad9..cbc143251962455b074d426f87928c2a25dd762a 100644 --- a/src/TNL/Functions/VectorField.h +++ b/src/TNL/Functions/VectorField.h @@ -87,7 +87,7 @@ class VectorField< Size, MeshFunction< Mesh, MeshEntityDimension, Real > > typedef MeshFunction< MeshType, MeshEntityDimension, RealType > FunctionType; typedef SharedPointer< FunctionType > FunctionPointer; typedef typename MeshType::DeviceType DeviceType; - typedef typename MeshType::IndexType IndexType; + typedef typename MeshType::GlobalIndexType IndexType; typedef VectorField< Size, MeshFunction< Mesh, MeshEntityDimension, RealType > > ThisType; typedef Containers::StaticVector< Size, RealType > VectorType; diff --git a/src/TNL/Meshes/BuildConfigTags.h b/src/TNL/Meshes/BuildConfigTags.h new file mode 100644 index 0000000000000000000000000000000000000000..35aa2b2f89041575587e3f9ac291db02475dd0fa --- /dev/null +++ b/src/TNL/Meshes/BuildConfigTags.h @@ -0,0 +1,142 @@ +/*************************************************************************** + BuildConfigTags.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/DefaultConfig.h> +#include <TNL/Meshes/Topologies/Edge.h> +#include <TNL/Meshes/Topologies/Triangle.h> +#include <TNL/Meshes/Topologies/Quadrilateral.h> +#include <TNL/Meshes/Topologies/Tetrahedron.h> +#include <TNL/Meshes/Topologies/Hexahedron.h> +#include <TNL/Meshes/Topologies/Simplex.h> + +namespace TNL { +namespace Meshes { +namespace BuildConfigTags { + +/**** + * Configuration for structured grids + */ + +// 1, 2, and 3 dimensions are enabled by default +template< typename ConfigTag, int Dimension > struct GridDimensionTag { enum { enabled = ( Dimension > 0 && Dimension <= 3 ) }; }; + +// Grids are enabled for all real types by default. +template< typename ConfigTag, typename Real > struct GridRealTag { enum { enabled = true }; }; + +// Grids are enabled on all available devices by default. +template< typename ConfigTag, typename Device > struct GridDeviceTag { enum { enabled = true }; }; +#ifndef HAVE_CUDA +template< typename ConfigTag > struct GridDeviceTag< ConfigTag, Devices::Cuda > { enum { enabled = false }; }; +#endif + +// Grids are enabled for all index types by default. +template< typename ConfigTag, typename Index > struct GridIndexTag { enum { enabled = true }; }; + +// The Grid is enabled for allowed dimensions and Real, Device and Index types. +// +// By specializing this tag you can enable or disable custom combinations of +// the grid template parameters. The default configuration is identical to the +// individual per-type tags. +template< typename ConfigTag, typename MeshType > struct GridTag { enum { enabled = false }; }; + +template< typename ConfigTag, int Dimension, typename Real, typename Device, typename Index > +struct GridTag< ConfigTag, Grid< Dimension, Real, Device, Index > > +{ + enum { enabled = GridDimensionTag< ConfigTag, Dimension >::enabled && + GridRealTag< ConfigTag, Real >::enabled && + GridDeviceTag< ConfigTag, Device >::enabled && + GridIndexTag< ConfigTag, Index >::enabled + }; +}; + + +/**** + * Configuration for unstructured meshes + */ + +// Meshes are enabled on all available devices by default. +template< typename ConfigTag, typename Device > struct MeshDeviceTag { enum { enabled = false }; }; +template< typename ConfigTag > struct MeshDeviceTag< ConfigTag, Devices::Host > { enum { enabled = true }; }; +#ifdef HAVE_CUDA +template< typename ConfigTag > struct MeshDeviceTag< ConfigTag, Devices::Cuda > { enum { enabled = true }; }; +#endif + +// All available cell topologies are disabled by default. +template< typename ConfigTag, typename CellTopology > struct MeshCellTopologyTag { enum { enabled = false }; }; +//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Edge > { enum { enabled = true }; }; +//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Triangle > { enum { enabled = true }; }; +//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Quadrilateral > { enum { enabled = true }; }; +//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; }; +//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Hexahedron > { enum { enabled = true }; }; +// TODO: Simplex has not been tested yet +//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Simplex > { enum { enabled = true }; }; + +// All sensible world dimensions are enabled by default. +template< typename ConfigTag, typename CellTopology, int WorldDimension > struct MeshWorldDimensionTag { enum { enabled = ( WorldDimension >= CellTopology::dimension && WorldDimension <= 3 ) }; }; + +// Meshes are enabled for all real types by default. +template< typename ConfigTag, typename Real > struct MeshRealTag { enum { enabled = true }; }; + +// Meshes are enabled for all global index types by default. +template< typename ConfigTag, typename GlobalIndex > struct MeshGlobalIndexTag { enum { enabled = true }; }; + +// Meshes are enabled for all local index types by default. +template< typename ConfigTag, typename LocalIndex > struct MeshLocalIndexTag { enum { enabled = true }; }; + +// Meshes are enabled for 'GlobalIndex' and 'void' id types by default. +template< typename ConfigTag, typename GlobalIndex, typename Id > struct MeshIdTag { enum { enabled = false }; }; +template< typename ConfigTag, typename GlobalIndex > struct MeshIdTag< ConfigTag, GlobalIndex, void > { enum { enabled = true }; }; +template< typename ConfigTag, typename GlobalIndex > struct MeshIdTag< ConfigTag, GlobalIndex, GlobalIndex > { enum { enabled = true }; }; + +// Config tag specifying the MeshConfig to use. +template< typename ConfigTag > +struct MeshConfigTemplateTag +{ + template< typename Cell, int WorldDimension, typename Real, typename GlobalIndex, typename LocalIndex, typename Id > + using MeshConfig = DefaultConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id >; +}; + +// The Mesh is enabled for allowed Device, CellTopology, WorldDimension, Real, +// GlobalIndex, LocalIndex and Id types as specified above. +// +// By specializing this tag you can enable or disable custom combinations of +// the grid template parameters. The default configuration is identical to the +// individual per-type tags. +// +// NOTE: We can't specialize the whole MeshType as it was done for the GridTag, +// because we don't know the MeshConfig and the compiler can't deduce it +// at the time of template specializations, so something like this does +// not work: +// +// struct MeshTag< ConfigTag, +// Mesh< typename MeshConfigTemplateTag< ConfigTag >:: +// template MeshConfig< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, Id > > > +// +template< typename ConfigTag, typename Device, typename CellTopology, int WorldDimension, typename Real, typename GlobalIndex, typename LocalIndex, typename Id > +struct MeshTag +{ + enum { enabled = + MeshDeviceTag< ConfigTag, Device >::enabled && + MeshCellTopologyTag< ConfigTag, CellTopology >::enabled && + MeshWorldDimensionTag< ConfigTag, CellTopology, WorldDimension >::enabled && + MeshRealTag< ConfigTag, Real >::enabled && + MeshGlobalIndexTag< ConfigTag, GlobalIndex >::enabled && + MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled && + MeshIdTag< ConfigTag, GlobalIndex, Id >::enabled + }; +}; + +} // namespace BuildConfigTags +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/CMakeLists.txt b/src/TNL/Meshes/CMakeLists.txt index d49d84212cdec3709d882af04f78ad7e2d680924..9dd51e9b858050cb095d3a3cb68b672a3ba263ae 100644 --- a/src/TNL/Meshes/CMakeLists.txt +++ b/src/TNL/Meshes/CMakeLists.txt @@ -1,17 +1,23 @@ +ADD_SUBDIRECTORY( Geometry ) ADD_SUBDIRECTORY( GridDetails ) ADD_SUBDIRECTORY( MeshDetails ) ADD_SUBDIRECTORY( DistributedMeshes ) +ADD_SUBDIRECTORY( Readers ) ADD_SUBDIRECTORY( Topologies ) +ADD_SUBDIRECTORY( TypeResolver ) +ADD_SUBDIRECTORY( Writers ) -SET( headers Grid.h - GridEntity.h - GridEntityConfig.h +SET( headers BuildConfigTags.h + DefaultConfig.h + DimensionTag.h DummyMesh.h - MeshDimensionTag.h - Mesh.h + GridEntityConfig.h + GridEntity.h + Grid.h + MeshBuilder.h MeshEntity.h + Mesh.h Traverser.h - MeshConfigBase.h ) SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Meshes ) diff --git a/src/TNL/Meshes/DefaultConfig.h b/src/TNL/Meshes/DefaultConfig.h new file mode 100644 index 0000000000000000000000000000000000000000..147a9ab10b911ba0a0bca9ec1dd3b74035508e6e --- /dev/null +++ b/src/TNL/Meshes/DefaultConfig.h @@ -0,0 +1,129 @@ +/*************************************************************************** + DefaultConfig.h - description + ------------------- + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/String.h> +#include <TNL/param-types.h> +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> + +namespace TNL { +namespace Meshes { + +/**** + * Basic structure for mesh configuration. + * Setting Id to GlobalIndex enables storage of entity Id. + * It means that each mesh entity stores its index in its + * mesh storage layer. + */ +template< typename Cell, + int WorldDimension = Cell::dimension, + typename Real = double, + typename GlobalIndex = int, + typename LocalIndex = GlobalIndex, + typename Id = void > +struct DefaultConfig +{ + using CellTopology = Cell; + using RealType = Real; + using GlobalIndexType = GlobalIndex; + using LocalIndexType = LocalIndex; + using IdType = Id; + + static constexpr int worldDimension = WorldDimension; + static constexpr int meshDimension = Cell::dimension; + + static String getType() + { + return String( "Meshes::DefaultConfig< " ) + + Cell::getType() + ", " + + String( WorldDimension ) + ", " + + TNL::getType< Real >() + ", " + + TNL::getType< GlobalIndex >() + ", " + + TNL::getType< LocalIndex >() + ", " + + TNL::getType< Id >() + " >"; + }; + + /**** + * Storage of mesh entities. + */ + static constexpr bool entityStorage( int dimension ) + { + /**** + * Vertices and cells must always be stored. + */ + return true; + //return ( dimension == 0 || dimension == cellDimension ); + } + + /**** + * Storage of subentities of mesh entities. + */ + template< typename EntityTopology > + static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) + { + /**** + * Subvertices of all stored entities must always be stored + */ + return entityStorage( EntityTopology::dimension ); + //return entityStorage( EntityTopology::dimension ) && + // SubentityDimension == 0; + } + + /**** + * Storage of subentity orientations of mesh entities. + * It must be false for vertices and cells. + */ + template< typename EntityTopology > + static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimension ) + { + return ( SubentityDimension > 0 ); + } + + /**** + * Storage of superentities of mesh entities. + */ + template< typename EntityTopology > + static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) + { + return entityStorage( EntityTopology::dimension ); + //return false; + } + + /**** + * Storage of boundary tags of mesh entities. Necessary for the mesh traverser. + * + * The configuration must satisfy the following necessary conditions in + * order to provide boundary tags: + * - faces must be stored + * - faces must store the cell indices in the superentity layer + * - if dim(entity) < dim(face), the entities on which the tags are stored + * must be stored as subentities of faces + * TODO: check this in the ConfigValidator + */ + template< typename EntityTopology > + static constexpr bool boundaryTagsStorage( EntityTopology ) + { + using FaceTopology = typename Topologies::Subtopology< CellTopology, meshDimension - 1 >::Topology; + return entityStorage( meshDimension - 1 ) && + superentityStorage( FaceTopology(), meshDimension ) && + ( EntityTopology::dimension >= meshDimension - 1 || subentityStorage( FaceTopology(), EntityTopology::dimension ) ); + //return false; + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDimensionTag.h b/src/TNL/Meshes/DimensionTag.h similarity index 61% rename from src/TNL/Meshes/MeshDimensionTag.h rename to src/TNL/Meshes/DimensionTag.h index 10dbcdaf71605a627f29154074dd1e76d0cc0df9..2cf42488ebacaf3abff0a7a12d3595a96b24d1ab 100644 --- a/src/TNL/Meshes/MeshDimensionTag.h +++ b/src/TNL/Meshes/DimensionTag.h @@ -1,19 +1,13 @@ /*************************************************************************** - MeshDimensionTag.h - description + DimensionTag.h - description ------------------- begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - #pragma once #include <TNL/Assert.h> @@ -30,31 +24,32 @@ namespace Meshes { * expression is a simple identifier. * * Therefore one cannot specialize the mesh layers just by integers saying the mesh - * layer dimensions but instead this tag must be used. This makes the code more difficult + * layer dimension but instead this tag must be used. This makes the code more difficult * to read and we would like to avoid it if it is possible sometime. - * On the other hand, MeshDimensionTag is also used for method overloading when + * On the other hand, DimensionTag is also used for method overloading when * asking for different mesh entities. In this case it makes sense and it cannot be * replaced. */ template< int Dimension > -class MeshDimensionTag +class DimensionTag { - public: + static_assert( Dimension >= 0, "The dimension cannot be negative." ); - static const int value = Dimension; +public: + static constexpr int value = Dimension; - typedef MeshDimensionTag< Dimension - 1 > Decrement; - - static_assert( value >= 0, "The value of the dimensions cannot be negative." ); + using Decrement = DimensionTag< Dimension - 1 >; + using Increment = DimensionTag< Dimension + 1 >; }; template<> -class MeshDimensionTag< 0 > +class DimensionTag< 0 > { - public: - - static const int value = 0; +public: + static const int value = 0; + + using Increment = DimensionTag< 1 >; }; } // namespace Meshes diff --git a/src/TNL/Meshes/DummyMesh.h b/src/TNL/Meshes/DummyMesh.h index ce4cd0bf42f92d8911fa482ca240e5e919ba00e1..4bff7ce1773978c95a9d16fa2edda1d0760ee7bd 100644 --- a/src/TNL/Meshes/DummyMesh.h +++ b/src/TNL/Meshes/DummyMesh.h @@ -2,7 +2,7 @@ DummyMesh.h - description ------------------- begin : Apr 17, 2013 - copyright : (C) 2013 by Tomas Oberhuber + copyright : (C) 2013 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,6 +10,9 @@ #pragma once +#include <TNL/String.h> +#include <TNL/Devices/Host.h> + namespace TNL { namespace Meshes { @@ -18,8 +21,7 @@ template< typename Real = double, typename Index = int > class DummyMesh { - public: - +public: typedef Real RealType; typedef Device DeviceType; typedef Index IndexType; diff --git a/src/TNL/Meshes/Geometry/CMakeLists.txt b/src/TNL/Meshes/Geometry/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c743984d782fee8eb9a28960b67682172306f4ff --- /dev/null +++ b/src/TNL/Meshes/Geometry/CMakeLists.txt @@ -0,0 +1,5 @@ +SET( headers getEntityCenter.h + getEntityMeasure.h +) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Geometry ) diff --git a/src/TNL/Meshes/Geometry/getEntityCenter.h b/src/TNL/Meshes/Geometry/getEntityCenter.h new file mode 100644 index 0000000000000000000000000000000000000000..59cd950ca180cdbf8095382536544e9fe0ffde51 --- /dev/null +++ b/src/TNL/Meshes/Geometry/getEntityCenter.h @@ -0,0 +1,66 @@ +/*************************************************************************** + getEntityCenter.h - description + ------------------- + begin : Nov 12, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Devices/CudaCallable.h> +#include <TNL/Meshes/GridEntity.h> +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/MeshEntity.h> + +namespace TNL { +namespace Meshes { + +// compatibility wrapper +template< typename Grid, int EntityDimension, typename Config > +__cuda_callable__ +typename Grid::PointType +getEntityCenter( const Grid & grid, const GridEntity< Grid, EntityDimension, Config > & entity ) +{ + return entity.getCenter(); +} + +template< typename MeshConfig, typename Device > +__cuda_callable__ +typename MeshTraits< MeshConfig >::PointType +getEntityCenter( const Mesh< MeshConfig, Device > & mesh, + const MeshEntity< MeshConfig, Device, Topologies::Vertex > & entity ) +{ + return entity.getPoint(); +} + +/* + * Get an arithmetic mean of the entity's subvertices. + * + * For an simplex entity this corresponds to the centroid of the entity, but + * note that other shapes such as general polygons have different formulas for + * the centroid: https://en.wikipedia.org/wiki/Centroid#Centroid_of_a_polygon + */ +template< typename MeshConfig, typename Device, typename EntityTopology > +__cuda_callable__ +typename MeshTraits< MeshConfig >::PointType +getEntityCenter( const Mesh< MeshConfig, Device > & mesh, + const MeshEntity< MeshConfig, Device, EntityTopology > & entity ) +{ + using EntityType = MeshEntity< MeshConfig, Device, EntityTopology >; + constexpr typename MeshConfig::LocalIndexType subvertices = EntityType::template getSubentitiesCount< 0 >(); + typename MeshTraits< MeshConfig >::PointType c{ 0.0 }; + for( typename MeshConfig::LocalIndexType i = 0; + i < subvertices; + i++ ) + { + const auto& v = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( i ) ); + c += v.getPoint(); + } + return ( 1.0 / subvertices ) * c; +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Geometry/getEntityMeasure.h b/src/TNL/Meshes/Geometry/getEntityMeasure.h new file mode 100644 index 0000000000000000000000000000000000000000..de61e571a4ae321200753ba086a445fd13f16b71 --- /dev/null +++ b/src/TNL/Meshes/Geometry/getEntityMeasure.h @@ -0,0 +1,168 @@ +/*************************************************************************** + getEntityMeasure.h - description + ------------------- + begin : Nov 12, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Devices/CudaCallable.h> +#include <TNL/Meshes/GridEntity.h> +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/MeshEntity.h> +#include <TNL/Meshes/Topologies/Vertex.h> +#include <TNL/Meshes/Topologies/Edge.h> +#include <TNL/Meshes/Topologies/Triangle.h> +#include <TNL/Meshes/Topologies/Quadrilateral.h> +#include <TNL/Meshes/Topologies/Tetrahedron.h> + +namespace TNL { +namespace Meshes { + +template< typename Grid, typename Config > +__cuda_callable__ +typename Grid::RealType +getEntityMeasure( const Grid & grid, const GridEntity< Grid, 0, Config > & entity ) +{ + // entity.getMeasure() returns 0.0 !!! + return 1.0; +} + +template< typename Grid, int EntityDimension, typename Config > +__cuda_callable__ +typename Grid::RealType +getEntityMeasure( const Grid & grid, const GridEntity< Grid, EntityDimension, Config > & entity ) +{ + return entity.getMeasure(); +} + +// Vertex +template< typename MeshConfig, typename Device > +__cuda_callable__ +typename MeshConfig::RealType +getEntityMeasure( const Mesh< MeshConfig, Device > & mesh, + const MeshEntity< MeshConfig, Device, Topologies::Vertex > & entity ) +{ + return 1.0; +} + +// TODO: move to StaticVector::norm +template< typename Real > +__cuda_callable__ +Real +getVectorLength( const TNL::Containers::StaticVector< 1, Real > & vector ) +{ + return TNL::abs( vector[ 0 ] ); +} + +template< int Size, typename Real > +__cuda_callable__ +Real +getVectorLength( const TNL::Containers::StaticVector< Size, Real > & vector ) +{ + return TNL::sqrt( vector * vector ); +} + +// Edge +template< typename MeshConfig, typename Device > +__cuda_callable__ +typename MeshConfig::RealType +getEntityMeasure( const Mesh< MeshConfig, Device > & mesh, + const MeshEntity< MeshConfig, Device, Topologies::Edge > & entity ) +{ + const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) ); + const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) ); + return getVectorLength( v1.getPoint() - v0.getPoint() ); +} + +// Triangle +template< typename Real > +__cuda_callable__ +Real +getTriangleArea( const TNL::Containers::StaticVector< 2, Real > & v1, + const TNL::Containers::StaticVector< 2, Real > & v2 ) +{ + return 0.5 * TNL::abs( v1.x() * v2.y() - v1.y() * v2.x() ); +} + +template< typename Real > +__cuda_callable__ +Real +getTriangleArea( const TNL::Containers::StaticVector< 3, Real > & v1, + const TNL::Containers::StaticVector< 3, Real > & v2 ) +{ + // formula from http://math.stackexchange.com/a/128999 + Real S = 0.0; + Real aux = v1.y() * v2.z() - v1.z() * v2.y(); // first component of the cross product + S += aux * aux; + aux = v1.z() * v2.x() - v1.x() * v2.z(); // second component of the cross product + S += aux * aux; + aux = v1.x() * v2.y() - v1.y() * v2.x(); // third component of the cross product + S += aux * aux; + return 0.5 * ::sqrt( S ); +} + +template< typename MeshConfig, typename Device > +__cuda_callable__ +typename MeshConfig::RealType +getEntityMeasure( const Mesh< MeshConfig, Device > & mesh, + const MeshEntity< MeshConfig, Device, Topologies::Triangle > & entity ) +{ + const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) ); + const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) ); + const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) ); + return getTriangleArea( v2.getPoint() - v0.getPoint(), v1.getPoint() - v0.getPoint() ); +} + +// Quadrilateral +template< typename MeshConfig, typename Device > +__cuda_callable__ +typename MeshConfig::RealType +getEntityMeasure( const Mesh< MeshConfig, Device > & mesh, + const MeshEntity< MeshConfig, Device, Topologies::Quadrilateral > & entity ) +{ + // measure = 0.5 * |AC x BD|, where AC and BD are the diagonals + // Hence, we can use the same formula as for the triangle area. + const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) ); + const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) ); + const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) ); + const auto& v3 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 3 ) ); + return getTriangleArea( v2.getPoint() - v0.getPoint(), v3.getPoint() - v1.getPoint() ); +} + +template< typename Real > +__cuda_callable__ +Real +getTetrahedronVolume( const TNL::Containers::StaticVector< 3, Real > & v1, + const TNL::Containers::StaticVector< 3, Real > & v2, + const TNL::Containers::StaticVector< 3, Real > & v3 ) +{ + // V = (1/6) * det(v1, v2, v3) + const Real det = v1.x() * v2.y() * v3.z() + + v1.y() * v2.z() * v3.x() + + v1.z() * v2.x() * v3.y() - + ( v1.z() * v2.y() * v3.x() + + v1.y() * v2.x() * v3.z() + + v1.x() * v2.z() * v3.y() ); + return ( 1.0 / 6.0 ) * TNL::abs( det ); +} + +template< typename MeshConfig, typename Device > +__cuda_callable__ +typename MeshConfig::RealType +getEntityMeasure( const Mesh< MeshConfig, Device > & mesh, + const MeshEntity< MeshConfig, Device, Topologies::Tetrahedron > & entity ) +{ + const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) ); + const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) ); + const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) ); + const auto& v3 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 3 ) ); + return getTetrahedronVolume( v3.getPoint() - v0.getPoint(), v2.getPoint() - v0.getPoint(), v1.getPoint() - v0.getPoint() ); +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/GridDetails/Grid1D.h b/src/TNL/Meshes/GridDetails/Grid1D.h index 673eabefed5902c29787bda0ba7157a2fa552540..e2c456c83bd966beb1aef2f34ba81edb34a25828 100644 --- a/src/TNL/Meshes/GridDetails/Grid1D.h +++ b/src/TNL/Meshes/GridDetails/Grid1D.h @@ -144,14 +144,6 @@ class Grid< 1, Real, Device, Index > : public Object bool load( const String& fileName ); - bool writeMesh( const String& fileName, - const String& format ) const; - - template< typename MeshFunction > - bool write( const MeshFunction& function, - const String& fileName, - const String& format ) const; - void writeProlog( Logger& logger ) const; protected: diff --git a/src/TNL/Meshes/GridDetails/Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Grid1D_impl.h index 214dfa588f292df2d9993cba29c6c572951b74ff..47bc02fff4f64e5db49bfb0eef539808cb982e7f 100644 --- a/src/TNL/Meshes/GridDetails/Grid1D_impl.h +++ b/src/TNL/Meshes/GridDetails/Grid1D_impl.h @@ -411,61 +411,8 @@ bool Grid< 1, Real, Device, Index >::load( const String& fileName ) } template< typename Real, - typename Device, - typename Index > -bool Grid< 1, Real, Device, Index >::writeMesh( const String& fileName, - const String& format ) const -{ - /***** - * TODO: implement this - */ - return true; -} - -template< typename Real, - typename Device, - typename Index > - template< typename MeshFunction > -bool Grid< 1, Real, Device, Index >::write( const MeshFunction& function, - const String& fileName, - const String& format ) const -{ - if( this->template getEntitiesCount< Cell >() != function. getSize() ) - { - std::cerr << "The size ( " << function. getSize() - << " ) of the mesh function does not agree with the DOFs ( " - << this->template getEntitiesCount< Cell >() << " ) of a mesh." << std::endl; - return false; - } - std::fstream file; - file. open( fileName. getString(), std::ios::out ); - if( ! file ) - { - std::cerr << "I am not able to open the file " << fileName << "." << std::endl; - return false; - } - file << std::setprecision( 12 ); - const RealType hx = getSpaceSteps(). x(); - if( format == "gnuplot" ) - { - typename ThisType::template EntityType< getMeshDimension() > entity( *this ); - for( entity.getCoordinates().x() = 0; - entity.getCoordinates().x() < getDimensions(). x(); - entity.getCoordinates().x() ++ ) - { - PointType v = entity.getCenter(); - GnuplotWriter::write( file, v ); - GnuplotWriter::write( file, function[ this->getEntityIndex( entity ) ] ); - file << std::endl; - } - } - file. close(); - return true; -} - -template< typename Real, - typename Device, - typename Index > + typename Device, + typename Index > void Grid< 1, Real, Device, Index >:: writeProlog( Logger& logger ) const diff --git a/src/TNL/Meshes/GridDetails/Grid2D.h b/src/TNL/Meshes/GridDetails/Grid2D.h index 4c25ede692369051483c9e94e65d195b23470022..cc860f4f393bbe81001d511013aedf135d194e5f 100644 --- a/src/TNL/Meshes/GridDetails/Grid2D.h +++ b/src/TNL/Meshes/GridDetails/Grid2D.h @@ -151,14 +151,6 @@ class Grid< 2, Real, Device, Index > : public Object bool load( const String& fileName ); - bool writeMesh( const String& fileName, - const String& format ) const; - - template< typename MeshFunction > - bool write( const MeshFunction& function, - const String& fileName, - const String& format ) const; - void writeProlog( Logger& logger ) const; protected: diff --git a/src/TNL/Meshes/GridDetails/Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Grid2D_impl.h index 91ccf4e1306a6d35b47b6c919833c6eaa6e455f8..4ef0717f37158c5fa1e6703849b431ea9bc9ad9e 100644 --- a/src/TNL/Meshes/GridDetails/Grid2D_impl.h +++ b/src/TNL/Meshes/GridDetails/Grid2D_impl.h @@ -492,174 +492,6 @@ bool Grid< 2, Real, Device, Index > :: load( const String& fileName ) template< typename Real, typename Device, typename Index > -bool Grid< 2, Real, Device, Index > :: writeMesh( const String& fileName, - const String& format ) const -{ - std::fstream file; - file. open( fileName. getString(), std::ios::out ); - if( ! file ) - { - std::cerr << "I am not able to open the file " << fileName << "." << std::endl; - return false; - } - if( format == "asymptote" ) - { - file << "size( " - << this->getProportions(). x() << "cm , " - << this->getProportions(). y() << "cm );" - << std::endl << std::endl; - Vertex vertex( *this ); - CoordinatesType& vertexCoordinates = vertex.getCoordinates(); - PointType v; - for( Index j = 0; j < this->dimensions. y(); j ++ ) - { - file << "draw( "; - vertexCoordinates.x() = 0; - vertexCoordinates.y() = j; - v = vertex.getCenter(); - file << "( " << v. x() << ", " << v. y() << " )"; - for( Index i = 0; i < this->dimensions. x(); i ++ ) - { - vertexCoordinates.x() = i + 1; - vertexCoordinates.y() = j; - v = vertex.getCenter(); - file << "--( " << v. x() << ", " << v. y() << " )"; - } - file << " );" << std::endl; - } - file << std::endl; - for( Index i = 0; i < this->dimensions. x(); i ++ ) - { - file << "draw( "; - vertexCoordinates.x() = i; - vertexCoordinates.y() = 0; - v = vertex.getCenter(); - file << "( " << v. x() << ", " << v. y() << " )"; - for( Index j = 0; j < this->dimensions. y(); j ++ ) - { - vertexCoordinates.x() = i; - vertexCoordinates.y() = j + 1; - v = vertex.getCenter(); - file << "--( " << v. x() << ", " << v. y() << " )"; - } - file << " );" << std::endl; - } - file << std::endl; - - Cell cell( *this ); - CoordinatesType& cellCoordinates = cell.getCoordinates(); - const RealType cellMeasure = this->getSpaceSteps().x() * this->getSpaceSteps().y(); - for( Index i = 0; i < this->dimensions. x(); i ++ ) - for( Index j = 0; j < this->dimensions. y(); j ++ ) - { - cellCoordinates.x() = i; - cellCoordinates.y() = j; - v = vertex.getCenter(); - file << "label( scale(0.33) * Label( \"$" << std::setprecision( 3 ) << cellMeasure << std::setprecision( 8 ) - << "$\" ), ( " << v. x() << ", " << v. y() << " ), S );" << std::endl; - } - - for( Index i = 0; i < this->dimensions. x(); i ++ ) - for( Index j = 0; j < this->dimensions. y(); j ++ ) - { - PointType v1, v2, c; - - /**** - * East edge normal - */ - /*v1 = this->getPoint( CoordinatesType( i + 1, j ), v1 ); - v2 = this->getPoint( CoordinatesType( i + 1, j + 1 ), v2 ); - c = ( ( Real ) 0.5 ) * ( v1 + v2 ); - this->getEdgeNormal< 1, 0 >( CoordinatesType( i, j ), v ); - v *= 0.5; - file << "draw( ( " << c. x() << ", " << c. y() << " )--( " - << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl; - */ - /**** - * West edge normal - */ - /*this->getPoint< -1, -1 >( CoordinatesType( i, j ), v1 ); - this->getPoint< -1, 1 >( CoordinatesType( i, j ), v2 ); - c = ( ( Real ) 0.5 ) * ( v1 + v2 ); - this->getEdgeNormal< -1, 0 >( CoordinatesType( i, j ), v ); - v *= 0.5; - file << "draw( ( " << c. x() << ", " << c. y() << " )--( " - << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl; - */ - /**** - * North edge normal - */ - /*this->getPoint< 1, 1 >( CoordinatesType( i, j ), v1 ); - this->getPoint< -1, 1 >( CoordinatesType( i, j ), v2 ); - c = ( ( Real ) 0.5 ) * ( v1 + v2 ); - this->getEdgeNormal< 0, 1 >( CoordinatesType( i, j ), v ); - v *= 0.5; - file << "draw( ( " << c. x() << ", " << c. y() << " )--( " - << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl; - */ - /**** - * South edge normal - */ - /*this->getPoint< 1, -1 >( CoordinatesType( i, j ), v1 ); - this->getPoint< -1, -1 >( CoordinatesType( i, j ), v2 ); - c = ( ( Real ) 0.5 ) * ( v1 + v2 ); - this->getEdgeNormal< 0, -1 >( CoordinatesType( i, j ), v ); - v *= 0.5; - file << "draw( ( " << c. x() << ", " << c. y() << " )--( " - << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl; - */ - } - return true; - } - return false; -} - -template< typename Real, - typename Device, - typename Index > - template< typename MeshFunction > -bool Grid< 2, Real, Device, Index > :: write( const MeshFunction& function, - const String& fileName, - const String& format ) const -{ - if( this->template getEntitiesCount< Cell >() != function. getSize() ) - { - std::cerr << "The size ( " << function. getSize() - << " ) of a mesh function does not agree with the DOFs ( " - << this->template getEntitiesCount< Cell >() << " ) of a mesh." << std::endl; - return false; - } - std::fstream file; - file. open( fileName. getString(), std::ios::out ); - if( ! file ) - { - std::cerr << "I am not able to open the file " << fileName << "." << std::endl; - return false; - } - file << std::setprecision( 12 ); - if( format == "gnuplot" ) - { - Cell cell( *this ); - CoordinatesType& cellCoordinates = cell.getCoordinates(); - for( cellCoordinates.y() = 0; cellCoordinates.y() < getDimensions(). y(); cellCoordinates.y() ++ ) - { - for( cellCoordinates.x() = 0; cellCoordinates.x() < getDimensions(). x(); cellCoordinates.x() ++ ) - { - PointType v = cell.getCenter(); - GnuplotWriter::write( file, v ); - GnuplotWriter::write( file, function[ this->getEntityIndex( cell ) ] ); - file << std::endl; - } - file << std::endl; - } - } - file. close(); - return true; -} - -template< typename Real, - typename Device, - typename Index > void Grid< 2, Real, Device, Index >:: writeProlog( Logger& logger ) const diff --git a/src/TNL/Meshes/GridDetails/Grid3D.h b/src/TNL/Meshes/GridDetails/Grid3D.h index 6f6c1e237c673071859b7cf605ff89887c20c56a..7056e33f655197d14c4c5a61f7f79240335c5876 100644 --- a/src/TNL/Meshes/GridDetails/Grid3D.h +++ b/src/TNL/Meshes/GridDetails/Grid3D.h @@ -142,14 +142,6 @@ class Grid< 3, Real, Device, Index > : public Object bool load( const String& fileName ); - bool writeMesh( const String& fileName, - const String& format ) const; - - template< typename MeshFunction > - bool write( const MeshFunction& function, - const String& fileName, - const String& format ) const; - void writeProlog( Logger& logger ) const; protected: diff --git a/src/TNL/Meshes/GridDetails/Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Grid3D_impl.h index fa1c32dd2ba9fab60f1e9fffc9ce1d592885bfb6..e2f4f273088780dfac733d050ed547468a88639d 100644 --- a/src/TNL/Meshes/GridDetails/Grid3D_impl.h +++ b/src/TNL/Meshes/GridDetails/Grid3D_impl.h @@ -563,72 +563,9 @@ bool Grid< 3, Real, Device, Index > :: load( const String& fileName ) return Object :: load( fileName ); }; -template< typename Real, - typename Device, - typename Index > -bool Grid< 3, Real, Device, Index >::writeMesh( const String& fileName, - const String& format ) const -{ - /***** - * TODO: implement this - */ - return true; -} - template< typename Real, typename Device, typename Index > - template< typename MeshFunction > -bool Grid< 3, Real, Device, Index > :: write( const MeshFunction& function, - const String& fileName, - const String& format ) const -{ - if( this->template getEntitiesCount< Cell >() != function. getSize() ) - { - std::cerr << "The size ( " << function. getSize() - << " ) of a mesh function does not agree with the DOFs ( " << this->template getEntitiesCount< Cell >() << " ) of a mesh." << std::endl; - return false; - } - std::fstream file; - file. open( fileName. getString(), std::ios::out ); - if( ! file ) - { - std::cerr << "I am not able to open the file " << fileName << "." << std::endl; - return false; - } - file << std::setprecision( 12 ); - if( format == "gnuplot" ) - { - Cell cell( *this ); - for( cell.getCoordinates().z() = 0; - cell.getCoordinates().z() < getDimensions().z(); - cell.getCoordinates().z()++ ) - { - for( cell.getCoordinates().y() = 0; - cell.getCoordinates().y() < getDimensions().y(); - cell.getCoordinates().y()++ ) - { - for( cell.getCoordinates().x() = 0; - cell.getCoordinates().x() < getDimensions().x(); - cell.getCoordinates().x()++ ) - { - PointType v = cell.getCenter(); - GnuplotWriter::write( file, v ); - GnuplotWriter::write( file, function[ this->template getEntityIndex( cell ) ] ); - file << std::endl; - } - } - file << std::endl; - } - } - - file. close(); - return true; -} - -template< typename Real, - typename Device, - typename Index > void Grid< 3, Real, Device, Index >:: writeProlog( Logger& logger ) const diff --git a/src/TNL/Meshes/GridDetails/GridEntity_impl.h b/src/TNL/Meshes/GridDetails/GridEntity_impl.h index 8703c064fd6e2271ea3705ddb4355261edf14cd9..7c3820f6b6bdda78ea29437c7d10ebc41a172afc 100644 --- a/src/TNL/Meshes/GridDetails/GridEntity_impl.h +++ b/src/TNL/Meshes/GridDetails/GridEntity_impl.h @@ -675,6 +675,19 @@ getCenter() const return GridEntityCenterGetter< ThisType >::getEntityCenter( *this ); } +template< int Dimension, + typename Real, + typename Device, + typename Index, + typename Config > +__cuda_callable__ inline +typename Meshes::Grid< Dimension, Real, Device, Index >::PointType +GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >:: +getPoint() const +{ + return getCenter(); +} + template< int Dimension, typename Real, typename Device, diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h b/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h index c8f3a999b90a08e02b9bcb2cfb29b0270476f046..2bef7d8bdffbe4f797367af3ffb49af01fb47970 100644 --- a/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h +++ b/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h @@ -11,7 +11,7 @@ #pragma once #include <TNL/Devices/Cuda.h> -#include <TNL/Meshes/MeshDimensionTag.h> +#include <TNL/Meshes/DimensionTag.h> #include <TNL/Meshes/GridEntityConfig.h> #include <TNL/Meshes/GridDetails/NeighborGridEntityGetter.h> @@ -44,7 +44,7 @@ class NeighborGridEntityLayer< GridEntity, NeighborEntityDimension, GridEntityCo {} __cuda_callable__ - const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< NeighborEntityDimension>& tag ) const + const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< NeighborEntityDimension>& tag ) const { return this->neighborEntities; } @@ -76,7 +76,7 @@ class NeighborGridEntityLayer< GridEntity, 0, GridEntityConfig, true > {} __cuda_callable__ - const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< 0 >& tag ) const + const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< 0 >& tag ) const { return this->neighborEntities; } @@ -112,7 +112,7 @@ class NeighborGridEntityLayer< GridEntity, NeighborEntityDimension, GridEntityCo {} __cuda_callable__ - const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< NeighborEntityDimension >& tag ) const {} + const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< NeighborEntityDimension >& tag ) const {} __cuda_callable__ void refresh( const typename GridEntity::GridType& grid, @@ -131,7 +131,7 @@ class NeighborGridEntityLayer< GridEntity, 0, GridEntityConfig, false > NeighborGridEntityLayer( const GridEntity& entity ){} __cuda_callable__ - const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< 0 >& tag ) const {} + const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< 0 >& tag ) const {} __cuda_callable__ void refresh( const typename GridEntity::GridType& grid, @@ -163,7 +163,7 @@ class NeighborGridEntitiesStorage const NeighborGridEntityGetter< GridEntity, EntityDimension >& getNeighborEntities() const { - return BaseType::getNeighborEntities( MeshDimensionTag< EntityDimension >() ); + return BaseType::getNeighborEntities( DimensionTag< EntityDimension >() ); } }; diff --git a/src/TNL/Meshes/GridEntity.h b/src/TNL/Meshes/GridEntity.h index 4db50173285c267e61736a36827073dcb323a002..abad0a57d52695df4c1b34f476e2e99c523bb6ff 100644 --- a/src/TNL/Meshes/GridEntity.h +++ b/src/TNL/Meshes/GridEntity.h @@ -362,6 +362,10 @@ class GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config > __cuda_callable__ inline PointType getCenter() const; + // compatibility with meshes, equivalent to getCenter + __cuda_callable__ inline + PointType getPoint() const; + __cuda_callable__ inline const RealType getMeasure() const; diff --git a/src/TNL/Meshes/Mesh.h b/src/TNL/Meshes/Mesh.h index 47060304a5072def2801b54990df03a54c368e24..55c5bca319646a16fb927e0e99c8a74a8dd21817 100644 --- a/src/TNL/Meshes/Mesh.h +++ b/src/TNL/Meshes/Mesh.h @@ -18,98 +18,181 @@ #include <ostream> #include <TNL/Object.h> +#include <TNL/Logger.h> +#include <TNL/Containers/Vector.h> #include <TNL/Meshes/MeshEntity.h> +#include <TNL/Meshes/MeshDetails/ConfigValidator.h> #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> -#include <TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h> -#include <TNL/Meshes/MeshDetails/config/MeshConfigValidator.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshInitializer.h> +#include <TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h> +#include <TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h> + +#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h> namespace TNL { namespace Meshes { -template< typename MeshConfig > //, - //typename Device = Devices::Host > -class Mesh : public Object/*, - public MeshStorageLayers< MeshConfig >*/ +template< typename MeshConfig > class Initializer; +template< typename Mesh > class EntityStorageRebinder; +template< typename Mesh, int Dimension > struct IndexPermutationApplier; + + +template< typename MeshConfig, typename Device, typename MeshType > +class MeshInitializableBase +{ + public: + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + + // The points and cellSeeds arrays will be reset when not needed to save memory. + void init( typename MeshTraitsType::PointArrayType& points, + typename MeshTraitsType::CellSeedArrayType& cellSeeds ); +}; + +// The mesh cannot be initialized on CUDA GPU, so this specialization is empty. +template< typename MeshConfig, typename MeshType > +class MeshInitializableBase< MeshConfig, Devices::Cuda, MeshType > +{ +}; + + +template< typename MeshConfig, + typename Device = Devices::Host > +class Mesh + : public Object, + public ConfigValidator< MeshConfig >, + public MeshInitializableBase< MeshConfig, Device, Mesh< MeshConfig, Device > >, + public StorageLayerFamily< MeshConfig, Device >, + public BoundaryTags::LayerFamily< MeshConfig, Device, Mesh< MeshConfig, Device > > { + using StorageBaseType = StorageLayerFamily< MeshConfig, Device >; + using BoundaryTagsLayerFamily = BoundaryTags::LayerFamily< MeshConfig, Device, Mesh >; + public: - - typedef MeshConfig Config; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::DeviceType DeviceType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::CellType CellType; - typedef typename MeshTraitsType::VertexType VertexType; - typedef typename MeshTraitsType::PointType PointType; - static const int dimension = MeshTraitsType::meshDimension; - template< int Dimension > using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >; - template< int Dimension > using EntityType = typename EntityTraits< Dimension >::EntityType; + using Config = MeshConfig; + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using DeviceType = typename MeshTraitsType::DeviceType; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using PointType = typename MeshTraitsType::PointType; + using RealType = typename PointType::RealType; + using GlobalIndexVector = Containers::Vector< GlobalIndexType, DeviceType, GlobalIndexType >; + + // shortcuts, compatibility with grids + using HostType = Mesh< MeshConfig, Devices::Host >; + using CudaType = Mesh< MeshConfig, Devices::Cuda >; + + template< int Dimension > + using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >; + + template< int Dimension > + using EntityType = typename EntityTraits< Dimension >::EntityType; + + // constructors + Mesh() = default; + + Mesh( const Mesh& mesh ); + + template< typename Device_ > + Mesh( const Mesh< MeshConfig, Device_ >& mesh ); + + Mesh& operator=( const Mesh& mesh ); + + template< typename Device_ > + Mesh& operator=( const Mesh< MeshConfig, Device_ >& mesh ); + + + static constexpr int getMeshDimension(); + + // types of common entities + using Cell = EntityType< getMeshDimension() >; + using Face = EntityType< getMeshDimension() - 1 >; + using Vertex = EntityType< 0 >; static String getType(); - + virtual String getTypeVirtual() const; - - static constexpr int getMeshDimension(); - template< int Dimension > - bool entitiesAvalable() const; - - GlobalIndexType getNumberOfCells() const; + static String getSerializationType(); + + virtual String getSerializationTypeVirtual() const; + - // TODO: rename to getEntitiesCount template< int Dimension > - GlobalIndexType getNumberOfEntities() const; + static constexpr bool entitiesAvailable(); - CellType& getCell( const GlobalIndexType entityIndex ); + template< int Dimension > + __cuda_callable__ + GlobalIndexType getEntitiesCount() const; - const CellType& getCell( const GlobalIndexType entityIndex ) const; + template< int Dimension > + __cuda_callable__ + EntityType< Dimension >& getEntity( const GlobalIndexType& entityIndex ); template< int Dimension > - EntityType< Dimension >& getEntity( const GlobalIndexType entityIndex ); - + __cuda_callable__ + const EntityType< Dimension >& getEntity( const GlobalIndexType& entityIndex ) const; + + + // duplicated for compatibility with grids + template< typename EntityType > + __cuda_callable__ + GlobalIndexType getEntitiesCount() const; + + template< typename EntityType > + __cuda_callable__ + EntityType& getEntity( const GlobalIndexType& entityIndex ); + + template< typename EntityType > + __cuda_callable__ + const EntityType& getEntity( const GlobalIndexType& entityIndex ) const; + + + /* + * The permutations follow the definition used in the Metis library: Let M + * be the original mesh and M' the permuted mesh. Then entity with index i + * in M' is the entity with index perm[i] in M and entity with index j in + * M is the entity with index iperm[j] in M'. + */ template< int Dimension > - const EntityType< Dimension >& getEntity( const GlobalIndexType entityIndex ) const; + void reorderEntities( const GlobalIndexVector& perm, + const GlobalIndexVector& iperm ); + bool save( File& file ) const; bool load( File& file ); - + using Object::load; using Object::save; - + void print( std::ostream& str ) const; bool operator==( const Mesh& mesh ) const; - // TODO: this is only for mesh intializer - remove it if possible - template< typename DimensionTag > - typename EntityTraits< DimensionTag::value >::StorageArrayType& entitiesArray(); - - - template< typename DimensionTag, typename SuperDimensionTag > - typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray(); - - template< typename EntityTopology, typename SuperdimensionsTag > - typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType& - getSuperentityStorageNetwork() + bool operator!=( const Mesh& mesh ) const; + + void writeProlog( Logger& logger ) const; + + DistributedMeshes::DistributedMesh< Mesh<MeshConfig,Device> >* GetDistMesh(void) const { - return entitiesStorage.template getSuperentityStorageNetwork< SuperdimensionsTag >( MeshDimensionTag< EntityTopology::dimensions >() ); - } - - bool init( const typename MeshTraitsType::PointArrayType& points, - const typename MeshTraitsType::CellSeedArrayType& cellSeeds ); - - + return NULL; + }; + protected: - - MeshStorageLayers< MeshConfig > entitiesStorage; - - MeshConfigValidator< MeshConfig > configValidator; + // Methods for the mesh initializer + using StorageBaseType::setEntitiesCount; + using StorageBaseType::getSubentityStorageNetwork; + using StorageBaseType::getSuperentityStorageNetwork; + + friend Initializer< MeshConfig >; + + friend EntityStorageRebinder< Mesh >; + + template< typename Mesh, int Dimension > + friend struct IndexPermutationApplier; }; -template< typename MeshConfig > -std::ostream& operator <<( std::ostream& str, const Mesh< MeshConfig >& mesh ); +template< typename MeshConfig, typename Device > +std::ostream& operator<<( std::ostream& str, const Mesh< MeshConfig, Device >& mesh ); } // namespace Meshes } // namespace TNL diff --git a/src/TNL/Meshes/MeshBuilder.h b/src/TNL/Meshes/MeshBuilder.h index cfa5058a280edadcfa489b971f9dbbac9e2ada98..f0d9996357d3048126d8ae8f06ca2e820aa32b39 100644 --- a/src/TNL/Meshes/MeshBuilder.h +++ b/src/TNL/Meshes/MeshBuilder.h @@ -16,6 +16,7 @@ #pragma once +#include <TNL/Containers/Vector.h> #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> namespace TNL { @@ -24,101 +25,96 @@ namespace Meshes { template< typename Mesh > class MeshBuilder { - //static constexpr const char *CLASS_NAME = "MeshBuilder"; - - public: - typedef Mesh MeshType; - typedef typename MeshType::MeshTraitsType MeshTraitsType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::PointType PointType; - typedef typename MeshTraitsType::CellTopology CellTopology; - typedef typename MeshTraitsType::CellSeedType CellSeedType; - - bool setPointsCount( const GlobalIndexType& points ) +public: + using MeshType = Mesh; + using MeshTraitsType = typename MeshType::MeshTraitsType; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using PointType = typename MeshTraitsType::PointType; + using CellTopology = typename MeshTraitsType::CellTopology; + using CellSeedType = typename MeshTraitsType::CellSeedType; + + void setPointsCount( const GlobalIndexType& points ) { - TNL_ASSERT( 0 <= points, std::cerr << "pointsCount = " << points ); this->points.setSize( points ); this->pointsSet.setSize( points ); pointsSet.setValue( false ); - return true; } - - bool setCellsCount( const GlobalIndexType& cellsCount ) + + void setCellsCount( const GlobalIndexType& cellsCount ) { - TNL_ASSERT( 0 <= cellsCount, std::cerr << "cellsCount = " << cellsCount ); this->cellSeeds.setSize( cellsCount ); - return true; } - - GlobalIndexType getPointsCount() const { return this->points.getSize(); } - - GlobalIndexType getCellsCount() const { return this->cellSeeds.getSize(); } - void setPoint( GlobalIndexType index, - const PointType& point ) + GlobalIndexType getPointsCount() const + { + return this->points.getSize(); + } + + GlobalIndexType getCellsCount() const { - TNL_ASSERT( 0 <= index && index < getPointsCount(), std::cerr << "Index = " << index ); + return this->cellSeeds.getSize(); + } - this->points[ index ] = point; - this->pointsSet[ index ] = true; + void setPoint( GlobalIndexType index, + const PointType& point ) + { + this->points[ index ] = point; + this->pointsSet[ index ] = true; } CellSeedType& getCellSeed( GlobalIndexType index ) { - TNL_ASSERT( 0 <= index && index < getCellsCount(), std::cerr << "Index = " << index ); - return this->cellSeeds[ index ]; } - bool build( MeshType& mesh ) const + bool build( MeshType& mesh ) { if( ! this->validate() ) return false; - if( ! mesh.init( this->points, this->cellSeeds ) ) - return false; + mesh.init( this->points, this->cellSeeds ); return true; } - private: - typedef typename MeshTraitsType::PointArrayType PointArrayType; - typedef typename MeshTraitsType::CellSeedArrayType CellSeedArrayType; - - bool validate() const - { - if( !allPointsSet() ) - { - std::cerr << "Mesh builder error: Not all points were set." << std::endl; - return false; - } +private: + using PointArrayType = typename MeshTraitsType::PointArrayType; + using CellSeedArrayType = typename MeshTraitsType::CellSeedArrayType; + using BoolVector = Containers::Vector< bool, Devices::Host, GlobalIndexType >; - for( GlobalIndexType i = 0; i < getCellsCount(); i++ ) - { - auto cornerIds = this->cellSeeds[ i ].getCornerIds(); - for( LocalIndexType j = 0; j < cornerIds.getSize(); j++ ) - if( cornerIds[ j ] < 0 || getPointsCount() <= cornerIds[ j ] ) - { - std::cerr << "Cell seed " << i << " is referencing unavailable point " << cornerIds[ j ] << std::endl; - return false; - } - } - return true; + bool validate() const + { + if( pointsSet.min() != true ) { + std::cerr << "Mesh builder error: Not all points were set." << std::endl; + return false; } + BoolVector assignedPoints; + assignedPoints.setLike( pointsSet ); + assignedPoints.setValue( false ); - bool allPointsSet() const - { - for( GlobalIndexType i = 0; i < this->points.getSize(); i++ ) - if (! this->pointsSet[ i ] ) + for( GlobalIndexType i = 0; i < getCellsCount(); i++ ) { + const auto cornerIds = this->cellSeeds[ i ].getCornerIds(); + for( LocalIndexType j = 0; j < cornerIds.getSize(); j++ ) { + assignedPoints[ cornerIds[ j ] ] = true; + if( cornerIds[ j ] < 0 || getPointsCount() <= cornerIds[ j ] ) { + std::cerr << "Cell seed " << i << " is referencing unavailable point " << cornerIds[ j ] << std::endl; return false; - return true; + } + } + } + + if( assignedPoints.min() != true ) { + std::cerr << "Mesh builder error: Some points were not used for cells." << std::endl; + return false; } - PointArrayType points; - CellSeedArrayType cellSeeds; - Containers::Array< bool, Devices::Host, GlobalIndexType > pointsSet; + return true; + } + + PointArrayType points; + CellSeedArrayType cellSeeds; + BoolVector pointsSet; }; } // namespace Meshes } // namespace TNL - diff --git a/src/TNL/Meshes/MeshConfigBase.h b/src/TNL/Meshes/MeshConfigBase.h deleted file mode 100644 index 523afce5b6d84824632eb1b9fd9d01c35ea2ffcb..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshConfigBase.h +++ /dev/null @@ -1,99 +0,0 @@ -/*************************************************************************** - MeshConfigBase.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -namespace TNL { -namespace Meshes { - -/**** - * Basic structure for mesh configuration. - * Setting Id to GlobalIndex enables storage of entity Id. - * It means that each mesh entity stores its index in its - * mesh storage layer. - */ -template< typename Cell, - int WorldDimension = Cell::dimensions, - typename Real = double, - typename GlobalIndex = int, - typename LocalIndex = GlobalIndex, - typename Id = void > -struct MeshConfigBase -{ - typedef Cell CellTopology; - typedef Real RealType; - typedef GlobalIndex GlobalIndexType; - typedef LocalIndex LocalIndexType; - typedef Id IdType; - - static const int worldDimension = WorldDimension; - static const int meshDimension = Cell::dimensions; - - static String getType() - { - return String( "MeshConfigBase< >"); - }; - - /**** - * Storage of mesh entities. - */ - static constexpr bool entityStorage( int dimensions ) - { - /**** - * Vertices and cells must always be stored - */ - return true; - //return ( dimensions == 0 || dimensions == cellDimension ); - } - - /**** - * Storage of subentities of mesh entities - */ - template< typename MeshEntity > - static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) - { - /**** - * Vertices must always be stored - */ - return true; - //return ( SubentityDimension == 0 ); - } - - /**** - * Storage of subentity orientations of mesh entities. - * It must be false for vertices and cells. - */ - template< typename MeshEntity > - static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) - { - return ( SubentityDimension > 0 ); - } - - /**** - * Storage of superentities of mesh entities - */ - template< typename MeshEntity > - static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) - { - return true; - //return false; - } - - static_assert( WorldDimension >= Cell::dimensions, "The number of the cell dimensions cannot be larger than the world dimension." ); -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/CMakeLists.txt index 95862f45e781e8be0a3fa163042abf121bcbc9b3..7e6b56e832798053c25c3bac527f2bebba90b586 100644 --- a/src/TNL/Meshes/MeshDetails/CMakeLists.txt +++ b/src/TNL/Meshes/MeshDetails/CMakeLists.txt @@ -1,21 +1,18 @@ -ADD_SUBDIRECTORY( config ) ADD_SUBDIRECTORY( initializer ) -ADD_SUBDIRECTORY( layers ) +ADD_SUBDIRECTORY( EntityLayers ) +ADD_SUBDIRECTORY( MeshLayers ) ADD_SUBDIRECTORY( traits ) -SET( headers MeshEntityId.h - MeshEntityIntegrityChecker.h +SET( headers ConfigValidator.h + EntityStorageRebinder.h + IndexPermutationApplier.h + MeshEntityIndex.h MeshEntityOrientation.h + MeshEntityReferenceOrientation.h MeshEntity_impl.h MeshIntegrityChecker.h MeshIntegrityCheckerLayer.h - MeshReaderNetgen.h - MeshWriterNetgen.h - MeshWriterVTKLegacy.h - Mesh_impl.h ) + Mesh_impl.h + Traverser_impl.h ) -SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Meshes/MeshDetails ) -SET( tnl_mesh_SOURCES ${tnl_mesh_griddetails_SOURCES} - PARENT_SCOPE ) - -INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails ) \ No newline at end of file +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails ) diff --git a/src/TNL/Meshes/MeshDetails/ConfigValidator.h b/src/TNL/Meshes/MeshDetails/ConfigValidator.h new file mode 100644 index 0000000000000000000000000000000000000000..9f27538383a012b2aebc2be2be78bf9817c0c039 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/ConfigValidator.h @@ -0,0 +1,125 @@ +/*************************************************************************** + ConfigValidator.h - description + ------------------- + begin : Aug 14, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> +#include <TNL/Meshes/DimensionTag.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename EntityTopology, + typename DimensionTag > +class ConfigValidatorSubtopologyLayer + : public ConfigValidatorSubtopologyLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement > +{ + static_assert( ! MeshConfig::subentityStorage( EntityTopology(), DimensionTag::value ) || + MeshConfig::entityStorage( EntityTopology::dimension ), + "entities of which subentities are stored must be stored" ); + static_assert( ! MeshConfig::subentityStorage( EntityTopology(), DimensionTag::value ) || + MeshConfig::entityStorage( DimensionTag::value ), + "entities that are stored as subentities must be stored"); + static_assert( ! MeshConfig::subentityOrientationStorage( EntityTopology(), DimensionTag::value ) || + MeshConfig::subentityStorage( EntityTopology(), DimensionTag::value ), + "orientation can be stored only for subentities that are stored"); +}; + +template< typename MeshConfig, + typename EntityTopology > +class ConfigValidatorSubtopologyLayer< MeshConfig, EntityTopology, DimensionTag< 0 > > +{ + static_assert( ! MeshConfig::subentityStorage( EntityTopology(), 0 ) || + MeshConfig::entityStorage( EntityTopology::dimension ), + "entities of which subvertices are stored must be stored" ); + static_assert( ! MeshConfig::subentityOrientationStorage( EntityTopology(), 0 ), + "storage of vertex orientation does not make sense" ); +}; + + +template< typename MeshConfig, + typename EntityTopology, + typename DimensionTag > +class ConfigValidatorSupertopologyLayer + : public ConfigValidatorSupertopologyLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement > +{ + static_assert( ! MeshConfig::superentityStorage( EntityTopology(), DimensionTag::value ) || + MeshConfig::entityStorage( EntityTopology::dimension ), + "entities of which superentities are stored must be stored"); + static_assert( ! MeshConfig::superentityStorage( EntityTopology(), DimensionTag::value ) || + MeshConfig::entityStorage( DimensionTag::value ), + "entities that are stored as superentities must be stored"); +}; + +template< typename MeshConfig, + typename EntityTopology > +class ConfigValidatorSupertopologyLayer< MeshConfig, EntityTopology, DimensionTag< EntityTopology::dimension > > +{}; + + +template< typename MeshConfig, int dimension > +class ConfigValidatorLayer + : public ConfigValidatorLayer< MeshConfig, dimension - 1 >, + public ConfigValidatorSubtopologyLayer< MeshConfig, + typename Topologies::Subtopology< typename MeshConfig::CellTopology, dimension >::Topology, + DimensionTag< dimension - 1 > >, + public ConfigValidatorSupertopologyLayer< MeshConfig, + typename Topologies::Subtopology< typename MeshConfig::CellTopology, dimension >::Topology, + DimensionTag< MeshConfig::CellTopology::dimension > > +{ + using Topology = typename Topologies::Subtopology< typename MeshConfig::CellTopology, dimension >::Topology; + + static_assert( ! MeshConfig::entityStorage( dimension ) || + MeshConfig::subentityStorage( Topology(), 0 ), + "subvertices of all stored entities must be stored"); +}; + +template< typename MeshConfig > +class ConfigValidatorLayer< MeshConfig, 0 > +{ +}; + +template< typename MeshConfig > +class ConfigValidatorLayerCell + : public ConfigValidatorLayer< MeshConfig, MeshConfig::CellTopology::dimension - 1 >, + public ConfigValidatorSubtopologyLayer< MeshConfig, + typename MeshConfig::CellTopology, + DimensionTag< MeshConfig::CellTopology::dimension - 1 > > +{ + using CellTopology = typename MeshConfig::CellTopology; + static constexpr int dimension = CellTopology::dimension; + + static_assert( ! MeshConfig::entityStorage( dimension ) || + MeshConfig::subentityStorage( CellTopology(), 0 ), + "subvertices of all stored entities must be stored" ); +}; + +template< typename MeshConfig > +class ConfigValidator + : public ConfigValidatorLayerCell< MeshConfig > +{ + static constexpr int meshDimension = MeshConfig::CellTopology::dimension; + + static_assert( 1 <= meshDimension, "zero dimensional meshes are not supported" ); + static_assert( meshDimension <= MeshConfig::worldDimension, "world dimension must not be less than mesh dimension" ); + + static_assert( MeshConfig::entityStorage( 0 ), "mesh vertices must be stored" ); + static_assert( MeshConfig::entityStorage( meshDimension ), "mesh cells must be stored" ); +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/EntityLayers/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/EntityLayers/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a53be02ead6d8dea884e6d7ab7f5f926a2617286 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/EntityLayers/CMakeLists.txt @@ -0,0 +1,5 @@ +SET( headers SubentityAccess.h + SuperentityAccess.h +) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/EntityLayers ) diff --git a/src/TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h b/src/TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h new file mode 100644 index 0000000000000000000000000000000000000000..4adc400d450d26dff4af235f11334d58249a28c9 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h @@ -0,0 +1,419 @@ +/*************************************************************************** + SubentityAccess.h - description + ------------------- + begin : Oct 26, 2016 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/File.h> +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> +#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h> +#include <TNL/Meshes/MeshDetails/MeshEntityOrientation.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename DimensionTag, + bool SubentityStorage = + WeakSubentityStorageTrait< MeshConfig, Device, EntityTopology, DimensionTag >::storageEnabled, + bool SubentityOrientationStorage = + MeshConfig::subentityOrientationStorage( EntityTopology(), DimensionTag::value ) > +class SubentityAccessLayer; + + +template< typename MeshConfig, + typename Device, + typename EntityTopology > +class SubentityAccessLayerFamily + : public SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + Meshes::DimensionTag< 0 > > +{ + using BaseType = SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + Meshes::DimensionTag< 0 > >; + + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + + template< int Subdimension > + using SubentityTraits = typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimension >; + +public: + template< int Subdimension > + __cuda_callable__ + void bindSubentitiesStorageNetwork( const typename SubentityTraits< Subdimension >::SubentityAccessorType& storage ) + { + static_assert( SubentityTraits< Subdimension >::storageEnabled, "You try to bind subentities which are not configured for storage." ); + BaseType::bindSubentitiesStorageNetwork( Meshes::DimensionTag< Subdimension >(), + storage ); + } + + template< int Subdimension > + static constexpr typename MeshTraitsType::LocalIndexType getSubentitiesCount() + { + return SubentityTraits< Subdimension >::count; + } + + template< int Subdimension > + __cuda_callable__ + void setSubentityIndex( const typename MeshTraitsType::LocalIndexType& localIndex, + const typename MeshTraitsType::GlobalIndexType& globalIndex ) + { + static_assert( SubentityTraits< Subdimension >::storageEnabled, "You try to set subentity which is not configured for storage." ); + BaseType::setSubentityIndex( Meshes::DimensionTag< Subdimension >(), + localIndex, + globalIndex ); + } + + template< int Subdimension > + __cuda_callable__ + typename MeshTraitsType::GlobalIndexType + getSubentityIndex( const typename MeshTraitsType::LocalIndexType localIndex ) const + { + static_assert( SubentityTraits< Subdimension >::storageEnabled, "You try to get subentity which is not configured for storage." ); + return BaseType::getSubentityIndex( Meshes::DimensionTag< Subdimension >(), + localIndex ); + } + + template< int Subdimension > + __cuda_callable__ + typename SubentityTraits< Subdimension >::OrientationArrayType& subentityOrientationsArray() + { + static_assert( SubentityTraits< Subdimension >::orientationEnabled, "You try to get subentity orientation which is not configured for storage." ); + return BaseType::subentityOrientationsArray( Meshes::DimensionTag< Subdimension >() ); + } + + template< int Subdimension > + __cuda_callable__ + typename SubentityTraits< Subdimension >::IdPermutationArrayType getSubentityOrientation( typename MeshTraitsType::LocalIndexType index ) const + { + static_assert( SubentityTraits< Subdimension >::orientationEnabled, "You try to get subentity orientation which is not configured for storage." ); + return BaseType::getSubentityOrientation( Meshes::DimensionTag< Subdimension >(), index ); + } + + __cuda_callable__ + bool operator==( const SubentityAccessLayerFamily& other ) const + { + return BaseType::operator==( other ); + } + + void print( std::ostream& str ) const + { + BaseType::print( str ); + } +}; + + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename DimensionTag > +class SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag, + true, + true > + : public SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + typename DimensionTag::Increment > +{ + using BaseType = SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + typename DimensionTag::Increment >; + + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using SubentityTraitsType = typename MeshTraitsType::template SubentityTraits< EntityTopology, DimensionTag::value >; + +protected: + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using SubentityAccessorType = typename SubentityTraitsType::SubentityAccessorType; + using OrientationArrayType = typename SubentityTraitsType::OrientationArrayType; + using IdPermutationArrayType = typename SubentityTraitsType::IdPermutationArrayType; + + SubentityAccessLayer() = default; + + __cuda_callable__ + explicit SubentityAccessLayer( const SubentityAccessLayer& layer ) + : BaseType( layer ) + { + this->subentityIndices.bind( layer.subentityIndices ); + } + + __cuda_callable__ + SubentityAccessLayer& operator=( const SubentityAccessLayer& layer ) + { + BaseType::operator=( layer ); + this->subentityIndices.bind( layer.subentityIndices ); + return *this; + } + + void print( std::ostream& str ) const + { + BaseType::print( str ); + str << "\t Subentities with dimension " << DimensionTag::value << " are: " << subentityIndices << "." << std::endl; + } + + __cuda_callable__ + bool operator==( const SubentityAccessLayer& layer ) const + { + return ( BaseType::operator==( layer ) && + subentityIndices == layer.subentityIndices ); + } + + /**** + * Make visible setters and getters of the lower subentities + */ + using BaseType::bindSubentitiesStorageNetwork; + using BaseType::getSubentityIndex; + using BaseType::setSubentityIndex; + using BaseType::getSubentityIndices; + + /**** + * Define setter/getter for the current level of the subentities + */ + __cuda_callable__ + void bindSubentitiesStorageNetwork( DimensionTag, + const SubentityAccessorType& storage ) + { + this->subentityIndices.bind( storage ); + } + + __cuda_callable__ + void setSubentityIndex( DimensionTag, + const LocalIndexType localIndex, + const GlobalIndexType globalIndex ) + { + this->subentityIndices[ localIndex ] = globalIndex; + } + + __cuda_callable__ + GlobalIndexType getSubentityIndex( DimensionTag, + const LocalIndexType localIndex ) const + { + return this->subentityIndices[ localIndex ]; + } + + __cuda_callable__ + const SubentityAccessorType& getSubentityIndices( DimensionTag ) const + { + return this->subentityIndices; + } + + __cuda_callable__ + SubentityAccessorType& getSubentityIndices( DimensionTag ) + { + return this->subentityIndices; + } + + using BaseType::getSubentityOrientation; + __cuda_callable__ + const IdPermutationArrayType& getSubentityOrientation( DimensionTag, LocalIndexType index) const + { + TNL_ASSERT_GE( index, 0, "index must be non-negative" ); + TNL_ASSERT_LT( index, SubentityTraitsType::count, "index is out of bounds" ); + return this->subentityOrientations[ index ].getSubvertexPermutation(); + } + + using BaseType::subentityOrientationsArray; + __cuda_callable__ + OrientationArrayType& subentityOrientationsArray( DimensionTag ) { return this->subentityOrientations; } + +private: + SubentityAccessorType subentityIndices; + + OrientationArrayType subentityOrientations; +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename DimensionTag > +class SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag, + true, + false > + : public SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + typename DimensionTag::Increment > +{ + static_assert( DimensionTag::value < EntityTopology::dimension, "" ); + using BaseType = SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + typename DimensionTag::Increment >; + + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using SubentityTraitsType = typename MeshTraitsType::template SubentityTraits< EntityTopology, DimensionTag::value >; + +protected: + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using SubentityAccessorType = typename SubentityTraitsType::SubentityAccessorType; + + SubentityAccessLayer() = default; + + __cuda_callable__ + explicit SubentityAccessLayer( const SubentityAccessLayer& layer ) + : BaseType( layer ) + { + this->subentityIndices.bind( layer.subentityIndices ); + } + + __cuda_callable__ + SubentityAccessLayer& operator=( const SubentityAccessLayer& layer ) + { + BaseType::operator=( layer ); + this->subentityIndices.bind( layer.subentityIndices ); + return *this; + } + + void print( std::ostream& str ) const + { + BaseType::print( str ); + str << "\t Subentities with dimension " << DimensionTag::value << " are: " << subentityIndices << "." << std::endl; + } + + __cuda_callable__ + bool operator==( const SubentityAccessLayer& layer ) const + { + return ( BaseType::operator==( layer ) && + subentityIndices == layer.subentityIndices ); + } + + /**** + * Make visible setters and getters of the lower subentities + */ + using BaseType::bindSubentitiesStorageNetwork; + using BaseType::getSubentityIndex; + using BaseType::setSubentityIndex; + using BaseType::getSubentityIndices; + + /**** + * Define setter/getter for the current level of the subentities + */ + __cuda_callable__ + void bindSubentitiesStorageNetwork( DimensionTag, + const SubentityAccessorType& storage ) + { + this->subentityIndices.bind( storage ); + } + + __cuda_callable__ + void setSubentityIndex( DimensionTag, + const LocalIndexType localIndex, + const GlobalIndexType globalIndex ) + { + this->subentityIndices[ localIndex ] = globalIndex; + } + + __cuda_callable__ + GlobalIndexType getSubentityIndex( DimensionTag, + const LocalIndexType localIndex ) const + { + return this->subentityIndices[ localIndex ]; + } + + __cuda_callable__ + const SubentityAccessorType& getSubentityIndices( DimensionTag ) const + { + return this->subentityIndices; + } + + __cuda_callable__ + SubentityAccessorType& getSubentityIndices( DimensionTag ) + { + return this->subentityIndices; + } + +private: + SubentityAccessorType subentityIndices; +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename DimensionTag, + bool SubentityOrientationStorage > +class SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag, + false, + SubentityOrientationStorage > + : public SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + typename DimensionTag::Increment > +{ +}; + +// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSubentityStorageTrait) +template< typename MeshConfig, + typename Device, + typename EntityTopology, + bool SubentityOrientationStorage > +class SubentityAccessLayer< MeshConfig, + Device, + EntityTopology, + Meshes::DimensionTag< EntityTopology::dimension >, + false, + SubentityOrientationStorage > +{ + using DimensionTag = Meshes::DimensionTag< EntityTopology::dimension >; + +protected: + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + using LocalIndexType = typename MeshConfig::LocalIndexType; + + /*** + * Necessary because of 'using BaseType::...;' in the derived classes + */ + template< typename SubentityAccessorType > + __cuda_callable__ + void bindSubentitiesStorageNetwork( DimensionTag, + const SubentityAccessorType& storage ) {} + __cuda_callable__ + void getSubentityIndex( DimensionTag, + const LocalIndexType localIndex ) const {} + __cuda_callable__ + void setSubentityIndex( DimensionTag, + const LocalIndexType& localIndex, + const GlobalIndexType& globalIndex ) {} + __cuda_callable__ + void getSubentityIndices() {} + + template< typename LocalIndexType > + __cuda_callable__ + void getSubentityOrientation( DimensionTag, LocalIndexType index) const {} + __cuda_callable__ + void subentityOrientationsArray( DimensionTag ) {} + + __cuda_callable__ + bool operator==( const SubentityAccessLayer& other ) const + { + return true; + } + + void print( std::ostream& str ) const {} +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h b/src/TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h new file mode 100644 index 0000000000000000000000000000000000000000..47457181651a631d6ccce3bcba216c78be18e38d --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h @@ -0,0 +1,288 @@ +/*************************************************************************** + SuperentityAccess.h - description + ------------------- + begin : Aug 15, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> +#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename DimensionTag, + bool SuperentityStorage = WeakSuperentityStorageTrait< MeshConfig, Device, EntityTopology, DimensionTag >::storageEnabled > +class SuperentityAccessLayer; + + +template< typename MeshConfig, + typename Device, + typename EntityTopology > +class SuperentityAccessLayerFamily + : public SuperentityAccessLayer< MeshConfig, + Device, + EntityTopology, + Meshes::DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > > +{ + using BaseType = SuperentityAccessLayer< MeshConfig, + Device, + EntityTopology, + Meshes::DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > >; + + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + + template< int Superdimension > + using SuperentityTraits = typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >; + +public: + template< int Superdimension > + __cuda_callable__ + void bindSuperentitiesStorageNetwork( const typename SuperentityTraits< Superdimension >::SuperentityAccessorType& storage ) + { + static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to bind superentities which are not configured for storage." ); + BaseType::bindSuperentitiesStorageNetwork( Meshes::DimensionTag< Superdimension >(), + storage ); + } + + template< int Superdimension > + __cuda_callable__ + void setNumberOfSuperentities( const typename MeshTraitsType::LocalIndexType size ) + { + static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to set number of superentities which are not configured for storage." ); + BaseType::setNumberOfSuperentities( Meshes::DimensionTag< Superdimension >(), + size ); + } + + template< int Superdimension > + __cuda_callable__ + typename MeshTraitsType::LocalIndexType + getSuperentitiesCount() const + { + static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to get number of superentities which are not configured for storage." ); + return BaseType::getSuperentitiesCount( Meshes::DimensionTag< Superdimension >() ); + } + + template< int Superdimension > + __cuda_callable__ + void + setSuperentityIndex( const typename MeshTraitsType::LocalIndexType& localIndex, + const typename MeshTraitsType::GlobalIndexType& globalIndex ) + { + static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to set superentities which are not configured for storage." ); + BaseType::setSuperentityIndex( Meshes::DimensionTag< Superdimension >(), + localIndex, + globalIndex ); + } + + template< int Superdimension > + __cuda_callable__ + typename MeshTraitsType::GlobalIndexType + getSuperentityIndex( const typename MeshTraitsType::LocalIndexType localIndex ) const + { + static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to get superentities which are not configured for storage." ); + return BaseType::getSuperentityIndex( Meshes::DimensionTag< Superdimension >(), + localIndex ); + } + + __cuda_callable__ + bool operator==( const SuperentityAccessLayerFamily& other ) const + { + return BaseType::operator==( other ); + } + + void print( std::ostream& str ) const + { + BaseType::print( str ); + } +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename DimensionTag > +class SuperentityAccessLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag, + true > + : public SuperentityAccessLayer< MeshConfig, Device, EntityTopology, typename DimensionTag::Decrement > +{ + using BaseType = SuperentityAccessLayer< MeshConfig, Device, EntityTopology, typename DimensionTag::Decrement >; + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using SuperentityTraitsType = typename MeshTraitsType::template SuperentityTraits< EntityTopology, DimensionTag::value >; + +public: + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using SuperentityAccessorType = typename SuperentityTraitsType::SuperentityAccessorType; + + /**** + * Make visible setters and getters of the lower superentities + */ + using BaseType::bindSuperentitiesStorageNetwork; + using BaseType::setNumberOfSuperentities; + using BaseType::getSuperentitiesCount; + using BaseType::setSuperentityIndex; + using BaseType::getSuperentityIndex; + using BaseType::getSuperentityIndices; + + SuperentityAccessLayer() = default; + + __cuda_callable__ + explicit SuperentityAccessLayer( const SuperentityAccessLayer& layer ) + : BaseType( layer ) + { + this->superentityIndices.bind( layer.superentityIndices ); + } + + __cuda_callable__ + SuperentityAccessLayer& operator=( const SuperentityAccessLayer& layer ) + { + BaseType::operator=( layer ); + this->superentityIndices.bind( layer.superentityIndices ); + return *this; + } + + /**** + * Define setter/getter for the current level of the superentities + */ + __cuda_callable__ + void bindSuperentitiesStorageNetwork( DimensionTag, + const SuperentityAccessorType& storage ) + { + this->superentityIndices.bind( storage ); + } + + __cuda_callable__ + void setNumberOfSuperentities( DimensionTag, + const LocalIndexType size ) + { + this->superentityIndices.setSize( size ); + } + + __cuda_callable__ + LocalIndexType getSuperentitiesCount( DimensionTag ) const + { + return this->superentityIndices.getSize(); + } + + __cuda_callable__ + void setSuperentityIndex( DimensionTag, + const LocalIndexType& localIndex, + const GlobalIndexType& globalIndex ) + { + this->superentityIndices[ localIndex ] = globalIndex; + } + + __cuda_callable__ + GlobalIndexType getSuperentityIndex( DimensionTag, + const LocalIndexType localIndex ) const + { + return this->superentityIndices[ localIndex ]; + } + + __cuda_callable__ + const SuperentityAccessorType& getSuperentityIndices( DimensionTag ) const + { + return this->superentityIndices; + } + + __cuda_callable__ + SuperentityAccessorType& getSuperentityIndices( DimensionTag ) + { + return this->superentityIndices; + } + + __cuda_callable__ + bool operator==( const SuperentityAccessLayer& other ) const + { + return ( BaseType::operator==( other ) && superentityIndices == other.superentityIndices ); + } + + void print( std::ostream& str ) const + { + BaseType::print( str ); + str << "\t Superentities with dimension " << DimensionTag::value << " are: " << this->superentityIndices << "." << std::endl; + } + +private: + SuperentityAccessorType superentityIndices; +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename DimensionTag > +class SuperentityAccessLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag, + false > + : public SuperentityAccessLayer< MeshConfig, Device, EntityTopology, typename DimensionTag::Decrement > +{ +}; + +// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSuperentityStorageTrait) +template< typename MeshConfig, + typename Device, + typename EntityTopology > +class SuperentityAccessLayer< MeshConfig, + Device, + EntityTopology, + Meshes::DimensionTag< EntityTopology::dimension >, + false > +{ + using DimensionTag = Meshes::DimensionTag< EntityTopology::dimension >; + +protected: + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + using LocalIndexType = typename MeshConfig::LocalIndexType; + + /*** + * Necessary because of 'using BaseType::...;' in the derived classes + */ + template< typename SuperentityAccessorType > + __cuda_callable__ + void bindSuperentitiesStorageNetwork( DimensionTag, + const SuperentityAccessorType& storage ) {} + __cuda_callable__ + void setNumberOfSuperentities( DimensionTag, + const LocalIndexType size ) {} + __cuda_callable__ + void getSuperentitiesCount( DimensionTag ) const {} + __cuda_callable__ + void getSuperentityIndex( DimensionTag, + const LocalIndexType localIndex ) const {} + __cuda_callable__ + void setSuperentityIndex( DimensionTag, + const LocalIndexType& localIndex, + const GlobalIndexType& globalIndex ) {} + __cuda_callable__ + void getSuperentityIndices() {} + + __cuda_callable__ + bool operator==( const SuperentityAccessLayer& other ) const + { + return true; + } + + void print( std::ostream& str ) const {} +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/EntityStorageRebinder.h b/src/TNL/Meshes/MeshDetails/EntityStorageRebinder.h new file mode 100644 index 0000000000000000000000000000000000000000..c5c6516cc8936c953a71c265bc024a323a41afb7 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/EntityStorageRebinder.h @@ -0,0 +1,159 @@ +/*************************************************************************** + EntityStorageRebinder.h - description + ------------------- + begin : Oct 22, 2016 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +/* + * Everything in this file is basically just a templatized version of the + * following pseudo-code (which does not work because normal variables are not + * usable in template arguments): + * + * for( int dimension = 0; dimension < MeshTraitsType::meshDimension; dimension++ ) + * for( int superdimension = dimension + 1; superdimension <= MeshTraitsType::meshDimension; superdimension++ ) + * if( EntityTraits< dimension >::SuperentityTraits< superdimension >::storageEnabled ) + * for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< dimension >(); i++ ) + * { + * auto& entity = mesh.template getEntity< dimension >( i ); + * entity.template bindSuperentitiesStorageNetwork< superdimension >( mesh.template getSuperentityStorageNetwork< superdimension >().getValues( i ) ); + * } + */ + +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/Mesh.h> +#include <TNL/DevicePointer.h> +#include <TNL/ParallelFor.h> +#include <TNL/StaticFor.h> + +namespace TNL { +namespace Meshes { + +template< typename Mesh > +class EntityStorageRebinder +{ + using IndexType = typename Mesh::GlobalIndexType; + using DeviceType = typename Mesh::DeviceType; + +// nvcc does not allow __cuda_callable__ lambdas inside private or protected sections +#ifdef __NVCC__ +public: +#endif + template< typename DimensionTag, + typename SuperdimensionTag, + bool Enabled = + Mesh::MeshTraitsType::template SuperentityTraits< typename Mesh::template EntityType< DimensionTag::value >::EntityTopology, + SuperdimensionTag::value >::storageEnabled + > + struct SuperentityWorker + { + static void bindSuperentities( Mesh& mesh ) + { + const IndexType entitiesCount = mesh.template getEntitiesCount< DimensionTag::value >(); + auto& superentitiesStorage = mesh.template getSuperentityStorageNetwork< DimensionTag::value, SuperdimensionTag::value >(); + using Multimap = typename std::remove_reference< decltype(superentitiesStorage) >::type; + DevicePointer< Mesh > meshPointer( mesh ); + DevicePointer< Multimap > superentitiesStoragePointer( superentitiesStorage ); + + auto kernel = [] __cuda_callable__ + ( IndexType i, + Mesh* mesh, + Multimap* superentitiesStorage ) + { + auto& subentity = mesh->template getEntity< DimensionTag::value >( i ); + subentity.template bindSuperentitiesStorageNetwork< SuperdimensionTag::value >( superentitiesStorage->getValues( i ) ); + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount, + kernel, + &meshPointer.template modifyData< DeviceType >(), + &superentitiesStoragePointer.template modifyData< DeviceType >() ); + } + }; + + template< typename DimensionTag, + typename SuperdimensionTag > + struct SuperentityWorker< DimensionTag, SuperdimensionTag, false > + { + static void bindSuperentities( Mesh& mesh ) {} + }; + + + template< typename DimensionTag, + typename SuperdimensionTag, + bool Enabled = + Mesh::MeshTraitsType::template SubentityTraits< typename Mesh::template EntityType< SuperdimensionTag::value >::EntityTopology, + DimensionTag::value >::storageEnabled + > + struct SubentityWorker + { + static void bindSubentities( Mesh& mesh ) + { + const IndexType entitiesCount = mesh.template getEntitiesCount< SuperdimensionTag::value >(); + auto& subentitiesStorage = mesh.template getSubentityStorageNetwork< SuperdimensionTag::value, DimensionTag::value >(); + using Multimap = typename std::remove_reference< decltype(subentitiesStorage) >::type; + DevicePointer< Mesh > meshPointer( mesh ); + DevicePointer< Multimap > subentitiesStoragePointer( subentitiesStorage ); + + auto kernel = [] __cuda_callable__ + ( IndexType i, + Mesh* mesh, + Multimap* subentitiesStorage ) + { + auto& superentity = mesh->template getEntity< SuperdimensionTag::value >( i ); + superentity.template bindSubentitiesStorageNetwork< DimensionTag::value >( subentitiesStorage->getValues( i ) ); + }; + + ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount, + kernel, + &meshPointer.template modifyData< DeviceType >(), + &subentitiesStoragePointer.template modifyData< DeviceType >() ); + } + }; + + template< typename DimensionTag, + typename SuperdimensionTag > + struct SubentityWorker< DimensionTag, SuperdimensionTag, false > + { + static void bindSubentities( Mesh& mesh ) {} + }; + + + template< int Dimension, int Superdimension > + struct InnerLoop + { + static void exec( Mesh& mesh ) + { + using DimensionTag = Meshes::DimensionTag< Dimension >; + using SuperdimensionTag = Meshes::DimensionTag< Superdimension >; + SuperentityWorker< DimensionTag, SuperdimensionTag >::bindSuperentities( mesh ); + SubentityWorker< DimensionTag, SuperdimensionTag >::bindSubentities( mesh ); + } + }; + + template< int Dimension > + struct OuterLoop + { + template< int Superdimension > + using Inner = InnerLoop< Dimension, Superdimension >; + + static void exec( Mesh& mesh ) + { + StaticFor< int, Dimension + 1, Mesh::getMeshDimension() + 1, Inner >::execHost( mesh ); + } + }; + +public: + static void exec( Mesh& mesh ) + { + StaticFor< int, 0, Mesh::getMeshDimension() + 1, OuterLoop >::execHost( mesh ); + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/IndexPermutationApplier.h b/src/TNL/Meshes/MeshDetails/IndexPermutationApplier.h new file mode 100644 index 0000000000000000000000000000000000000000..2bf9a007c6e76b532718a11174f8525c9fec0b25 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/IndexPermutationApplier.h @@ -0,0 +1,184 @@ +/*************************************************************************** + IndexPermutationApplier.h - description + ------------------- + begin : Mar 10, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/Mesh.h> +#include <TNL/Containers/Multimaps/MultimapPermutationApplier.h> + +namespace TNL { +namespace Meshes { + +template< typename Mesh, int Dimension > +struct IndexPermutationApplier +{ +private: + using GlobalIndexVector = typename Mesh::GlobalIndexVector; + + template< int Subdimension, + bool Enabled = + Mesh::MeshTraitsType::template SubentityTraits< typename Mesh::template EntityType< Dimension >::EntityTopology, + Subdimension >::storageEnabled + > + struct _SubentitiesStorageWorker + { + static void exec( Mesh& mesh, const GlobalIndexVector& perm ) + { + auto& subentitiesStorage = mesh.template getSubentityStorageNetwork< Dimension, Subdimension >(); + permuteMultimapKeys( subentitiesStorage, perm ); + } + }; + + template< int Subdimension > + struct _SubentitiesStorageWorker< Subdimension, false > + { + static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {} + }; + + + template< int Superdimension, + bool Enabled = + Mesh::MeshTraitsType::template SuperentityTraits< typename Mesh::template EntityType< Dimension >::EntityTopology, + Superdimension >::storageEnabled + > + struct _SuperentitiesStorageWorker + { + static void exec( Mesh& mesh, const GlobalIndexVector& perm ) + { + auto& superentitiesStorage = mesh.template getSuperentityStorageNetwork< Dimension, Superdimension >(); + permuteMultimapKeys( superentitiesStorage, perm ); + } + }; + + template< int Superdimension > + struct _SuperentitiesStorageWorker< Superdimension, false > + { + static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {} + }; + + + template< int Subdimension, + bool Enabled = + Mesh::MeshTraitsType::template SuperentityTraits< typename Mesh::template EntityType< Subdimension >::EntityTopology, + Dimension >::storageEnabled + > + struct IndexPermutationApplierSubentitiesWorker + { + static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) + { + auto& superentitiesStorage = mesh.template getSuperentityStorageNetwork< Subdimension, Dimension >(); + permuteMultimapValues( superentitiesStorage, iperm ); + } + }; + + template< int Subdimension > + struct IndexPermutationApplierSubentitiesWorker< Subdimension, false > + { + static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {} + }; + + + template< int Superdimension, + bool Enabled = + Mesh::MeshTraitsType::template SubentityTraits< typename Mesh::template EntityType< Superdimension >::EntityTopology, + Dimension >::storageEnabled + > + struct IndexPermutationApplierSuperentitiesWorker + { + static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) + { + auto& subentitiesStorage = mesh.template getSubentityStorageNetwork< Superdimension, Dimension >(); + permuteMultimapValues( subentitiesStorage, iperm ); + } + }; + + template< int Superdimension > + struct IndexPermutationApplierSuperentitiesWorker< Superdimension, false > + { + static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {} + }; + + + // template aliases needed to hide the 'Enabled' parameter + template< int Subdimension > + using SubentitiesStorageWorker = _SubentitiesStorageWorker< Subdimension >; + + template< int Superdimension > + using SuperentitiesStorageWorker = _SuperentitiesStorageWorker< Superdimension >; + + template< int Subdimension > + using SubentitiesWorker = IndexPermutationApplierSubentitiesWorker< Subdimension >; + + template< int Superdimension > + using SuperentitiesWorker = IndexPermutationApplierSuperentitiesWorker< Superdimension >; + +public: + static void exec( Mesh& mesh, + const GlobalIndexVector& perm, + const GlobalIndexVector& iperm ) + { + using IndexType = typename Mesh::GlobalIndexType; + using DeviceType = typename Mesh::DeviceType; + using StorageArrayType = typename Mesh::template EntityTraits< Dimension >::StorageArrayType; + + const IndexType entitiesCount = mesh.template getEntitiesCount< Dimension >(); + + StorageArrayType entities; + entities.setSize( entitiesCount ); + + // kernel to copy entities to new array, applying the permutation + auto kernel1 = [] __cuda_callable__ + ( IndexType i, + const Mesh* mesh, + typename StorageArrayType::ElementType* entitiesArray, + const IndexType* perm ) + { + entitiesArray[ i ] = mesh->template getEntity< Dimension >( perm[ i ] ); + }; + + // kernel to copy permuted entities back to the mesh + auto kernel2 = [] __cuda_callable__ + ( IndexType i, + Mesh* mesh, + const typename StorageArrayType::ElementType* entitiesArray ) + { + auto& entity = mesh->template getEntity< Dimension >( i ); + entity = entitiesArray[ i ]; + entity.setIndex( i ); + }; + + DevicePointer< Mesh > meshPointer( mesh ); + ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount, + kernel1, + &meshPointer.template getData< DeviceType >(), + entities.getData(), + perm.getData() ); + ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount, + kernel2, + &meshPointer.template modifyData< DeviceType >(), + entities.getData() ); + + // permute superentities storage + StaticFor< int, 0, Dimension, SubentitiesStorageWorker >::execHost( mesh, perm ); + + // permute subentities storage + StaticFor< int, Dimension + 1, Mesh::getMeshDimension() + 1, SuperentitiesStorageWorker >::execHost( mesh, perm ); + + // update superentity indices from the subentities + StaticFor< int, 0, Dimension, SubentitiesWorker >::execHost( mesh, iperm ); + + // update subentity indices from the superentities + StaticFor< int, Dimension + 1, Mesh::getMeshDimension() + 1, SuperentitiesWorker >::execHost( mesh, iperm ); + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityId.h b/src/TNL/Meshes/MeshDetails/MeshEntityId.h deleted file mode 100644 index c514b1b09d86d25998851de8779772d871439766..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/MeshEntityId.h +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************** - MeshEntityId.h - description - ------------------- - begin : Feb 28, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -namespace TNL { -namespace Meshes { - -template< typename IDType, - typename GlobalIndexType > -class MeshEntityId -{ - public: - - MeshEntityId() - : id( -1 ) - {} - - const IDType &getId() const - { - TNL_ASSERT( this->id >= 0, ); - return this->id; - } - - void setId( GlobalIndexType id ) - { - this->id = id; - } - - bool operator==( const MeshEntityId< IDType, GlobalIndexType >& id ) const - { - return ( this->id == id.id ); - } - - protected: - IDType id; -}; - -template< typename GlobalIndexType > -class MeshEntityId< void, GlobalIndexType > -{ - public: - void setId( GlobalIndexType ) - {} - - bool operator==( const MeshEntityId< void, GlobalIndexType >& id ) const - { - return true; - } -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityIndex.h b/src/TNL/Meshes/MeshDetails/MeshEntityIndex.h new file mode 100644 index 0000000000000000000000000000000000000000..64485dc3c7ecb31ebdeb9891830244776550e315 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshEntityIndex.h @@ -0,0 +1,75 @@ +/*************************************************************************** + MeshEntityIndex.h - description + ------------------- + begin : Feb 28, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Assert.h> +#include <TNL/Devices/Cuda.h> + +namespace TNL { +namespace Meshes { + +template< typename IDType > +class MeshEntityIndex +{ +public: + // FIXME: IDType may be unsigned + MeshEntityIndex() + : id( -1 ) + {} + + __cuda_callable__ + const IDType& getIndex() const + { + TNL_ASSERT_GE( this->id, 0, "entity index is negative" ); + return this->id; + } + + __cuda_callable__ + bool operator==( const MeshEntityIndex& id ) const + { + return ( this->id == id.id ); + } + +protected: + __cuda_callable__ + void setIndex( IDType id ) + { + this->id = id; + } + + IDType id; +}; + +template<> +class MeshEntityIndex< void > +{ +public: + __cuda_callable__ + bool operator==( const MeshEntityIndex& id ) const + { + return true; + } + +protected: + template< typename Index > + __cuda_callable__ + void setIndex( Index ) + {} +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h b/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h index f497c6306015e97aa60a00728e1153770b94ded1..10132513a0013dbe8e5ababfcde46621aeb715b3 100644 --- a/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h +++ b/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h @@ -25,23 +25,19 @@ template< typename MeshConfig, typename EntityTopology> class MeshEntityOrientation { - template< typename, typename> friend class MeshEntityReferenceOrientation; + template< typename, typename> + friend class MeshEntityReferenceOrientation; public: - typedef typename MeshTraits< MeshConfig >::IdPermutationArrayAccessorType IdPermutationArrayAccessorType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using IdPermutationArrayType = typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 >::IdPermutationArrayType; - IdPermutationArrayAccessorType getSubvertexPermutation() const + const IdPermutationArrayType& getSubvertexPermutation() const { - IdPermutationArrayAccessorType accessor; - accessor.bind( this->subvertexPermutation ); - return accessor; - //return this->subvertexPermutation.subarray( 0, this->subvertexPermutation.getSize() ); + return subvertexPermutation; } private: - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 >::IdPermutationArrayType IdPermutationArrayType; - void setPermutationValue( LocalIndexType index, LocalIndexType value ) { this->subvertexPermutation[ index ] = value; diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h b/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h index bad26901bc0cdbfb1366ea28eecf34103c82e745..e14e909a52d6824192e66e8d93d469a877ae70ca 100644 --- a/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h +++ b/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h @@ -16,6 +16,10 @@ #pragma once +#include <map> + +#include <TNL/Meshes/MeshDetails/MeshEntityOrientation.h> + namespace TNL { namespace Meshes { @@ -26,8 +30,8 @@ class MeshEntityReferenceOrientation typedef typename MeshTraits< MeshConfig >::GlobalIndexType GlobalIndexType; public: - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshEntityOrientation< MeshConfig, EntityTopology > EntityOrientation; + typedef EntitySeed< MeshConfig, EntityTopology > SeedType; + typedef MeshEntityOrientation< MeshConfig, EntityTopology > EntityOrientation; MeshEntityReferenceOrientation() = default; @@ -36,7 +40,8 @@ class MeshEntityReferenceOrientation auto referenceCornerIds = referenceSeed.getCornerIds(); for( LocalIndexType i = 0; i < referenceCornerIds.getSize(); i++ ) { - TNL_ASSERT( this->cornerIdsMap.find( referenceCornerIds[i]) == this->cornerIdsMap.end(), ); + TNL_ASSERT_TRUE( this->cornerIdsMap.find( referenceCornerIds[ i ] ) == this->cornerIdsMap.end(), + "detected duplicate index in the reference seed" ); this->cornerIdsMap.insert( std::make_pair( referenceCornerIds[i], i ) ); } } @@ -49,7 +54,8 @@ class MeshEntityReferenceOrientation auto cornerIds = seed.getCornerIds(); for( LocalIndexType i = 0; i < cornerIds.getSize(); i++ ) { - TNL_ASSERT( this->cornerIdsMap.find( cornerIds[ i ] ) != this->cornerIdsMap.end(), ); + TNL_ASSERT_TRUE( this->cornerIdsMap.find( cornerIds[ i ] ) != this->cornerIdsMap.end(), + "unable to find index for entity orientation" ); result.setPermutationValue( i, this->cornerIdsMap.find( cornerIds[ i ])->second ); } return result; diff --git a/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h b/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h index 9e9ff9b8aac46c8434d00b55c4b9361bcdcecc4d..8a21168de1496d497c248d7cd8fb05c9787066e4 100644 --- a/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h +++ b/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h @@ -22,474 +22,323 @@ namespace TNL { namespace Meshes { template< typename MeshConfig, + typename Device, typename EntityTopology > -MeshEntity< MeshConfig, EntityTopology >:: -MeshEntity( const SeedType& entitySeed ) +__cuda_callable__ +MeshEntity< MeshConfig, Device, EntityTopology >:: +MeshEntity( const MeshEntity& entity ) + : SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >( entity ), + SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >( entity ), + MeshEntityIndex< typename MeshConfig::IdType >( entity ) { - typedef typename SeedType::LocalIndexType LocalIndexType; - for( LocalIndexType i = 0; i < entitySeed.getCornerIds().getSize(); i++ ) - this->template setSubentityIndex< 0 >( i, entitySeed.getCornerIds()[ i ] ); } +template< typename MeshConfig, + typename Device, + typename EntityTopology > + template< typename Device_ > +MeshEntity< MeshConfig, Device, EntityTopology >:: +MeshEntity( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity ) + // no cross-device copy of subentities and superentities here - Mesh constructor has to rebind pointers + : MeshEntityIndex< typename MeshConfig::IdType >( entity ) +{ + static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" ); +} template< typename MeshConfig, + typename Device, typename EntityTopology > -MeshEntity< MeshConfig, EntityTopology >:: -MeshEntity() +__cuda_callable__ +MeshEntity< MeshConfig, Device, EntityTopology >& +MeshEntity< MeshConfig, Device, EntityTopology >:: +operator=( const MeshEntity& entity ) { + SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator=( entity ); + SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator=( entity ); + MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity ); + return *this; } template< typename MeshConfig, + typename Device, typename EntityTopology > -MeshEntity< MeshConfig, EntityTopology >:: -~MeshEntity() + template< typename Device_ > +__cuda_callable__ +MeshEntity< MeshConfig, Device, EntityTopology >& +MeshEntity< MeshConfig, Device, EntityTopology >:: +operator=( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity ) { - //cerr << " Destroying entity with " << EntityTopology::dimensions << " dimensions..." << std::endl; + static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" ); + + // no cross-device copy of subentities and superentities here - Mesh::operator= has to rebind pointers + MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity ); + return *this; } template< typename MeshConfig, + typename Device, typename EntityTopology > String -MeshEntity< MeshConfig, EntityTopology >:: +MeshEntity< MeshConfig, Device, EntityTopology >:: getType() { - return String( "Mesh< ... >" ); + return String( "MeshEntity< " ) + + MeshConfig::getType() + ", " + + EntityTopology::getType() + " >"; } template< typename MeshConfig, + typename Device, typename EntityTopology > String -MeshEntity< MeshConfig, EntityTopology >:: +MeshEntity< MeshConfig, Device, EntityTopology >:: getTypeVirtual() const { return this->getType(); } template< typename MeshConfig, + typename Device, typename EntityTopology > bool -MeshEntity< MeshConfig, EntityTopology >:: +MeshEntity< MeshConfig, Device, EntityTopology >:: save( File& file ) const { - if( ! MeshSubentityStorageLayers< MeshConfig, EntityTopology >::save( file ) /*|| - ! MeshSuperentityStorageLayers< MeshConfig, EntityTopology >::save( file )*/ ) - return false; + // no I/O for subentities and superentities - not loaded anyway return true; } template< typename MeshConfig, + typename Device, typename EntityTopology > bool -MeshEntity< MeshConfig, EntityTopology >:: +MeshEntity< MeshConfig, Device, EntityTopology >:: load( File& file ) { - if( ! MeshSubentityStorageLayers< MeshConfig, EntityTopology >::load( file ) /*|| - ! MeshSuperentityStorageLayers< MeshConfig, EntityTopology >::load( file ) */ ) - return false; + // no I/O for subentities and superentities - Mesh::load has to rebind pointers return true; } template< typename MeshConfig, + typename Device, typename EntityTopology > void -MeshEntity< MeshConfig, EntityTopology >:: +MeshEntity< MeshConfig, Device, EntityTopology >:: print( std::ostream& str ) const { - str << "\t Mesh entity dimension: " << EntityTopology::dimensions << std::endl; - MeshSubentityStorageLayers< MeshConfig, EntityTopology >::print( str ); - MeshSuperentityAccess< MeshConfig, EntityTopology >::print( str ); + str << "\t Mesh entity dimension: " << EntityTopology::dimension << std::endl; + SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::print( str ); + SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::print( str ); } template< typename MeshConfig, + typename Device, typename EntityTopology > +__cuda_callable__ bool -MeshEntity< MeshConfig, EntityTopology >:: +MeshEntity< MeshConfig, Device, EntityTopology >:: operator==( const MeshEntity& entity ) const { - return ( MeshSubentityStorageLayers< MeshConfig, EntityTopology >::operator==( entity ) && - MeshSuperentityAccess< MeshConfig, EntityTopology >::operator==( entity ) && - MeshEntityId< typename MeshConfig::IdType, - typename MeshConfig::GlobalIndexType >::operator==( entity ) ); -} - -template< typename MeshConfig, - typename EntityTopology > -constexpr int -MeshEntity< MeshConfig, EntityTopology >:: -getEntityDimension() const -{ - return EntityTopology::dimensions; -} - -/**** - * Subentities - */ -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -constexpr bool -MeshEntity< MeshConfig, EntityTopology >:: -subentitiesAvailable() const -{ - return SubentityTraits< Subdimensions >::storageEnabled; -}; - -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -constexpr typename MeshEntity< MeshConfig, EntityTopology >::LocalIndexType -MeshEntity< MeshConfig, EntityTopology >:: -getNumberOfSubentities() const -{ - return SubentityTraits< Subdimensions >::count; -}; - -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -typename MeshEntity< MeshConfig, EntityTopology >::GlobalIndexType -MeshEntity< MeshConfig, EntityTopology >:: -getSubentityIndex( const LocalIndexType localIndex) const -{ - static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to get subentity which is not configured for storage." ); - TNL_ASSERT( 0 <= localIndex && - localIndex < SubentityTraits< Subdimensions >::count, - std::cerr << "localIndex = " << localIndex - << " subentitiesCount = " - << SubentityTraits< Subdimensions >::count ); - typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology > SubentityBaseType; - return SubentityBaseType::getSubentityIndex( MeshDimensionTag< Subdimensions >(), - localIndex ); -} - -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::AccessArrayType& -MeshEntity< MeshConfig, EntityTopology >:: - getSubentitiesIndices() -{ - static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to get subentities which are not configured for storage." ); - typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology > SubentityBaseType; - return SubentityBaseType::getSubentitiesIndices( MeshDimensionTag< Subdimensions >() ); -} - -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -const typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::AccessArrayType& -MeshEntity< MeshConfig, EntityTopology >:: -getSubentitiesIndices() const -{ - static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to set subentities which are not configured for storage." ); - typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology > SubentityBaseType; - return SubentityBaseType::getSubentitiesIndices( MeshDimensionTag< Subdimensions >() ); + return ( SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator==( entity ) && + SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator==( entity ) && + MeshEntityIndex< typename MeshConfig::IdType >::operator==( entity ) ); } template< typename MeshConfig, + typename Device, typename EntityTopology > - template< int SuperDimension > -typename MeshEntity< MeshConfig, EntityTopology >::LocalIndexType -MeshEntity< MeshConfig, EntityTopology >:: -getNumberOfSuperentities() const -{ - static_assert( SuperentityTraits< SuperDimension >::available, "You try to get number of superentities which are not configured for storage." ); - typedef MeshSuperentityAccess< MeshConfig, EntityTopology > SuperentityBaseType; - return SuperentityBaseType::getNumberOfSuperentities( MeshDimensionTag< SuperDimension >() ); -} - -template< typename MeshConfig, - typename EntityTopology > - template< int SuperDimension > -typename MeshEntity< MeshConfig, EntityTopology >::GlobalIndexType -MeshEntity< MeshConfig, EntityTopology >:: -getSuperentityIndex( const LocalIndexType localIndex ) const -{ - static_assert( SuperentityTraits< SuperDimension >::storageEnabled, "You try to get superentity which is not configured for storage." ); - TNL_ASSERT( localIndex < this->getNumberOfSuperentities< SuperDimension >(), - std::cerr << " localIndex = " << localIndex - << " this->getNumberOfSuperentities< Dimension >() = " << this->getNumberOfSuperentities< SuperDimension >() << std::endl; ); - typedef MeshSuperentityAccess< MeshConfig, EntityTopology > SuperentityBaseType; - return SuperentityBaseType::getSuperentityIndex( MeshDimensionTag< SuperDimension >(), - localIndex ); -} - -template< typename MeshConfig, - typename EntityTopology > - template< int SuperDimension > -typename MeshEntity< MeshConfig, EntityTopology >::template SuperentityTraits< SuperDimension >::AccessArrayType& -MeshEntity< MeshConfig, EntityTopology >:: -getSuperentitiesIndices() +__cuda_callable__ +bool +MeshEntity< MeshConfig, Device, EntityTopology >:: +operator!=( const MeshEntity& entity ) const { - static_assert( SuperentityTraits< SuperDimension >::storageEnabled, "You try to get superentities which are not configured for storage." ); - typedef MeshSuperentityAccess< MeshConfig, EntityTopology > SuperentityBaseType; - //return SuperentityBaseType::getSuperentitiesIndices( MeshDimensionTag< Dimension >() ); + return ! ( *this == entity ); } template< typename MeshConfig, + typename Device, typename EntityTopology > - template< int SuperDimension > -const typename MeshEntity< MeshConfig, EntityTopology >::template SuperentityTraits< SuperDimension >::AccessArrayType& -MeshEntity< MeshConfig, EntityTopology >:: -getSuperentitiesIndices() const +constexpr int +MeshEntity< MeshConfig, Device, EntityTopology >:: +getEntityDimension() { - static_assert( SuperentityTraits< SuperDimension >::storageEnabled, "You try to get superentities which are not configured for storage." ); - typedef MeshSuperentityAccess< MeshConfig, EntityTopology > SuperentityBaseType; - return SuperentityBaseType::getSubentitiesIndices( MeshDimensionTag< SuperDimension >() ); + return EntityTopology::dimension; } +/**** + * Subentities + */ template< typename MeshConfig, + typename Device, typename EntityTopology > -constexpr typename MeshEntity< MeshConfig, EntityTopology >::LocalIndexType -MeshEntity< MeshConfig, EntityTopology >:: -getNumberOfVertices() const +constexpr typename MeshEntity< MeshConfig, Device, EntityTopology >::LocalIndexType +MeshEntity< MeshConfig, Device, EntityTopology >:: +getVerticesCount() { return SubentityTraits< 0 >::count; } template< typename MeshConfig, + typename Device, typename EntityTopology > -typename MeshEntity< MeshConfig, EntityTopology >::GlobalIndexType -MeshEntity< MeshConfig, EntityTopology >:: +typename MeshEntity< MeshConfig, Device, EntityTopology >::GlobalIndexType +MeshEntity< MeshConfig, Device, EntityTopology >:: getVertexIndex( const LocalIndexType localIndex ) const { - return this->getSubentityIndex< 0 >( localIndex ); -} - -template< typename MeshConfig, - typename EntityTopology > -typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< 0 >::AccessArrayType& -MeshEntity< MeshConfig, EntityTopology >:: -getVerticesIndices() -{ - return this->getSubentitiesIndices< 0 >(); + return this->template getSubentityIndex< 0 >( localIndex ); } -template< typename MeshConfig, - typename EntityTopology > -const typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< 0 >::AccessArrayType& -MeshEntity< MeshConfig, EntityTopology >:: -getVerticesIndices() const -{ - return this->getSubentitiesIndices< 0 >(); -} - -template< typename MeshConfig, - typename EntityTopology > - template< int Dimension > -typename MeshEntity< MeshConfig, EntityTopology >::IdPermutationArrayAccessorType -MeshEntity< MeshConfig, EntityTopology >:: -subentityOrientation( LocalIndexType index ) const -{ - static const LocalIndexType subentitiesCount = SubentityTraits< Dimension >::count; - TNL_ASSERT( 0 <= index && index < subentitiesCount, ); - - return SubentityStorageLayers::subentityOrientation( MeshDimensionTag< Dimension >(), index ); -} /**** - * Mesh initialization method + * Vertex entity specialization */ - -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -void -MeshEntity< MeshConfig, EntityTopology >:: -setSubentityIndex( const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) +template< typename MeshConfig, typename Device > +__cuda_callable__ +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: +MeshEntity( const MeshEntity& entity ) + : SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >( entity ), + MeshEntityIndex< typename MeshConfig::IdType >( entity ) { - static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to set subentity which is not configured for storage." ); - TNL_ASSERT( 0 <= localIndex && - localIndex < SubentityTraits< Subdimensions >::count, - std::cerr << "localIndex = " << localIndex - << " subentitiesCount = " - << SubentityTraits< Subdimensions >::count ); - typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology > SubentityBaseType; - SubentityBaseType::setSubentityIndex( MeshDimensionTag< Subdimensions >(), - localIndex, - globalIndex ); + setPoint( entity.getPoint() ); } -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::IdArrayType& -MeshEntity< MeshConfig, EntityTopology >:: -subentityIdsArray() +template< typename MeshConfig, typename Device > + template< typename Device_ > +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: +MeshEntity( const MeshEntity< MeshConfig, Device_, Topologies::Vertex >& entity ) + // no cross-device copy of superentities here - Mesh constructor has to rebind pointers + : MeshEntityIndex< typename MeshConfig::IdType >( entity ) { - return SubentityStorageLayers::subentityIdsArray( MeshDimensionTag< Subdimensions >() ); + static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" ); + + setPoint( entity.getPoint() ); } -template< typename MeshConfig, - typename EntityTopology > - template< int Superdimensions > -typename MeshEntity< MeshConfig, EntityTopology >::IdArrayAccessorType& -MeshEntity< MeshConfig, EntityTopology >:: -superentityIdsArray() +template< typename MeshConfig, typename Device > +__cuda_callable__ +MeshEntity< MeshConfig, Device, Topologies::Vertex >& +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: +operator=( const MeshEntity& entity ) { - return SuperentityAccessBase::superentityIdsArray( MeshDimensionTag< Superdimensions >()); + SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::operator=( entity ); + MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity ); + setPoint( entity.getPoint() ); + return *this; } -template< typename MeshConfig, - typename EntityTopology > - template< int Subdimensions > -typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::OrientationArrayType& -MeshEntity< MeshConfig, EntityTopology >:: -subentityOrientationsArray() +template< typename MeshConfig, typename Device > + template< typename Device_ > +__cuda_callable__ +MeshEntity< MeshConfig, Device, Topologies::Vertex >& +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: +operator=( const MeshEntity< MeshConfig, Device_, Topologies::Vertex >& entity ) { - return SubentityStorageLayers::subentityOrientationsArray( MeshDimensionTag< Subdimensions >() ); + static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" ); + + // no cross-device copy of superentities here - Mesh::operator= has to rebind pointers + MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity ); + setPoint( entity.getPoint() ); + return *this; } -/**** - * Vertex entity specialization - */ -template< typename MeshConfig > +template< typename MeshConfig, typename Device > String -MeshEntity< MeshConfig, MeshVertexTopology >:: +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: getType() { - return String( "Mesh< ... >" ); + return String( "MeshEntity< ... >" ); } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > String -MeshEntity< MeshConfig, MeshVertexTopology >:: +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: getTypeVirtual() const { return this->getType(); } -template< typename MeshConfig > -MeshEntity< MeshConfig, MeshVertexTopology >:: -~MeshEntity() -{ - //cerr << " Destroying entity with " << MeshVertexTopology::dimensions << " dimensions..." << std::endl; -} - -template< typename MeshConfig > +template< typename MeshConfig, typename Device > bool -MeshEntity< MeshConfig, MeshVertexTopology >:: +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: save( File& file ) const { - if( //! MeshSuperentityStorageLayers< MeshConfig, MeshVertexTopology >::save( file ) || - ! point.save( file ) ) + // no I/O for superentities - not loaded anyway + if( ! point.save( file ) ) return false; return true; } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > bool -MeshEntity< MeshConfig, MeshVertexTopology >:: +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: load( File& file ) { - if( //! MeshSuperentityStorageLayers< MeshConfig, MeshVertexTopology >::load( file ) || - ! point.load( file ) ) + // no I/O for superentities - Mesh::load has to rebind pointers + if( ! point.load( file ) ) return false; return true; } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > void -MeshEntity< MeshConfig, MeshVertexTopology >:: +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: print( std::ostream& str ) const { - str << "\t Mesh entity dimension: " << MeshVertexTopology::dimensions << std::endl; - str << "\t Coordinates = ( " << point << " )"; - MeshSuperentityAccess< MeshConfig, MeshVertexTopology >::print( str ); + str << "\t Mesh entity dimension: " << Topologies::Vertex::dimension << std::endl; + str << "\t Coordinates = " << point << std::endl; + SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::print( str ); } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > +__cuda_callable__ bool -MeshEntity< MeshConfig, MeshVertexTopology >:: +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: operator==( const MeshEntity& entity ) const { - return ( //MeshSuperentityAccess< MeshConfig, MeshVertexTopology >::operator==( entity ) && - MeshEntityId< typename MeshConfig::IdType, - typename MeshConfig::GlobalIndexType >::operator==( entity ) && + return ( SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::operator==( entity ) && + MeshEntityIndex< typename MeshConfig::IdType >::operator==( entity ) && point == entity.point ); } -template< typename MeshConfig > -constexpr int -MeshEntity< MeshConfig, MeshVertexTopology >:: -getEntityDimension() const -{ - return EntityTopology::dimensions; -} - -template< typename MeshConfig > - template< int Superdimensions > -typename MeshEntity< MeshConfig, MeshVertexTopology >::LocalIndexType -MeshEntity< MeshConfig, MeshVertexTopology >:: -getNumberOfSuperentities() const -{ - typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology > SuperentityBaseType; - return SuperentityBaseType::getNumberOfSuperentities( MeshDimensionTag< Superdimensions >() ); -} - -template< typename MeshConfig > - template< int Superdimensions > -typename MeshEntity< MeshConfig, MeshVertexTopology >::template SuperentityTraits< Superdimensions >::AccessArrayType& -MeshEntity< MeshConfig, MeshVertexTopology >:: -getSuperentitiesIndices() -{ - typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology > SuperentityBaseType; - return SuperentityBaseType::getSuperentitiesIndices( MeshDimensionTag< Superdimensions >() ); -} - -template< typename MeshConfig > - template< int Superdimensions > -const typename MeshEntity< MeshConfig, MeshVertexTopology >::template SuperentityTraits< Superdimensions >::AccessArrayType& -MeshEntity< MeshConfig, MeshVertexTopology >:: -getSuperentitiesIndeces() const +template< typename MeshConfig, typename Device > +__cuda_callable__ +bool +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: +operator!=( const MeshEntity& entity ) const { - typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology > SuperentityBaseType; - return SuperentityBaseType::getSubentitiesIndices( MeshDimensionTag< Superdimensions >() ); + return ! ( *this == entity ); } -template< typename MeshConfig > - template< int Dimension > -typename MeshEntity< MeshConfig, MeshVertexTopology >::GlobalIndexType -MeshEntity< MeshConfig, MeshVertexTopology >:: -getSuperentityIndex( const LocalIndexType localIndex ) const +template< typename MeshConfig, typename Device > +constexpr int +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: +getEntityDimension() { - TNL_ASSERT( localIndex < this->getNumberOfSuperentities< Dimension >(), - std::cerr << " localIndex = " << localIndex - << " this->getNumberOfSuperentities< Dimension >() = " << this->getNumberOfSuperentities< Dimension >() << std::endl; ); - typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology > SuperentityBaseType; - return SuperentityBaseType::getSuperentityIndex( MeshDimensionTag< Dimension >(), - localIndex ); + return EntityTopology::dimension; } -template< typename MeshConfig > -typename MeshEntity< MeshConfig, MeshVertexTopology >::PointType -MeshEntity< MeshConfig, MeshVertexTopology >:: +template< typename MeshConfig, typename Device > +__cuda_callable__ +typename MeshEntity< MeshConfig, Device, Topologies::Vertex >::PointType +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: getPoint() const { return this->point; } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > +__cuda_callable__ void -MeshEntity< MeshConfig, MeshVertexTopology >:: +MeshEntity< MeshConfig, Device, Topologies::Vertex >:: setPoint( const PointType& point ) { this->point = point; } -template< typename MeshConfig > - template< int Superdimensions > -typename MeshEntity< MeshConfig, MeshVertexTopology >::MeshTraitsType::IdArrayAccessorType& -MeshEntity< MeshConfig, MeshVertexTopology >:: -superentityIdsArray() -{ - return SuperentityAccessBase::superentityIdsArray( MeshDimensionTag< Superdimensions >()); -} - template< typename MeshConfig, + typename Device, typename EntityTopology > -std::ostream& operator <<( std::ostream& str, const MeshEntity< MeshConfig, EntityTopology >& entity ) +std::ostream& operator<<( std::ostream& str, const MeshEntity< MeshConfig, Device, EntityTopology >& entity ) { entity.print( str ); return str; @@ -497,4 +346,3 @@ std::ostream& operator <<( std::ostream& str, const MeshEntity< MeshConfig, Enti } // namespace Meshes } // namespace TNL - diff --git a/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h b/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h index 42ddaa1d2dded36a364bcdafe3ab66828be45c61..13fec6787827ec6177815984096dbfe0ff10e59d 100644 --- a/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h +++ b/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h @@ -2,7 +2,7 @@ MeshIntegrityChecker.h - description ------------------- begin : Mar 20, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -25,9 +25,9 @@ namespace Meshes { template< typename MeshType > class MeshIntegrityChecker : public MeshIntegrityCheckerLayer< MeshType, - MeshDimensionTag< MeshType::Config::CellType::dimensions > > + DimensionTag< MeshType::Config::CellType::dimension > > { - typedef MeshDimensionTag< MeshType::Config::CellType::dimensions > DimensionTag; + typedef Meshes::DimensionTag< MeshType::Config::CellType::dimension > DimensionTag; typedef MeshIntegrityCheckerLayer< MeshType, DimensionTag > BaseType; public: diff --git a/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h b/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h index 302ed0b05ad395eb1fdf4d1a26228c49f5bdfbad..13e415d4567effbc8c8f5b735c7523045f718cad 100644 --- a/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h +++ b/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h @@ -2,7 +2,7 @@ MeshIntegrityCheckerLayer.h - description ------------------- begin : Mar 21, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -17,7 +17,7 @@ #pragma once #include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h> -#include <TNL/Meshes/MeshDimensionTag.h> +#include <TNL/Meshes/DimensionTag.h> namespace TNL { namespace Meshes { @@ -25,29 +25,29 @@ namespace Meshes { template< typename MeshType, typename DimensionTag, bool EntityStorageTag = MeshEntityTraits< typename MeshType::Config, - DimensionTag::value >::storageEnabled > + DimensionTag::value >::storageEnabled > class MeshIntegrityCheckerLayer; template< typename MeshType, typename DimensionTag > class MeshIntegrityCheckerLayer< MeshType, - DimensionTag, - true > + DimensionTag, + true > : public MeshIntegrityCheckerLayer< MeshType, - typename DimensionTag::Decrement > + typename DimensionTag::Decrement > { public: typedef MeshIntegrityCheckerLayer< MeshType, - typename DimensionTag::Decrement > BaseType; - enum { dimensions = DimensionTag::value }; + typename DimensionTag::Decrement > BaseType; + enum { dimension = DimensionTag::value }; static bool checkEntities( const MeshType& mesh ) { - typedef typename MeshType::template EntitiesTraits< dimensions >::ContainerType ContainerType; + typedef typename MeshType::template EntitiesTraits< dimension >::ContainerType ContainerType; typedef typename ContainerType::IndexType GlobalIndexType; - std::cout << "Checking entities with " << dimensions << " dimensions ..." << std::endl; + std::cout << "Checking entities with dimension " << dimension << " ..." << std::endl; for( GlobalIndexType entityIdx = 0; - entityIdx < mesh.template getNumberOfEntities< dimensions >(); + entityIdx < mesh.template getEntitiesCount< dimension >(); entityIdx++ ) { std::cout << "Entity no. " << entityIdx << " \r" << std::flush; @@ -61,19 +61,19 @@ class MeshIntegrityCheckerLayer< MeshType, template< typename MeshType > class MeshIntegrityCheckerLayer< MeshType, - MeshDimensionTag< 0 >, - true > + DimensionTag< 0 >, + true > { public: - enum { dimensions = 0 }; + enum { dimension = 0 }; static bool checkEntities( const MeshType& mesh ) { - typedef typename MeshType::template EntitiesTraits< dimensions >::ContainerType ContainerType; + typedef typename MeshType::template EntitiesTraits< dimension >::ContainerType ContainerType; typedef typename ContainerType::IndexType GlobalIndexType; - std::cout << "Checking entities with " << dimensions << " dimensions ..." << std::endl; + std::cout << "Checking entities with dimension " << dimension << " ..." << std::endl; for( GlobalIndexType entityIdx = 0; - entityIdx < mesh.template getNumberOfEntities< dimensions >(); + entityIdx < mesh.template getEntitiesCount< dimension >(); entityIdx++ ) { std::cout << "Entity no. " << entityIdx << " \r" << std::flush; @@ -81,26 +81,23 @@ class MeshIntegrityCheckerLayer< MeshType, std::cout << std::endl; return true; } - }; template< typename MeshType, typename DimensionTag > class MeshIntegrityCheckerLayer< MeshType, - DimensionTag, - false > + DimensionTag, + false > : public MeshIntegrityCheckerLayer< MeshType, - typename DimensionTag::Decrement > + typename DimensionTag::Decrement > { - }; template< typename MeshType > class MeshIntegrityCheckerLayer< MeshType, - MeshDimensionTag< 0 >, - false > + DimensionTag< 0 >, + false > { - }; } // namespace Meshes diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5cf6216c750686a27d87c157fbd85a6239febbad --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/CMakeLists.txt @@ -0,0 +1,8 @@ +SET( headers ConfigValidator.h + Layer.h + LayerFamily.h + Initializer.h + Traits.h +) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/MeshLayers/BoundaryTags ) diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/ConfigValidator.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/ConfigValidator.h new file mode 100644 index 0000000000000000000000000000000000000000..aba84ba806b3954aa3812db9f3977db8ce0d251e --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/ConfigValidator.h @@ -0,0 +1,63 @@ +/*************************************************************************** + ConfigValidator.h - description + ------------------- + begin : Aug 14, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> + +namespace TNL { +namespace Meshes { +namespace BoundaryTags { + +template< typename MeshConfig, + typename EntityTopology, + bool BoundaryTagsStorage = MeshConfig::boundaryTagsStorage( EntityTopology() ) > +class ConfigValidatorBoundaryTagsLayer +{ + using FaceTopology = typename Topologies::Subtopology< typename MeshConfig::CellTopology, MeshConfig::meshDimension - 1 >::Topology; + + static_assert( MeshConfig::entityStorage( MeshConfig::meshDimension - 1 ), + "Faces must be stored when any entity has boundary tags." ); + static_assert( MeshConfig::superentityStorage( FaceTopology(), MeshConfig::meshDimension ), + "Faces must store the cell superentity indices when any entity has boundary tags." ); + static_assert( EntityTopology::dimension >= MeshConfig::meshDimension - 1 || MeshConfig::subentityStorage( FaceTopology(), EntityTopology::dimension ), + "Faces must store the subentity indices of the entities on which the boundary tags are stored." ); +}; + +template< typename MeshConfig, + typename EntityTopology > +class ConfigValidatorBoundaryTagsLayer< MeshConfig, EntityTopology, false > +{ +}; + + +template< typename MeshConfig, int dimension = MeshConfig::meshDimension > +class ConfigValidatorLayer + : public ConfigValidatorLayer< MeshConfig, dimension - 1 >, + public ConfigValidatorBoundaryTagsLayer< MeshConfig, + typename MeshTraits< MeshConfig >::template EntityTraits< dimension >::EntityTopology > +{ +}; + +template< typename MeshConfig > +class ConfigValidatorLayer< MeshConfig, 0 > +{ +}; + +template< typename MeshConfig > +class ConfigValidator + : public ConfigValidatorLayer< MeshConfig > +{ +}; + +} // namespace BoundaryTags +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Initializer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Initializer.h new file mode 100644 index 0000000000000000000000000000000000000000..a475ddcb4396bc4fadd5a50388379a0f40f6068b --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Initializer.h @@ -0,0 +1,168 @@ +/*************************************************************************** + Initializer.h - description + ------------------- + begin : Dec 26, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/StaticFor.h> +#include <TNL/ParallelFor.h> +#include <TNL/DevicePointer.h> +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h> + +namespace TNL { +namespace Meshes { +namespace BoundaryTags { + +template< typename MeshConfig, typename Device, typename Mesh > +class Initializer +{ + using DeviceType = Device; + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + using LocalIndexType = typename MeshConfig::LocalIndexType; + +protected: + // _T is necessary to force *partial* specialization, since explicit specializations + // at class scope are forbidden + template< typename CurrentDimension = DimensionTag< MeshConfig::meshDimension >, typename _T = void > + struct BoundaryTagsNeedInitialization + { + using EntityTopology = typename MeshEntityTraits< MeshConfig, DeviceType, CurrentDimension::value >::EntityTopology; + static constexpr bool value = MeshConfig::boundaryTagsStorage( EntityTopology() ) || + BoundaryTagsNeedInitialization< typename CurrentDimension::Decrement >::value; + }; + + template< typename _T > + struct BoundaryTagsNeedInitialization< DimensionTag< 0 >, _T > + { + using EntityTopology = typename MeshEntityTraits< MeshConfig, DeviceType, 0 >::EntityTopology; + static constexpr bool value = MeshConfig::boundaryTagsStorage( EntityTopology() ); + }; + + template< int Dimension > + struct SetEntitiesCount + { + static void exec( Mesh& mesh ) + { + mesh.template boundaryTagsSetEntitiesCount< Dimension >( mesh.template getEntitiesCount< Dimension >() ); + } + }; + + template< int Dimension > + struct ResetBoundaryTags + { + static void exec( Mesh& mesh ) + { + mesh.template resetBoundaryTags< Dimension >(); + } + }; + + template< int Subdimension > + class InitializeSubentities + { + using SubentityTopology = typename MeshEntityTraits< MeshConfig, DeviceType, Subdimension >::EntityTopology; + static constexpr bool enabled = MeshConfig::boundaryTagsStorage( SubentityTopology() ); + + // _T is necessary to force *partial* specialization, since explicit specializations + // at class scope are forbidden + template< bool enabled = true, typename _T = void > + struct Worker + { + __cuda_callable__ + static void exec( Mesh& mesh, const GlobalIndexType& faceIndex, const typename Mesh::Face& face ) + { + const LocalIndexType subentitiesCount = face.template getSubentitiesCount< Subdimension >(); + for( LocalIndexType i = 0; i < subentitiesCount; i++ ) { + const GlobalIndexType subentityIndex = face.template getSubentityIndex< Subdimension >( i ); + mesh.template setIsBoundaryEntity< Subdimension >( subentityIndex, true ); + } + } + }; + + template< typename _T > + struct Worker< false, _T > + { + __cuda_callable__ + static void exec( Mesh& mesh, const GlobalIndexType& faceIndex, const typename Mesh::Face& face ) {} + }; + + public: + __cuda_callable__ + static void exec( Mesh& mesh, const GlobalIndexType& faceIndex, const typename Mesh::Face& face ) + { + Worker< enabled >::exec( mesh, faceIndex, face ); + } + }; + + template< int Dimension > + struct UpdateBoundaryIndices + { + static void exec( Mesh& mesh ) + { + mesh.template updateBoundaryIndices< Dimension >(); + } + }; + +// nvcc does not allow __cuda_callable__ lambdas inside private or protected sections +#ifdef __NVCC__ +public: +#endif + // _T is necessary to force *partial* specialization, since explicit specializations + // at class scope are forbidden + template< bool AnyBoundaryTags = BoundaryTagsNeedInitialization<>::value, typename _T = void > + class Worker + { + public: + static void exec( Mesh& mesh ) + { + StaticFor< int, 0, Mesh::getMeshDimension() + 1, SetEntitiesCount >::execHost( mesh ); + StaticFor< int, 0, Mesh::getMeshDimension() + 1, ResetBoundaryTags >::execHost( mesh ); + + auto kernel = [] __cuda_callable__ + ( GlobalIndexType faceIndex, + Mesh* mesh ) + { + const auto& face = mesh->template getEntity< Mesh::getMeshDimension() - 1 >( faceIndex ); + if( face.template getSuperentitiesCount< Mesh::getMeshDimension() >() == 1 ) { + // initialize the face + mesh->template setIsBoundaryEntity< Mesh::getMeshDimension() - 1 >( faceIndex, true ); + // initialize the cell superentity + const GlobalIndexType cellIndex = face.template getSuperentityIndex< Mesh::getMeshDimension() >( 0 ); + mesh->template setIsBoundaryEntity< Mesh::getMeshDimension() >( cellIndex, true ); + // initialize all subentities + StaticFor< int, 0, Mesh::getMeshDimension() - 1, InitializeSubentities >::exec( *mesh, faceIndex, face ); + } + }; + + const GlobalIndexType facesCount = mesh.template getEntitiesCount< Mesh::getMeshDimension() - 1 >(); + DevicePointer< Mesh > meshPointer( mesh ); + ParallelFor< DeviceType >::exec( (GlobalIndexType) 0, facesCount, + kernel, + &meshPointer.template modifyData< DeviceType >() ); + + StaticFor< int, 0, Mesh::getMeshDimension() + 1, UpdateBoundaryIndices >::execHost( mesh ); + } + }; + + template< typename _T > + struct Worker< false, _T > + { + static void exec( Mesh& mesh ) {} + }; + +public: + void initLayer() + { + Worker<>::exec( *static_cast<Mesh*>(this) ); + } +}; + +} // namespace BoundaryTags +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h new file mode 100644 index 0000000000000000000000000000000000000000..06401f1a351bc087922799f31472337cfac0d988 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h @@ -0,0 +1,272 @@ +/*************************************************************************** + Layer.h - description + ------------------- + begin : Dec 25, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/File.h> +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> +#include <TNL/Containers/Vector.h> + +#include "Traits.h" + +namespace TNL { +namespace Meshes { +namespace BoundaryTags { + +// This is the implementation of the boundary tags layer for one specific dimension. +// It is inherited by the BoundaryTags::LayerFamily. +template< typename MeshConfig, + typename Device, + typename DimensionTag, + bool TagStorage = WeakStorageTrait< MeshConfig, Device, DimensionTag >::boundaryTagsEnabled > +class Layer +{ + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + +public: + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using BoundaryTagsArray = Containers::Array< bool, Device, GlobalIndexType >; + using OrderingArray = Containers::Array< GlobalIndexType, Device, GlobalIndexType >; + + Layer() = default; + + explicit Layer( const Layer& other ) + { + operator=( other ); + } + + template< typename Device_ > + Layer( const Layer< MeshConfig, Device_, DimensionTag >& other ) + { + operator=( other ); + } + + Layer& operator=( const Layer& other ) + { + boundaryTags.setLike( other.boundaryTags ); + boundaryIndices.setLike( other.boundaryIndices ); + interiorIndices.setLike( other.interiorIndices ); + boundaryTags = other.boundaryTags; + boundaryIndices = other.boundaryIndices; + interiorIndices = other.interiorIndices; + return *this; + } + + template< typename Device_ > + Layer& operator=( const Layer< MeshConfig, Device_, DimensionTag >& other ) + { + boundaryTags.setLike( other.boundaryTags ); + boundaryIndices.setLike( other.boundaryIndices ); + interiorIndices.setLike( other.interiorIndices ); + boundaryTags = other.boundaryTags; + boundaryIndices = other.boundaryIndices; + interiorIndices = other.interiorIndices; + return *this; + } + + + void setEntitiesCount( DimensionTag, const GlobalIndexType& entitiesCount ) + { + boundaryTags.setSize( entitiesCount ); + } + + void resetBoundaryTags( DimensionTag ) + { + boundaryTags.setValue( false ); + } + + __cuda_callable__ + void setIsBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex, bool isBoundary ) + { + boundaryTags[ entityIndex ] = isBoundary; + } + + __cuda_callable__ + bool isBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex ) const + { + return boundaryTags[ entityIndex ]; + } + + void updateBoundaryIndices( DimensionTag ) + { + // Array does not have sum(), Vector of bools does not fit due to arithmetics + Containers::Vector< typename BoundaryTagsArray::ElementType, typename BoundaryTagsArray::DeviceType, typename BoundaryTagsArray::IndexType > _boundaryTagsVector; + _boundaryTagsVector.bind( boundaryTags.getData(), boundaryTags.getSize() ); + const GlobalIndexType boundaryEntities = _boundaryTagsVector.template sum< GlobalIndexType >(); + boundaryIndices.setSize( boundaryEntities ); + interiorIndices.setSize( boundaryTags.getSize() - boundaryEntities ); + + if( std::is_same< Device, Devices::Host >::value ) { + GlobalIndexType b = 0; + GlobalIndexType i = 0; + while( b + i < boundaryTags.getSize() ) { + const GlobalIndexType e = b + i; + if( boundaryTags[ e ] ) + boundaryIndices[ b++ ] = e; + else + interiorIndices[ i++ ] = e; + } + } + // TODO: parallelize directly on the device + else { + using BoundaryTagsHostArray = typename BoundaryTagsArray::HostType; + using OrderingHostArray = typename OrderingArray::HostType; + + BoundaryTagsHostArray hostBoundaryTags; + OrderingHostArray hostBoundaryIndices; + OrderingHostArray hostInteriorIndices; + + hostBoundaryTags.setLike( boundaryTags ); + hostBoundaryIndices.setLike( boundaryIndices ); + hostInteriorIndices.setLike( interiorIndices ); + + hostBoundaryTags = boundaryTags; + + GlobalIndexType b = 0; + GlobalIndexType i = 0; + while( b + i < boundaryTags.getSize() ) { + const GlobalIndexType e = b + i; + if( hostBoundaryTags[ e ] ) + hostBoundaryIndices[ b++ ] = e; + else + hostInteriorIndices[ i++ ] = e; + } + + boundaryIndices = hostBoundaryIndices; + interiorIndices = hostInteriorIndices; + } + } + + __cuda_callable__ + GlobalIndexType getBoundaryEntitiesCount( DimensionTag ) const + { + return boundaryIndices.getSize(); + } + + __cuda_callable__ + GlobalIndexType getBoundaryEntityIndex( DimensionTag, const GlobalIndexType& i ) const + { + return boundaryIndices[ i ]; + } + + __cuda_callable__ + GlobalIndexType getInteriorEntitiesCount( DimensionTag ) const + { + return interiorIndices.getSize(); + } + + __cuda_callable__ + GlobalIndexType getInteriorEntityIndex( DimensionTag, const GlobalIndexType& i ) const + { + return interiorIndices[ i ]; + } + + bool save( File& file ) const + { + if( ! boundaryTags.save( file ) ) + { + std::cerr << "Failed to save the boundary tags of the entities with dimension " << DimensionTag::value << "." << std::endl; + return false; + } + return true; + } + + bool load( File& file ) + { + if( ! boundaryTags.load( file ) ) + { + std::cerr << "Failed to load the boundary tags of the entities with dimension " << DimensionTag::value << "." << std::endl; + return false; + } + updateBoundaryIndices( DimensionTag() ); + return true; + } + + void print( std::ostream& str ) const + { + str << "Boundary tags for entities of dimension " << DimensionTag::value << " are: "; + str << boundaryTags << std::endl; + str << "Indices of the boundary entities of dimension " << DimensionTag::value << " are: "; + str << boundaryIndices << std::endl; + str << "Indices of the interior entities of dimension " << DimensionTag::value << " are: "; + str << interiorIndices << std::endl; + } + + bool operator==( const Layer& layer ) const + { + TNL_ASSERT( ( boundaryTags == layer.boundaryTags && boundaryIndices == layer.boundaryIndices && interiorIndices == layer.interiorIndices ) || + ( boundaryTags != layer.boundaryTags && boundaryIndices != layer.boundaryIndices && interiorIndices != layer.interiorIndices ), + std::cerr << "The BoundaryTags layer is in inconsistent state - this is probably a bug in the boundary tags initializer." << std::endl + << "boundaryTags = " << boundaryTags << std::endl + << "layer.boundaryTags = " << layer.boundaryTags << std::endl + << "boundaryIndices = " << boundaryIndices << std::endl + << "layer.boundaryIndices = " << layer.boundaryIndices << std::endl + << "interiorIndices = " << interiorIndices << std::endl + << "layer.interiorIndices = " << layer.interiorIndices << std::endl; ); + return boundaryTags == layer.boundaryTags; + } + +private: + BoundaryTagsArray boundaryTags; + OrderingArray boundaryIndices; + OrderingArray interiorIndices; + + // friend class is needed for templated assignment operators + template< typename MeshConfig_, typename Device_, typename DimensionTag_, bool TagStorage_ > + friend class Layer; +}; + +template< typename MeshConfig, + typename Device, + typename DimensionTag > +class Layer< MeshConfig, Device, DimensionTag, false > +{ +protected: + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + + Layer() = default; + explicit Layer( const Layer& other ) {} + template< typename Device_ > + Layer( const Layer< MeshConfig, Device_, DimensionTag >& other ) {} + Layer& operator=( const Layer& other ) { return *this; } + template< typename Device_ > + Layer& operator=( const Layer< MeshConfig, Device_, DimensionTag >& other ) { return *this; } + + void setEntitiesCount( DimensionTag, const GlobalIndexType& entitiesCount ) {} + void resetBoundaryTags( DimensionTag ) {} + void setIsBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex, bool isBoundary ) {} + void isBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex ) const {} + void updateBoundaryIndices( DimensionTag ) {} + void getBoundaryEntitiesCount( DimensionTag ) const {} + void getBoundaryEntityIndex( DimensionTag, const GlobalIndexType& i ) const {} + void getInteriorEntitiesCount( DimensionTag ) const {} + void getInteriorEntityIndex( DimensionTag, const GlobalIndexType& i ) const {} + + bool save( File& file ) const + { + return true; + } + + bool load( File& file ) + { + return true; + } + + void print( std::ostream& str ) const {} + + bool operator==( const Layer& layer ) const + { + return true; + } +}; + +} // namespace BoundaryTags +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h new file mode 100644 index 0000000000000000000000000000000000000000..44f6cdc445d00a7f6ae49587500e20b950121873 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h @@ -0,0 +1,240 @@ +/*************************************************************************** + LayerFamily.h - description + ------------------- + begin : Nov 9, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include "ConfigValidator.h" +#include "Initializer.h" +#include "Layer.h" +#include "Traits.h" + +namespace TNL { +namespace Meshes { +namespace BoundaryTags { + +template< typename MeshConfig, typename Device, typename Dimension = DimensionTag< 0 > > +class LayerInheritor + : public Layer< MeshConfig, Device, Dimension >, + public LayerInheritor< MeshConfig, Device, typename Dimension::Increment > +{ + using LayerType = Layer< MeshConfig, Device, Dimension >; + using BaseType = LayerInheritor< MeshConfig, Device, typename Dimension::Increment >; +protected: + using LayerType::setEntitiesCount; + using LayerType::resetBoundaryTags; + using LayerType::setIsBoundaryEntity; + using LayerType::isBoundaryEntity; + using LayerType::updateBoundaryIndices; + using LayerType::getBoundaryEntitiesCount; + using LayerType::getBoundaryEntityIndex; + using LayerType::getInteriorEntitiesCount; + using LayerType::getInteriorEntityIndex; + + using BaseType::setEntitiesCount; + using BaseType::resetBoundaryTags; + using BaseType::setIsBoundaryEntity; + using BaseType::isBoundaryEntity; + using BaseType::updateBoundaryIndices; + using BaseType::getBoundaryEntitiesCount; + using BaseType::getBoundaryEntityIndex; + using BaseType::getInteriorEntitiesCount; + using BaseType::getInteriorEntityIndex; + + + LayerInheritor() = default; + + explicit LayerInheritor( const LayerInheritor& other ) + { + operator=( other ); + } + + template< typename Device_ > + LayerInheritor( const LayerInheritor< MeshConfig, Device_, Dimension >& other ) + { + operator=( other ); + } + + LayerInheritor& operator=( const LayerInheritor& other ) + { + LayerType::operator=( other ); + BaseType::operator=( other ); + return *this; + } + + template< typename Device_ > + LayerInheritor& operator=( const LayerInheritor< MeshConfig, Device_, Dimension >& other ) + { + LayerType::operator=( other ); + BaseType::operator=( other ); + return *this; + } + + + bool save( File& file ) const + { + return LayerType::save( file ) && + BaseType::save( file ); + } + + bool load( File& file ) + { + return LayerType::load( file ) && + BaseType::load( file ); + } + + void print( std::ostream& str ) const + { + LayerType::print( str ); + BaseType::print( str ); + } + + bool operator==( const LayerInheritor& layer ) const + { + return LayerType::operator==( layer ) && + BaseType::operator==( layer ); + } +}; + +template< typename MeshConfig, typename Device > +class LayerInheritor< MeshConfig, Device, DimensionTag< MeshConfig::meshDimension + 1 > > +{ +protected: + void setEntitiesCount(); + void resetBoundaryTags(); + void setIsBoundaryEntity(); + void isBoundaryEntity(); + void updateBoundaryIndices(); + void getBoundaryEntitiesCount(); + void getBoundaryEntityIndex(); + void getInteriorEntitiesCount(); + void getInteriorEntityIndex(); + + LayerInheritor() = default; + explicit LayerInheritor( const LayerInheritor& other ) {} + template< typename Device_ > + LayerInheritor( const LayerInheritor< MeshConfig, Device_, DimensionTag< MeshConfig::meshDimension + 1 > >& other ) {} + LayerInheritor& operator=( const LayerInheritor& other ) { return *this; } + template< typename Device_ > + LayerInheritor& operator=( const LayerInheritor< MeshConfig, Device_, DimensionTag< MeshConfig::meshDimension + 1 > >& other ) { return *this; } + + bool save( File& file ) const + { + return true; + } + + bool load( File& file ) + { + return true; + } + + void print( std::ostream& str ) const {} + + bool operator==( const LayerInheritor& layer ) const + { + return true; + } +}; + +// Note that MeshType is an incomplete type and therefore cannot be used to access +// MeshType::Config etc. at the time of declaration of this class template. +template< typename MeshConfig, typename Device, typename MeshType > +class LayerFamily + : public ConfigValidator< MeshConfig >, + public Initializer< MeshConfig, Device, MeshType >, + public LayerInheritor< MeshConfig, Device > +{ + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using BaseType = LayerInheritor< MeshConfig, Device, DimensionTag< 0 > >; + template< int Dimension > + using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >; + template< int Dimension > + using WeakTrait = WeakStorageTrait< MeshConfig, Device, DimensionTag< Dimension > >; + + friend Initializer< MeshConfig, Device, MeshType >; + +public: + // inherit constructors and assignment operators (including templated versions) + using BaseType::BaseType; + using BaseType::operator=; + + // getters for boundary tags + template< int Dimension > + __cuda_callable__ + bool isBoundaryEntity( const GlobalIndexType& entityIndex ) const + { + static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." ); + return BaseType::isBoundaryEntity( DimensionTag< Dimension >(), entityIndex ); + } + + template< int Dimension > + __cuda_callable__ + GlobalIndexType getBoundaryEntitiesCount() const + { + static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." ); + return BaseType::getBoundaryEntitiesCount( DimensionTag< Dimension >() ); + } + + template< int Dimension > + __cuda_callable__ + GlobalIndexType getBoundaryEntityIndex( const GlobalIndexType& i ) const + { + static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." ); + return BaseType::getBoundaryEntityIndex( DimensionTag< Dimension >(), i ); + } + + template< int Dimension > + __cuda_callable__ + GlobalIndexType getInteriorEntitiesCount() const + { + static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." ); + return BaseType::getInteriorEntitiesCount( DimensionTag< Dimension >() ); + } + + template< int Dimension > + __cuda_callable__ + GlobalIndexType getInteriorEntityIndex( const GlobalIndexType& i ) const + { + static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." ); + return BaseType::getInteriorEntityIndex( DimensionTag< Dimension >(), i ); + } + +protected: + // setters for boundary tags + template< int Dimension > + void boundaryTagsSetEntitiesCount( const GlobalIndexType& entitiesCount ) + { + BaseType::setEntitiesCount( DimensionTag< Dimension >(), entitiesCount ); + } + + template< int Dimension > + void resetBoundaryTags() + { + BaseType::resetBoundaryTags( DimensionTag< Dimension >() ); + } + + template< int Dimension > + void updateBoundaryIndices() + { + BaseType::updateBoundaryIndices( DimensionTag< Dimension >() ); + } + + template< int Dimension > + __cuda_callable__ + void setIsBoundaryEntity( const GlobalIndexType& entityIndex, bool isBoundary ) + { + static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." ); + BaseType::setIsBoundaryEntity( DimensionTag< Dimension >(), entityIndex, isBoundary ); + } +}; + +} // namespace BoundaryTags +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Traits.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Traits.h new file mode 100644 index 0000000000000000000000000000000000000000..0d67f0db1d82e29bd893515fab155e9312820fb9 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Traits.h @@ -0,0 +1,39 @@ +/*************************************************************************** + Traits.h - description + ------------------- + begin : Nov 9, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> + +namespace TNL { +namespace Meshes { +namespace BoundaryTags { + +template< typename MeshConfig, + typename Device, + typename DimensionTag, + bool sensible = (DimensionTag::value <= MeshConfig::meshDimension) > +struct WeakStorageTrait +{ + using EntityTopology = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::EntityTopology; + static constexpr bool boundaryTagsEnabled = MeshConfig::boundaryTagsStorage( EntityTopology() ); +}; + +template< typename MeshConfig, + typename Device, + typename DimensionTag > +struct WeakStorageTrait< MeshConfig, Device, DimensionTag, false > +{ + static constexpr bool boundaryTagsEnabled = false; +}; + +} // namespace BoundaryTags +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/MeshLayers/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a213ba3ae1da52cde09adb2fb5850e78a6ce75d5 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/CMakeLists.txt @@ -0,0 +1,8 @@ +ADD_SUBDIRECTORY( BoundaryTags ) + +SET( headers StorageLayer.h + SubentityStorageLayer.h + SuperentityStorageLayer.h +) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/MeshLayers ) diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..80bb94da67d4f89b62f2d99794686f4a031a0bb5 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h @@ -0,0 +1,290 @@ +/*************************************************************************** + StorageLayer.h - description + ------------------- + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/File.h> +#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h> +#include <TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h> +#include <TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename Device, + typename DimensionTag, + bool EntityStorage = WeakEntityStorageTrait< MeshConfig, Device, DimensionTag >::storageEnabled > +class StorageLayer; + + +template< typename MeshConfig, typename Device > +class StorageLayerFamily + : public StorageLayer< MeshConfig, Device, DimensionTag< 0 > > +{ + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using BaseType = StorageLayer< MeshConfig, Device, DimensionTag< 0 > >; + template< int Dimension > + using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >; + +public: + // inherit constructors and assignment operators (including templated versions) + using BaseType::BaseType; + using BaseType::operator=; + +protected: + template< int Dimension > + void setEntitiesCount( const typename MeshTraitsType::GlobalIndexType& entitiesCount ) + { + static_assert( EntityTraits< Dimension >::storageEnabled, "You try to set number of entities which are not configured for storage." ); + BaseType::setEntitiesCount( DimensionTag< Dimension >(), entitiesCount ); + } + + template< int Dimension, int Subdimension > + typename MeshTraitsType::template SubentityTraits< typename EntityTraits< Dimension >::EntityTopology, Subdimension >::StorageNetworkType& + getSubentityStorageNetwork() + { + static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get subentity storage of entities which are not configured for storage." ); + static_assert( Dimension > Subdimension, "Invalid combination of Dimension and Subdimension." ); + using BaseType = SubentityStorageLayerFamily< MeshConfig, + Device, + typename EntityTraits< Dimension >::EntityTopology >; + return BaseType::template getSubentityStorageNetwork< Subdimension >(); + } + + template< int Dimension, int Superdimension > + typename MeshTraitsType::template SuperentityTraits< typename EntityTraits< Dimension >::EntityTopology, Superdimension >::StorageNetworkType& + getSuperentityStorageNetwork() + { + static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get superentity storage of entities which are not configured for storage." ); + static_assert( Dimension < Superdimension, "Invalid combination of Dimension and Superdimension." ); + using BaseType = SuperentityStorageLayerFamily< MeshConfig, + Device, + typename EntityTraits< Dimension >::EntityTopology >; + return BaseType::template getSuperentityStorageNetwork< Superdimension >(); + } +}; + + +template< typename MeshConfig, + typename Device, + typename DimensionTag > +class StorageLayer< MeshConfig, + Device, + DimensionTag, + true > + : public SubentityStorageLayerFamily< MeshConfig, + Device, + typename MeshTraits< MeshConfig, Device >::template EntityTraits< DimensionTag::value >::EntityTopology >, + public SuperentityStorageLayerFamily< MeshConfig, + Device, + typename MeshTraits< MeshConfig, Device >::template EntityTraits< DimensionTag::value >::EntityTopology >, + public StorageLayer< MeshConfig, Device, typename DimensionTag::Increment > +{ +public: + using BaseType = StorageLayer< MeshConfig, Device, typename DimensionTag::Increment >; + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< DimensionTag::value >; + using StorageArrayType = typename EntityTraitsType::StorageArrayType; + using EntityType = typename EntityTraitsType::EntityType; + using EntityTopology = typename EntityTraitsType::EntityTopology; + using SubentityStorageBaseType = SubentityStorageLayerFamily< MeshConfig, Device, EntityTopology >; + using SuperentityStorageBaseType = SuperentityStorageLayerFamily< MeshConfig, Device, EntityTopology >; + + StorageLayer() = default; + + explicit StorageLayer( const StorageLayer& other ) + { + operator=( other ); + } + + template< typename Device_ > + StorageLayer( const StorageLayer< MeshConfig, Device_, DimensionTag >& other ) + { + operator=( other ); + } + + StorageLayer& operator=( const StorageLayer& other ) + { + entities.setLike( other.entities ); + entities = other.entities; + SubentityStorageBaseType::operator=( other ); + SuperentityStorageBaseType::operator=( other ); + BaseType::operator=( other ); + return *this; + } + + template< typename Device_ > + StorageLayer& operator=( const StorageLayer< MeshConfig, Device_, DimensionTag >& other ) + { + entities.setLike( other.entities ); + entities = other.entities; + SubentityStorageBaseType::operator=( other ); + SuperentityStorageBaseType::operator=( other ); + BaseType::operator=( other ); + return *this; + } + + bool save( File& file ) const + { + if( ! SubentityStorageBaseType::save( file ) || + ! SuperentityStorageBaseType::save( file ) || + ! this->entities.save( file ) || + ! BaseType::save( file ) ) + { + std::cerr << "Saving of the mesh entities with dimension " << DimensionTag::value << " failed." << std::endl; + return false; + } + return true; + } + + bool load( File& file ) + { + if( ! SubentityStorageBaseType::load( file ) || + ! SuperentityStorageBaseType::load( file ) || + ! this->entities.load( file ) || + ! BaseType::load( file ) ) + { + std::cerr << "Loading of the mesh entities with dimension " << DimensionTag::value << " failed." << std::endl; + return false; + } + return true; + } + + void print( std::ostream& str ) const + { + str << "The entities with dimension " << DimensionTag::value << " are: " << std::endl; + for( GlobalIndexType i = 0; i < entities.getSize(); i++ ) + str << i << " " << entities[ i ] << std::endl; + SubentityStorageBaseType::print( str ); + SuperentityStorageBaseType::print( str ); + str << std::endl; + BaseType::print( str ); + } + + bool operator==( const StorageLayer& meshLayer ) const + { + return ( entities == meshLayer.entities && + SubentityStorageBaseType::operator==( meshLayer ) && + SuperentityStorageBaseType::operator==( meshLayer ) && + BaseType::operator==( meshLayer ) ); + } + + + using BaseType::getEntitiesCount; + __cuda_callable__ + GlobalIndexType getEntitiesCount( DimensionTag ) const + { + return this->entities.getSize(); + } + + using BaseType::getEntity; + __cuda_callable__ + EntityType& getEntity( DimensionTag, + const GlobalIndexType entityIndex ) + { + return this->entities[ entityIndex ]; + } + + __cuda_callable__ + const EntityType& getEntity( DimensionTag, + const GlobalIndexType entityIndex ) const + { + return this->entities[ entityIndex ]; + } + +protected: + using BaseType::setEntitiesCount; + void setEntitiesCount( DimensionTag, const GlobalIndexType& entitiesCount ) + { + this->entities.setSize( entitiesCount ); + SubentityStorageBaseType::setEntitiesCount( entitiesCount ); + SuperentityStorageBaseType::setEntitiesCount( entitiesCount ); + } + + StorageArrayType entities; + + // friend class is needed for templated assignment operators + template< typename MeshConfig_, typename Device_, typename DimensionTag_, bool Storage_ > + friend class StorageLayer; +}; + +template< typename MeshConfig, + typename Device, + typename DimensionTag > +class StorageLayer< MeshConfig, Device, DimensionTag, false > + : public StorageLayer< MeshConfig, Device, typename DimensionTag::Increment > +{ + using BaseType = StorageLayer< MeshConfig, Device, typename DimensionTag::Increment >; +public: + // inherit constructors and assignment operators (including templated versions) + using BaseType::BaseType; + using BaseType::operator=; +}; + +// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakEntityStorageTrait) +template< typename MeshConfig, + typename Device > +class StorageLayer< MeshConfig, Device, DimensionTag< MeshConfig::meshDimension + 1 >, false > +{ +protected: + using DimensionTag = Meshes::DimensionTag< MeshConfig::meshDimension >; + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + + StorageLayer() = default; + + explicit StorageLayer( const StorageLayer& other ) {} + + template< typename Device_ > + StorageLayer( const StorageLayer< MeshConfig, Device_, DimensionTag >& other ) {} + + StorageLayer& operator=( const StorageLayer& other ) + { + return *this; + } + + template< typename Device_ > + StorageLayer& operator=( const StorageLayer< MeshConfig, Device_, DimensionTag >& other ) + { + return *this; + } + + + void setEntitiesCount() {} + void getEntitiesCount() const {} + void getEntity() const {} + + bool save( File& file ) const + { + return true; + } + + bool load( File& file ) + { + return true; + } + + void print( std::ostream& str ) const {} + + bool operator==( const StorageLayer& meshLayer ) const + { + return true; + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..c26e525a9c5e532708a3bb430bdeb140b56f0dc4 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h @@ -0,0 +1,228 @@ +/*************************************************************************** + SubentityStorageLayer.h - description + ------------------- + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/File.h> +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> +#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SubdimensionTag, + bool SubentityStorage = WeakSubentityStorageTrait< MeshConfig, Device, EntityTopology, SubdimensionTag >::storageEnabled > +class SubentityStorageLayer; + +template< typename MeshConfig, + typename Device, + typename EntityTopology > +class SubentityStorageLayerFamily + : public SubentityStorageLayer< MeshConfig, Device, EntityTopology, DimensionTag< 0 > > +{ + using BaseType = SubentityStorageLayer< MeshConfig, Device, EntityTopology, DimensionTag< 0 > >; + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + +public: + // inherit constructors and assignment operators (including templated versions) + using BaseType::BaseType; + using BaseType::operator=; + +protected: + template< int Subdimension > + typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimension >::StorageNetworkType& + getSubentityStorageNetwork() + { + static_assert( EntityTopology::dimension > Subdimension, "Invalid combination of Dimension and Subdimension." ); + return BaseType::getSubentityStorageNetwork( DimensionTag< Subdimension >() ); + } +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SubdimensionTag > +class SubentityStorageLayer< MeshConfig, + Device, + EntityTopology, + SubdimensionTag, + true > + : public SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment > +{ + using BaseType = SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment >; + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using SubentityTraitsType = typename MeshTraitsType::template SubentityTraits< EntityTopology, SubdimensionTag::value >; + +protected: + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using StorageNetworkType = typename SubentityTraitsType::StorageNetworkType; + + SubentityStorageLayer() = default; + + explicit SubentityStorageLayer( const SubentityStorageLayer& other ) + { + operator=( other ); + } + + template< typename Device_ > + SubentityStorageLayer( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other ) + { + operator=( other ); + } + + SubentityStorageLayer& operator=( const SubentityStorageLayer& other ) + { + BaseType::operator=( other ); + storageNetwork.setLike( other.storageNetwork ); + storageNetwork = other.storageNetwork; + return *this; + } + + template< typename Device_ > + SubentityStorageLayer& operator=( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other ) + { + BaseType::operator=( other ); + storageNetwork.setLike( other.storageNetwork ); + storageNetwork = other.storageNetwork; + return *this; + } + + + bool save( File& file ) const + { + if( ! BaseType::save( file ) || + ! this->storageNetwork.save( file ) ) + { + std::cerr << "Saving of the entity subentities layer with " << SubdimensionTag::value << " dimension failed." << std::endl; + return false; + } + return true; + } + + bool load( File& file ) + { + if( ! BaseType::load( file ) || + ! this->storageNetwork.load( file ) ) + { + std::cerr << "Loading of the entity subentities layer with " << SubdimensionTag::value << " dimension failed." << std::endl; + return false; + } + return true; + } + + void print( std::ostream& str ) const + { + BaseType::print( str ); + str << "Storage network for subentities with dimension " << SubdimensionTag::value << " of entities with dimension " << EntityTopology::dimension << " is: " << std::endl; + str << this->storageNetwork << std::endl; + } + + bool operator==( const SubentityStorageLayer& layer ) const + { + return ( BaseType::operator==( layer ) && + storageNetwork == layer.storageNetwork ); + } + +protected: + void setEntitiesCount( const GlobalIndexType& entitiesCount ) + { + BaseType::setEntitiesCount( entitiesCount ); + this->storageNetwork.setKeysRange( entitiesCount ); + this->storageNetwork.allocate(); + } + + using BaseType::getSubentityStorageNetwork; + StorageNetworkType& getSubentityStorageNetwork( SubdimensionTag ) + { + return this->storageNetwork; + } + +private: + StorageNetworkType storageNetwork; + + // friend class is needed for templated assignment operators + template< typename MeshConfig_, typename Device_, typename EntityTopology_, typename SubdimensionTag_, bool Storage_ > + friend class SubentityStorageLayer; +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SubdimensionTag > +class SubentityStorageLayer< MeshConfig, + Device, + EntityTopology, + SubdimensionTag, + false > + : public SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment > +{ + using BaseType = SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment >; +public: + // inherit constructors and assignment operators (including templated versions) + using BaseType::BaseType; + using BaseType::operator=; +}; + +// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSubentityStorageTrait) +template< typename MeshConfig, + typename Device, + typename EntityTopology > +class SubentityStorageLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag< EntityTopology::dimension >, + false > +{ + using SubdimensionTag = DimensionTag< EntityTopology::dimension >; + +protected: + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + + SubentityStorageLayer() = default; + explicit SubentityStorageLayer( const SubentityStorageLayer& other ) {} + template< typename Device_ > + SubentityStorageLayer( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other ) {} + template< typename Device_ > + SubentityStorageLayer& operator=( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other ) { return *this; } + + void setEntitiesCount( GlobalIndexType entitiesCount ) {} + + void print( std::ostream& str ) const {} + + bool operator==( const SubentityStorageLayer& layer ) const + { + return true; + } + + bool save( File& file ) const + { + return true; + } + + bool load( File& file ) + { + return true; + } + + void getSubentityStorageNetwork( SubdimensionTag ) {} +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h new file mode 100644 index 0000000000000000000000000000000000000000..62d86fe7bff83042f19ab41f68023c91c4cf83ee --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h @@ -0,0 +1,221 @@ +/*************************************************************************** + SuperentityStorageLayer.h - description + ------------------- + begin : Feb 13, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/File.h> +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> +#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SuperdimensionTag, + bool SuperentityStorage = WeakSuperentityStorageTrait< MeshConfig, Device, EntityTopology, SuperdimensionTag >::storageEnabled > +class SuperentityStorageLayer; + +template< typename MeshConfig, + typename Device, + typename EntityTopology > +class SuperentityStorageLayerFamily + : public SuperentityStorageLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > > +{ + using BaseType = SuperentityStorageLayer< MeshConfig, + Device, + EntityTopology, + DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > >; + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + +public: + // inherit constructors and assignment operators (including templated versions) + using BaseType::BaseType; + using BaseType::operator=; + +protected: + template< int Superdimension > + typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >::StorageNetworkType& + getSuperentityStorageNetwork() + { + static_assert( EntityTopology::dimension < Superdimension, "Invalid combination of Dimension and Superdimension." ); + return BaseType::getSuperentityStorageNetwork( DimensionTag< Superdimension >() ); + } +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SuperdimensionTag > +class SuperentityStorageLayer< MeshConfig, Device, EntityTopology, SuperdimensionTag, true > + : public SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement > +{ + using BaseType = SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement >; + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using SuperentityTraitsType = typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionTag::value >; + +protected: + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using StorageNetworkType = typename SuperentityTraitsType::StorageNetworkType; + + SuperentityStorageLayer() = default; + + explicit SuperentityStorageLayer( const SuperentityStorageLayer& other ) + { + operator=( other ); + } + + template< typename Device_ > + SuperentityStorageLayer( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other ) + { + operator=( other ); + } + + SuperentityStorageLayer& operator=( const SuperentityStorageLayer& other ) + { + BaseType::operator=( other ); + storageNetwork.setLike( other.storageNetwork ); + storageNetwork = other.storageNetwork; + return *this; + } + + template< typename Device_ > + SuperentityStorageLayer& operator=( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other ) + { + BaseType::operator=( other ); + storageNetwork.setLike( other.storageNetwork ); + storageNetwork = other.storageNetwork; + return *this; + } + + + bool save( File& file ) const + { + if( ! BaseType::save( file ) || + ! this->storageNetwork.save( file ) ) + { + std::cerr << "Saving of the entity superentities layer with " << SuperdimensionTag::value << " dimension failed." << std::endl; + return false; + } + return true; + } + + bool load( File& file ) + { + if( ! BaseType::load( file ) || + ! this->storageNetwork.load( file ) ) + { + std::cerr << "Loading of the entity superentities layer with " << SuperdimensionTag::value << " dimension failed." << std::endl; + return false; + } + return true; + } + + void print( std::ostream& str ) const + { + BaseType::print( str ); + str << "Storage network for superentities with dimension " << SuperdimensionTag::value << " of entities with dimension " << EntityTopology::dimension << " is: " << std::endl; + str << this->storageNetwork << std::endl; + } + + bool operator==( const SuperentityStorageLayer& layer ) const + { + return ( BaseType::operator==( layer ) && + storageNetwork == layer.storageNetwork ); + } + +protected: + void setEntitiesCount( const GlobalIndexType& entitiesCount ) + { + BaseType::setEntitiesCount( entitiesCount ); + this->storageNetwork.setKeysRange( entitiesCount ); + } + + using BaseType::getSuperentityStorageNetwork; + StorageNetworkType& getSuperentityStorageNetwork( SuperdimensionTag ) + { + return this->storageNetwork; + } + +private: + StorageNetworkType storageNetwork; + + // friend class is needed for templated assignment operators + template< typename MeshConfig_, typename Device_, typename EntityTopology_, typename SuperdimensionTag_, bool Storage_ > + friend class SuperentityStorageLayer; +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SuperdimensionTag > +class SuperentityStorageLayer< MeshConfig, Device, EntityTopology, SuperdimensionTag, false > + : public SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement > +{ + using BaseType = SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement >; +public: + // inherit constructors and assignment operators (including templated versions) + using BaseType::BaseType; + using BaseType::operator=; +}; + +// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSuperentityStorageTrait) +template< typename MeshConfig, + typename Device, + typename EntityTopology > +class SuperentityStorageLayer< MeshConfig, Device, EntityTopology, DimensionTag< EntityTopology::dimension >, false > +{ + using SuperdimensionTag = DimensionTag< EntityTopology::dimension >; + +protected: + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + + SuperentityStorageLayer() = default; + explicit SuperentityStorageLayer( const SuperentityStorageLayer& other ) {} + template< typename Device_ > + SuperentityStorageLayer( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other ) {} + template< typename Device_ > + SuperentityStorageLayer& operator=( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other ) { return *this; } + + void setEntitiesCount( GlobalIndexType entitiesCount ) {} + + void print( std::ostream& str ) const {} + + bool operator==( const SuperentityStorageLayer& layer ) const + { + return true; + } + + bool save( File& file ) const + { + return true; + } + + bool load( File& file ) + { + return true; + } + + void getSuperentityStorageNetwork( SuperdimensionTag ) {} +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshWriterNetgen.h b/src/TNL/Meshes/MeshDetails/MeshWriterNetgen.h deleted file mode 100644 index 82cbc84a24ae2b57bbac34d5b995a6a99befc627..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/MeshWriterNetgen.h +++ /dev/null @@ -1,82 +0,0 @@ -/*************************************************************************** - MeshWriterNetgen.h - description - ------------------- - begin : Feb 22, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <fstream> -#include <istream> -#include <sstream> -#include <iomanip> - -namespace TNL { -namespace Meshes { - -class MeshWriterNetgen -{ - public: - - template< typename MeshType > - static bool writeMesh( const String& fileName, - MeshType& mesh, - bool verbose ) - { - std::fstream outputFile; - outputFile.open( fileName.getString(), std::ios::out ); - if( ! outputFile ) - { - std::cerr << "I am not able to open the output file " << fileName << "." << std::endl; - return false; - } - outputFile << std::setprecision( 6 ); - outputFile << fixed; - - const int meshDimension = MeshType::meshDimension; - typedef typename MeshType::template EntitiesTraits< 0 >::GlobalIndexType VerticesIndexType; - typedef typename MeshType::PointType PointType; - const VerticesIndexType numberOfVertices = mesh.getNumberOfVertices(); - outputFile << numberOfVertices << std::endl; - for( VerticesIndexType i = 0; i < numberOfVertices; i++ ) - { - const PointType& point = mesh.getVertex( i ).getPoint(); - outputFile << " "; - for( int d = 0; d < meshDimension; d++ ) - outputFile << " " << point[ d ]; - outputFile << std::endl; - } - - typedef typename MeshType::template EntitiesTraits< meshDimension >::GlobalIndexType CellIndexType; - typedef typename MeshType::template EntitiesTraits< meshDimension >::Type CellType; - typedef typename CellType::LocalIndexType LocalIndexType; - - const CellIndexType numberOfCells = mesh.template getNumberOfEntities< meshDimension >(); - outputFile << numberOfCells << std::endl; - for( CellIndexType cellIdx = 0; cellIdx < numberOfCells; cellIdx++ ) - { - const CellType& cell = mesh.template getEntity< meshDimension >( cellIdx ); - outputFile << " 1"; - for( LocalIndexType cellVertexIdx = 0; - cellVertexIdx < meshDimension + 1; - cellVertexIdx++ ) - outputFile << " " << cell.getVertexIndex( cellVertexIdx ); - outputFile << std::endl; - } - - return true; - } -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h b/src/TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h deleted file mode 100644 index 930e00e5ba977111f3b9f4adf30a00d7d2a62003..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************** - MeshWriterVTKLegacy.h - description - ------------------- - begin : Mar 20, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <fstream> -#include <istream> -#include <sstream> -#include <iomanip> - -#include <TNL/Meshes/Topologies/MeshTriangleTopology.h> -#include <TNL/Meshes/Topologies/MeshQuadrilateralTopology.h> -#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h> -#include <TNL/Meshes/Topologies/MeshHexahedronTopology.h> -#include <TNL/Meshes/MeshEntity.h> - -namespace TNL { -namespace Meshes { - -enum tnlVTKMeshEntities { tnlVTKVertex = 1, - tnlVTKPolyVertex = 2, - tnlVTKLine = 3, - tnlVTKPolyLine = 4, - tnlVTKTriangle = 5, - tnlVTKTriangleStrip = 6, - tnlVTKPolygon = 7, - tnlVTKPixel = 8, - tnlVTKQuad = 9, - tnlVTKTetra = 10, - tnlVTKVoxel = 11, - tnlVTKHexahedron = 12, - tnlVTKWedge = 13, - tnlVTKPyramid = 14 }; - -template< typename MeshEntity > -struct MeshEntityVTKType{}; - -template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshTriangleTopology > > { enum { VTKType = tnlVTKTriangle }; }; -template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshQuadrilateralTopology > >{ enum { VTKType = tnlVTKQuad }; }; -template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshTetrahedronTopology > > { enum { VTKType = tnlVTKTetra }; }; -template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshHexahedronTopology > > { enum { VTKType = tnlVTKHexahedron }; }; - -class MeshWriterVTKLegacy -{ - public: - - template< typename MeshType > - static bool write( const String& fileName, - MeshType& mesh, - bool verbose ) - { - if( MeshType::dimensions > 3 ) - { - std::cerr << "You try to write mesh with " << MeshType::dimensions - << "dimensions but VTK legacy format supports only 1D, 2D and 3D meshes." << std::endl; - return false; - } - std::fstream outputFile; - outputFile.open( fileName.getString(), std::ios::out ); - if( ! outputFile ) - { - std::cerr << "I am not able to open the output file " << fileName << "." << std::endl; - return false; - } - outputFile << std::setprecision( 6 ); - outputFile << std::fixed; - - return writeMesh( outputFile, mesh, verbose ); - } - - template< typename MeshType > - static bool writeMesh( std::ostream& file, - MeshType& mesh, - bool verbose ) - { - typedef typename MeshType::MeshTraitsType::CellType CellType; - file << "# vtk DataFile Version 2.0" << std::endl; - file << "TNL Mesh" << std::endl; - file << "ASCII" << std::endl; - file << "DATASET UNSTRUCTURED_GRID" << std::endl; - file << std::endl; - file << "POINTS " << mesh.template getNumberOfEntities< 0 >() << " double" << std::endl; - for( int i = 0; i < mesh.template getNumberOfEntities< 0 >(); i++ ) - { - mesh.template getEntity< 0 >( i ).getPoint().write( file ); - for( int j = MeshType::dimensions; j < 3; j++ ) - file << " 0.0"; - file << std::endl; - } - file << std::endl; - file << "CELLS " << mesh.getNumberOfCells(); - long int listSize( 0 ); - for( int i = 0; i < mesh.getNumberOfCells(); i++ ) - listSize += mesh.getCell( i ).template getNumberOfSubentities< 0 >() + 1; - file << " " << listSize << std::endl; - for( int i = 0; i < mesh.getNumberOfCells(); i++ ) - { - int numberOfVertices = mesh.getCell( i ).template getNumberOfSubentities< 0 >(); - file << numberOfVertices << " "; - for( int j = 0; j < numberOfVertices - 1; j++ ) - file << mesh.getCell( i ).template getSubentityIndex< 0 >( j ) << " "; - file << mesh.getCell( i ).template getSubentityIndex< 0 >( numberOfVertices - 1 ) << std::endl; - } - file << std::endl; - file << "CELL_TYPES " << mesh.getNumberOfCells() << std::endl; - for( int i = 0; i < mesh.getNumberOfCells(); i++ ) - { - file << MeshEntityVTKType< CellType >::VTKType << std::endl; - } - file << std::endl; - return true; - } - - -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/Mesh_impl.h b/src/TNL/Meshes/MeshDetails/Mesh_impl.h index eb5f457a6b4449832e750ac96eecba033e173ded..cd704edafc8dd0488ef971586235ed8534ccb0b3 100644 --- a/src/TNL/Meshes/MeshDetails/Mesh_impl.h +++ b/src/TNL/Meshes/MeshDetails/Mesh_impl.h @@ -17,101 +17,232 @@ #pragma once #include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/MeshDetails/EntityStorageRebinder.h> +#include <TNL/Meshes/MeshDetails/IndexPermutationApplier.h> +#include <TNL/Meshes/MeshDetails/initializer/Initializer.h> namespace TNL { namespace Meshes { -template< typename MeshConfig > +template< typename MeshConfig, typename Device, typename MeshType > +void +MeshInitializableBase< MeshConfig, Device, MeshType >:: +init( typename MeshTraitsType::PointArrayType& points, + typename MeshTraitsType::CellSeedArrayType& cellSeeds ) +{ + Initializer< typename MeshType::Config > initializer; + initializer.createMesh( points, cellSeeds, *static_cast<MeshType*>(this) ); + // init boundary tags + static_cast< BoundaryTags::LayerFamily< MeshConfig, Device, MeshType >* >( static_cast< MeshType* >( this ) )->initLayer(); +} + + +template< typename MeshConfig, typename Device > +Mesh< MeshConfig, Device >:: +Mesh( const Mesh& mesh ) + : StorageBaseType( mesh ), + BoundaryTagsLayerFamily( mesh ) +{ + // update pointers from entities into the subentity and superentity storage networks + EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this ); +} + +template< typename MeshConfig, typename Device > + template< typename Device_ > +Mesh< MeshConfig, Device >:: +Mesh( const Mesh< MeshConfig, Device_ >& mesh ) + : StorageBaseType( mesh ), + BoundaryTagsLayerFamily( mesh ) +{ + // update pointers from entities into the subentity and superentity storage networks + EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this ); +} + +template< typename MeshConfig, typename Device > +Mesh< MeshConfig, Device >& +Mesh< MeshConfig, Device >:: +operator=( const Mesh& mesh ) +{ + StorageBaseType::operator=( mesh ); + BoundaryTagsLayerFamily::operator=( mesh ); + // update pointers from entities into the subentity and superentity storage networks + EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this ); + return *this; +} + +template< typename MeshConfig, typename Device > + template< typename Device_ > +Mesh< MeshConfig, Device >& +Mesh< MeshConfig, Device >:: +operator=( const Mesh< MeshConfig, Device_ >& mesh ) +{ + StorageBaseType::operator=( mesh ); + BoundaryTagsLayerFamily::operator=( mesh ); + // update pointers from entities into the subentity and superentity storage networks + EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this ); + return *this; +} + +template< typename MeshConfig, typename Device > +constexpr int +Mesh< MeshConfig, Device >:: +getMeshDimension() +{ + return MeshTraitsType::meshDimension; +} + +template< typename MeshConfig, typename Device > String -Mesh< MeshConfig >:: +Mesh< MeshConfig, Device >:: getType() { return String( "Meshes::Mesh< ") + MeshConfig::getType() + " >"; } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > String -Mesh< MeshConfig >:: +Mesh< MeshConfig, Device >:: getTypeVirtual() const { return this->getType(); } -template< typename MeshConfig > -constexpr int -Mesh< MeshConfig >:: -getMeshDimension() +template< typename MeshConfig, typename Device > +String +Mesh< MeshConfig, Device >:: +getSerializationType() +{ + return Mesh::getType(); +} + +template< typename MeshConfig, typename Device > +String +Mesh< MeshConfig, Device >:: +getSerializationTypeVirtual() const { - return dimension; + return this->getSerializationType(); } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > template< int Dimension > -bool -Mesh< MeshConfig >:: -entitiesAvalable() const +constexpr bool +Mesh< MeshConfig, Device >:: +entitiesAvailable() { - return MeshTraitsType::template EntityTraits< Dimension >::available; + return MeshTraitsType::template EntityTraits< Dimension >::storageEnabled; } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > template< int Dimension > -typename Mesh< MeshConfig >::GlobalIndexType -Mesh< MeshConfig >:: -getNumberOfEntities() const +__cuda_callable__ +typename Mesh< MeshConfig, Device >::GlobalIndexType +Mesh< MeshConfig, Device >:: +getEntitiesCount() const { - return entitiesStorage.getNumberOfEntities( MeshDimensionTag< Dimension >() ); + static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get number of entities which are not configured for storage." ); + return StorageBaseType::getEntitiesCount( DimensionTag< Dimension >() ); } -template< typename MeshConfig > -typename Mesh< MeshConfig >::GlobalIndexType -Mesh< MeshConfig >:: -template getNumberOfCells() const +template< typename MeshConfig, typename Device > + template< int Dimension > +__cuda_callable__ +typename Mesh< MeshConfig, Device >::template EntityType< Dimension >& +Mesh< MeshConfig, Device >:: +getEntity( const GlobalIndexType& entityIndex ) { - return entitiesStorage.getNumberOfEntities( MeshDimensionTag< dimensions >() ); + static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get entity which is not configured for storage." ); + return StorageBaseType::getEntity( DimensionTag< Dimension >(), entityIndex ); } -template< typename MeshConfig > -typename Mesh< MeshConfig >::CellType& -Mesh< MeshConfig >:: -getCell( const GlobalIndexType cellIndex ) +template< typename MeshConfig, typename Device > + template< int Dimension > +__cuda_callable__ +const typename Mesh< MeshConfig, Device >::template EntityType< Dimension >& +Mesh< MeshConfig, Device >:: +getEntity( const GlobalIndexType& entityIndex ) const { - return entitiesStorage.getEntity( MeshDimensionTag< dimensions >(), cellIndex ); + static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get entity which is not configured for storage." ); + return StorageBaseType::getEntity( DimensionTag< Dimension >(), entityIndex ); } -template< typename MeshConfig > -const typename Mesh< MeshConfig >::CellType& -Mesh< MeshConfig >:: -getCell( const GlobalIndexType cellIndex ) const + +// duplicated for compatibility with grids +template< typename MeshConfig, typename Device > + template< typename Entity > +__cuda_callable__ +typename Mesh< MeshConfig, Device >::GlobalIndexType +Mesh< MeshConfig, Device >:: +getEntitiesCount() const { - return entitiesStorage.getEntity( MeshDimensionTag< dimensions >(), cellIndex ); + return getEntitiesCount< Entity::getEntityDimension() >(); } -template< typename MeshConfig > - template< int Dimension > -typename Mesh< MeshConfig >::template EntityType< Dimension >& -Mesh< MeshConfig >:: -getEntity( const GlobalIndexType entityIndex ) +template< typename MeshConfig, typename Device > + template< typename Entity > +__cuda_callable__ +Entity& +Mesh< MeshConfig, Device >:: +getEntity( const GlobalIndexType& entityIndex ) { - return entitiesStorage.getEntity( MeshDimensionTag< Dimension >(), entityIndex ); + return getEntity< Entity::getEntityDimension() >( entityIndex ); } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > + template< typename Entity > +__cuda_callable__ +const Entity& +Mesh< MeshConfig, Device >:: +getEntity( const GlobalIndexType& entityIndex ) const +{ + return getEntity< Entity::getEntityDimension() >( entityIndex ); +} + + +template< typename MeshConfig, typename Device > template< int Dimension > -const typename Mesh< MeshConfig >::template EntityType< Dimension >& -Mesh< MeshConfig >:: -getEntity( const GlobalIndexType entityIndex ) const +void +Mesh< MeshConfig, Device >:: +reorderEntities( const GlobalIndexVector& perm, + const GlobalIndexVector& iperm ) { - return entitiesStorage.getEntity( MeshDimensionTag< Dimension >(), entityIndex ); + static_assert( entitiesAvailable< Dimension >(), "Entities which are not stored cannot be reordered." ); + + const GlobalIndexType entitiesCount = getEntitiesCount< Dimension >(); + + // basic sanity check + if( perm.getSize() != entitiesCount || iperm.getSize() != entitiesCount ) { + throw std::logic_error( "Wrong size of permutation vectors: " + "perm = " + std::to_string( perm ) + ", " + "iperm = " + std::to_string( iperm ) ); + } + TNL_ASSERT( perm.min() == 0 && perm.max() == entitiesCount - 1, + std::cerr << "Given array is not a permutation: min = " << perm.min() + << ", max = " << perm.max() + << ", number of entities = " << entitiesCount + << ", array = " << perm << std::endl; ); + TNL_ASSERT( iperm.min() == 0 && iperm.max() == entitiesCount - 1, + std::cerr << "Given array is not a permutation: min = " << iperm.min() + << ", max = " << iperm.max() + << ", number of entities = " << entitiesCount + << ", array = " << iperm << std::endl; ); + + IndexPermutationApplier< Mesh, Dimension >::exec( *this, perm, iperm ); + // update pointers from entities into the subentity and superentity storage networks + // TODO: it would be enough to rebind just the permuted entities + EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this ); + // update boundary tags + static_cast< BoundaryTagsLayerFamily* >( this )->initLayer(); } - -template< typename MeshConfig > + + +template< typename MeshConfig, typename Device > bool -Mesh< MeshConfig >:: +Mesh< MeshConfig, Device >:: save( File& file ) const { if( ! Object::save( file ) || - ! entitiesStorage.save( file ) ) + ! StorageBaseType::save( file ) || + ! BoundaryTagsLayerFamily::save( file ) ) { std::cerr << "Mesh saving failed." << std::endl; return false; @@ -119,67 +250,71 @@ save( File& file ) const return true; } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > bool -Mesh< MeshConfig >:: +Mesh< MeshConfig, Device >:: load( File& file ) { if( ! Object::load( file ) || - ! entitiesStorage.load( file ) ) + ! StorageBaseType::load( file ) || + ! BoundaryTagsLayerFamily::load( file ) ) { std::cerr << "Mesh loading failed." << std::endl; return false; } + // update pointers from entities into the subentity and superentity storage networks + EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this ); return true; } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > void -Mesh< MeshConfig >:: +Mesh< MeshConfig, Device >:: print( std::ostream& str ) const { - entitiesStorage.print( str ); + // FIXME: there is a problem with multimaps and accessors holding pointers into the device memory + if( std::is_same< Device, Devices::Cuda >::value ) { + str << "Textual representation of meshes stored on the CUDA device is not supported." << std::endl; + } + else { + StorageBaseType::print( str ); + BoundaryTagsLayerFamily::print( str ); + } } -template< typename MeshConfig > +template< typename MeshConfig, typename Device > bool -Mesh< MeshConfig >:: +Mesh< MeshConfig, Device >:: operator==( const Mesh& mesh ) const { - return entitiesStorage.operator==( mesh.entitiesStorage ); + return StorageBaseType::operator==( mesh ) && + BoundaryTagsLayerFamily::operator==( mesh ); } -template< typename MeshConfig > - template< typename DimensionTag > -typename Mesh< MeshConfig >::template EntityTraits< DimensionTag::value >::StorageArrayType& -Mesh< MeshConfig >:: -entitiesArray() -{ - return entitiesStorage.entitiesArray( DimensionTag() ); -} - -template< typename MeshConfig > - template< typename DimensionTag, typename SuperDimensionTag > -typename Mesh< MeshConfig >::MeshTraitsType::GlobalIdArrayType& -Mesh< MeshConfig >:: -superentityIdsArray() +template< typename MeshConfig, typename Device > +bool +Mesh< MeshConfig, Device >:: +operator!=( const Mesh& mesh ) const { - return entitiesStorage.template superentityIdsArray< SuperDimensionTag >( DimensionTag() ); + return ! operator==( mesh ); } -template< typename MeshConfig > -bool -Mesh< MeshConfig >:: -init( const typename Mesh< MeshConfig >::MeshTraitsType::PointArrayType& points, - const typename Mesh< MeshConfig >::MeshTraitsType::CellSeedArrayType& cellSeeds ) +template< typename MeshConfig, typename Device > +void +Mesh< MeshConfig, Device >:: +writeProlog( Logger& logger ) const { - MeshInitializer< MeshConfig> meshInitializer; - return meshInitializer.createMesh( points, cellSeeds, *this ); + logger.writeParameter( "Dimension:", getMeshDimension() ); + logger.writeParameter( "Number of cells:", getEntitiesCount< getMeshDimension() >() ); + if( getMeshDimension() > 1 ) + logger.writeParameter( "Number of faces:", getEntitiesCount< getMeshDimension() - 1 >() ); + logger.writeParameter( "Number of vertices:", getEntitiesCount< 0 >() ); + // TODO: more parameters? } -template< typename MeshConfig > -std::ostream& operator <<( std::ostream& str, const Mesh< MeshConfig >& mesh ) +template< typename MeshConfig, typename Device > +std::ostream& operator<<( std::ostream& str, const Mesh< MeshConfig, Device >& mesh ) { mesh.print( str ); return str; @@ -187,4 +322,3 @@ std::ostream& operator <<( std::ostream& str, const Mesh< MeshConfig >& mesh ) } // namespace Meshes } // namespace TNL - diff --git a/src/TNL/Meshes/MeshDetails/Traverser_impl.h b/src/TNL/Meshes/MeshDetails/Traverser_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..12b24868b0f6941b5844dfdeb9de919be5f514a0 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/Traverser_impl.h @@ -0,0 +1,241 @@ +/*************************************************************************** + Traverser_impl.h - description + ------------------- + begin : Dec 25, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/Traverser.h> + +#include <TNL/Exceptions/CudaSupportMissing.h> + +namespace TNL { +namespace Meshes { + +template< typename Mesh, + typename MeshEntity, + int EntitiesDimension > + template< typename UserData, + typename EntitiesProcessor > +void +Traverser< Mesh, MeshEntity, EntitiesDimension >:: +processBoundaryEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const +{ + auto entitiesCount = meshPointer->template getBoundaryEntitiesCount< EntitiesDimension >(); +#ifdef HAVE_OPENMP +#pragma omp parallel for if( Devices::Host::isOMPEnabled() ) +#endif + for( decltype(entitiesCount) i = 0; i < entitiesCount; i++ ) { + const auto entityIndex = meshPointer->template getBoundaryEntityIndex< EntitiesDimension >( i ); + auto& entity = meshPointer->template getEntity< EntitiesDimension >( entityIndex ); + // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex + EntitiesProcessor::processEntity( *meshPointer, *userDataPointer, entity ); + } +} + +template< typename Mesh, + typename MeshEntity, + int EntitiesDimension > + template< typename UserData, + typename EntitiesProcessor > +void +Traverser< Mesh, MeshEntity, EntitiesDimension >:: +processInteriorEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const +{ + auto entitiesCount = meshPointer->template getInteriorEntitiesCount< EntitiesDimension >(); +#ifdef HAVE_OPENMP +#pragma omp parallel for if( Devices::Host::isOMPEnabled() ) +#endif + for( decltype(entitiesCount) i = 0; i < entitiesCount; i++ ) { + const auto entityIndex = meshPointer->template getInteriorEntityIndex< EntitiesDimension >( i ); + auto& entity = meshPointer->template getEntity< EntitiesDimension >( entityIndex ); + // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex + EntitiesProcessor::processEntity( *meshPointer, *userDataPointer, entity ); + } +} + +template< typename Mesh, + typename MeshEntity, + int EntitiesDimension > + template< typename UserData, + typename EntitiesProcessor > +void +Traverser< Mesh, MeshEntity, EntitiesDimension >:: +processAllEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const +{ + auto entitiesCount = meshPointer->template getEntitiesCount< EntitiesDimension >(); +#ifdef HAVE_OPENMP +#pragma omp parallel for if( Devices::Host::isOMPEnabled() ) +#endif + for( decltype(entitiesCount) entityIndex = 0; entityIndex < entitiesCount; entityIndex++ ) { + auto& entity = meshPointer->template getEntity< EntitiesDimension >( entityIndex ); + // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex + EntitiesProcessor::processEntity( *meshPointer, *userDataPointer, entity ); + } +} + + +#ifdef HAVE_CUDA +template< int EntitiesDimension, + typename EntitiesProcessor, + typename Mesh, + typename UserData > +__global__ void +MeshTraverserBoundaryEntitiesKernel( const Mesh* mesh, + UserData* userData, + typename Mesh::GlobalIndexType entitiesCount ) +{ + for( typename Mesh::GlobalIndexType i = blockIdx.x * blockDim.x + threadIdx.x; + i < entitiesCount; + i += blockDim.x * gridDim.x ) + { + const auto entityIndex = mesh->template getBoundaryEntityIndex< EntitiesDimension >( i ); + auto& entity = mesh->template getEntity< EntitiesDimension >( entityIndex ); + // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex + EntitiesProcessor::processEntity( *mesh, *userData, entity ); + } +} + +template< int EntitiesDimension, + typename EntitiesProcessor, + typename Mesh, + typename UserData > +__global__ void +MeshTraverserInteriorEntitiesKernel( const Mesh* mesh, + UserData* userData, + typename Mesh::GlobalIndexType entitiesCount ) +{ + for( typename Mesh::GlobalIndexType i = blockIdx.x * blockDim.x + threadIdx.x; + i < entitiesCount; + i += blockDim.x * gridDim.x ) + { + const auto entityIndex = mesh->template getInteriorEntityIndex< EntitiesDimension >( i ); + auto& entity = mesh->template getEntity< EntitiesDimension >( entityIndex ); + // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex + EntitiesProcessor::processEntity( *mesh, *userData, entity ); + } +} + +template< int EntitiesDimension, + typename EntitiesProcessor, + typename Mesh, + typename UserData > +__global__ void +MeshTraverserAllEntitiesKernel( const Mesh* mesh, + UserData* userData, + typename Mesh::GlobalIndexType entitiesCount ) +{ + for( typename Mesh::GlobalIndexType entityIndex = blockIdx.x * blockDim.x + threadIdx.x; + entityIndex < entitiesCount; + entityIndex += blockDim.x * gridDim.x ) + { + auto& entity = mesh->template getEntity< EntitiesDimension >( entityIndex ); + // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex + EntitiesProcessor::processEntity( *mesh, *userData, entity ); + } +} +#endif + +template< typename MeshConfig, + typename MeshEntity, + int EntitiesDimension > + template< typename UserData, + typename EntitiesProcessor > +void +Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension >:: +processBoundaryEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const +{ +#ifdef HAVE_CUDA + auto entitiesCount = meshPointer->template getBoundaryEntitiesCount< EntitiesDimension >(); + + dim3 blockSize( 256 ); + dim3 gridSize; + const int desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() ); + gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( entitiesCount, blockSize.x ) ); + + Devices::Cuda::synchronizeDevice(); + MeshTraverserBoundaryEntitiesKernel< EntitiesDimension, EntitiesProcessor > + <<< gridSize, blockSize >>> + ( &meshPointer.template getData< Devices::Cuda >(), + &userDataPointer.template modifyData< Devices::Cuda >(), + entitiesCount ); + cudaDeviceSynchronize(); + TNL_CHECK_CUDA_DEVICE; +#else + throw Exceptions::CudaSupportMissing(); +#endif +} + +template< typename MeshConfig, + typename MeshEntity, + int EntitiesDimension > + template< typename UserData, + typename EntitiesProcessor > +void +Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension >:: +processInteriorEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const +{ +#ifdef HAVE_CUDA + auto entitiesCount = meshPointer->template getInteriorEntitiesCount< EntitiesDimension >(); + + dim3 blockSize( 256 ); + dim3 gridSize; + const int desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() ); + gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( entitiesCount, blockSize.x ) ); + + Devices::Cuda::synchronizeDevice(); + MeshTraverserInteriorEntitiesKernel< EntitiesDimension, EntitiesProcessor > + <<< gridSize, blockSize >>> + ( &meshPointer.template getData< Devices::Cuda >(), + &userDataPointer.template modifyData< Devices::Cuda >(), + entitiesCount ); + cudaDeviceSynchronize(); + TNL_CHECK_CUDA_DEVICE; +#else + throw Exceptions::CudaSupportMissing(); +#endif +} + +template< typename MeshConfig, + typename MeshEntity, + int EntitiesDimension > + template< typename UserData, + typename EntitiesProcessor > +void +Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension >:: +processAllEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const +{ +#ifdef HAVE_CUDA + auto entitiesCount = meshPointer->template getEntitiesCount< EntitiesDimension >(); + + dim3 blockSize( 256 ); + dim3 gridSize; + const int desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() ); + gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( entitiesCount, blockSize.x ) ); + + Devices::Cuda::synchronizeDevice(); + MeshTraverserAllEntitiesKernel< EntitiesDimension, EntitiesProcessor > + <<< gridSize, blockSize >>> + ( &meshPointer.template getData< Devices::Cuda >(), + &userDataPointer.template modifyData< Devices::Cuda >(), + entitiesCount ); + cudaDeviceSynchronize(); + TNL_CHECK_CUDA_DEVICE; +#else + throw Exceptions::CudaSupportMissing(); +#endif +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/config/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/config/CMakeLists.txt deleted file mode 100644 index c99141552867ae7b6f139e8ee9f98bb9a3dc3688..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/config/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -SET( headers MeshConfigValidator.h ) - -INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/config ) \ No newline at end of file diff --git a/src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h b/src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h deleted file mode 100644 index ba079790e1d18079e881b4b19af4935fa68df1b6..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h +++ /dev/null @@ -1,115 +0,0 @@ -/*************************************************************************** - MeshConfigValidator.h - description - ------------------- - begin : Aug 14, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Assert.h> -#include <TNL/Meshes/Topologies/MeshEntityTopology.h> -#include <TNL/Meshes/MeshDimensionTag.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename MeshEntity, - typename dimensions > -class MeshConfigValidatorSubtopologyLayer : -public MeshConfigValidatorSubtopologyLayer< MeshConfig, MeshEntity, typename dimensions::Decrement > -{ - static_assert( ! MeshConfig::subentityStorage( MeshEntity(), dimensions::value ) || - MeshConfig::entityStorage( MeshEntity::dimensions ), "entities of which subentities are stored must be stored" ); - static_assert( ! MeshConfig::subentityStorage( MeshEntity(), dimensions::value ) || - MeshConfig::entityStorage( dimensions::value ), "entities that are stored as subentities must be stored"); - static_assert( ! MeshConfig::subentityOrientationStorage( MeshEntity(), dimensions::value ) || - MeshConfig::subentityStorage( MeshEntity(), dimensions::value ), "orientation can be stored only for subentities that are stored"); -}; - -template< typename MeshConfig, - typename MeshEntity > -class MeshConfigValidatorSubtopologyLayer< MeshConfig, MeshEntity, MeshDimensionTag< 0 > > -{ - static_assert( ! MeshConfig::subentityStorage( MeshEntity(), 0 ) || - MeshConfig::entityStorage( 0 ), "entities that are stored as subentities must be stored" ); - static_assert( ! MeshConfig::subentityOrientationStorage( MeshEntity(), 0 ), "storage of vertex orientation does not make sense" ); -}; - - -template< typename MeshConfig, - typename MeshEntity, - typename dimensions > -class MeshConfigValidatorSupertopologyLayer : -public MeshConfigValidatorSupertopologyLayer< MeshConfig, MeshEntity, typename dimensions::Decrement > -{ - static_assert( ! MeshConfig::superentityStorage( MeshEntity(), 0 ) || - MeshConfig::entityStorage( MeshEntity::dimensions ), "entities of which superentities are stored must be stored"); - static_assert( ! MeshConfig::superentityStorage( MeshEntity(), 0 ) || - MeshConfig::entityStorage( dimensions::value ), "entities that are stored as superentities must be stored"); -}; - -template< typename MeshConfig, - typename MeshEntity > -class MeshConfigValidatorSupertopologyLayer< MeshConfig, MeshEntity, MeshDimensionTag< MeshEntity::dimensions > > -{}; - - -template< typename MeshConfig, int dimensions > -class MeshConfigValidatorLayer : - public MeshConfigValidatorLayer< MeshConfig, dimensions - 1 >, - public MeshConfigValidatorSubtopologyLayer< MeshConfig, - typename MeshSubtopology< typename MeshConfig::CellTopology, dimensions >::Topology, - MeshDimensionTag< dimensions - 1 > >, - public MeshConfigValidatorSupertopologyLayer< MeshConfig, - typename MeshSubtopology< typename MeshConfig::CellTopology, dimensions >::Topology, - MeshDimensionTag< MeshConfig::CellTopology::dimensions > > -{ - typedef typename MeshSubtopology< typename MeshConfig::CellTopology, dimensions >::Topology Topology; - - static_assert( ! MeshConfig::entityStorage( dimensions ) || MeshConfig::subentityStorage( Topology(), 0 ), "subvertices of all stored entities must be stored"); -}; - -template< typename MeshConfig > -class MeshConfigValidatorLayer< MeshConfig, 0 > -{ -}; - -template< typename MeshConfig > -class MeshConfigValidatorLayerCell : - public MeshConfigValidatorLayer< MeshConfig, MeshConfig::CellTopology::dimensions - 1 >, - public MeshConfigValidatorSubtopologyLayer< MeshConfig, - typename MeshConfig::CellTopology, - MeshDimensionTag< MeshConfig::CellTopology::dimensions - 1 > > -{ - typedef typename MeshConfig::CellTopology CellTopology; - static const int dimensions = CellTopology::dimensions; - - static_assert( !MeshConfig::entityStorage( dimensions ) || MeshConfig::subentityStorage( CellTopology(), 0 ), "subvertices of all stored entities must be stored"); -}; - -template<typename MeshConfig > -class MeshConfigValidator : public MeshConfigValidatorLayerCell< MeshConfig > -{ - static const int meshDimension = MeshConfig::CellTopology::dimensions; - - static_assert(1 <= meshDimension, "zero dimensional meshes are not supported"); - static_assert( meshDimension <= MeshConfig::worldDimension, "world dimension must not be less than mesh dimension"); - - static_assert( MeshConfig::entityStorage( 0 ), "mesh vertices must be stored"); - static_assert( MeshConfig::entityStorage( meshDimension ), "mesh cells must be stored"); -}; - -} // namespace Meshes -} // namespace TNL - diff --git a/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt index 9f41f3338965936638f4d57795b20a6b30ce396c..f452c0c02285e94471d7cd8cf91f991b48146132 100644 --- a/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt +++ b/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt @@ -1,13 +1,8 @@ -SET( headers MeshEntityInitializer.h - MeshEntitySeed.h - MeshEntitySeedKey.h - MeshInitializer.h - MeshSubentitySeedCreator.h - MeshSuperentityStorageInitializer.h - ) +SET( headers EntityInitializer.h + EntitySeed.h + Initializer.h + SubentitySeedsCreator.h + SuperentityStorageInitializer.h +) -SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Meshes/MeshDetails/initializer ) -SET( tnl_mesh_initializer_SOURCES - PARENT_SCOPE ) - -INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/initializer ) \ No newline at end of file +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/initializer ) diff --git a/src/TNL/Meshes/MeshDetails/initializer/EntityInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/EntityInitializer.h new file mode 100644 index 0000000000000000000000000000000000000000..684e60543bc5b8ab8e5702c070c18294706df910 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/initializer/EntityInitializer.h @@ -0,0 +1,435 @@ +/*************************************************************************** + EntityInitializer.h - description + ------------------- + begin : Feb 23, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/StaticFor.h> + +#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h> +#include <TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h> +#include <TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig > +class Initializer; + +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag, + // storage in the superentity + bool SubentityStorage = + MeshConfig::subentityStorage( typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >::EntityTopology(), + SubdimensionTag::value ), + bool SubentityOrientationStorage = + MeshConfig::subentityOrientationStorage( typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >::EntityTopology(), + SubdimensionTag::value ) && + MeshTraits< MeshConfig >::template EntityTraits< SubdimensionTag::value >::orientationNeeded, + // storage in the subentity + bool SuperentityStorage = + MeshConfig::superentityStorage( typename MeshTraits< MeshConfig >::template EntityTraits< SubdimensionTag::value >::EntityTopology(), + SuperdimensionTag::value ), + // necessary to disambiguate the stop condition for specializations + bool valid_dimension = ! std::is_same< SubdimensionTag, SuperdimensionTag >::value > +class EntityInitializerLayer; + +template< typename MeshConfig, + typename EntityTopology > +class EntityInitializer + : public EntityInitializerLayer< MeshConfig, + DimensionTag< EntityTopology::dimension >, + DimensionTag< MeshTraits< MeshConfig >::meshDimension > > +{ + using BaseType = EntityInitializerLayer< MeshConfig, + DimensionTag< EntityTopology::dimension >, + DimensionTag< MeshTraits< MeshConfig >::meshDimension > >; + + using MeshTraitsType = MeshTraits< MeshConfig >; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< EntityTopology::dimension >; + using EntityType = typename EntityTraitsType::EntityType; + + using SeedType = EntitySeed< MeshConfig, EntityTopology >; + using InitializerType = Initializer< MeshConfig >; + +public: + static String getType() { return "EntityInitializer"; }; + + static void initEntity( EntityType& entity, const GlobalIndexType& entityIndex, const SeedType& entitySeed, InitializerType& initializer) + { + initializer.setEntityIndex( entity, entityIndex ); + // this is necessary if we want to use existing entities instead of intermediate seeds to create subentity seeds + for( LocalIndexType i = 0; i < entitySeed.getCornerIds().getSize(); i++ ) + initializer.template setSubentityIndex< 0 >( entity, entityIndex, i, entitySeed.getCornerIds()[ i ] ); + } +}; + +template< typename MeshConfig > +class EntityInitializer< MeshConfig, Topologies::Vertex > + : public EntityInitializerLayer< MeshConfig, + DimensionTag< 0 >, + DimensionTag< MeshTraits< MeshConfig >::meshDimension > > +{ +public: + using VertexType = typename MeshTraits< MeshConfig >::VertexType; + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using PointType = typename MeshTraits< MeshConfig >::PointType; + using InitializerType = Initializer< MeshConfig >; + + static String getType() { return "EntityInitializer"; }; + + static void initEntity( VertexType& entity, const GlobalIndexType& entityIndex, const PointType& point, InitializerType& initializer) + { + initializer.setEntityIndex( entity, entityIndex ); + initializer.setVertexPoint( entity, point ); + } +}; + + +/**** + * Mesh entity initializer layer with specializations + * + * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE + * TRUE FALSE TRUE + */ +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag > +class EntityInitializerLayer< MeshConfig, + SubdimensionTag, + SuperdimensionTag, + true, + false, + true, + true > + : public EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement > +{ + using BaseType = EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement >; + using InitializerType = Initializer< MeshConfig >; + using MeshType = typename InitializerType::MeshType; + + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using SuperentityTraitsType = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >; + using SuperentityTopology = typename SuperentityTraitsType::EntityTopology; + using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >; + using SuperentityInitializerType = SuperentityStorageInitializer< MeshConfig, SubdimensionTag, SuperdimensionTag >; + +public: + static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh ) + { + //std::cout << " Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl; + SuperentityInitializerType superentityInitializer; + + for( GlobalIndexType superentityIndex = 0; + superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >(); + superentityIndex++ ) + { + auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex ); + auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) ); + + for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) + { + const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); + meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex ); + superentityInitializer.addSuperentity( subentityIndex, superentityIndex ); + } + } + + superentityInitializer.initSuperentities( meshInitializer ); + + BaseType::initSuperentities( meshInitializer, mesh ); + } +}; + +/**** + * Mesh entity initializer layer with specializations + * + * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE + * TRUE TRUE TRUE + */ +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag > +class EntityInitializerLayer< MeshConfig, + SubdimensionTag, + SuperdimensionTag, + true, + true, + true, + true > + : public EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement > +{ + using BaseType = EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement >; + using InitializerType = Initializer< MeshConfig >; + using MeshType = typename InitializerType::MeshType; + + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using SuperentityTraitsType = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >; + using SuperentityTopology = typename SuperentityTraitsType::EntityTopology; + using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >; + using SuperentityInitializerType = SuperentityStorageInitializer< MeshConfig, SubdimensionTag, SuperdimensionTag >; + +public: + static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh ) + { + //std::cout << " Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl; + SuperentityInitializerType superentityInitializer; + + for( GlobalIndexType superentityIndex = 0; + superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >(); + superentityIndex++ ) + { + auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex ); + auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) ); + + auto& subentityOrientationsArray = InitializerType::template subentityOrientationsArray< SubdimensionTag >( superentity ); + + for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) + { + const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); + meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex ); + superentityInitializer.addSuperentity( subentityIndex, superentityIndex ); + + subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< SubdimensionTag >( subentityIndex ).createOrientation( subentitySeeds[ i ] ); + } + } + + superentityInitializer.initSuperentities( meshInitializer ); + + BaseType::initSuperentities( meshInitializer, mesh ); + } +}; + +/**** + * Mesh entity initializer layer with specializations + * + * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE + * TRUE TRUE FALSE + */ +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag > +class EntityInitializerLayer< MeshConfig, + SubdimensionTag, + SuperdimensionTag, + true, + true, + false, + true > + : public EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement > +{ + using BaseType = EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement >; + using InitializerType = Initializer< MeshConfig >; + using MeshType = typename InitializerType::MeshType; + + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using SuperentityTraitsType = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >; + using SuperentityTopology = typename SuperentityTraitsType::EntityTopology; + using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >; + +public: + static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh ) + { + //std::cout << " Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl; + for( GlobalIndexType superentityIndex = 0; + superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >(); + superentityIndex++ ) + { + auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex ); + auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) ); + + auto& subentityOrientationsArray = InitializerType::template subentityOrientationsArray< SubdimensionTag >( superentity ); + + for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) + { + const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); + meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex ); + + subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< SubdimensionTag >( subentityIndex ).createOrientation( subentitySeeds[ i ] ); + } + } + + BaseType::initSuperentities( meshInitializer, mesh ); + } +}; + +/**** + * Mesh entity initializer layer with specializations + * + * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE + * TRUE FALSE FALSE + */ +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag > +class EntityInitializerLayer< MeshConfig, + SubdimensionTag, + SuperdimensionTag, + true, + false, + false, + true > + : public EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement > +{ + using BaseType = EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement >; + using InitializerType = Initializer< MeshConfig >; + using MeshType = typename InitializerType::MeshType; + + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using SuperentityTraitsType = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >; + using SuperentityTopology = typename SuperentityTraitsType::EntityTopology; + using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >; + +public: + static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh ) + { + //std::cout << " Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl; + for( GlobalIndexType superentityIndex = 0; + superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >(); + superentityIndex++ ) + { + auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex ); + auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) ); + + for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) + { + const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); + meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex ); + } + } + + BaseType::initSuperentities( meshInitializer, mesh ); + } +}; + +/**** + * Mesh entity initializer layer with specializations + * + * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE + * FALSE FALSE TRUE + */ +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag > +class EntityInitializerLayer< MeshConfig, + SubdimensionTag, + SuperdimensionTag, + false, + false, + true, + true > + : public EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement > +{ + using BaseType = EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement >; + using InitializerType = Initializer< MeshConfig >; + using MeshType = typename InitializerType::MeshType; + + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using SuperentityTraitsType = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >; + using SuperentityTopology = typename SuperentityTraitsType::EntityTopology; + using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >; + using SuperentityInitializerType = SuperentityStorageInitializer< MeshConfig, SubdimensionTag, SuperdimensionTag >; + +public: + static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh ) + { + //std::cout << " Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl; + SuperentityInitializerType superentityInitializer; + + for( GlobalIndexType superentityIndex = 0; + superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >(); + superentityIndex++ ) + { + auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex ); + auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) ); + + for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) + { + const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); + superentityInitializer.addSuperentity( subentityIndex, superentityIndex ); + } + } + + superentityInitializer.initSuperentities( meshInitializer ); + + BaseType::initSuperentities( meshInitializer, mesh ); + } +}; + +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag > +class EntityInitializerLayer< MeshConfig, + SubdimensionTag, + SuperdimensionTag, + false, + false, + false, + true > + : public EntityInitializerLayer< MeshConfig, + SubdimensionTag, + typename SuperdimensionTag::Decrement > +{}; + +template< typename MeshConfig, + typename SubdimensionTag, + bool SubentityStorage, + bool SubentityOrientationStorage, + bool SuperentityStorage > +class EntityInitializerLayer< MeshConfig, + SubdimensionTag, + SubdimensionTag, + SubentityStorage, + SubentityOrientationStorage, + SuperentityStorage, + false > +{ + using InitializerType = Initializer< MeshConfig >; + using MeshType = typename InitializerType::MeshType; + +public: + static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh ) {} +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/EntitySeed.h b/src/TNL/Meshes/MeshDetails/initializer/EntitySeed.h new file mode 100644 index 0000000000000000000000000000000000000000..b9d34d070114bf40f71d79df1a0d266f545d7347 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/initializer/EntitySeed.h @@ -0,0 +1,166 @@ +/*************************************************************************** + EntitySeed.h - description + ------------------- + begin : Aug 18, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> + +namespace TNL { +namespace Meshes { + +template< typename EntitySeed > +struct EntitySeedHash; +template< typename EntitySeed > +struct EntitySeedEq; + +template< typename MeshConfig, + typename EntityTopology > +class EntitySeed +{ + using MeshConfigTraits = MeshTraits< MeshConfig >; + using SubvertexTraits = typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 >; + + public: + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using IdArrayType = Containers::StaticArray< SubvertexTraits::count, GlobalIndexType >; + using HashType = EntitySeedHash< EntitySeed >; + using KeyEqual = EntitySeedEq< EntitySeed >; + + static String getType() { return String( "EntitySeed<>" ); } + + static constexpr LocalIndexType getCornersCount() + { + return SubvertexTraits::count; + } + + void setCornerId( const LocalIndexType& cornerIndex, const GlobalIndexType& pointIndex ) + { + TNL_ASSERT_GE( cornerIndex, 0, "corner index must be non-negative" ); + TNL_ASSERT_LT( cornerIndex, getCornersCount(), "corner index is out of bounds" ); + TNL_ASSERT_GE( pointIndex, 0, "point index must be non-negative" ); + + this->cornerIds[ cornerIndex ] = pointIndex; + } + + IdArrayType& getCornerIds() + { + return cornerIds; + } + + const IdArrayType& getCornerIds() const + { + return cornerIds; + } + + private: + IdArrayType cornerIds; +}; + +template< typename MeshConfig > +class EntitySeed< MeshConfig, Topologies::Vertex > +{ + using MeshConfigTraits = MeshTraits< MeshConfig >; + + public: + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using IdArrayType = Containers::StaticArray< 1, GlobalIndexType >; + using HashType = EntitySeedHash< EntitySeed >; + using KeyEqual = EntitySeedEq< EntitySeed >; + + static String getType() { return String( "EntitySeed<>" ); } + + static constexpr LocalIndexType getCornersCount() + { + return 1; + } + + void setCornerId( const LocalIndexType& cornerIndex, const GlobalIndexType& pointIndex ) + { + TNL_ASSERT_EQ( cornerIndex, 0, "corner index must be 0" ); + TNL_ASSERT_GE( pointIndex, 0, "point index must be non-negative" ); + + this->cornerIds[ cornerIndex ] = pointIndex; + } + + IdArrayType& getCornerIds() + { + return cornerIds; + } + + const IdArrayType& getCornerIds() const + { + return cornerIds; + } + + private: + IdArrayType cornerIds; +}; + +template< typename MeshConfig, typename EntityTopology > +std::ostream& operator<<( std::ostream& str, const EntitySeed< MeshConfig, EntityTopology >& e ) +{ + str << e.getCornerIds(); + return str; +}; + +template< typename EntitySeed > +struct EntitySeedHash +{ + std::size_t operator()( const EntitySeed& seed ) const + { + using LocalIndexType = typename EntitySeed::LocalIndexType; + using GlobalIndexType = typename EntitySeed::GlobalIndexType; + + // Note that we must use an associative function to combine the hashes, + // because we *want* to ignore the order of the corner IDs. + std::size_t hash = 0; + for( LocalIndexType i = 0; i < EntitySeed::getCornersCount(); i++ ) +// hash ^= std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] ); + hash += std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] ); + return hash; + } +}; + +template< typename EntitySeed > +struct EntitySeedEq +{ + bool operator()( const EntitySeed& left, const EntitySeed& right ) const + { + using IdArrayType = typename EntitySeed::IdArrayType; + + IdArrayType sortedLeft( left.getCornerIds() ); + IdArrayType sortedRight( right.getCornerIds() ); + sortedLeft.sort(); + sortedRight.sort(); + return sortedLeft == sortedRight; + } +}; + +template< typename MeshConfig > +struct EntitySeedEq< EntitySeed< MeshConfig, Topologies::Vertex > > +{ + using Seed = EntitySeed< MeshConfig, Topologies::Vertex >; + + bool operator()( const Seed& left, const Seed& right ) const + { + return left.getCornerIds() == right.getCornerIds(); + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/Initializer.h b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h new file mode 100644 index 0000000000000000000000000000000000000000..fe97e530eaa68e711ed7b14d4cdb559145067d0d --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h @@ -0,0 +1,470 @@ +/*************************************************************************** + Initializer.h - description + ------------------- + begin : Feb 23, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/MeshDetails/initializer/EntityInitializer.h> +#include <TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h> +#include <TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h> +#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h> + +/* + * How this beast works: + * + * The algorithm is optimized for memory requirements. Therefore, the mesh is + * not allocated at once, but by parts (by dimensions). The flow is roughly the + * following: + * + * - Allocate cells and set their subvertex indices (but not other subentity + * indices), deallocate cell seeds (the cells will be used later). + * - For all dimensions D from (cell dimension - 1) to 1: + * - Create intermediate entity seeds, count the number of entities with + * current dimension. + * - Allocate entities and set their subvertex indices. Create an indexed + * set of entity seeds and reference orientations (if applicable). + * - For all superdimensions S > D: + * - Iterate over entities with dimension S and initialize their + * subentity indices with dimension D. Inverse mapping (D->S) is + * recorded in the process. + * - For entities with dimension D, initialize their superentity indices + * with dimension S. + * - Deallocate all intermediate data structures. + * - Allocate vertices and set their physical coordinates, deallocate input + * array of points. + * - For all superdimensions S > 0, repeat the same steps as above. + * + * Optimization notes: + * - Recomputing the seed key involves sorting all subvertex indices, but the + * cost is negligible compared to memory consumption incurred by storing + * both the key and original seed in the indexed set. + * - Since std::set and std::map don't provide a shrink_to_fit method like + * std::vector, these dynamic structures should be kept as local variables + * if possible. This is probably the only way to be sure that the unused + * space is not wasted. + */ + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename DimensionTag, + bool EntityStorage = + MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::storageEnabled, + bool EntityReferenceOrientationStorage = + MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::orientationNeeded > +class InitializerLayer; + + +template< typename MeshConfig > +class Initializer + : public InitializerLayer< MeshConfig, + typename MeshTraits< MeshConfig >::DimensionTag > +{ + protected: + // must be declared before its use in expression with decltype() + Mesh< MeshConfig >* mesh; + + public: + using MeshType = Mesh< MeshConfig >; + using MeshTraitsType = MeshTraits< MeshConfig >; + using DimensionTag = Meshes::DimensionTag< MeshTraitsType::meshDimension >; + using BaseType = InitializerLayer< MeshConfig, DimensionTag >; + using PointArrayType = typename MeshTraitsType::PointArrayType; + using CellSeedArrayType = typename MeshTraitsType::CellSeedArrayType; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + + + Initializer() + : mesh( 0 ) + {} + + // The points and cellSeeds arrays will be reset when not needed to save memory. + void createMesh( PointArrayType& points, + CellSeedArrayType& cellSeeds, + MeshType& mesh ) + { + this->mesh = &mesh; + BaseType::initEntities( *this, points, cellSeeds, mesh ); + // set pointers from entities into the subentity and superentity storage networks + EntityStorageRebinder< Mesh< MeshConfig > >::exec( mesh ); + } + + template< typename Entity, typename GlobalIndex > + void setEntityIndex( Entity& entity, const GlobalIndex& index ) + { + entity.setIndex( index ); + } + + template< int Dimension > + void setEntitiesCount( const GlobalIndexType& entitiesCount ) + { + //std::cout << "Setting number of entities with " << Dimension << " dimension to " << entitiesCount << std::endl; + mesh->template setEntitiesCount< Dimension >( entitiesCount ); + } + + template< int Subdimension, typename EntityType, typename LocalIndex, typename GlobalIndex > + void + setSubentityIndex( const EntityType& entity, const GlobalIndex& entityIndex, const LocalIndex& localIndex, const GlobalIndex& globalIndex ) + { + // The mesh entities are not yet bound to the storage network at this point, + // so we operate directly on the storage. + mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, Subdimension >().getValues( entityIndex )[ localIndex ] = globalIndex; + } + + template< int Subdimension, typename EntityType, typename LocalIndex, typename GlobalIndex > + GlobalIndex + getSubentityIndex( const EntityType& entity, const GlobalIndex& entityIndex, const LocalIndex& localIndex ) + { + // The mesh entities are not yet bound to the storage network at this point, + // so we operate directly on the storage. + return mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, Subdimension >().getValues( entityIndex )[ localIndex ]; + } + + template< typename EntityType, typename GlobalIndex > + auto + getSubvertices( const EntityType& entity, const GlobalIndex& entityIndex ) + -> decltype( this->mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, 0 >().getValues( 0 ) ) + { + // The mesh entities are not yet bound to the storage network at this point, + // so we operate directly on the storage. + return mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, 0 >().getValues( entityIndex ); + } + + template< typename EntityTopology, int Superdimension > + typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >::StorageNetworkType& + meshSuperentityStorageNetwork() + { + return mesh->template getSuperentityStorageNetwork< EntityTopology::dimension, Superdimension >(); + } + + static void + setVertexPoint( typename MeshType::Vertex& vertex, const typename MeshType::PointType& point ) + { + vertex.setPoint( point ); + } + + + template< typename SubDimensionTag, typename MeshEntity > + static typename MeshTraitsType::template SubentityTraits< typename MeshEntity::EntityTopology, SubDimensionTag::value >::OrientationArrayType& + subentityOrientationsArray( MeshEntity& entity ) + { + return entity.template subentityOrientationsArray< SubDimensionTag::value >(); + } + + template< typename DimensionTag > + const MeshEntityReferenceOrientation< MeshConfig, typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology >& + getReferenceOrientation( GlobalIndexType index ) const + { + return BaseType::getReferenceOrientation( DimensionTag(), index ); + } +}; + +/**** + * Mesh initializer layer for cells + * - entities storage must turned on (cells must always be stored ) + * - entities orientation does not make sense for cells => it is turned off + */ +template< typename MeshConfig > +class InitializerLayer< MeshConfig, + typename MeshTraits< MeshConfig >::DimensionTag, + true, + false > + : public InitializerLayer< MeshConfig, + typename MeshTraits< MeshConfig >::DimensionTag::Decrement > +{ + using MeshTraitsType = MeshTraits< MeshConfig >; + using DimensionTag = typename MeshTraitsType::DimensionTag; + using BaseType = InitializerLayer< MeshConfig, typename DimensionTag::Decrement >; + + using MeshType = Mesh< MeshConfig >; + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< DimensionTag::value >; + using EntityTopology = typename EntityTraitsType::EntityTopology; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + + using InitializerType = Initializer< MeshConfig >; + using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >; + using CellSeedArrayType = typename MeshTraitsType::CellSeedArrayType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using PointArrayType = typename MeshTraitsType::PointArrayType; + + public: + + void initEntities( InitializerType& initializer, PointArrayType& points, CellSeedArrayType& cellSeeds, MeshType& mesh ) + { + //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl; + initializer.template setEntitiesCount< DimensionTag::value >( cellSeeds.getSize() ); + for( GlobalIndexType i = 0; i < cellSeeds.getSize(); i++ ) + EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( i ), i, cellSeeds[ i ], initializer ); + cellSeeds.reset(); + + BaseType::initEntities( initializer, points, mesh ); + } + + using BaseType::findEntitySeedIndex; +}; + +/**** + * Mesh initializer layer for other mesh entities than cells + * - entities storage is turned on + * - entities orientation storage is turned off + */ +template< typename MeshConfig, + typename DimensionTag > +class InitializerLayer< MeshConfig, + DimensionTag, + true, + false > + : public InitializerLayer< MeshConfig, + typename DimensionTag::Decrement > +{ + using BaseType = InitializerLayer< MeshConfig, typename DimensionTag::Decrement >; + using MeshType = Mesh< MeshConfig >; + using MeshTraitsType = MeshTraits< MeshConfig >; + + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< DimensionTag::value >; + using EntityTopology = typename EntityTraitsType::EntityTopology; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + + using InitializerType = Initializer< MeshConfig >; + using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using PointArrayType = typename MeshTraitsType::PointArrayType; + using SeedType = EntitySeed< MeshConfig, EntityTopology >; + using SeedIndexedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType; + using SeedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedSetType; + + public: + + GlobalIndexType getEntitiesCount( InitializerType& initializer, MeshType& mesh ) + { + using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >; + SeedSet seedSet; + + for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ ) + { + auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) ); + for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ ) + seedSet.insert( subentitySeeds[ j ] ); + } + + return seedSet.size(); + } + + using BaseType::findEntitySeedIndex; + GlobalIndexType findEntitySeedIndex( const SeedType& seed ) + { + return this->seedsIndexedSet.insert( seed ); + } + + void initEntities( InitializerType& initializer, PointArrayType& points, MeshType& mesh ) + { + //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl; + const GlobalIndexType numberOfEntities = getEntitiesCount( initializer, mesh ); + initializer.template setEntitiesCount< DimensionTag::value >( numberOfEntities ); + + using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >; + for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ ) + { + auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) ); + for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ ) + { + auto& seed = subentitySeeds[ j ]; + const auto pair = this->seedsIndexedSet.try_insert( seed ); + const GlobalIndexType& entityIndex = pair.first; + if( pair.second ) { + // insertion took place, initialize the entity + EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( entityIndex ), entityIndex, seed, initializer ); + } + } + } + + EntityInitializerType::initSuperentities( initializer, mesh ); + this->seedsIndexedSet.clear(); + + BaseType::initEntities( initializer, points, mesh ); + } + + using BaseType::getReferenceOrientation; + using ReferenceOrientationType = typename EntityTraitsType::ReferenceOrientationType; + const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index ) const {} + + private: + SeedIndexedSet seedsIndexedSet; +}; + +/**** + * Mesh initializer layer for other mesh entities than cells + * - entities storage is turned on + * - entities orientation storage is turned on + */ +template< typename MeshConfig, + typename DimensionTag > +class InitializerLayer< MeshConfig, + DimensionTag, + true, + true > + : public InitializerLayer< MeshConfig, + typename DimensionTag::Decrement > +{ + using BaseType = InitializerLayer< MeshConfig, typename DimensionTag::Decrement >; + using MeshType = Mesh< MeshConfig >; + using MeshTraitsType = typename MeshType::MeshTraitsType; + + using EntityTraitsType = typename MeshType::template EntityTraits< DimensionTag::value >; + using EntityTopology = typename EntityTraitsType::EntityTopology; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + + using InitializerType = Initializer< MeshConfig >; + using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using PointArrayType = typename MeshTraitsType::PointArrayType; + using SeedType = EntitySeed< MeshConfig, EntityTopology >; + using SeedIndexedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType; + using SeedSet = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedSetType; + using ReferenceOrientationType = typename EntityTraitsType::ReferenceOrientationType; + using ReferenceOrientationArrayType = typename EntityTraitsType::ReferenceOrientationArrayType; + + public: + + GlobalIndexType getEntitiesCount( InitializerType& initializer, MeshType& mesh ) + { + using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >; + SeedSet seedSet; + + for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ ) + { + auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) ); + for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ ) + seedSet.insert( subentitySeeds[ j ] ); + } + + return seedSet.size(); + } + + using BaseType::findEntitySeedIndex; + GlobalIndexType findEntitySeedIndex( const SeedType& seed ) + { + return this->seedsIndexedSet.insert( seed ); + } + + void initEntities( InitializerType& initializer, PointArrayType& points, MeshType& mesh ) + { + //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl; + const GlobalIndexType numberOfEntities = getEntitiesCount( initializer, mesh ); + initializer.template setEntitiesCount< DimensionTag::value >( numberOfEntities ); + this->referenceOrientations.setSize( numberOfEntities ); + + using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >; + for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ ) + { + auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) ); + for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ ) + { + auto& seed = subentitySeeds[ j ]; + const auto pair = this->seedsIndexedSet.try_insert( seed ); + const GlobalIndexType& entityIndex = pair.first; + if( pair.second ) { + // insertion took place, initialize the entity + EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( entityIndex ), entityIndex, seed, initializer ); + this->referenceOrientations[ entityIndex ] = ReferenceOrientationType( seed ); + } + } + } + + EntityInitializerType::initSuperentities( initializer, mesh ); + this->seedsIndexedSet.clear(); + this->referenceOrientations.reset(); + + BaseType::initEntities( initializer, points, mesh ); + } + + using BaseType::getReferenceOrientation; + const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index ) const + { + return this->referenceOrientations[ index ]; + } + + private: + SeedIndexedSet seedsIndexedSet; + ReferenceOrientationArrayType referenceOrientations; +}; + +/**** + * Mesh initializer layer for entities not being stored + */ +template< typename MeshConfig, + typename DimensionTag > +class InitializerLayer< MeshConfig, + DimensionTag, + false, + false > + : public InitializerLayer< MeshConfig, + typename DimensionTag::Decrement > +{}; + +/**** + * Mesh initializer layer for vertices + * - vertices must always be stored + * - their orientation does not make sense + */ +template< typename MeshConfig > +class InitializerLayer< MeshConfig, + DimensionTag< 0 >, + true, + false > +{ + using MeshType = Mesh< MeshConfig >; + using MeshTraitsType = typename MeshType::MeshTraitsType; + using DimensionTag = Meshes::DimensionTag< 0 >; + + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< DimensionTag::value >; + using EntityTopology = typename EntityTraitsType::EntityTopology; + + using InitializerType = Initializer< MeshConfig >; + using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType; + using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType; + using PointArrayType = typename MeshTraits< MeshConfig >::PointArrayType; + using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >; + using SeedType = EntitySeed< MeshConfig, EntityTopology >; + + public: + + GlobalIndexType findEntitySeedIndex( const SeedType& seed ) + { + return seed.getCornerIds()[ 0 ]; + } + + void initEntities( InitializerType& initializer, PointArrayType& points, MeshType& mesh ) + { + //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl; + initializer.template setEntitiesCount< 0 >( points.getSize() ); + for( GlobalIndexType i = 0; i < points.getSize(); i++ ) + EntityInitializerType::initEntity( mesh.template getEntity< 0 >( i ), i, points[ i ], initializer ); + points.reset(); + + EntityInitializerType::initSuperentities( initializer, mesh ); + } + + // This method is due to 'using BaseType::findEntityIndex;' in the derived class. + void findEntitySeedIndex() {} + + using ReferenceOrientationType = typename EntityTraitsType::ReferenceOrientationType; + const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index ) const {} +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h deleted file mode 100644 index 162ff643063852e9315236fc2ab3ecbe545cd091..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h +++ /dev/null @@ -1,549 +0,0 @@ -/*************************************************************************** - MeshEntityInitializer.h - description - ------------------- - begin : Feb 23, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/StaticFor.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h> - -#include "MeshEntitySeed.h" - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig > -class MeshInitializer; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag, - bool SubentityStorage = MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::storageEnabled, - bool SubentityOrientationStorage = MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::orientationEnabled, - bool SuperentityStorage = MeshSuperentityTraits< MeshConfig, - typename MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::SubentityTopology, - EntityTopology::dimensions >::storageEnabled > -class MeshEntityInitializerLayer; - -template< typename MeshConfig, - typename EntityTopology > -class MeshEntityInitializer - : public MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< EntityTopology::dimensions - 1 > > -{ - typedef MeshDimensionTag< EntityTopology::dimensions > DimensionTag; - private: - - typedef MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< EntityTopology::dimensions - 1 > > BaseType; - - typedef - MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< EntityTopology::dimensions - 1 > > SubentityBaseType; - typedef - MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - typename - MeshTraits< MeshConfig >::DimensionTag > SuperentityBaseType; - - static const int Dimension = DimensionTag::value; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::template EntityTraits< Dimension > EntityTraitsType; - - typedef typename EntityTraitsType::EntityType EntityType; - typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 > SubvertexTraits; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - - template< typename > class SubentitiesCreator; - - public: - - //using SuperentityBaseType::setNumberOfSuperentities; - - static String getType() { return "MeshEntityInitializer"; }; - - MeshEntityInitializer() : entity(0), entityIndex( -1 ) {} - - static void initEntity( EntityType &entity, GlobalIndexType entityIndex, const SeedType &entitySeed, InitializerType &initializer) - { - entity = EntityType( entitySeed ); - BaseType::initSubentities( entity, entityIndex, entitySeed, initializer ); - } - - template< typename SuperentityDimensionTag > - typename MeshSuperentityTraits< MeshConfig, EntityTopology, SuperentityDimensionTag::value >::SharedContainerType& getSuperentityContainer( SuperentityDimensionTag ) - { - return this->entity->template getSuperentitiesIndices< SuperentityDimensionTag::value >(); - } - - static void setEntityVertex( EntityType& entity, - LocalIndexType localIndex, - GlobalIndexType globalIndex ) - { - entity.setVertexIndex( localIndex, globalIndex ); - } - - private: - EntityType *entity; - GlobalIndexType entityIndex; - -}; - -template< typename MeshConfig > -class MeshEntityInitializer< MeshConfig, MeshVertexTopology > -{ - public: - typedef typename MeshTraits< MeshConfig >::VertexType VertexType; - typedef typename MeshTraits< MeshConfig >::PointType PointType; - typedef MeshInitializer< MeshConfig > InitializerType; - - static String getType() { return "MeshEntityInitializer"; }; - - static void setVertexPoint( VertexType& vertex, - const PointType& point, - InitializerType& initializer ) - { - initializer.setVertexPoint( vertex, point ); - } -}; - - -/**** - * Mesh entity initializer layer with specializations - * - * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE - * TRUE FALSE TRUE - */ -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - true, - false, - true > - : public MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - static const int Dimension = DimensionTag::value; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension > SubentityTraitsType; - typedef typename SubentityTraitsType::SubentityContainerType SubentityContainerType; - typedef typename SubentityTraitsType::AccessArrayType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< EntityTopology::dimensions > EntityDimensionTag; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag > SubentitySeedsCreatorType; - typedef typename SubentityTraitsType::IdArrayType IdArrayType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - - protected: - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed, - InitializerType& meshInitializer ) - { - //cout << " Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl; - auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed ); - - IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity ); - for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) - { - //cout << " Adding subentity " << subentityIdsArray[ i ] << std::endl; - subentityIdsArray[ i ] = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); - meshInitializer. - template getSuperentityInitializer< DimensionTag >(). - addSuperentity( EntityDimensionTag(), subentityIdsArray[ i ], entityIndex ); - } - BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer ); - } -}; - -/**** - * Mesh entity initializer layer with specializations - * - * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE - * TRUE TRUE TRUE - */ -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - true, - true, - true > - : public MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - typedef MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value > SubentitiesTraits; - typedef typename SubentitiesTraits::SubentityContainerType SubentityContainerType; - typedef typename SubentitiesTraits::AccessArrayType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< EntityTopology::dimensions > EntityDimensionTag; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag > SubentitySeedsCreatorType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::IdArrayType IdArrayType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - typedef typename SubentitiesTraits::OrientationArrayType OrientationArrayType; - - protected: - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed, - InitializerType& meshInitializer ) - { - //cout << " Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl; - auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed ); - - IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity ); - OrientationArrayType &subentityOrientationsArray = InitializerType::template subentityOrientationsArray< DimensionTag >( entity ); - for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) - { - //cout << " Adding subentity " << subentityIdsArray[ i ] << std::endl; - GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); - subentityIdsArray[ i ] = subentityIndex; - subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< DimensionTag >( subentityIndex ).createOrientation( subentitySeeds[ i ] ); - //cout << " Subentity orientation = " << subentityOrientationsArray[ i ].getSubvertexPermutation() << std::endl; - meshInitializer. - template getSuperentityInitializer< DimensionTag >(). - addSuperentity( EntityDimensionTag(), subentityIdsArray[ i ], entityIndex ); - } - - BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer ); - } -}; - -/**** - * Mesh entity initializer layer with specializations - * - * SUBENTITY STORAGE SUBENTITY ORIENTATION SUPERENTITY STORAGE - * TRUE TRUE FALSE - */ -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - true, - true, - false > - : public MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - typedef MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value > SubentitiesTraits; - typedef typename SubentitiesTraits::SubentityContainerType SubentityContainerType; - typedef typename SubentitiesTraits::SharedContainerType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< EntityTopology::dimensions > EntityDimensionTag; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag > SubentitySeedsCreatorType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - typedef typename SubentitiesTraits::OrientationArrayType OrientationArrayType; - - protected: - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed, - InitializerType& meshInitializer ) - { - //cout << " Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl; - auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed ); - - IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity ); - OrientationArrayType &subentityOrientationsArray = InitializerType::template subentityOrientationsArray< DimensionTag >( entity ); - for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ ) - { - //cout << " Adding subentity " << subentityIdsArray[ i ] << std::endl; - subentityIdsArray[ i ] = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); - subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< DimensionTag >( subentitySeeds[ i ] ).createOrientation( subentitySeeds[ i ] ); - } - BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer ); - } -}; - - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - true, - false, - false > - : public MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - typedef typename MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value >::SubentityContainerType SubentityContainerType; - typedef typename MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value >::SharedContainerType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag > SubentitySeedsCreatorType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - - protected: - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed, - InitializerType& meshInitializer ) - { - //cout << " Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl; - auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed ); - - IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity ); - for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++) - subentityIdsArray[ i ] = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); - - BaseType::initSubentities(entity, entityIndex, entitySeed, meshInitializer); - } -}; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - false, - false, - true > - : public MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - typedef typename MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value >::SubentityContainerType SubentityContainerType; - typedef typename MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value >::SharedContainerType SharedContainerType; - typedef typename SharedContainerType::DataType GlobalIndexType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< EntityTopology::dimensions > EntityDimensionTag; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag > SubentitySeedsCreatorType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - - - protected: - - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed, - InitializerType& meshInitializer ) - { - //cout << " Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl; - auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed ); - IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity ); - for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++) - { - GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] ); - meshInitializer. - template getSuperentityInitializer< DimensionTag >(). - addSuperentity( EntityDimensionTag(), subentityIndex, entityIndex ); - } - BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer ); - } -}; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - false, - false, - false > - : public MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{}; - -template< typename MeshConfig, - typename EntityTopology > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< 0 >, - true, - false, - true > -{ - typedef MeshDimensionTag< 0 > DimensionTag; - typedef MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value > SubentitiesTraits; - - typedef typename SubentitiesTraits::AccessArrayType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< EntityTopology::dimensions > EntityDimensionTag; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag > SubentitySeedsCreatorType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::IdArrayType IdArrayType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - - - protected: - - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed, - InitializerType& meshInitializer ) - { - //cout << " Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl; - const IdArrayType &subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >(entity); - for( LocalIndexType i = 0; i < subentityIdsArray.getSize(); i++ ) - meshInitializer.template getSuperentityInitializer< DimensionTag >().addSuperentity( EntityDimensionTag(), subentityIdsArray[ i ], entityIndex); - } - -}; - -template< typename MeshConfig, - typename EntityTopology > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< 0 >, - true, - false, - false > -{ - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, - EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< 0 > DimensionTag; - typedef MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value > SubentitiesTraits; - typedef typename SubentitiesTraits::SharedContainerType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag > SubentitySeedsCreatorType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - - - protected: - - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed, - InitializerType& meshInitializer ) {}; - -}; - -template< typename MeshConfig, - typename EntityTopology, - bool SuperEntityStorage > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< 0 >, - false, - true, - SuperEntityStorage > // Forces termination of recursive inheritance (prevents compiler from generating huge error logs) -{ - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< 0 > DimensionTag; - typedef MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value > SubentitiesTraits; - typedef typename SubentitiesTraits::SharedContainerType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - - protected: - static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, EntityInitializerType&, InitializerType& ) {} -}; - -template< typename MeshConfig, - typename EntityTopology, - bool SuperEntityStorage > -class MeshEntityInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< 0 >, - false, - false, - SuperEntityStorage > // Forces termination of recursive inheritance (prevents compiler from generating huge error logs) -{ - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshDimensionTag< 0 > DimensionTag; - typedef MeshSubentityTraits< MeshConfig, - EntityTopology, - DimensionTag::value > SubentitiesTraits; - typedef typename SubentitiesTraits::SharedContainerType SharedContainerType; - typedef typename SharedContainerType::ElementType GlobalIndexType; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - - protected: - void initSubentities( EntityType& entity, GlobalIndexType entityIndex, EntityInitializerType&, - InitializerType& ) {} -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h b/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h deleted file mode 100644 index a0f7e561bfead6e1602d3ca754ece09475b29faf..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************** - MeshEntitySeed.h - description - ------------------- - begin : Aug 18, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename EntityTopology > -class MeshEntitySeed -{ - typedef MeshTraits< MeshConfig > MeshConfigTraits; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 > SubvertexTraits; - - public: - typedef typename MeshTraits< MeshConfig >::GlobalIndexType GlobalIndexType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - typedef typename MeshTraits< MeshConfig >::IdArrayAccessorType IdArrayAccessorType; - typedef typename SubvertexTraits::IdArrayType IdArrayType; - - static String getType() { return String( "MeshEntitySeed<>" ); } - - static constexpr LocalIndexType getCornersCount() - { - return SubvertexTraits::count; - } - - void setCornerId( LocalIndexType cornerIndex, GlobalIndexType pointIndex ) - { - TNL_ASSERT( 0 <= cornerIndex && cornerIndex < getCornersCount(), std::cerr << "cornerIndex = " << cornerIndex ); - TNL_ASSERT( 0 <= pointIndex, std::cerr << "pointIndex = " << pointIndex ); - - this->cornerIds[ cornerIndex ] = pointIndex; - } - - IdArrayAccessorType getCornerIds() - { - IdArrayAccessorType accessor; - accessor.bind( this->corners.getData(), this->corners.getSize() ); - return accessor; - } - - - const IdArrayAccessorType getCornerIds() const - { - IdArrayAccessorType accessor; - accessor.bind( this->cornerIds.getData(), this->cornerIds.getSize() ); - return accessor; - } - - private: - - IdArrayType cornerIds; -}; - -template< typename MeshConfig, typename EntityTopology > -std::ostream& operator << ( std::ostream& str, const MeshEntitySeed< MeshConfig, EntityTopology >& e ) -{ - str << e.getCornerIds(); - return str; -}; - -} // namespace Meshes -} // namespace TNL - diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h b/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h deleted file mode 100644 index 32ecff1df3b89d6db6c6f96b22aefa3e67f046c2..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************** - MeshEntitySeedKey.h - description - ------------------- - begin : Feb 13, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/MeshDimensionTag.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename EntityTopology > -class MeshEntitySeed; - -template< typename MeshConfig, - typename EntityTopology, - int Dimension > -class MeshSubentityTraits; - -/**** - * Unique identification of a mesh entity by its vertices. - * Uniqueness is preserved for entities of the same type only. - */ -template< typename MeshConfig, - typename EntityTopology > -class MeshEntitySeedKey -{ - typedef - MeshEntitySeed< MeshConfig, EntityTopology > EntitySeedType; - - typedef typename - MeshSubentityTraits< MeshConfig, - EntityTopology, - 0 >::StorageArrayType StorageArrayType; - - public: - - explicit MeshEntitySeedKey( const EntitySeedType& entitySeed ) - { - for( typename StorageArrayType::IndexType i = 0; - i < entitySeed.getCornersCount(); - i++ ) - this->sortedCorners[ i ] = entitySeed.getCornerIds()[ i ]; - sortedCorners.sort( ); - } - - bool operator<( const MeshEntitySeedKey& other ) const - { - for( typename StorageArrayType::IndexType i = 0; - i < StorageArrayType::size; - i++) - { - if( sortedCorners[ i ] < other.sortedCorners[ i ] ) - return true; - else - if( sortedCorners[ i ] > other.sortedCorners[ i ] ) - return false; - } - return false; - } - - private: - - StorageArrayType sortedCorners; -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/MeshInitializer.h deleted file mode 100644 index e690d35918246db0e51c7206d9a2d90ae2739a6c..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/initializer/MeshInitializer.h +++ /dev/null @@ -1,629 +0,0 @@ -/*************************************************************************** - MeshInitializer.h - description - ------------------- - begin : Feb 23, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/MeshDimensionTag.h> -#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h> -#include <TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h> -#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h> -#include <TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig > -class Mesh; - -template< typename MeshConfig, - typename DimensionTag, - bool EntityStorage = - MeshEntityTraits< MeshConfig, DimensionTag::value >::storageEnabled, - bool EntityReferenceOrientationStorage = - MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::orientationNeeded > -class MeshInitializerLayer; - - -template< typename MeshConfig, - typename EntityTopology> -class MeshEntityInitializer; - -template< typename MeshConfig > -class MeshInitializer - : public MeshInitializerLayer< MeshConfig, - typename MeshTraits< MeshConfig >::DimensionTag > -{ - public: - - typedef Mesh< MeshConfig > MeshType; - typedef MeshTraits< MeshConfig > MeshTraitsType; - static const int Dimension = MeshTraitsType::meshDimension; - typedef MeshDimensionTag< Dimension > DimensionTag; - typedef MeshInitializerLayer< MeshConfig, DimensionTag > BaseType; - typedef typename MeshTraitsType::PointArrayType PointArrayType; - typedef typename MeshTraitsType::CellSeedArrayType CellSeedArrayType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - - template< typename DimensionTag, typename SuperdimensionsTag > using SuperentityStorageNetwork = - typename MeshTraitsType::template SuperentityTraits< - typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology, - SuperdimensionsTag::value >::StorageNetworkType; - - - MeshInitializer() - : verbose( false ), mesh( 0 ) - {} - - void setVerbose( bool verbose ) - { - this->verbose = verbose; - } - - bool createMesh( const PointArrayType& points, - const CellSeedArrayType& cellSeeds, - MeshType& mesh ) - { - std::cout << "======= Starting mesh initiation ========" << std::endl; - this->mesh = &mesh; - - std::cout << "========= Creating entity seeds =============" << std::endl; - BaseType::createEntitySeedsFromCellSeeds( cellSeeds ); - - std::cout << "========= Creating entity reference orientations =============" << std::endl; - BaseType::createEntityReferenceOrientations(); - - std::cout << "====== Initiating entities ==============" << std::endl; - BaseType::initEntities( *this, points, cellSeeds ); - - return true; - } - - template<typename SubDimensionTag, typename EntityType > - static typename MeshTraitsType::template SubentityTraits< typename EntityType::EntityTopology, SubDimensionTag::value >::IdArrayType& - subentityIdsArray( EntityType& entity ) - { - return entity.template subentityIdsArray< SubDimensionTag::value >(); - } - - template< typename SuperDimensionTag, typename MeshEntity> - static typename MeshTraitsType::IdArrayAccessorType& - superentityIdsArray( MeshEntity& entity ) - { - return entity.template superentityIdsArray< SuperDimensionTag::value >(); - } - - template<typename SubDimensionTag, typename MeshEntity > - static typename MeshTraitsType::template SubentityTraits< typename MeshEntity::EntityTopology, SubDimensionTag::value >::OrientationArrayType& - subentityOrientationsArray( MeshEntity &entity ) - { - return entity.template subentityOrientationsArray< SubDimensionTag::value >(); - } - - template< typename DimensionTag > - typename MeshTraitsType::template EntityTraits< DimensionTag::value >::StorageArrayType& - meshEntitiesArray() - { - return mesh->template entitiesArray< DimensionTag >(); - } - - template< typename DimensionTag, typename SuperDimensionTag > - typename MeshTraitsType::GlobalIdArrayType& - meshSuperentityIdsArray() - { - return mesh->template superentityIdsArray< DimensionTag, SuperDimensionTag >(); - } - - template< typename EntityTopology, typename SuperdimensionsTag > - typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType& - meshSuperentityStorageNetwork() - { - return mesh->template getSuperentityStorageNetwork< EntityTopology, SuperdimensionsTag >(); - } - - static void - setVertexPoint( typename MeshType::VertexType& vertex, const typename MeshType::PointType& point ) - { - vertex.setPoint( point ); - } - - template< typename DimensionTag > - MeshSuperentityStorageInitializer< MeshConfig, typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology >& - getSuperentityInitializer() - { - return BaseType::getSuperentityInitializer( DimensionTag() ); - } - - - template< typename DimensionTag > - const MeshEntityReferenceOrientation< MeshConfig, typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology >& - getReferenceOrientation( GlobalIndexType index) const - { - return BaseType::getReferenceOrientation( DimensionTag(), index); - } - - protected: - - bool verbose; - - MeshType* mesh; -}; - -/**** - * Mesh initializer layer for cells - * - entities storage must turned on (cells must always be stored ) - * - entities orientation does not make sense for cells => it is turned off - */ -template< typename MeshConfig > -class MeshInitializerLayer< MeshConfig, - typename MeshTraits< MeshConfig >::DimensionTag, - true, - false > - : public MeshInitializerLayer< MeshConfig, - typename MeshTraits< MeshConfig >::DimensionTag::Decrement > -{ - typedef MeshTraits< MeshConfig > MeshTraitsType; - static const int Dimension = MeshTraitsType::meshDimension; - typedef MeshDimensionTag< Dimension > DimensionTag; - typedef MeshInitializerLayer< MeshConfig, typename DimensionTag::Decrement > BaseType; - - typedef Mesh< MeshConfig > MeshType; - typedef typename MeshTraitsType::template EntityTraits< Dimension > EntityTraitsType; - typedef typename EntityTraitsType::EntityTopology EntityTopology; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::CellTopology CellTopology; - typedef typename EntityTraitsType::StorageArrayType StorageArrayType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > CellInitializerType; - typedef Containers::Array< CellInitializerType, Devices::Host, GlobalIndexType > CellInitializerContainerType; - typedef typename MeshTraitsType::CellSeedArrayType CellSeedArrayType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::PointArrayType PointArrayType; - typedef MeshEntitySeed< MeshConfig, CellTopology > SeedType; - typedef MeshSuperentityStorageInitializer< MeshConfig, EntityTopology > SuperentityInitializerType; - - public: - - void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds ) - { - BaseType::createEntitySeedsFromCellSeeds( cellSeeds ); - } - - void initEntities( InitializerType &initializer, const PointArrayType &points, const CellSeedArrayType &cellSeeds) - { - StorageArrayType &entityArray = initializer.template meshEntitiesArray< DimensionTag >(); - //cout << " Initiating entities with " << DimensionTag::value << " dimensions ... " << std::endl; - entityArray.setSize( cellSeeds.getSize() ); - for( GlobalIndexType i = 0; i < entityArray.getSize(); i++ ) - { - //cout << " Initiating entity " << i << std::endl; - EntityInitializerType::initEntity( entityArray[i], i, cellSeeds[i], initializer ); - } - /*** - * There are no superentities in this layer storing mesh cells. - */ - - BaseType::initEntities( initializer, points ); - } - - using BaseType::findEntitySeedIndex; - GlobalIndexType findEntitySeedIndex( const SeedType& seed ) const - { - return this->seedsIndexedSet.find( seed ); - } - - using BaseType::getSuperentityInitializer; - SuperentityInitializerType& getSuperentityInitializer( DimensionTag ) - { - return this->superentityInitializer; - } - - bool checkCells() - { - typedef typename MeshEntity< MeshConfig, EntityTopology >::template SubentitiesTraits< 0 >::LocalIndexType LocalIndexType; - const GlobalIndexType numberOfVertices( this->getMesh().getNumberOfVertices() ); - for( GlobalIndexType cell = 0; - cell < this->getMesh().template getEntitiesCount< typename MeshType::Cell >(); - cell++ ) - for( LocalIndexType i = 0; - i < this->getMesh().getCell( cell ).getNumberOfVertices(); - i++ ) - { - if( this->getMesh().getCell( cell ).getVerticesIndices()[ i ] == - 1 ) - { - std::cerr << "The cell number " << cell << " does not have properly set vertex index number " << i << "." << std::endl; - return false; - } - if( this->getMesh().getCell( cell ).getVerticesIndices()[ i ] >= numberOfVertices ) - { - std::cerr << "The cell number " << cell << " does not have properly set vertex index number " << i - << ". The index " << this->getMesh().getCell( cell ).getVerticesIndices()[ i ] - << "is higher than the number of all vertices ( " << numberOfVertices - << " )." << std::endl; - return false; - } - } - return true; - } - - private: - typedef typename MeshEntityTraits< MeshConfig, DimensionTag::value >::SeedIndexedSetType SeedIndexedSet; - - SeedIndexedSet seedsIndexedSet; - SuperentityInitializerType superentityInitializer; -}; - -/**** - * Mesh initializer layer for other mesh entities than cells - * - entities storage is turned on - * - entities orientation storage is turned off - */ -template< typename MeshConfig, - typename DimensionTag > -class MeshInitializerLayer< MeshConfig, - DimensionTag, - true, - false > - : public MeshInitializerLayer< MeshConfig, - typename DimensionTag::Decrement > -{ - typedef MeshTraits< MeshConfig > MeshTraitsType; - static const int Dimension = DimensionTag::value; - typedef MeshInitializerLayer< MeshConfig, typename DimensionTag::Decrement > BaseType; - - typedef Mesh< MeshConfig > MeshType; - typedef typename MeshTraitsType::template EntityTraits< Dimension > EntityTraitsType; - typedef typename EntityTraitsType::EntityTopology EntityTopology; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::CellTopology CellTopology; - typedef typename EntityTraitsType::StorageArrayType StorageArrayType; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > CellInitializerType; - typedef Containers::Array< CellInitializerType, Devices::Host, GlobalIndexType > CellInitializerContainerType; - typedef typename EntityTraitsType::SeedArrayType EntitySeedArrayType; - typedef typename MeshTraitsType::CellSeedArrayType CellSeedArrayType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::PointArrayType PointArrayType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSuperentityStorageInitializer< MeshConfig, EntityTopology > SuperentityInitializerType; - - typedef typename - MeshSubentityTraits< MeshConfig, - typename MeshConfig::CellTopology, - DimensionTag::value >::SubentityContainerType SubentitiesContainerType; - - public: - - using BaseType::getEntityInitializer; - EntityInitializerType& getEntityInitializer( DimensionTag, GlobalIndexType index ) - { - //return entityInitializerContainer[ index ]; - } - - void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds ) - { - typedef MeshSubentitySeedsCreator< MeshConfig, CellTopology, DimensionTag > SubentitySeedsCreator; - //cout << " Creating mesh entities with " << DimensionTag::value << " dimensions ... " << std::endl; - for( GlobalIndexType i = 0; i < cellSeeds.getSize(); i++ ) - { - //cout << " Creating mesh entities from cell number " << i << " : " << cellSeeds[ i ] << std::endl; - typedef typename SubentitySeedsCreator::SubentitySeedArray SubentitySeedArray; - SubentitySeedArray subentytiSeeds( SubentitySeedsCreator::create( cellSeeds[ i ] ) ); - for( LocalIndexType j = 0; j < subentytiSeeds.getSize(); j++ ) - { - //cout << "Creating subentity seed no. " << j << " : " << subentytiSeeds[ j ] << std::endl; - //MeshEntitySeed< MeshConfigBase< CellTopology >, EntityTopology >& entitySeed = subentytiSeeds[ j ]; - this->seedsIndexedSet.insert( subentytiSeeds[ j ] ); - } - } - BaseType::createEntitySeedsFromCellSeeds( cellSeeds ); - } - - using BaseType::findEntitySeedIndex; - GlobalIndexType findEntitySeedIndex( const SeedType& seed ) const - { - // FIXME: index may be uninitialized (when seedsIndexedSet.find returns false) - GlobalIndexType index; - this->seedsIndexedSet.find( seed, index ); - return index; - } - - using BaseType::getSuperentityInitializer; - SuperentityInitializerType& getSuperentityInitializer( DimensionTag ) - { - return this->superentityInitializer; - } - - void initEntities( InitializerType& initializer, const PointArrayType& points ) - { - StorageArrayType &entityArray = initializer.template meshEntitiesArray< DimensionTag >(); - //cout << " Initiating entities with " << DimensionTag::value << " dimensions ... " << std::endl; - entityArray.setSize( this->seedsIndexedSet.getSize() ); - EntitySeedArrayType seedsArray; - seedsArray.setSize( this->seedsIndexedSet.getSize() ); - this->seedsIndexedSet.toArray( seedsArray ); - for( GlobalIndexType i = 0; i < this->seedsIndexedSet.getSize(); i++ ) - { - //cout << " Initiating entity " << i << std::endl; - EntityInitializerType::initEntity( entityArray[ i ], i, seedsArray[ i ], initializer ); - } - this->seedsIndexedSet.reset(); - - this->superentityInitializer.initSuperentities( initializer ); - - BaseType::initEntities(initializer, points); - } - - void createEntityReferenceOrientations() const {} - private: - - typedef typename MeshEntityTraits< MeshConfig, DimensionTag::value >::SeedIndexedSetType SeedIndexedSet; - SeedIndexedSet seedsIndexedSet; - SuperentityInitializerType superentityInitializer; -}; - -/**** - * Mesh initializer layer for other mesh entities than cells - * - entities storage is turned on - * - entities orientation storage is turned on - */ -template< typename MeshConfig, - typename DimensionTag > -class MeshInitializerLayer< MeshConfig, - DimensionTag, - true, - true > - : public MeshInitializerLayer< MeshConfig, - typename DimensionTag::Decrement > -{ - typedef MeshInitializerLayer< MeshConfig, - typename DimensionTag::Decrement > BaseType; - typedef Mesh< MeshConfig > MeshType; - typedef typename MeshType::MeshTraitsType MeshTraitsType; - - typedef typename MeshType::template EntityTraits< DimensionTag::value > EntityTraitsType; - typedef typename EntityTraitsType::EntityTopology EntityTopology; - typedef typename EntityTraitsType::EntityType EntityType; - typedef typename EntityTraitsType::StorageArrayType ContainerType; - typedef typename EntityTraitsType::UniqueContainerType UniqueContainerType; - typedef typename ContainerType::IndexType GlobalIndexType; - typedef typename MeshTraitsType::CellTopology CellTopology; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, CellTopology > CellInitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef Containers::Array< EntityInitializerType, Devices::Host, GlobalIndexType > EntityInitializerContainerType; - typedef typename MeshTraitsType::CellSeedArrayType CellSeedArrayType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::PointArrayType PointArrayType; - typedef typename EntityTraitsType::StorageArrayType EntityArrayType; - typedef typename EntityTraitsType::SeedArrayType SeedArrayType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshSuperentityStorageInitializer< MeshConfig, EntityTopology > SuperentityInitializerType; - typedef typename EntityTraitsType::ReferenceOrientationType ReferenceOrientationType; - typedef typename EntityTraitsType::ReferenceOrientationArrayType ReferenceOrientationArrayType; - - - typedef typename - MeshSubentityTraits< MeshConfig, - typename MeshConfig::CellTopology, - DimensionTag::value >::SubentityContainerType SubentitiesContainerType; - - public: - - using BaseType::getEntityInitializer; - EntityInitializerType& getEntityInitializer( DimensionTag, GlobalIndexType index ) - { - //return entityInitializerContainer[ index ]; - } - - void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds ) - { - typedef MeshSubentitySeedsCreator< MeshConfig, CellTopology, DimensionTag > SubentitySeedsCreator; - //cout << " Creating mesh entities with " << DimensionTag::value << " dimensions ... " << std::endl; - for( GlobalIndexType i = 0; i < cellSeeds.getSize(); i++ ) - { - //cout << " Creating mesh entities from cell number " << i << " : " << cellSeeds[ i ] << std::endl; - typedef typename SubentitySeedsCreator::SubentitySeedArray SubentitySeedArray; - SubentitySeedArray subentytiSeeds( SubentitySeedsCreator::create( cellSeeds[ i ] ) ); - for( LocalIndexType j = 0; j < subentytiSeeds.getSize(); j++ ) - { - //cout << "Creating subentity seed no. " << j << " : " << subentytiSeeds[ j ] << std::endl; - //MeshEntitySeed< MeshConfigBase< CellTopology >, EntityTopology >& entitySeed = subentytiSeeds[ j ]; - this->seedsIndexedSet.insert( subentytiSeeds[ j ] ); - } - } - BaseType::createEntitySeedsFromCellSeeds( cellSeeds ); - } - - using BaseType::findEntitySeedIndex; - GlobalIndexType findEntitySeedIndex( const SeedType& seed ) const - { - GlobalIndexType index; - this->seedsIndexedSet.find( seed, index ); - return index; - } - - using BaseType::getSuperentityInitializer; - SuperentityInitializerType& getSuperentityInitializer( DimensionTag ) - { - return this->superentityInitializer; - } - - void initEntities( InitializerType& initializer, const PointArrayType& points ) - { - EntityArrayType &entityArray = initializer.template meshEntitiesArray< DimensionTag >(); - //cout << " Initiating entities with " << DimensionTag::value << " dimensions ... " << std::endl; - entityArray.setSize( this->seedsIndexedSet.getSize() ); - SeedArrayType seedsArray; - seedsArray.setSize( this->seedsIndexedSet.getSize() ); - this->seedsIndexedSet.toArray( seedsArray ); - for( GlobalIndexType i = 0; i < this->seedsIndexedSet.getSize(); i++ ) - { - //cout << " Initiating entity " << i << std::endl; - EntityInitializerType::initEntity( entityArray[ i ], i, seedsArray[ i ], initializer ); - } - this->seedsIndexedSet.reset(); - - this->superentityInitializer.initSuperentities( initializer ); - - BaseType::initEntities(initializer, points); - } - - using BaseType::getReferenceOrientation; - const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index) const - { - return this->referenceOrientations[ index ]; - } - - void createEntityReferenceOrientations() - { - //cout << " Creating entity reference orientations with " << DimensionTag::value << " dimensions ... " << std::endl; - SeedArrayType seedsArray; - seedsArray.setSize( this->seedsIndexedSet.getSize() ); - this->seedsIndexedSet.toArray( seedsArray ); - this->referenceOrientations.setSize( seedsArray.getSize() ); - for( GlobalIndexType i = 0; i < seedsArray.getSize(); i++ ) - { - //cout << " Creating reference orientation for entity " << i << std::endl; - this->referenceOrientations[ i ] = ReferenceOrientationType( seedsArray[ i ] ); - } - BaseType::createEntityReferenceOrientations(); - } - - private: - - typedef typename MeshEntityTraits< MeshConfig, DimensionTag::value >::SeedIndexedSetType SeedIndexedSet; - SeedIndexedSet seedsIndexedSet; - SuperentityInitializerType superentityInitializer; - ReferenceOrientationArrayType referenceOrientations; -}; - -/**** - * Mesh initializer layer for entities not being stored - */ -template< typename MeshConfig, - typename DimensionTag > -class MeshInitializerLayer< MeshConfig, - DimensionTag, - false, - false > - : public MeshInitializerLayer< MeshConfig, - typename DimensionTag::Decrement > -{}; - -/**** - * Mesh initializer layer for vertices - * - vertices must always be stored - * - their orientation does not make sense - */ -template< typename MeshConfig > -class MeshInitializerLayer< MeshConfig, - MeshDimensionTag< 0 >, - true, - false > -{ - typedef Mesh< MeshConfig > MeshType; - typedef typename MeshType::MeshTraitsType MeshTraitsType; - typedef MeshDimensionTag< 0 > DimensionTag; - - typedef typename MeshType::template EntityTraits< DimensionTag::value > EntityTraitsType; - typedef typename EntityTraitsType::EntityTopology EntityTopology; - typedef typename EntityTraitsType::StorageArrayType ContainerType; - typedef typename EntityTraitsType::AccessArrayType SharedContainerType; - typedef typename ContainerType::IndexType GlobalIndexType; - - typedef typename MeshTraitsType::CellTopology CellTopology; - - typedef MeshInitializer< MeshConfig > InitializerType; - typedef MeshEntityInitializer< MeshConfig, CellTopology > CellInitializerType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > VertexInitializerType; - typedef Containers::Array< VertexInitializerType, Devices::Host, GlobalIndexType > VertexInitializerContainerType; - typedef typename MeshTraits< MeshConfig >::CellSeedArrayType CellSeedArrayType; - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - typedef typename MeshTraits< MeshConfig >::PointArrayType PointArrayType; - typedef typename EntityTraitsType::StorageArrayType EntityArrayType; - typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType; - typedef MeshSuperentityStorageInitializer< MeshConfig, EntityTopology > SuperentityInitializerType; - - public: - - void setMesh( MeshType& mesh ) - { - this->mesh = &mesh; - } - - MeshType& getMesh() - { - TNL_ASSERT( this->mesh, ); - return *( this->mesh ); - } - - VertexInitializerType& getEntityInitializer( DimensionTag, GlobalIndexType index ) - { - TNL_ASSERT( index >= 0 && index < vertexInitializerContainer.getSize(), - std::cerr << " index = " << index - << " vertexInitializerContainer.getSize() = " << vertexInitializerContainer.getSize() << std::endl; ); - return vertexInitializerContainer[ index ]; - } - - void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds ){}; - - void initEntities( InitializerType& initializer, const PointArrayType& points ) - { - EntityArrayType &vertexArray = initializer.template meshEntitiesArray< DimensionTag >(); - vertexArray.setSize( points.getSize() ); - for( GlobalIndexType i = 0; i < vertexArray.getSize(); i++ ) - EntityInitializerType::setVertexPoint( vertexArray[i], points[i], initializer ); - - superentityInitializer.initSuperentities( initializer ); - } - - void findEntitySeedIndex() const {} // This method is due to 'using BaseType::findEntityIndex;' in the derived class. - - void createEntityInitializers() - { - vertexInitializerContainer.setSize( this->getMesh().template getNumberOfEntities< DimensionTag::value >() ); - } - - SuperentityInitializerType& getSuperentityInitializer( DimensionTag ) - { - return this->superentityInitializer; - } - - void createEntityReferenceOrientations() const {} - - void getReferenceOrientation() const {} - - private: - - SuperentityInitializerType superentityInitializer; - - VertexInitializerContainerType vertexInitializerContainer; - - MeshType* mesh; -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h b/src/TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h deleted file mode 100644 index f7069f4cf5d5e674f61b37d8f604a10dd0c17140..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h +++ /dev/null @@ -1,84 +0,0 @@ -/*************************************************************************** - MeshSubentitySeedCreator.h - description - ------------------- - begin : Aug 20, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/StaticFor.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename EntityTopology, - typename SubDimensionTag > -class MeshSubentitySeedsCreator -{ - typedef typename MeshTraits< MeshConfig >::LocalIndexType LocalIndexType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, SubDimensionTag::value > SubentityTraits; - typedef typename SubentityTraits::SubentityTopology SubentityTopology; - typedef typename MeshTraits< MeshConfig >::IdArrayAccessorType IdArrayAccessorType; - typedef typename MeshTraits< MeshConfig >::template SubentityTraits< SubentityTopology, 0 > SubentityVertexTraits; - - static const LocalIndexType SUBENTITIES_COUNT = SubentityTraits::count; - static const LocalIndexType SUBENTITY_VERTICES_COUNT = SubentityVertexTraits::count; - - public: - typedef typename SubentityTraits::SeedArrayType SubentitySeedArray; - typedef MeshEntitySeed< MeshConfig, EntityTopology > EntitySeed; - //typedef typename MeshEntityTraits< MeshConfig, SubDimensionTag >::SeedIndexedSetType SeedIndexedSet; - - //template< typename SeedIndexedSet > - static SubentitySeedArray create( const EntitySeed &entitySeed ) - { - SubentitySeedArray subentitySeeds; - StaticFor< LocalIndexType, 0, SUBENTITIES_COUNT, CreateSubentitySeeds >::exec( subentitySeeds, entitySeed.getCornerIds() ); - //StaticFor< LocalIndexType, 0, SUBENTITIES_COUNT, CreateSubentitySeeds >::exec( indexedSet, entitySeed.getCornerIds() ); - - return subentitySeeds; - } - - private: - typedef MeshEntitySeed< MeshConfig, SubentityTopology > SubentitySeed; - - template< LocalIndexType subentityIndex > - class CreateSubentitySeeds - { - public: - static void exec( SubentitySeedArray &subentitySeeds, IdArrayAccessorType vertexIds ) - //static void exec( SeedIndexedSet& indexedSet, IdArrayAccessorType vertexIds ) - { - //EntitySeed seed; - StaticFor< LocalIndexType, 0, SUBENTITY_VERTICES_COUNT, SetSubentitySeedVertex >::exec( subentitySeeds[ subentityIndex ], vertexIds ); - //indexedSet.insert( seed ); - } - - private: - template< LocalIndexType subentityVertexIndex > - class SetSubentitySeedVertex - { - public: - static void exec( SubentitySeed &subentitySeed, IdArrayAccessorType vertexIds ) - { - static const LocalIndexType VERTEX_INDEX = SubentityTraits::template Vertex< subentityIndex, subentityVertexIndex >::index; - subentitySeed.setCornerId( subentityVertexIndex, vertexIds[ VERTEX_INDEX ] ); - } - }; - }; -}; - -} // namespace Meshes -} // namespace TNL - diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h deleted file mode 100644 index 587cb03a30c89f22a82a05045ef2dad456b3ab02..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h +++ /dev/null @@ -1,203 +0,0 @@ -/*************************************************************************** - MeshSuperentityStorageInitializer.h - description - ------------------- - begin : Feb 27, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/MeshDimensionTag.h> -#include <algorithm> -#include <vector> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig > -class MeshInitializer; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag, - bool SuperentityStorage = MeshSuperentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::storageEnabled > -class MeshSuperentityStorageInitializerLayer; - -template< typename MeshConfig, - typename EntityTopology > -class MeshSuperentityStorageInitializer : - public MeshSuperentityStorageInitializerLayer< MeshConfig, EntityTopology, MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > > -{}; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - true > - : public MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - static const int Dimension = DimensionTag::value; - typedef MeshDimensionTag< EntityTopology::dimensions > EntityDimension; - - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::GlobalIdArrayType GlobalIdArrayType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef MeshInitializer< MeshConfig > MeshInitializerType; - typedef typename MeshTraitsType::template SuperentityTraits< EntityTopology, Dimension > SuperentityTraitsType; - typedef typename SuperentityTraitsType::StorageNetworkType SuperentityStorageNetwork; - - public: - using BaseType::addSuperentity; - - void addSuperentity( DimensionTag, GlobalIndexType entityIndex, GlobalIndexType superentityIndex) - { - //cout << "Adding superentity with " << DimensionTag::value << " dimensions of enity with " << EntityDimension::value << " ... " << std::endl; - indexPairs.push_back( IndexPair{ entityIndex, superentityIndex } ); - } - - using BaseType::initSuperentities; - void initSuperentities( MeshInitializerType& meshInitializer ) - { - throw( 0 ); // TODO: fix this - or it may work with newer version of gcc - /*std::sort( indexPairs.begin(), - indexPairs.end(), - []( IndexPair pair0, IndexPair pair1 ){ return ( pair0.entityIndex < pair1.entityIndex ); } );*/ - - GlobalIdArrayType &superentityIdsArray = meshInitializer.template meshSuperentityIdsArray< EntityDimension, DimensionTag >(); - superentityIdsArray.setSize( static_cast< GlobalIndexType >( indexPairs.size() ) ); - GlobalIndexType currentBegin = 0; - GlobalIndexType lastEntityIndex = 0; - std::cout << "There are " << superentityIdsArray.getSize() << " superentities with " << DimensionTag::value << " dimensions of enities with " << EntityDimension::value << " ... " << std::endl; - for( GlobalIndexType i = 0; i < superentityIdsArray.getSize(); i++) - { - superentityIdsArray[ i ] = indexPairs[i].superentityIndex; - - //cout << "Adding superentity " << indexPairs[i].superentityIndex << " to entity " << lastEntityIndex << std::endl; - if( indexPairs[ i ].entityIndex != lastEntityIndex ) - { - meshInitializer.template superentityIdsArray< DimensionTag >( meshInitializer.template meshEntitiesArray< EntityDimension >()[ lastEntityIndex ] ).bind( superentityIdsArray, currentBegin, i - currentBegin ); - currentBegin = i; - lastEntityIndex = indexPairs[ i ].entityIndex; - } - } - - meshInitializer.template superentityIdsArray< DimensionTag >( meshInitializer.template meshEntitiesArray< EntityDimension >()[ lastEntityIndex ] ).bind( superentityIdsArray, currentBegin, superentityIdsArray.getSize() - currentBegin ); - indexPairs.clear(); - - /**** - * Network initializer - */ - SuperentityStorageNetwork& superentityStorageNetwork = meshInitializer.template meshSuperentityStorageNetwork< EntityTopology, DimensionTag >(); - //GlobalIndexType lastEntityIndex( 0 ); - superentityStorageNetwork.setRanges( - meshInitializer.template meshEntitiesArray< EntityDimension >().getSize(), - meshInitializer.template meshEntitiesArray< DimensionTag >().getSize() ); - lastEntityIndex = 0; - typename SuperentityStorageNetwork::ValuesAllocationVectorType storageNetworkAllocationVector; - storageNetworkAllocationVector.setSize( meshInitializer.template meshEntitiesArray< EntityDimension >().getSize() ); - storageNetworkAllocationVector.setValue( 0 ); - for( GlobalIndexType i = 0; i < superentityIdsArray.getSize(); i++) - { - if( indexPairs[ i ].entityIndex == lastEntityIndex ) - storageNetworkAllocationVector[ lastEntityIndex ]++; - else - lastEntityIndex++; - } - superentityStorageNetwork.allocate( storageNetworkAllocationVector ); - lastEntityIndex = 0; - LocalIndexType superentitiesCount( 0 ); - typename SuperentityStorageNetwork::ValuesAccessorType superentitiesIndecis = - superentityStorageNetwork.getValues( lastEntityIndex ); - for( GlobalIndexType i = 0; i < superentityIdsArray.getSize(); i++) - { - if( indexPairs[ i ].entityIndex != lastEntityIndex ) - { - superentitiesIndecis = superentityStorageNetwork.getValues( ++lastEntityIndex ); - superentitiesCount = 0; - } - superentitiesIndecis[ superentitiesCount++ ] = indexPairs[ i ].superentityIndex; - } - BaseType::initSuperentities( meshInitializer ); - } - - private: - struct IndexPair - { - GlobalIndexType entityIndex; - GlobalIndexType superentityIndex; - }; - - std::vector< IndexPair > indexPairs; - -}; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - DimensionTag, - false > - : public MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - typedef MeshInitializer< MeshConfig > MeshInitializerType; - - public: - void addSuperentity() {} // This method is due to 'using BaseType::...;' in the derived classes. - using BaseType::initSuperentities; - void initSuperentities( MeshInitializerType& ) { std::cerr << "***" << std::endl;} -}; - -template< typename MeshConfig, - typename EntityTopology > -class MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< EntityTopology::dimensions >, - true > -{ - typedef MeshInitializer< MeshConfig > MeshInitializerType; - - public: - void addSuperentity() {} // This method is due to 'using BaseType::...;' in the derived classes. - void initSuperentities( MeshInitializerType& ) {} -}; - -template< typename MeshConfig, - typename EntityTopology > -class MeshSuperentityStorageInitializerLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< EntityTopology::dimensions >, - false > -{ - typedef MeshInitializer< MeshConfig > MeshInitializerType; - - public: - void addSuperentity() {} // This method is due to 'using BaseType::...;' in the derived classes. - void initSuperentities( MeshInitializerType& ) {} -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h b/src/TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..6d76ae0696f62bf51e3027bb70c699b10d2c6a1d --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h @@ -0,0 +1,109 @@ +/*************************************************************************** + SubentitySeedsCreator.h - description + ------------------- + begin : Aug 20, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/StaticFor.h> +#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename EntityDimensionTag, + typename SubentityDimensionTag > +class SubentitySeedsCreator +{ + using MeshTraitsType = MeshTraits< MeshConfig >; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< EntityDimensionTag::value >; + using EntityType = typename EntityTraitsType::EntityType; + using EntityTopology = typename EntityTraitsType::EntityTopology; + using SubvertexAccessorType = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >::SubentityAccessorType; + using SubentityTraits = typename MeshTraitsType::template SubentityTraits< EntityTopology, SubentityDimensionTag::value >; + using SubentityType = typename SubentityTraits::SubentityType; + using SubentityTopology = typename SubentityTraits::SubentityTopology; + + static const LocalIndexType SUBENTITIES_COUNT = EntityType::template getSubentitiesCount< SubentityDimensionTag::value >(); + static const LocalIndexType SUBENTITY_VERTICES_COUNT = SubentityType::template getSubentitiesCount< 0 >(); + +public: + using SubentitySeedArray = typename SubentityTraits::SeedArrayType; + + static SubentitySeedArray create( const SubvertexAccessorType& subvertices ) + { + SubentitySeedArray subentitySeeds; + StaticFor< LocalIndexType, 0, SUBENTITIES_COUNT, CreateSubentitySeeds >::execHost( subentitySeeds, subvertices ); + + return subentitySeeds; + } + +private: + using SubentitySeed = EntitySeed< MeshConfig, SubentityTopology >; + + template< LocalIndexType subentityIndex > + class CreateSubentitySeeds + { + public: + static void exec( SubentitySeedArray& subentitySeeds, const SubvertexAccessorType& subvertices ) + { + StaticFor< LocalIndexType, 0, SUBENTITY_VERTICES_COUNT, SetSubentitySeedVertex >::execHost( subentitySeeds[ subentityIndex ], subvertices ); + } + + private: + template< LocalIndexType subentityVertexIndex > + class SetSubentitySeedVertex + { + public: + static void exec( SubentitySeed& subentitySeed, const SubvertexAccessorType& subvertices ) + { + static const LocalIndexType VERTEX_INDEX = SubentityTraits::template Vertex< subentityIndex, subentityVertexIndex >::index; + subentitySeed.setCornerId( subentityVertexIndex, subvertices[ VERTEX_INDEX ] ); + } + }; + }; +}; + +template< typename MeshConfig, + typename EntityDimensionTag > +class SubentitySeedsCreator< MeshConfig, EntityDimensionTag, DimensionTag< 0 > > +{ + using MeshTraitsType = MeshTraits< MeshConfig >; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< EntityDimensionTag::value >; + using EntityType = typename EntityTraitsType::EntityType; + using EntityTopology = typename EntityTraitsType::EntityTopology; + using SubvertexAccessorType = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >::SubentityAccessorType; + using SubentityTraits = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >; + + static const LocalIndexType SUBENTITIES_COUNT = EntityType::template getSubentitiesCount< 0 >(); + +public: + using SubentitySeedArray = typename SubentityTraits::SeedArrayType; + + static SubentitySeedArray create( const SubvertexAccessorType& subvertices ) + { + SubentitySeedArray seeds; + for( LocalIndexType i = 0; i < seeds.getSize(); i++ ) + seeds[ i ].setCornerId( 0, subvertices[ i ] ); + return seeds; + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h new file mode 100644 index 0000000000000000000000000000000000000000..c0327785d64dacc22bfffb380fe3235c5f734051 --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h @@ -0,0 +1,103 @@ +/*************************************************************************** + SuperentityStorageInitializer.h - description + ------------------- + begin : Feb 27, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <set> +#include <unordered_map> + +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig > +class Initializer; + +template< typename MeshConfig, + typename SubdimensionTag, + typename SuperdimensionTag > +class SuperentityStorageInitializer +{ + using MeshTraitsType = MeshTraits< MeshConfig >; + using InitializerType = Initializer< MeshConfig >; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using EntityTraitsType = typename MeshTraitsType::template EntityTraits< SubdimensionTag::value >; + using EntityTopology = typename EntityTraitsType::EntityTopology; + using EntityType = typename EntityTraitsType::EntityType; + using SuperentityTraitsType = typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionTag::value >; + using SuperentityStorageNetwork = typename SuperentityTraitsType::StorageNetworkType; + +public: + void addSuperentity( GlobalIndexType entityIndex, GlobalIndexType superentityIndex) + { + //std::cout << "Adding superentity with " << SuperdimensionTag::value << " dimension of entity with " << SubdimensionTag::value << " dimension: entityIndex = " << entityIndex << ", superentityIndex = " << superentityIndex << std::endl; + auto& indexSet = this->dynamicStorageNetwork[ entityIndex ]; + TNL_ASSERT( indexSet.count( superentityIndex ) == 0, + std::cerr << "Superentity " << superentityIndex << " with dimension " << SuperdimensionTag::value + << " of entity " << entityIndex << " with dimension " << SubdimensionTag::value + << " has been already added. This is probably a bug in the mesh initializer." << std::endl; ); + indexSet.insert( superentityIndex ); + } + + void initSuperentities( InitializerType& meshInitializer ) + { + TNL_ASSERT_GT( dynamicStorageNetwork.size(), (size_t) 0, + "No superentity indices were collected. This is a bug in the mesh initializer." ); + TNL_ASSERT_EQ( (size_t) getMaxSuperentityIndex(), dynamicStorageNetwork.size() - 1, + "Superentities for some entities are missing. " + "This is probably a bug in the mesh initializer." ); + + SuperentityStorageNetwork& superentityStorageNetwork = meshInitializer.template meshSuperentityStorageNetwork< EntityTopology, SuperdimensionTag::value >(); + TNL_ASSERT_EQ( (size_t) superentityStorageNetwork.getKeysRange(), dynamicStorageNetwork.size(), + "Sizes of the static and dynamic storage networks don't match. " + "This is probably a bug in the mesh initializer." ); + + typename SuperentityStorageNetwork::ValuesAllocationVectorType storageNetworkAllocationVector; + storageNetworkAllocationVector.setSize( superentityStorageNetwork.getKeysRange() ); + for( auto it = dynamicStorageNetwork.cbegin(); it != dynamicStorageNetwork.cend(); it++ ) + storageNetworkAllocationVector[ it->first ] = it->second.size(); + superentityStorageNetwork.allocate( storageNetworkAllocationVector ); + + for( auto it = dynamicStorageNetwork.cbegin(); it != dynamicStorageNetwork.cend(); it++ ) { + auto superentitiesIndices = superentityStorageNetwork.getValues( it->first ); + LocalIndexType i = 0; + for( auto v_it = it->second.cbegin(); v_it != it->second.cend(); v_it++ ) + superentitiesIndices[ i++ ] = *v_it; + } + + dynamicStorageNetwork.clear(); + } + +private: + using DynamicIndexSet = std::set< GlobalIndexType >; + std::unordered_map< GlobalIndexType, DynamicIndexSet > dynamicStorageNetwork; + + GlobalIndexType getMaxSuperentityIndex() + { + GlobalIndexType max = 0; + for( auto it = dynamicStorageNetwork.cbegin(); it != dynamicStorageNetwork.cend(); it++ ) { + if( it->first > max ) + max = it->first; + } + return max; + } +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/layers/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/layers/CMakeLists.txt deleted file mode 100644 index 04987a5db350cd2b9d7b7defd52d863b4df7b118..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/layers/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -SET( headers MeshStorageLayer.h - MeshSubentityStorageLayer.h - MeshSuperentityStorageLayer.h ) - -INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/layers ) \ No newline at end of file diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h b/src/TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h deleted file mode 100644 index bd31795a5cb2d774d8a76e87aa6c4c99b96dcab4..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h +++ /dev/null @@ -1,343 +0,0 @@ -/*************************************************************************** - MeshStorageLayer.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/File.h> -#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> -#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h> -#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename DimensionTag, - bool EntityStorage = MeshEntityTraits< MeshConfig, DimensionTag::value >::storageEnabled > -class MeshStorageLayer; - - -template< typename MeshConfig > -class MeshStorageLayers - : public MeshStorageLayer< MeshConfig, typename MeshTraits< MeshConfig >::DimensionTag > -{ -}; - - -template< typename MeshConfig, - typename DimensionTag > -class MeshStorageLayer< MeshConfig, - DimensionTag, - true > - : public MeshStorageLayer< MeshConfig, typename DimensionTag::Decrement >, - public MeshSuperentityStorageLayers< MeshConfig, - typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::EntityTopology > -{ - public: - - static const int Dimension = DimensionTag::value; - typedef MeshStorageLayer< MeshConfig, typename DimensionTag::Decrement > BaseType; - typedef MeshSuperentityStorageLayers< MeshConfig, - typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::EntityTopology > SuperentityStorageBaseType; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template EntityTraits< Dimension > EntityTraitsType; - - typedef typename EntityTraitsType::StorageArrayType StorageArrayType; - typedef typename EntityTraitsType::AccessArrayType AccessArrayType; - typedef typename EntityTraitsType::GlobalIndexType GlobalIndexType; - typedef typename EntityTraitsType::EntityType EntityType; - typedef typename EntityTraitsType::EntityTopology EntityTopology; - - - using BaseType::getNumberOfEntities; - using BaseType::getEntity; - using BaseType::getEntities; - - MeshStorageLayer() - { - } - - GlobalIndexType getNumberOfEntities( DimensionTag ) const - { - return this->entities.getSize(); - } - - EntityType& getEntity( DimensionTag, - const GlobalIndexType entityIndex ) - { - return this->entities[ entityIndex ]; - } - - const EntityType& getEntity( DimensionTag, - const GlobalIndexType entityIndex ) const - { - return this->entities[ entityIndex ]; - } - - AccessArrayType& getEntities( DimensionTag ) - { - return this->sharedEntities; - } - - const AccessArrayType& getEntities( DimensionTag ) const - { - return this->sharedEntities; - } - - bool save( File& file ) const - { - if( ! BaseType::save( file ) || - ! this->entities.save( file ) ) - { - std::cerr << "Saving of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl; - return false; - } - return true; - } - - bool load( File& file ) - { - //cout << "Loading mesh layer with dimensions " << DimensionTag::value << std::endl; - if( ! BaseType::load( file ) || - ! this->entities.load( file ) ) - { - std::cerr << "Loading of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl; - return false; - } - this->entitiesAccess.bind( this->entities ); - return true; - } - - void print( std::ostream& str ) const - { - BaseType::print( str ); - str << "The entities with " << DimensionTag::value << " dimensions are: " << std::endl; - for( GlobalIndexType i = 0; i < entities.getSize();i ++ ) - { - str << i << " "; - entities[ i ].print( str ); - str << std::endl; - } - SuperentityStorageBaseType::print( str ); - } - - bool operator==( const MeshStorageLayer& meshLayer ) const - { - return ( BaseType::operator==( meshLayer ) && entities == meshLayer.entities ); - } - - - protected: - StorageArrayType entities; - - AccessArrayType entitiesAccess; - - // TODO: this is only for the mesh initializer - fix it - public: - - using BaseType::entitiesArray; - - typename EntityTraitsType::StorageArrayType& entitiesArray( DimensionTag ) - { - return entities; - } - - using BaseType::superentityIdsArray; - - template< typename SuperDimensionTag > - typename MeshTraitsType::GlobalIdArrayType& superentityIdsArray( DimensionTag ) - { - return SuperentityStorageBaseType::superentityIdsArray( SuperDimensionTag() ); - } - - using BaseType::getSuperentityStorageNetwork; - template< typename SuperdimensionsTag > - typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType& - getSuperentityStorageNetwork( MeshDimensionTag< EntityTopology::dimensions > ) - { - return SuperentityStorageBaseType::getStorageNetwork( SuperdimensionsTag() ); - } -}; - -template< typename MeshConfig, - typename DimensionTag > -class MeshStorageLayer< MeshConfig, DimensionTag, false > - : public MeshStorageLayer< MeshConfig, typename DimensionTag::Decrement > -{ -}; - -template< typename MeshConfig > -class MeshStorageLayer< MeshConfig, MeshDimensionTag< 0 >, true > : - public MeshSuperentityStorageLayers< MeshConfig, - MeshVertexTopology > - -{ - public: - - typedef MeshDimensionTag< 0 > DimensionTag; - - typedef MeshSuperentityStorageLayers< MeshConfig, - MeshVertexTopology > SuperentityStorageBaseType; - - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template EntityTraits< 0 > EntityTraitsType; - - typedef typename EntityTraitsType::StorageArrayType StorageArrayType; - typedef typename EntityTraitsType::AccessArrayType AccessArrayType; - typedef typename EntityTraitsType::GlobalIndexType GlobalIndexType; - typedef typename EntityTraitsType::EntityType VertexType; - typedef typename VertexType::PointType PointType; - typedef MeshVertexTopology EntityTopology; - - MeshStorageLayer() - { - } - - GlobalIndexType getNumberOfVertices() const - { - return this->vertices.getSize(); - } - - void setVertex( const GlobalIndexType vertexIndex, - const VertexType& vertex ) const - { - this->vertices.setElement( vertexIndex, vertex ); - } - - VertexType& getVertex( const GlobalIndexType vertexIndex ) - { - return this->vertices[ vertexIndex ]; - } - - const VertexType& getVertex( const GlobalIndexType vertexIndex ) const - { - return this->vertices[ vertexIndex ]; - } - - - void setVertex( const GlobalIndexType vertexIndex, - const PointType& point ) - { - this->vertices[ vertexIndex ].setPoint( point ); - } - - /**** - * This is only for the completeness and compatibility - * with higher dimensions entities storage layers. - */ - - GlobalIndexType getNumberOfEntities( DimensionTag ) const - { - return this->vertices.getSize(); - } - - VertexType& getEntity( DimensionTag, - const GlobalIndexType entityIndex ) - { - return this->vertices[ entityIndex ]; - } - - const VertexType& getEntity( DimensionTag, - const GlobalIndexType entityIndex ) const - { - return this->vertices.getElement( entityIndex ); - } - - AccessArrayType& getEntities( DimensionTag ) - { - return this->sharedVertices; - } - - const AccessArrayType& getEntities( DimensionTag ) const - { - return this->sharedVertices; - } - - bool save( File& file ) const - { - if( ! this->vertices.save( file ) ) - { - std::cerr << "Saving of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl; - return false; - } - return true; - } - - bool load( File& file ) - { - if( ! this->vertices.load( file ) ) - { - std::cerr << "Loading of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl; - return false; - } - this->verticesAccess.bind( this->vertices ); - return true; - } - - void print( std::ostream& str ) const - { - str << "The mesh vertices are: " << std::endl; - for( GlobalIndexType i = 0; i < vertices.getSize();i ++ ) - { - str << i << vertices[ i ] << std::endl; - } - SuperentityStorageBaseType::print( str ); - } - - bool operator==( const MeshStorageLayer& meshLayer ) const - { - return ( vertices == meshLayer.vertices ); - } - - private: - - StorageArrayType vertices; - - AccessArrayType verticesAccess; - - // TODO: this is only for the mesh initializer - fix it - public: - - typename EntityTraitsType::StorageArrayType& entitiesArray( DimensionTag ) - { - return vertices; - } - - - template< typename SuperDimensionTag > - typename MeshTraitsType::GlobalIdArrayType& superentityIdsArray( DimensionTag ) - { - return SuperentityStorageBaseType::superentityIdsArray( SuperDimensionTag() ); - } - - template< typename SuperdimensionsTag > - typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType& getSuperentityStorageNetwork( MeshDimensionTag< EntityTopology::dimensions > ) - { - return SuperentityStorageBaseType::getStorageNetwork( SuperdimensionsTag() ); - } - -}; - -/**** - * Forces termination of recursive inheritance (prevents compiler from generating huge error logs) - */ -template< typename MeshConfig > -class MeshStorageLayer< MeshConfig, MeshDimensionTag< 0 >, false > -{ -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h deleted file mode 100644 index 13d40fd980f9616741eaf14986c6010ab9fb9beb..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h +++ /dev/null @@ -1,408 +0,0 @@ -/*************************************************************************** - MeshSubentityStorageLayer.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/File.h> -#include <TNL/Meshes/MeshDimensionTag.h> -#include <TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h> -#include <TNL/Meshes/MeshDetails/MeshEntityOrientation.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag, - bool SubentityStorage = - MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::storageEnabled, - bool SubentityOrientationStorage = - MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::orientationEnabled > -class MeshSubentityStorageLayer; - - -template< typename MeshConfig, - typename EntityTopology > -class MeshSubentityStorageLayers - : public MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< EntityTopology::dimensions - 1 > > -{ -}; - - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - DimensionTag, - true, - true > - : public MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - protected: - - static const int Dimension = DimensionTag::value; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension > SubentityTraitsType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename SubentityTraitsType::IdArrayType IdArrayType; - typedef typename SubentityTraitsType::OrientationArrayType OrientationArrayType; - typedef typename MeshTraitsType::IdPermutationArrayAccessorType IdPermutationArrayAccessorType; - - MeshSubentityStorageLayer() - { - this->subentitiesIndices.setValue( -1 ); - } - - ~MeshSubentityStorageLayer() - { - //cout << " Destroying " << this->sharedSubentitiesIndices.getSize() << " subentities with "<< DimensionTag::value << " dimensions." << std::endl; - } - - MeshSubentityStorageLayer& operator = ( const MeshSubentityStorageLayer& layer ) - { - BaseType::operator=( layer ); - this->subentitiesIndices = layer.subentitiesIndices; - return *this; - } - - bool save( File& file ) const - { - if( ! BaseType::save( file ) || - ! this->subentitiesIndices.save( file ) ) - { - std::cerr << "Saving of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - bool load( File& file ) - { - if( ! BaseType::load( file ) || - ! this->subentitiesIndices.load( file ) ) - { - std::cerr << "Loading of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - void print( std::ostream& str ) const - { - BaseType::print( str ); - str << std::endl; - str << "\t Subentities with " << DimensionTag::value << " dimensions are: " << subentitiesIndices << "."; - } - - bool operator==( const MeshSubentityStorageLayer& layer ) const - { - return ( BaseType::operator==( layer ) && - subentitiesIndices == layer.subentitiesIndices ); - } - - /**** - * Make visible setters and getters of the lower subentities - */ - using BaseType::getSubentityIndex; - using BaseType::setSubentityIndex; - - /**** - * Define setter/getter for the current level of the subentities - */ - void setSubentityIndex( DimensionTag, - const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) - { - this->subentitiesIndices[ localIndex ] = globalIndex; - } - - GlobalIndexType getSubentityIndex( DimensionTag, - const LocalIndexType localIndex ) const - { - return this->subentitiesIndices[ localIndex ]; - } - - using BaseType::subentityIdsArray; - IdArrayType& subentityIdsArray( DimensionTag ) { return this->subentitiesIndices; } - - using BaseType::subentityOrientation; - IdPermutationArrayAccessorType subentityOrientation( DimensionTag, LocalIndexType index) const - { - TNL_ASSERT( 0 <= index && index < SubentityTraitsType::count, ); - - return this->subentityOrientations[ index ].getSubvertexPermutation(); - } - - using BaseType::subentityOrientationsArray; - OrientationArrayType& subentityOrientationsArray( DimensionTag ) { return this->subentityOrientations; } - - private: - IdArrayType subentitiesIndices; - - OrientationArrayType subentityOrientations; -}; - - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - DimensionTag, - true, - false > - : public MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ - typedef MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > BaseType; - - protected: - - static const int Dimension = DimensionTag::value; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension > SubentityTraitsType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename SubentityTraitsType::IdArrayType IdArrayType; - typedef typename SubentityTraitsType::OrientationArrayType OrientationArrayType; - typedef typename MeshTraitsType::IdPermutationArrayAccessorType IdPermutationArrayAccessorType; - - MeshSubentityStorageLayer() - { - this->subentitiesIndices.setValue( -1 ); - } - - ~MeshSubentityStorageLayer() - { - //cout << " Destroying " << this->sharedSubentitiesIndices.getSize() << " subentities with "<< DimensionTag::value << " dimensions." << std::endl; - } - - MeshSubentityStorageLayer& operator = ( const MeshSubentityStorageLayer& layer ) - { - BaseType::operator=( layer ); - this->subentitiesIndices = layer.subentitiesIndices; - return *this; - } - - bool save( File& file ) const - { - if( ! BaseType::save( file ) || - ! this->subentitiesIndices.save( file ) ) - { - std::cerr << "Saving of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - bool load( File& file ) - { - if( ! BaseType::load( file ) || - ! this->subentitiesIndices.load( file ) ) - { - std::cerr << "Loading of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - void print( std::ostream& str ) const - { - BaseType::print( str ); - str << std::endl; - str << "\t Subentities with " << DimensionTag::value << " dimensions are: " << subentitiesIndices << "."; - } - - bool operator==( const MeshSubentityStorageLayer& layer ) const - { - return ( BaseType::operator==( layer ) && - subentitiesIndices == layer.subentitiesIndices ); - } - - /**** - * Make visible setters and getters of the lower subentities - */ - using BaseType::getSubentityIndex; - using BaseType::setSubentityIndex; - - /**** - * Define setter/getter for the current level of the subentities - */ - void setSubentityIndex( DimensionTag, - const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) - { - this->subentitiesIndices[ localIndex ] = globalIndex; - } - - GlobalIndexType getSubentityIndex( DimensionTag, - const LocalIndexType localIndex ) const - { - return this->subentitiesIndices[ localIndex ]; - } - - using BaseType::subentityIdsArray; - IdArrayType& subentityIdsArray( DimensionTag ) { return this->subentitiesIndices; } - - using BaseType::subentityOrientationsArray; - void subentityOrientationsArray() {} - - private: - IdArrayType subentitiesIndices; -}; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - DimensionTag, - false, - false > - : public MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - typename DimensionTag::Decrement > -{ -}; - - -template< typename MeshConfig, - typename EntityTopology > -class MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< 0 >, - true, - false > -{ - typedef MeshDimensionTag< 0 > DimensionTag; - - protected: - static const int Dimension = 0; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension > SubentityTraitsType; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename SubentityTraitsType::IdArrayType IdArrayType; - - MeshSubentityStorageLayer() - { - this->verticesIndices.setValue( -1 ); - } - - ~MeshSubentityStorageLayer() - { - //cout << " Destroying " << this->sharedVerticesIndices.getSize() << " subentities with "<< DimensionTag::value << " dimensions." << std::endl; - } - - - MeshSubentityStorageLayer& operator = ( const MeshSubentityStorageLayer& layer ) - { - this->verticesIndices = layer.verticesIndices; - return *this; - } - - bool save( File& file ) const - { - if( ! this->verticesIndices.save( file ) ) - { - std::cerr << "Saving of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - bool load( File& file ) - { - if( ! this->verticesIndices.load( file ) ) - { - std::cerr << "Loading of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - void print( std::ostream& str ) const - { - str << "\t Subentities with " << DimensionTag::value << " dimensions are: " << this->verticesIndices << "."; - } - - bool operator==( const MeshSubentityStorageLayer& layer ) const - { - return ( verticesIndices == layer.verticesIndices ); - } - - GlobalIndexType getSubentityIndex( DimensionTag, - const LocalIndexType localIndex ) const - { - return this->verticesIndices[ localIndex ]; - } - void setSubentityIndex( DimensionTag, - const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) - { - this->verticesIndices[ localIndex ] = globalIndex; - } - - IdArrayType& subentityIdsArray( DimensionTag ) { return this->verticesIndices; } - - protected: - - /*** - * Necessary because of 'using TBase::...;' in the derived classes - */ - void subentityOrientation() {} - void subentityOrientationsArray() {} - - IdArrayType verticesIndices; -}; - -template< typename MeshConfig, - typename EntityTopology > -class MeshSubentityStorageLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< 0 >, - false, - false > -{ - public: - - bool save( File& file ) const - { - return true; - } - - bool load( File& file ) - { - return true; - } - -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h b/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h deleted file mode 100644 index 44476c81cdb57ce40482ba63b5b62206176dfc8f..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h +++ /dev/null @@ -1,159 +0,0 @@ -/*************************************************************************** - MeshSuperentityAccess.h - description - ------------------- - begin : Aug 15, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename MeshEntity, - typename DimensionTag, - bool SuperentityStorage = - MeshTraits< MeshConfig >::template SuperentityTraits< MeshEntity, DimensionTag::value >::storageEnabled > -class MeshSuperentityAccessLayer; - - -template< typename MeshConfig, - typename MeshEntity > -class MeshSuperentityAccess : - public MeshSuperentityAccessLayer< MeshConfig, - MeshEntity, - MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > > -{ - public: - typedef MeshSuperentityAccessLayer< MeshConfig, - MeshEntity, - MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > > BaseType; - - bool operator == ( const MeshSuperentityAccess< MeshConfig, MeshEntity>& a ) const { return true; } // TODO: fix - - void print( std::ostream& str ) const - { - BaseType::print( str ); - }; - -}; - -template< typename MeshConfig, - typename MeshEntity, - typename Dimension > -class MeshSuperentityAccessLayer< MeshConfig, - MeshEntity, - Dimension, - true > : - public MeshSuperentityAccessLayer< MeshConfig, MeshEntity, typename Dimension::Decrement > -{ - typedef MeshSuperentityAccessLayer< MeshConfig, MeshEntity, typename Dimension::Decrement > BaseType; - - public: - - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template SuperentityTraits< MeshEntity, Dimension::value > SuperentityTraitsType; - typedef typename MeshTraitsType::IdArrayAccessorType IdArrayAccessorType; - typedef typename SuperentityTraitsType::StorageNetworkType StorageNetworkType; - typedef typename SuperentityTraitsType::SuperentityAccessorType SuperentityAccessorType; - //typedef typename StorageNetworkType::PortsType SuperentityAccessorType; - - using BaseType::superentityIds; - IdArrayAccessorType superentityIds( Dimension ) const { return m_superentityIndices; } - - using BaseType::superentityIdsArray; - IdArrayAccessorType &superentityIdsArray( Dimension ) { return m_superentityIndices; } - - using BaseType::getSuperentityIndices; - const SuperentityAccessorType& getSuperentityIndices( Dimension ) const - { - std::cerr << "###" << std::endl; - return this->superentityIndices; - } - - SuperentityAccessorType& getSuperentityIndices( Dimension ) - { - std::cerr << "######" << std::endl; - return this->superentityIndices; - } - - void print( std::ostream& str ) const - { - str << "Superentities with " << Dimension::value << " dimensions are: " << - this->superentityIndices << std::endl; - BaseType::print( str ); - } - - //bool operator == ( const MeshSuperentityAccessLayer< MeshConfig, MeshEntity, Dimension, tnlStorageTraits< true > >& l ) { return true; } // TODO: fix - - private: - IdArrayAccessorType m_superentityIndices; - - SuperentityAccessorType superentityIndices; - -}; - -template< typename MeshConfig, - typename MeshEntity, - typename Dimension > -class MeshSuperentityAccessLayer< MeshConfig, - MeshEntity, - Dimension, - false > : - public MeshSuperentityAccessLayer< MeshConfig, MeshEntity, typename Dimension::Decrement > -{ -}; - -template< typename MeshConfig, - typename MeshEntity > -class MeshSuperentityAccessLayer< MeshConfig, - MeshEntity, - MeshDimensionTag< MeshEntity::dimensions >, - false > -{ - protected: - /*** - * Necessary because of 'using TBase::...;' in the derived classes - */ - void superentityIds() {} - void superentityIdsArray() {} - - void getSuperentityIndices() {}; - - void print( std::ostream& str ) const {}; -}; - -template< typename MeshConfig, - typename MeshEntity > -class MeshSuperentityAccessLayer< MeshConfig, - MeshEntity, - MeshDimensionTag< MeshEntity::dimensions >, - true > -{ - protected: - /*** - * Necessary because of 'using TBase::...;' in the derived classes - */ - void superentityIds() {} - void superentityIdsArray() {} - - void getSuperentityIndices() {}; - - void print( std::ostream& str ) const {}; -}; - -} // namespace Meshes -} // namespace TNL - diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h b/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h deleted file mode 100644 index ebe8ee41940190935657615eef3b95419def2d41..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************** - MeshSuperentityAccessor.h - description - ------------------- - begin : Sep 11, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -namespace TNL { -namespace Meshes { - -template< typename IndexMultimapValues > -class MeshSuperentityAccessor -{ - public: - - typedef typename IndexMultimapValues::IndexType GlobalIndexType; - typedef typename IndexMultimapValues::IndexType LocalIndexType; - - // TODO: Add LocalIndexType to EllpackIndexMultimap - - LocalIndexType getSupernetitiesCount() const - { - return this->indexes.getPortsCount(); - }; - - void setSuperentityIndex( const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) - { - indexes.setOutput( localIndex, globalIndex ); - } - - GlobalIndexType getSuperentityIndex( const LocalIndexType localIndex ) const - { - return indexes.getOutput( localIndex ); - } - - GlobalIndexType& operator[]( const LocalIndexType localIndex ) - { - return this->indexes[ localIndex ]; - } - - const GlobalIndexType& operator[]( const LocalIndexType localIndex ) const - { - return this->indexes[ localIndex ]; - } - - void print( std::ostream& str ) const - { - str << indexes; - } - - protected: - - IndexMultimapValues indexes; - -}; - -template< typename IndexMultimapValues > -std::ostream& operator << ( std::ostream& str, const MeshSuperentityAccessor< IndexMultimapValues >& superentityAccessor ) -{ - superentityAccessor.print( str ); - return str; -} - -} // namespace Meshes -} // namespace TNL - diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h deleted file mode 100644 index d02a1beafb69f6fbf1d86592c0dbc78f9dc4ce07..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h +++ /dev/null @@ -1,346 +0,0 @@ -/*************************************************************************** - MeshSuperentityStorageLayer.h - description - ------------------- - begin : Feb 13, 2014 - copyright : (C) 2014 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/File.h> -#include <TNL/Meshes/MeshDimensionTag.h> -#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> -#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h> - -namespace TNL { -namespace Meshes { - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag, - bool SuperentityStorage = - MeshSuperentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::storageEnabled > -class MeshSuperentityStorageLayer; - -template< typename MeshConfig, - typename EntityTopology > -class MeshSuperentityStorageLayers - : public MeshSuperentityStorageLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > > -{ -}; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshSuperentityStorageLayer< MeshConfig, EntityTopology, DimensionTag, true > - : public MeshSuperentityStorageLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement > -{ - typedef - MeshSuperentityStorageLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement > BaseType; - - static const int Dimension = DimensionTag::value; - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef typename MeshTraitsType::template SuperentityTraits< EntityTopology, Dimension > SuperentityTraitsType; - - protected: - - typedef typename SuperentityTraitsType::StorageArrayType StorageArrayType; - typedef typename SuperentityTraitsType::AccessArrayType AccessArrayType; - typedef typename SuperentityTraitsType::GlobalIndexType GlobalIndexType; - typedef typename SuperentityTraitsType::LocalIndexType LocalIndexType; - - typedef typename SuperentityTraitsType::StorageNetworkType StorageNetworkType; - - /**** - * Make visible setters and getters of the lower superentities - */ - using BaseType::setNumberOfSuperentities; - using BaseType::getNumberOfSuperentities; - using BaseType::getSuperentityIndex; - using BaseType::setSuperentityIndex; - using BaseType::getSuperentitiesIndices; - - MeshSuperentityStorageLayer() - { - } - - /*~MeshSuperentityStorageLayer() - { - std::cerr << " Destroying " << this->superentitiesIndices.getSize() << " superentities with "<< DimensionTag::value << " dimensions." << std::endl; - std::cerr << " this->superentitiesIndices.getName() = " << this->superentitiesIndices.getName() << std::endl; - std::cerr << " this->sharedSuperentitiesIndices.getName() = " << this->sharedSuperentitiesIndices.getName() << std::endl; - }*/ - - MeshSuperentityStorageLayer& operator = ( const MeshSuperentityStorageLayer& layer ) - { - this->superentitiesIndices.setSize( layer.superentitiesIndices.getSize() ); - this->superentitiesIndices = layer.superentitiesIndices; - this->sharedSuperentitiesIndices.bind( this->superentitiesIndices ); - return *this; - } - - /**** - * Define setter/getter for the current level of the superentities - */ - bool setNumberOfSuperentities( DimensionTag, - const LocalIndexType size ) - { - if( ! this->superentitiesIndices.setSize( size ) ) - return false; - this->superentitiesIndices.setValue( -1 ); - this->sharedSuperentitiesIndices.bind( this->superentitiesIndices ); - return true; - } - - LocalIndexType getNumberOfSuperentities( DimensionTag ) const - { - return this->superentitiesIndices.getSize(); - } - - void setSuperentityIndex( DimensionTag, - const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) - { - this->superentitiesIndices[ localIndex ] = globalIndex; - } - - GlobalIndexType getSuperentityIndex( DimensionTag, - const LocalIndexType localIndex ) const - { - return this->superentitiesIndices[ localIndex ]; - } - - AccessArrayType& getSuperentitiesIndices( DimensionTag ) - { - return this->sharedSuperentitiesIndices; - } - - const AccessArrayType& getSuperentitiesIndices( DimensionTag ) const - { - return this->sharedSuperentitiesIndices; - } - - bool save( File& file ) const - { - if( ! BaseType::save( file ) || - ! this->superentitiesIndices.save( file ) ) - { - //cerr << "Saving of the entity superentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - bool load( File& file ) - { - if( ! BaseType::load( file ) || - ! this->superentitiesIndices.load( file ) ) - { - //cerr << "Loading of the entity superentities layer with " << DimensionTag::value << " failed." << std::endl; - return false; - } - return true; - } - - void print( std::ostream& str ) const - { - BaseType::print( str ); - str << std::endl << "\t Superentities with " << DimensionTag::value << " dimensions are: " << this->superentitiesIndices << "."; - } - - bool operator==( const MeshSuperentityStorageLayer& layer ) const - { - return ( BaseType::operator==( layer ) && - superentitiesIndices == layer.superentitiesIndices ); - } - - private: - - StorageArrayType superentitiesIndices; - - AccessArrayType sharedSuperentitiesIndices; - - StorageNetworkType storageNetwork; - - // TODO: this is only for the mesh initializer - fix it - public: - - using BaseType::superentityIdsArray; - typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray( DimensionTag ) - { - return this->superentitiesIndices; - } - - using BaseType::getStorageNetwork; - StorageNetworkType& getStorageNetwork( DimensionTag ) - { - return this->storageNetwork; - } -}; - -template< typename MeshConfig, - typename EntityTopology, - typename DimensionTag > -class MeshSuperentityStorageLayer< MeshConfig, EntityTopology, DimensionTag, false > - : public MeshSuperentityStorageLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement > -{ - public: - -}; - -template< typename MeshConfig, - typename EntityTopology > -class MeshSuperentityStorageLayer< MeshConfig, EntityTopology, MeshDimensionTag< EntityTopology::dimensions >, false > -{ - static const int Dimension = EntityTopology::dimensions; - typedef MeshDimensionTag< EntityTopology::dimensions > DimensionTag; - - typedef MeshSuperentityTraits< MeshConfig, EntityTopology, Dimension > SuperentityTraits; - - typedef MeshSuperentityStorageLayer< MeshConfig, - EntityTopology, - DimensionTag, - false > ThisType; - - protected: - - typedef typename SuperentityTraits::ContainerType ContainerType; - typedef typename ContainerType::ElementType GlobalIndexType; - typedef int LocalIndexType; - - typedef typename SuperentityTraits::StorageNetworkType StorageNetworkType; - - /**** - * These methods are due to 'using BaseType::...;' in the derived classes. - */ - bool setNumberOfSuperentities( DimensionTag, - const LocalIndexType size ); - LocalIndexType getNumberOfSuperentities( DimensionTag ) const; - GlobalIndexType getSuperentityIndex( DimensionTag, - const LocalIndexType localIndex ){} - void setSuperentityIndex( DimensionTag, - const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) {} - - void print( std::ostream& str ) const{} - - bool operator==( const ThisType& layer ) const - { - return true; - } - - ContainerType& getSuperentitiesIndices(){} - - const ContainerType& getSuperentitiesIndices() const{} - - bool save( File& file ) const - { - return true; - } - - bool load( File& file ) - { - return true; - } - - typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray( DimensionTag ) - { - TNL_ASSERT( false, ); - //return this->superentitiesIndices; - } - - StorageNetworkType& getStorageNetwork( DimensionTag ) - { - TNL_ASSERT( false, ); - //return this->storageNetwork; - } - -}; - -template< typename MeshConfig, - typename EntityTopology > -class MeshSuperentityStorageLayer< MeshConfig, - EntityTopology, - MeshDimensionTag< EntityTopology::dimensions >, - true > -{ - static const int Dimension = EntityTopology::dimensions; - typedef MeshDimensionTag< Dimension > DimensionTag; - - typedef MeshSuperentityTraits< MeshConfig, - EntityTopology, - Dimension > SuperentityTraits; - typedef MeshSuperentityStorageLayer< MeshConfig, - EntityTopology, - DimensionTag, - true > ThisType; - - protected: - - typedef typename SuperentityTraits::StorageArrayType StorageArrayType; - typedef typename SuperentityTraits::GlobalIndexType GlobalIndexType; - typedef typename SuperentityTraits::LocalIndexType LocalIndexType; - - typedef typename SuperentityTraits::StorageNetworkType StorageNetworkType; - - /**** - * These methods are due to 'using BaseType::...;' in the derived classes. - */ - bool setNumberOfSuperentities( DimensionTag, - const LocalIndexType size ); - LocalIndexType getNumberOfSuperentities( DimensionTag ) const; - GlobalIndexType getSuperentityIndex( DimensionTag, - const LocalIndexType localIndex ){} - void setSuperentityIndex( DimensionTag, - const LocalIndexType localIndex, - const GlobalIndexType globalIndex ) {} - - void print( std::ostream& str ) const{} - - bool operator==( const ThisType& layer ) const - { - return true; - } - - StorageArrayType& getSuperentitiesIndices(){} - - const StorageArrayType& getSuperentitiesIndices() const{} - - bool save( File& file ) const - { - return true; - } - - bool load( File& file ) - { - return true; - } - - typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray( DimensionTag ) - { - TNL_ASSERT( false, ); - //return this->superentitiesIndices; - } - - StorageNetworkType& getStorageNetwork( DimensionTag ) - { - TNL_ASSERT( false, ); - //return this->storageNetwork; - } - - -}; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt index b82bb335ac96401c3155520b1f6c983249ee9116..90b0fafc1c54ec0891b343dc4ac3e3b178f77d14 100644 --- a/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt +++ b/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt @@ -2,6 +2,7 @@ SET( headers MeshTraits.h MeshEntityTraits.h MeshSubentityTraits.h MeshSuperentityTraits.h + WeakStorageTraits.h ) -INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/traits ) \ No newline at end of file +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/traits ) diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h index c8c8be6b9a5c45dea478cacfa349d4525d82aad9..6b21bcde966fc8e16c4e5bfe1894fb66f924d4bf 100644 --- a/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h +++ b/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h @@ -2,7 +2,7 @@ MeshEntityTraits.h - description ------------------- begin : Feb 13, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -16,77 +16,79 @@ #pragma once -#include <TNL/Containers/StaticVector.h> #include <TNL/Containers/Array.h> -#include <TNL/Containers/SharedArray.h> -//#include <TNL/Containers/ConstSharedArray.h> -#include <TNL/Containers/IndexedSet.h> -#include <TNL/Meshes/Topologies/MeshEntityTopology.h> -#include <TNL/Meshes/MeshConfigBase.h> +#include <TNL/Containers/UnorderedIndexedSet.h> +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> +#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h> + +#include <unordered_set> namespace TNL { namespace Meshes { -template< typename MeshConfig, typename EntityTopology > class MeshEntity; -template< typename MeshConfig, typename EntityTopology > class MeshEntitySeed; -template< typename MeshConfig, typename EntityTopology > class MeshEntitySeedKey; +template< typename MeshConfig, typename Device, typename EntityTopology > class MeshEntity; template< typename MeshConfig, typename EntityTopology > class MeshEntityReferenceOrientation; template< typename MeshConfig, - typename DimensionTag, - typename SuperDimensionTag = MeshDimensionTag< MeshConfig::meshDimension > > + typename EntityDimensionTag, + typename SuperDimensionTag = DimensionTag< MeshConfig::meshDimension > > class MeshEntityOrientationNeeded { - static_assert( 0 <= DimensionTag::value && DimensionTag::value < MeshConfig::CellTopology::dimensions, "invalid dimensions" ); - static_assert( DimensionTag::value < SuperDimensionTag::value && SuperDimensionTag::value <= MeshConfig::CellTopology::dimensions, "invalid superentity dimension"); - - typedef typename MeshTraits< MeshConfig >::template EntityTraits< SuperDimensionTag::value >::EntityTopology SuperentityTopology; + using SuperentityTopology = typename MeshTraits< MeshConfig >::template EntityTraits< SuperDimensionTag::value >::EntityTopology; - static const bool previousSuperDimensionValue = MeshEntityOrientationNeeded< MeshConfig, DimensionTag, typename SuperDimensionTag::Decrement >::value; - static const bool thisSuperDimensionValue = MeshTraits< MeshConfig >::template SubentityTraits< SuperentityTopology, DimensionTag::value >::orientationEnabled; + static constexpr bool previousSuperDimensionValue = MeshEntityOrientationNeeded< MeshConfig, EntityDimensionTag, typename SuperDimensionTag::Decrement >::value; + static constexpr bool thisSuperDimensionValue = MeshTraits< MeshConfig >::template SubentityTraits< SuperentityTopology, EntityDimensionTag::value >::orientationEnabled; - public: - static const bool value = ( previousSuperDimensionValue || thisSuperDimensionValue ); +public: + static constexpr bool value = ( previousSuperDimensionValue || thisSuperDimensionValue ); }; template< typename MeshConfig, typename DimensionTag > class MeshEntityOrientationNeeded< MeshConfig, DimensionTag, DimensionTag > { - static_assert( 0 <= DimensionTag::value && DimensionTag::value <= MeshConfig::CellTopology::dimensions, "invalid dimensions" ); +public: + static constexpr bool value = false; +}; + + +template< typename MeshConfig, + typename DimensionTag > +struct EntityTopologyGetter +{ + static_assert( DimensionTag::value <= MeshConfig::meshDimension, "There are no entities with dimension higher than the mesh dimension." ); + using Topology = typename Topologies::Subtopology< typename MeshConfig::CellTopology, DimensionTag::value >::Topology; +}; - public: - static const bool value = false; +template< typename MeshConfig > +struct EntityTopologyGetter< MeshConfig, DimensionTag< MeshConfig::CellTopology::dimension > > +{ + using Topology = typename MeshConfig::CellTopology; }; template< typename MeshConfig, + typename Device, int Dimension > class MeshEntityTraits { - public: - - static const bool storageEnabled = MeshConfig::entityStorage( Dimension ); - static const bool orientationNeeded = MeshEntityOrientationNeeded< MeshConfig, MeshDimensionTag< Dimension > >::value; + using GlobalIndexType = typename MeshConfig::GlobalIndexType; - typedef typename MeshConfig::GlobalIndexType GlobalIndexType; - typedef typename MeshConfig::LocalIndexType LocalIndexType; - typedef typename MeshEntityTopology< MeshConfig, Dimension >::Topology EntityTopology; - - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - typedef MeshEntityReferenceOrientation< MeshConfig, EntityTopology > ReferenceOrientationType; - typedef MeshEntitySeedKey< MeshConfig, EntityTopology > Key; +public: + static_assert( 0 <= Dimension && Dimension <= MeshConfig::meshDimension, "invalid dimension" ); + using EntityTopology = typename EntityTopologyGetter< MeshConfig, DimensionTag< Dimension > >::Topology; + using EntityType = MeshEntity< MeshConfig, Device, EntityTopology >; + using SeedType = EntitySeed< MeshConfig, EntityTopology >; + using ReferenceOrientationType = MeshEntityReferenceOrientation< MeshConfig, EntityTopology >; - typedef Containers::Array< EntityType, Devices::Host, GlobalIndexType > StorageArrayType; - typedef Containers::SharedArray< EntityType, Devices::Host, GlobalIndexType > AccessArrayType; - typedef Containers::IndexedSet< EntityType, GlobalIndexType, Key > UniqueContainerType; - typedef Containers::IndexedSet< SeedType, GlobalIndexType, Key > SeedIndexedSetType; - typedef Containers::Array< SeedType, Devices::Host, GlobalIndexType > SeedArrayType; - typedef Containers::Array< ReferenceOrientationType, Devices::Host, GlobalIndexType > ReferenceOrientationArrayType; + using StorageArrayType = Containers::Array< EntityType, Device, GlobalIndexType >; + using SeedIndexedSetType = Containers::UnorderedIndexedSet< SeedType, GlobalIndexType, typename SeedType::HashType, typename SeedType::KeyEqual >; + using SeedSetType = std::unordered_set< typename SeedIndexedSetType::key_type, typename SeedIndexedSetType::hasher, typename SeedIndexedSetType::key_equal >; + using ReferenceOrientationArrayType = Containers::Array< ReferenceOrientationType, Device, GlobalIndexType >; - typedef Containers::tnlConstSharedArray< EntityType, Devices::Host, GlobalIndexType > SharedArrayType; + static constexpr bool storageEnabled = MeshConfig::entityStorage( Dimension ); + static constexpr bool orientationNeeded = MeshEntityOrientationNeeded< MeshConfig, DimensionTag< Dimension > >::value; }; } // namespace Meshes diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h index cbdd144932f6509f14082ea4d7981ba3e3ee47bf..6f44e834e4da3722351abf50f3c73cc73c4434c0 100644 --- a/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h +++ b/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h @@ -2,7 +2,7 @@ MeshSubentityTraits.h - description ------------------- begin : Feb 12, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -17,57 +17,65 @@ #pragma once #include <TNL/Containers/StaticArray.h> -#include <TNL/Containers/SharedArray.h> #include <TNL/Meshes/MeshEntity.h> -#include <TNL/Meshes/MeshConfigBase.h> -#include <TNL/Meshes/Topologies/MeshEntityTopology.h> +#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h> +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> +#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h> namespace TNL { namespace Meshes { -template< typename MeshConfig, typename EntityTopology > class MeshEntityOrientation; +template< typename MeshConfig, typename EntityTopology > +class MeshEntityOrientation; +template< typename MeshConfig, typename EntityTopology > +class EntitySeed; template< typename MeshConfig, + typename Device, typename EntityTopology, int Dimension > class MeshSubentityTraits { - public: - static const bool storageEnabled = MeshConfig::subentityStorage( EntityTopology(), Dimension ); - static const bool orientationEnabled = MeshConfig::subentityOrientationStorage( EntityTopology(), Dimension ); + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + using LocalIndexType = typename MeshConfig::LocalIndexType; - typedef typename MeshConfig::GlobalIndexType GlobalIndexType; - typedef typename MeshConfig::LocalIndexType LocalIndexType; - typedef MeshSubtopology< EntityTopology, Dimension > Subtopology; - typedef typename Subtopology::Topology SubentityTopology; - typedef MeshEntity< MeshConfig, SubentityTopology > SubentityType; - typedef MeshEntitySeed< MeshConfig, SubentityTopology > Seed; - typedef MeshEntityOrientation< MeshConfig, SubentityTopology > Orientation; +public: + static_assert( 0 <= Dimension && Dimension <= MeshConfig::meshDimension, "invalid dimension" ); + static_assert( EntityTopology::dimension > Dimension, "Subentity dimension must be smaller than the entity dimension." ); + static constexpr bool storageEnabled = MeshConfig::subentityStorage( EntityTopology(), Dimension ); + static constexpr bool orientationEnabled = MeshConfig::subentityOrientationStorage( EntityTopology(), Dimension ); + static constexpr int count = Topologies::Subtopology< EntityTopology, Dimension >::count; - static const int count = Subtopology::count; + using SubentityTopology = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityTopology; + using SubentityType = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityType; + using Seed = EntitySeed< MeshConfig, SubentityTopology >; + using Orientation = MeshEntityOrientation< MeshConfig, SubentityTopology >; - typedef Containers::StaticArray< count, GlobalIndexType > StorageArrayType; - typedef Containers::SharedArray< GlobalIndexType, - Devices::Host, - LocalIndexType > AccessArrayType; - typedef Containers::StaticArray< count, GlobalIndexType > IdArrayType; - typedef Containers::StaticArray< count, SubentityType > SubentityContainerType; - typedef Containers::StaticArray< count, Seed > SeedArrayType; - typedef Containers::StaticArray< count, Orientation > OrientationArrayType; - typedef Containers::StaticArray< count, LocalIndexType > IdPermutationArrayType; + /**** + * Type of container for storing of the subentities indices. + */ + // TODO: write general operator= for different SliceSize and remove the '32' here + using StorageNetworkType = StaticEllpackIndexMultimap< count, GlobalIndexType, Device, LocalIndexType, 32 >; + using SubentityAccessorType = typename StorageNetworkType::ValuesAccessorType; - template< LocalIndexType subentityIndex, - LocalIndexType subentityPointIndex > - struct Point - { - enum { index = tnlSubentityPoint< EntityTopology, - SubentityTopology, - subentityIndex, - subentityPointIndex>::index }; - }; + // static array used in MeshSubentitySeedCreator + using SeedArrayType = Containers::StaticArray< count, Seed >; - static_assert( EntityTopology::dimensions > Dimension, "You try to create subentities traits where subentity dimension are not smaller than the entity dimension." ); + // orientation and its accessor + using OrientationArrayType = Containers::StaticArray< count, Orientation >; + using IdPermutationArrayType = Containers::StaticArray< count, LocalIndexType >; + + template< LocalIndexType subentityIndex, + LocalIndexType subentityVertexIndex > + struct Vertex + { + static constexpr int index = Topologies::SubentityVertexMap< + EntityTopology, + SubentityTopology, + subentityIndex, + subentityVertexIndex >::index; + }; }; } // namespace Meshes diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h index b4e816399673a2a71ddcc46bac1e273923afdea8..efee12537b1d11bc32e099ea4b8b5930e68a7cb7 100644 --- a/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h +++ b/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h @@ -2,7 +2,7 @@ MeshSuperentityTraits.h - description ------------------- begin : Feb 13, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -16,58 +16,37 @@ #pragma once -#include <TNL/Containers/Array.h> -#include <TNL/Containers/ConstSharedArray.h> -#include <TNL/Containers/List.h> #include <TNL/Meshes/MeshEntity.h> -#include <TNL/Meshes/MeshConfigBase.h> -#include <TNL/Meshes/Topologies/MeshEntityTopology.h> #include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h> -#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h> -#include <TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h> +#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h> namespace TNL { namespace Meshes { template< typename MeshConfig, + typename Device, typename EntityTopology, int Dimension > class MeshSuperentityTraits { - public: - - typedef typename MeshConfig::GlobalIndexType GlobalIndexType; - typedef typename MeshConfig::LocalIndexType LocalIndexType; + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + using LocalIndexType = typename MeshConfig::LocalIndexType; +public: + static_assert( 0 <= Dimension && Dimension <= MeshConfig::meshDimension, "invalid dimension" ); + static_assert( EntityTopology::dimension < Dimension, "Superentity dimension must be higher than the entity dimension." ); - static const bool storageEnabled = MeshConfig::template superentityStorage< EntityTopology >( EntityTopology(), Dimension ); - //typedef tnlStorageTraits< storageEnabled > SuperentityStorageTag; - typedef MeshEntity< MeshConfig, EntityTopology > EntityType; - typedef MeshEntityTraits< MeshConfig, Dimension > EntityTraits; - typedef typename EntityTraits::EntityTopology SuperentityTopology; - typedef typename EntityTraits::EntityType SuperentityType; + static constexpr bool storageEnabled = MeshConfig::template superentityStorage< EntityTopology >( EntityTopology(), Dimension ); + using SuperentityTopology = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityTopology; + using SuperentityType = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityType; /**** - * Type of container for storing of the superentities indecis. + * Type of container for storing of the superentities indices. */ - typedef Containers::Array< GlobalIndexType, Devices::Host, LocalIndexType > StorageArrayType; - - typedef EllpackIndexMultimap< GlobalIndexType, Devices::Host > StorageNetworkType; - typedef MeshSuperentityAccessor< typename StorageNetworkType::ValuesAccessorType > SuperentityAccessorType; - - /**** - * Type for passing the superentities indecis by the getSuperentitiesIndices() - * method. We introduce it because of the compatibility with the subentities - * which are usually stored in static array. - */ - typedef Containers::SharedArray< GlobalIndexType, Devices::Host, LocalIndexType > AccessArrayType; - - /**** - * This is used by the mesh initializer. - */ - typedef Containers::List< GlobalIndexType > GrowableContainerType; - + // TODO: write general operator= for different SliceSize and remove the '32' here + using StorageNetworkType = EllpackIndexMultimap< GlobalIndexType, Device, LocalIndexType, 32 >; + using SuperentityAccessorType = typename StorageNetworkType::ValuesAccessorType; }; } // namespace Meshes diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h index 4cd115593b534804fd9815f466214388f6556cfa..545edbb23a2a0c8bdbb68f962adbd635ce24cec6 100644 --- a/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h +++ b/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h @@ -2,7 +2,7 @@ MeshTraits.h - description ------------------- begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -18,57 +18,49 @@ #include <TNL/Containers/StaticVector.h> #include <TNL/Containers/Array.h> -#include <TNL/Containers/SharedArray.h> -#include <TNL/Containers/ConstSharedArray.h> -#include <TNL/Meshes/MeshDimensionTag.h> +#include <TNL/Meshes/DimensionTag.h> +#include <TNL/Meshes/Topologies/Vertex.h> namespace TNL { namespace Meshes { -struct MeshVertexTopology; -template< typename MeshConfig, typename EntityTopology > class MeshEntity; -template< typename MeshConfig, typename EntityTopology > class MeshEntitySeed; -template< typename MeshConfig, int Dimension > class MeshEntityTraits; -template< typename MeshConfig, typename MeshEntity, int SubDimension > class MeshSubentityTraits; -template< typename MeshConfig, typename MeshEntity, int SuperDimension > class MeshSuperentityTraits; +template< typename MeshConfig, typename Device, typename EntityTopology > class MeshEntity; +template< typename MeshConfig, typename EntityTopology > class EntitySeed; +template< typename MeshConfig, typename Device, int Dimension > class MeshEntityTraits; +template< typename MeshConfig, typename Device, typename MeshEntity, int Subdimension > class MeshSubentityTraits; +template< typename MeshConfig, typename Device, typename MeshEntity, int Superdimension > class MeshSuperentityTraits; template< typename MeshConfig, typename Device = Devices::Host > class MeshTraits { - public: - - static const int meshDimension = MeshConfig::CellTopology::dimensions; - static const int worldDimension = MeshConfig::worldDimension; +public: + static constexpr int meshDimension = MeshConfig::CellTopology::dimension; + static constexpr int worldDimension = MeshConfig::worldDimension; - typedef Device DeviceType; - typedef typename MeshConfig::GlobalIndexType GlobalIndexType; - typedef typename MeshConfig::LocalIndexType LocalIndexType; - - typedef typename MeshConfig::CellTopology CellTopology; - typedef MeshEntity< MeshConfig, CellTopology > CellType; - typedef MeshEntity< MeshConfig, MeshVertexTopology > VertexType; - typedef Containers::StaticVector< worldDimension, typename MeshConfig::RealType > PointType; - typedef MeshEntitySeed< MeshConfig, CellTopology > CellSeedType; - - typedef Containers::Array< PointType, Devices::Host, GlobalIndexType > PointArrayType; - typedef Containers::Array< CellSeedType, Devices::Host, GlobalIndexType > CellSeedArrayType; - typedef Containers::Array< GlobalIndexType, Devices::Host, GlobalIndexType > GlobalIdArrayType; - typedef Containers::tnlConstSharedArray< GlobalIndexType, Devices::Host, LocalIndexType > IdArrayAccessorType; - typedef Containers::tnlConstSharedArray< LocalIndexType, Devices::Host, LocalIndexType > IdPermutationArrayAccessorType; - - template< int Dimension > using EntityTraits = - MeshEntityTraits< MeshConfig, Dimension >; - - template< typename EntityTopology, int SubDimension > using SubentityTraits = - MeshSubentityTraits< MeshConfig, EntityTopology, SubDimension >; - - template< typename EntityTopology, int SuperDimension > using SuperentityTraits = - MeshSuperentityTraits< MeshConfig, EntityTopology, SuperDimension >; - - - typedef MeshDimensionTag< meshDimension > DimensionTag; + using DeviceType = Device; + using GlobalIndexType = typename MeshConfig::GlobalIndexType; + using LocalIndexType = typename MeshConfig::LocalIndexType; + using CellTopology = typename MeshConfig::CellTopology; + using CellType = MeshEntity< MeshConfig, Device, CellTopology >; + using VertexType = MeshEntity< MeshConfig, Device, Topologies::Vertex >; + using PointType = Containers::StaticVector< worldDimension, typename MeshConfig::RealType >; + using CellSeedType = EntitySeed< MeshConfig, CellTopology >; + + using PointArrayType = Containers::Array< PointType, DeviceType, GlobalIndexType >; + using CellSeedArrayType = Containers::Array< CellSeedType, DeviceType, GlobalIndexType >; + + template< int Dimension > + using EntityTraits = MeshEntityTraits< MeshConfig, DeviceType, Dimension >; + + template< typename EntityTopology, int Subdimension > + using SubentityTraits = MeshSubentityTraits< MeshConfig, DeviceType, EntityTopology, Subdimension >; + + template< typename EntityTopology, int Superdimension > + using SuperentityTraits = MeshSuperentityTraits< MeshConfig, DeviceType, EntityTopology, Superdimension >; + + using DimensionTag = Meshes::DimensionTag< meshDimension >; }; } // namespace Meshes diff --git a/src/TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h b/src/TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h new file mode 100644 index 0000000000000000000000000000000000000000..154681fdd52d29376e26d940a7723e56ba99eddc --- /dev/null +++ b/src/TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h @@ -0,0 +1,83 @@ +/*************************************************************************** + MeshSuperentityStorageLayer.h - description + ------------------- + begin : Feb 13, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h> +#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h> + +namespace TNL { +namespace Meshes { + +template< typename MeshConfig, + typename Device, + typename DimensionTag, + bool sensible = (DimensionTag::value <= MeshConfig::meshDimension) > +struct WeakEntityStorageTrait +{ + static constexpr bool storageEnabled = MeshTraits< MeshConfig, Device >::template EntityTraits< DimensionTag::value >::storageEnabled; +}; + +template< typename MeshConfig, + typename Device, + typename DimensionTag > +struct WeakEntityStorageTrait< MeshConfig, Device, DimensionTag, false > +{ + static constexpr bool storageEnabled = false; +}; + + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SubdimensionTag, + bool sensible = (SubdimensionTag::value < EntityTopology::dimension) > +struct WeakSubentityStorageTrait +{ + static constexpr bool storageEnabled = MeshTraits< MeshConfig, Device >::template SubentityTraits< EntityTopology, SubdimensionTag::value >::storageEnabled; +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SubdimensionTag > +struct WeakSubentityStorageTrait< MeshConfig, Device, EntityTopology, SubdimensionTag, false > +{ + static constexpr bool storageEnabled = false; +}; + + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SuperdimensionTag, + bool sensible = (SuperdimensionTag::value > EntityTopology::dimension) > +struct WeakSuperentityStorageTrait +{ + static constexpr bool storageEnabled = MeshTraits< MeshConfig, Device >::template SuperentityTraits< EntityTopology, SuperdimensionTag::value >::storageEnabled; +}; + +template< typename MeshConfig, + typename Device, + typename EntityTopology, + typename SuperdimensionTag > +struct WeakSuperentityStorageTrait< MeshConfig, Device, EntityTopology, SuperdimensionTag, false > +{ + static constexpr bool storageEnabled = false; +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshEntity.h b/src/TNL/Meshes/MeshEntity.h index 0aedeb356d1074741efcc6ebaef1bb6a0334b261..7c97686808d3f670f51b0d0fdc9c9f3cd63a0049 100644 --- a/src/TNL/Meshes/MeshEntity.h +++ b/src/TNL/Meshes/MeshEntity.h @@ -17,50 +17,60 @@ #pragma once #include <TNL/File.h> -#include <TNL/Containers/DynamicTypeTag.h> -#include <TNL/Meshes/MeshDetails/MeshEntityId.h> #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h> -#include <TNL/Meshes/MeshDimensionTag.h> -#include <TNL/Meshes/Topologies/MeshVertexTopology.h> -#include <TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h> -#include <TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h> -#include <TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h> +#include <TNL/Meshes/Topologies/Vertex.h> +#include <TNL/Meshes/MeshDetails/MeshEntityIndex.h> +#include <TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h> +#include <TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h> namespace TNL { namespace Meshes { -template< typename MeshConfig > -class MeshInitializer; +template< typename MeshConfig, typename Device > class Mesh; +template< typename MeshConfig > class Initializer; +template< typename Mesh > class EntityStorageRebinder; +template< typename Mesh, int Dimension > struct IndexPermutationApplier; template< typename MeshConfig, + typename Device, typename EntityTopology_ > class MeshEntity - : public MeshSubentityStorageLayers< MeshConfig, EntityTopology_ >, - public MeshSuperentityAccess< MeshConfig, EntityTopology_ >, - public MeshEntityId< typename MeshConfig::IdType, - typename MeshConfig::GlobalIndexType > + : protected SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >, + protected SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >, + public MeshEntityIndex< typename MeshConfig::IdType > { + static_assert( std::is_same< EntityTopology_, typename MeshTraits< MeshConfig, Device >::template EntityTraits< EntityTopology_::dimension >::EntityTopology >::value, + "Specified entity topology is not compatible with the MeshConfig." ); + public: + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using DeviceType = Device; + using EntityTopology = EntityTopology_; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + + template< int Subdimension > + using SubentityTraits = typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimension >; + + template< int Superdimension > + using SuperentityTraits = typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >; + + // constructors + MeshEntity() = default; + + __cuda_callable__ + MeshEntity( const MeshEntity& entity ); + + template< typename Device_ > + MeshEntity( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity ); + + __cuda_callable__ + MeshEntity& operator=( const MeshEntity& entity ); + + template< typename Device_ > + __cuda_callable__ + MeshEntity& operator=( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity ); - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef EntityTopology_ EntityTopology; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::IdPermutationArrayAccessorType IdPermutationArrayAccessorType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - - template< int Subdimensions > using SubentityTraits = - typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimensions >; - - template< int SuperDimension > using SuperentityTraits = - typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperDimension >; - - MeshEntity( const SeedType& entitySeed ); - - MeshEntity(); - - ~MeshEntity(); static String getType(); @@ -72,170 +82,144 @@ class MeshEntity void print( std::ostream& str ) const; + __cuda_callable__ bool operator==( const MeshEntity& entity ) const; - - constexpr int getEntityDimension() const; + + __cuda_callable__ + bool operator!=( const MeshEntity& entity ) const; + + static constexpr int getEntityDimension(); /**** * Subentities */ - template< int Subdimensions > - constexpr bool subentitiesAvailable() const; - - template< int Subdimensions > - constexpr LocalIndexType getNumberOfSubentities() const; - - template< int Subdimensions > - GlobalIndexType getSubentityIndex( const LocalIndexType localIndex) const; - - template< int Subdimensions > - typename SubentityTraits< Subdimensions >::AccessArrayType& getSubentitiesIndices(); - - template< int Subdimensions > - const typename SubentityTraits< Subdimensions >::AccessArrayType& getSubentitiesIndices() const; + using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSubentitiesCount; + using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSubentityIndex; + using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSubentityOrientation; /**** * Superentities */ - template< int SuperDimension > - LocalIndexType getNumberOfSuperentities() const; - - template< int SuperDimension > - GlobalIndexType getSuperentityIndex( const LocalIndexType localIndex ) const; - - template< int SuperDimension > - typename SuperentityTraits< SuperDimension >::AccessArrayType& getSuperentitiesIndices(); - - template< int SuperDimension > - const typename SuperentityTraits< SuperDimension >::AccessArrayType& getSuperentitiesIndices() const; + using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSuperentitiesCount; + using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSuperentityIndex; /**** * Vertices */ - constexpr LocalIndexType getNumberOfVertices() const; + static constexpr LocalIndexType getVerticesCount(); GlobalIndexType getVertexIndex( const LocalIndexType localIndex ) const; - typename SubentityTraits< 0 >::AccessArrayType& getVerticesIndices(); - - const typename SubentityTraits< 0 >::AccessArrayType& getVerticesIndices() const; - - template< int Dimension > - IdPermutationArrayAccessorType subentityOrientation( LocalIndexType index ) const; - protected: - /**** * Methods for the mesh initialization */ - typedef MeshSuperentityAccess< MeshConfig, EntityTopology > SuperentityAccessBase; - typedef typename MeshTraitsType::IdArrayAccessorType IdArrayAccessorType; - typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology > SubentityStorageLayers; - - template< int Subdimensions > - void setSubentityIndex( const LocalIndexType localIndex, - const GlobalIndexType globalIndex ); - - template< int Subdimensions > - typename SubentityTraits< Subdimensions >::IdArrayType& subentityIdsArray(); - - template< int Superdimensions > - IdArrayAccessorType& superentityIdsArray(); - - template< int Subdimensions > - typename SubentityTraits< Subdimensions >::OrientationArrayType& subentityOrientationsArray(); - - friend MeshInitializer< MeshConfig >; - + using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::bindSubentitiesStorageNetwork; + using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::setSubentityIndex; + using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::subentityOrientationsArray; + + using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::bindSuperentitiesStorageNetwork; + using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::setNumberOfSuperentities; + using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::setSuperentityIndex; + + friend Initializer< MeshConfig >; + + friend EntityStorageRebinder< Mesh< MeshConfig, DeviceType > >; + + template< typename Mesh, int Dimension > + friend struct IndexPermutationApplier; }; /**** * Vertex entity specialization */ -template< typename MeshConfig > -class MeshEntity< MeshConfig, MeshVertexTopology > - : public MeshSuperentityAccess< MeshConfig, MeshVertexTopology >, - public MeshEntityId< typename MeshConfig::IdType, - typename MeshConfig::GlobalIndexType > +template< typename MeshConfig, typename Device > +class MeshEntity< MeshConfig, Device, Topologies::Vertex > + : protected SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >, + public MeshEntityIndex< typename MeshConfig::IdType > { public: + using MeshTraitsType = MeshTraits< MeshConfig, Device >; + using DeviceType = Device; + using EntityTopology = Topologies::Vertex; + using GlobalIndexType = typename MeshTraitsType::GlobalIndexType; + using LocalIndexType = typename MeshTraitsType::LocalIndexType; + using PointType = typename MeshTraitsType::PointType; + + template< int Superdimension > + using SuperentityTraits = typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >; + + // constructors + MeshEntity() = default; + + __cuda_callable__ + MeshEntity( const MeshEntity& entity ); + + template< typename Device_ > + MeshEntity( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity ); + + __cuda_callable__ + MeshEntity& operator=( const MeshEntity& entity ); + + template< typename Device_ > + __cuda_callable__ + MeshEntity& operator=( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity ); - typedef MeshTraits< MeshConfig > MeshTraitsType; - typedef MeshVertexTopology EntityTopology; - typedef typename MeshTraitsType::GlobalIndexType GlobalIndexType; - typedef typename MeshTraitsType::LocalIndexType LocalIndexType; - typedef typename MeshTraitsType::PointType PointType; - typedef typename MeshTraitsType::IdPermutationArrayAccessorType IdPermutationArrayAccessorType; - typedef MeshEntitySeed< MeshConfig, EntityTopology > SeedType; - - template< int SuperDimension > using SuperentityTraits = - typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperDimension >; static String getType(); String getTypeVirtual() const; - ~MeshEntity(); - bool save( File& file ) const; bool load( File& file ); void print( std::ostream& str ) const; + __cuda_callable__ bool operator==( const MeshEntity& entity ) const; - - constexpr int getEntityDimension() const; - - template< int Superdimensions > LocalIndexType getNumberOfSuperentities() const; - template< int Superdimensions > - typename SuperentityTraits< Superdimensions >::AccessArrayType& getSuperentitiesIndices(); + __cuda_callable__ + bool operator!=( const MeshEntity& entity ) const; - template< int Superdimensions > - const typename SuperentityTraits< Superdimensions >::AccessArrayType& getSuperentitiesIndeces() const; + static constexpr int getEntityDimension(); - template< int Dimension > - GlobalIndexType getSuperentityIndex( const LocalIndexType localIndex ) const; + /**** + * Superentities + */ + using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::getSuperentitiesCount; + using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::getSuperentityIndex; /**** * Points */ + __cuda_callable__ PointType getPoint() const; + __cuda_callable__ void setPoint( const PointType& point ); protected: - - typedef typename MeshTraitsType::IdArrayAccessorType IdArrayAccessorType; - typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology > SuperentityAccessBase; - - template< int Superdimensions > - IdArrayAccessorType& superentityIdsArray(); + using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::bindSuperentitiesStorageNetwork; + using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::setNumberOfSuperentities; + using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::setSuperentityIndex; PointType point; - - friend MeshInitializer< MeshConfig >; -}; -template< typename MeshConfig, - typename EntityTopology > -std::ostream& operator <<( std::ostream& str, const MeshEntity< MeshConfig, EntityTopology >& entity ); -} // namespace Meshes + friend Initializer< MeshConfig >; + + friend EntityStorageRebinder< Mesh< MeshConfig, DeviceType > >; + + template< typename Mesh, int Dimension > + friend struct IndexPermutationApplier; +}; -/**** - * This tells the compiler that theMeshEntity is a type with a dynamic memory allocation. - * It is necessary for the loading and the saving of the mesh entities arrays. - */ -namespace Containers{ template< typename MeshConfig, + typename Device, typename EntityTopology > -struct DynamicTypeTag< Meshes::MeshEntity< MeshConfig, EntityTopology > > -{ - enum { value = true }; -}; -} +std::ostream& operator<<( std::ostream& str, const MeshEntity< MeshConfig, Device, EntityTopology >& entity ); +} // namespace Meshes } // namespace TNL #include <TNL/Meshes/MeshDetails/MeshEntity_impl.h> diff --git a/src/TNL/Meshes/Readers/CMakeLists.txt b/src/TNL/Meshes/Readers/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5d46f5259dc41e2713eeca95adfdf8ec8f6d810d --- /dev/null +++ b/src/TNL/Meshes/Readers/CMakeLists.txt @@ -0,0 +1,7 @@ +SET( headers EntityShape.h + NetgenReader.h + TNLReader.h + VTKReader.h +) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Readers ) diff --git a/src/TNL/Meshes/Readers/EntityShape.h b/src/TNL/Meshes/Readers/EntityShape.h new file mode 100644 index 0000000000000000000000000000000000000000..c2c39eae53352568bd3f6d5208f5446eb6e85e57 --- /dev/null +++ b/src/TNL/Meshes/Readers/EntityShape.h @@ -0,0 +1,133 @@ +/*************************************************************************** + EntityShape.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <ostream> + +#include <TNL/Meshes/Topologies/Edge.h> +#include <TNL/Meshes/Topologies/Triangle.h> +#include <TNL/Meshes/Topologies/Quadrilateral.h> +#include <TNL/Meshes/Topologies/Tetrahedron.h> +#include <TNL/Meshes/Topologies/Hexahedron.h> + +namespace TNL { +namespace Meshes { +namespace Readers { + +/* + * Enumeration of entity shapes, inspired by the VTK library. + */ +enum class EntityShape +{ + Vertex = 1, + PolyVertex = 2, + Line = 3, + PolyLine = 4, + Triangle = 5, + TriangleStrip = 6, + Polygon = 7, + Pixel = 8, + Quad = 9, + Tetra = 10, + Voxel = 11, + Hexahedron = 12, + Wedge = 13, + Pyramid = 14 +}; + +inline std::ostream& operator<<( std::ostream& str, EntityShape shape ) +{ + switch( shape ) + { + case EntityShape::Vertex: + str << "Entity::Vertex"; + break; + case EntityShape::PolyVertex: + str << "Entity::PolyVertex"; + break; + case EntityShape::Line: + str << "Entity::Line"; + break; + case EntityShape::PolyLine: + str << "Entity::PolyLine"; + break; + case EntityShape::Triangle: + str << "Entity::Triangle"; + break; + case EntityShape::TriangleStrip: + str << "Entity::TriangleStrip"; + break; + case EntityShape::Polygon: + str << "Entity::Polygon"; + break; + case EntityShape::Pixel: + str << "Entity::Pixel"; + break; + case EntityShape::Quad: + str << "Entity::Quad"; + break; + case EntityShape::Tetra: + str << "Entity::Tetra"; + break; + case EntityShape::Voxel: + str << "Entity::Voxel"; + break; + case EntityShape::Hexahedron: + str << "Entity::Hexahedron"; + break; + case EntityShape::Wedge: + str << "Entity::Wedge"; + break; + case EntityShape::Pyramid: + str << "Entity::Pyramid"; + break; + default: + str << "<unknown entity>"; + } + return str; +} + +inline int getEntityDimension( EntityShape shape ) +{ + switch( shape ) + { + case EntityShape::Vertex: return 0; + case EntityShape::PolyVertex: return 0; + case EntityShape::Line: return 1; + case EntityShape::PolyLine: return 1; + case EntityShape::Triangle: return 2; + case EntityShape::TriangleStrip: return 2; + case EntityShape::Polygon: return 2; + case EntityShape::Pixel: return 2; + case EntityShape::Quad: return 2; + case EntityShape::Tetra: return 3; + case EntityShape::Voxel: return 3; + case EntityShape::Hexahedron: return 3; + case EntityShape::Wedge: return 3; + case EntityShape::Pyramid: return 3; + } + // this just avoids a compiler warning in GCC and nvcc (clang actually knows if the + // switch above covers all cases, and print a warning only when it does not) + throw 1; +} + +// static mapping of TNL entity topologies to EntityShape +template< typename Topology > struct TopologyToEntityShape {}; +template<> struct TopologyToEntityShape< Topologies::Vertex > { static constexpr EntityShape shape = EntityShape::Vertex; }; +template<> struct TopologyToEntityShape< Topologies::Edge > { static constexpr EntityShape shape = EntityShape::Line; }; +template<> struct TopologyToEntityShape< Topologies::Triangle > { static constexpr EntityShape shape = EntityShape::Triangle; }; +template<> struct TopologyToEntityShape< Topologies::Quadrilateral > { static constexpr EntityShape shape = EntityShape::Quad; }; +template<> struct TopologyToEntityShape< Topologies::Tetrahedron > { static constexpr EntityShape shape = EntityShape::Tetra; }; +template<> struct TopologyToEntityShape< Topologies::Hexahedron > { static constexpr EntityShape shape = EntityShape::Hexahedron; }; + +} // namespace Readers +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshReaderNetgen.h b/src/TNL/Meshes/Readers/NetgenReader.h similarity index 50% rename from src/TNL/Meshes/MeshDetails/MeshReaderNetgen.h rename to src/TNL/Meshes/Readers/NetgenReader.h index d3264a480aefc1bc82a42ae3affb08f95a73e517..a694280ac054735c7b9a87a9453b1bee0f97505f 100644 --- a/src/TNL/Meshes/MeshDetails/MeshReaderNetgen.h +++ b/src/TNL/Meshes/Readers/NetgenReader.h @@ -1,8 +1,8 @@ /*************************************************************************** - MeshReaderNetgen.h - description + NetgenReader.h - description ------------------- begin : Feb 19, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -21,20 +21,21 @@ #include <sstream> #include <TNL/Meshes/MeshBuilder.h> +#include <TNL/Meshes/Readers/EntityShape.h> namespace TNL { namespace Meshes { +namespace Readers { -class MeshReaderNetgen +class NetgenReader { - public: - - MeshReaderNetgen() - : dimensions( 0 ){} - +public: bool detectMesh( const String& fileName ) { - std::fstream inputFile( fileName.getString() ); + this->reset(); + this->fileName = fileName; + + std::ifstream inputFile( fileName.getString() ); if( ! inputFile ) { std::cerr << "I am not able to open the file " << fileName << "." << std::endl; @@ -69,12 +70,12 @@ class MeshReaderNetgen getline( inputFile, line ); iss.clear(); iss.str( line ); - this->dimensions = -1; + meshDimension = worldDimension = -1; while( iss ) { double aux; iss >> aux; - this->dimensions++; + meshDimension = ++worldDimension; } /**** @@ -113,28 +114,46 @@ class MeshReaderNetgen getline( inputFile, line ); iss.clear(); iss.str( line ); - this->verticesInCell = -2; + int verticesInCell = -2; while( iss ) { int aux; iss >> aux; - this->verticesInCell++; + verticesInCell++; + } + //cout << "There are " << verticesInCell << " vertices in cell ..." << std::endl; + + if( meshDimension == 1 && verticesInCell == 2 ) + cellShape = EntityShape::Line; + else if( meshDimension == 2 ) { + if( verticesInCell == 3 ) + cellShape = EntityShape::Triangle; + else if( verticesInCell == 4 ) + cellShape = EntityShape::Quad; + } + else if( meshDimension == 3 ) { + if( verticesInCell == 4 ) + cellShape = EntityShape::Tetra; + else if( verticesInCell == 8 ) + cellShape = EntityShape::Hexahedron; + } + if( cellShape == EntityShape::Vertex ) { + std::cerr << "Unknown cell topology: mesh dimension is " << meshDimension << ", number of vertices in cells is " << verticesInCell << "." << std::endl; + return false; } - //cout << "There are " << this->verticesInCell << " vertices in cell ..." << std::endl; + return true; } template< typename MeshType > - static bool readMesh( const String& fileName, - MeshType& mesh, - bool verbose ) + static bool readMesh( const String& fileName, MeshType& mesh ) { typedef typename MeshType::PointType PointType; typedef MeshBuilder< MeshType > MeshBuilder; - const int dimensions = PointType::size; + const int dimension = PointType::size; - std::fstream inputFile( fileName.getString() ); + std::ifstream inputFile( fileName.getString() ); if( ! inputFile ) { std::cerr << "I am not able to open the file " << fileName << "." << std::endl; @@ -157,14 +176,10 @@ class MeshReaderNetgen return false; getline( inputFile, line ); iss.str( line ); - typedef typename MeshType::MeshTraitsType::template EntityTraits< 0 >::GlobalIndexType VertexIndexType; + typedef typename MeshType::Config::GlobalIndexType VertexIndexType; VertexIndexType pointsCount; iss >> pointsCount; - if( ! meshBuilder.setPointsCount( pointsCount ) ) - { - std::cerr << "I am not able to allocate enough memory for " << pointsCount << " vertices." << std::endl; - return false; - } + meshBuilder.setPointsCount( pointsCount ); for( VertexIndexType i = 0; i < pointsCount; i++ ) { @@ -172,80 +187,117 @@ class MeshReaderNetgen iss.clear(); iss.str( line ); PointType p; - for( int d = 0; d < dimensions; d++ ) + for( int d = 0; d < dimension; d++ ) iss >> p[ d ]; //cout << "Setting point number " << i << " of " << pointsCount << std::endl; meshBuilder.setPoint( i, p ); - if( verbose ) - std::cout << pointsCount << " vertices expected ... " << i+1 << "/" << pointsCount << " \r" << std::flush; //const PointType& point = mesh.getVertex( i ).getPoint(); } - if( verbose ) - std::cout << std::endl; /**** * Skip white spaces */ - inputFile >> std::ws; + inputFile >> std::ws; /**** * Read number of cells */ - typedef typename MeshType::MeshTraitsType::template EntityTraits< dimensions >::GlobalIndexType CellIndexType; - if( ! inputFile ) - { - std::cerr << "I cannot read the mesh cells." << std::endl; - return false; - } - getline( inputFile, line ); - iss.clear(); - iss.str( line ); - CellIndexType numberOfCells=atoi( line.data() ); - //iss >> numberOfCells; // TODO: I do not know why this does not work - if( ! meshBuilder.setCellsCount( numberOfCells ) ) - { - std::cerr << "I am not able to allocate enough memory for " << numberOfCells << " cells." << std::endl; - return false; - } - for( CellIndexType i = 0; i < numberOfCells; i++ ) - { - getline( inputFile, line ); - iss.clear(); - iss.str( line ); - int subdomainIndex; - iss >> subdomainIndex; - //cout << "Setting cell number " << i << " of " << numberOfCells << std::endl; - typedef typename MeshBuilder::CellSeedType CellSeedType; - for( int cellVertex = 0; cellVertex < CellSeedType::getCornersCount(); cellVertex++ ) - { - VertexIndexType vertexIdx; - iss >> vertexIdx; - meshBuilder.getCellSeed( i ).setCornerId( cellVertex, vertexIdx - 1 ); - } - if( verbose ) - std::cout << numberOfCells << " cells expected ... " << i+1 << "/" << numberOfCells << " \r" << std::flush; - } - if( verbose ) - std::cout << std::endl; - meshBuilder.build( mesh ); - return true; + typedef typename MeshType::Config::GlobalIndexType CellIndexType; + if( ! inputFile ) + { + std::cerr << "I cannot read the mesh cells." << std::endl; + return false; + } + getline( inputFile, line ); + iss.clear(); + iss.str( line ); + CellIndexType numberOfCells = atoi( line.data() ); + //iss >> numberOfCells; // TODO: I do not know why this does not work + meshBuilder.setCellsCount( numberOfCells ); + for( CellIndexType i = 0; i < numberOfCells; i++ ) + { + getline( inputFile, line ); + iss.clear(); + iss.str( line ); + int subdomainIndex; + iss >> subdomainIndex; + //cout << "Setting cell number " << i << " of " << numberOfCells << std::endl; + typedef typename MeshBuilder::CellSeedType CellSeedType; + for( int cellVertex = 0; cellVertex < CellSeedType::getCornersCount(); cellVertex++ ) + { + VertexIndexType vertexIdx; + iss >> vertexIdx; + meshBuilder.getCellSeed( i ).setCornerId( cellVertex, vertexIdx - 1 ); + } + } + meshBuilder.build( mesh ); + return true; } - int getDimension() const + String + getMeshType() const { - return this->dimensions; + return "Meshes::Mesh"; } - - int getVerticesInCell() const + + int getMeshDimension() const { - return this->verticesInCell; + return this->meshDimension; } - protected: + int + getWorldDimension() const + { + return worldDimension; + } - int dimensions, verticesInCell; + EntityShape + getCellShape() const + { + return cellShape; + } + + String + getRealType() const + { + // not stored in the Netgen file + return "float"; + } + String + getGlobalIndexType() const + { + // not stored in the Netgen file + return "int"; + } + + String + getLocalIndexType() const + { + // not stored in the Netgen file + return "short int"; + } + + String + getIdType() const + { + // not stored in the Netgen file + return "int"; + } + +protected: + String fileName; + int meshDimension, worldDimension; + EntityShape cellShape = EntityShape::Vertex; + + void reset() + { + fileName = ""; + meshDimension = worldDimension = 0; + cellShape = EntityShape::Vertex; + } }; +} // namespace Readers } // namespace Meshes } // namespace TNL diff --git a/src/TNL/Meshes/Readers/TNLReader.h b/src/TNL/Meshes/Readers/TNLReader.h new file mode 100644 index 0000000000000000000000000000000000000000..ba602b0f97fda13115b171a46d9a3dd4d884c835 --- /dev/null +++ b/src/TNL/Meshes/Readers/TNLReader.h @@ -0,0 +1,178 @@ +/*************************************************************************** + TNL.h - description + ------------------- + begin : Nov 20, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/String.h> +#include <TNL/Object.h> +#include <TNL/Containers/List.h> +#include <TNL/Meshes/Readers/EntityShape.h> + +namespace TNL { +namespace Meshes { +namespace Readers { + +class TNLReader +{ +public: + bool + detectMesh( const String& fileName ) + { + this->reset(); + this->fileName = fileName; + + String objectType; + if( ! getObjectType( fileName, objectType ) ) { + std::cerr << "Failed to detect the mesh type from the file " << fileName << "." << std::endl; + return EXIT_FAILURE; + } + + Containers::List< String > parsedMeshType; + if( ! parseObjectType( objectType, parsedMeshType ) ) { + std::cerr << "Unable to parse the mesh type " << meshType << "." << std::endl; + return false; + } + + meshType = parsedMeshType[ 0 ]; + if( meshType == "Meshes::Grid" ) { + // save parts necessary to determine the mesh type + meshDimension = worldDimension = std::atoi( parsedMeshType[ 1 ].getString() ); + realType = parsedMeshType[ 2 ]; + globalIndexType = localIndexType = idType = parsedMeshType[ 4 ]; + // populate entity types (not necessary for GridTypeResolver, but while we're at it...) + if( meshDimension == 1 ) + cellShape = EntityShape::Line; + else if( meshDimension == 2 ) + cellShape = EntityShape::Quad; + else if( meshDimension == 3 ) + cellShape = EntityShape::Hexahedron; + } + else if( meshType == "Meshes::Mesh" ) { + Containers::List< String > parsedMeshConfig; + if( ! parseObjectType( parsedMeshType[ 1 ], parsedMeshConfig ) ) { + std::cerr << "Unable to parse the mesh config type " << parsedMeshType[ 1 ] << "." << std::endl; + return false; + } + if( parsedMeshConfig.getSize() != 7 ) { + std::cerr << "The parsed mesh config type has wrong size (expected 7 elements):" << std::endl + << parsedMeshConfig << std::endl; + return false; + } + + // save parts necessary to determine the mesh type + const String topology = parsedMeshConfig[ 1 ]; + worldDimension = std::atoi( parsedMeshConfig[ 2 ].getString() ); + realType = parsedMeshConfig[ 3 ]; + globalIndexType = parsedMeshConfig[ 4 ]; + localIndexType = parsedMeshConfig[ 5 ]; + idType = parsedMeshConfig[ 6 ]; + + if( topology == "MeshEdgeTopology" ) + cellShape = EntityShape::Line; + else if( topology == "MeshTriangleTopology" ) + cellShape = EntityShape::Triangle; + else if( topology == "MeshQuadrilateralTopology" ) + cellShape = EntityShape::Quad; + else if( topology == "MeshTetrahedronTopology" ) + cellShape = EntityShape::Tetra; + else if( topology == "MeshHexahedronTopology" ) + cellShape = EntityShape::Hexahedron; + else { + std::cerr << "Detected topology '" << topology << "' is not supported." << std::endl; + return false; + } + } + else { + std::cerr << "The mesh type " << meshType << " is not supported (yet)." << std::endl; + return false; + } + + return true; + } + + template< typename MeshType > + static bool + readMesh( const String& fileName, MeshType& mesh ) + { + return mesh.load( fileName ); + } + + String + getMeshType() const + { + return meshType; + } + + int + getMeshDimension() const + { + return meshDimension; + } + + int + getWorldDimension() const + { + return worldDimension; + } + + EntityShape + getCellShape() const + { + return cellShape; + } + + String + getRealType() const + { + return realType; + } + + String + getGlobalIndexType() const + { + return globalIndexType; + } + + String + getLocalIndexType() const + { + return localIndexType; + } + + String + getIdType() const + { + return idType; + } + +protected: + String fileName; + String meshType; + int meshDimension = 0; + int worldDimension = 0; + EntityShape cellShape = EntityShape::Vertex; + String realType; + String globalIndexType; + String localIndexType; + String idType; + + void reset() + { + fileName = ""; + meshType = ""; + meshDimension = worldDimension = 0; + cellShape = EntityShape::Vertex; + realType = localIndexType = globalIndexType = idType = ""; + } +}; + +} // namespace Readers +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Readers/VTKReader.h b/src/TNL/Meshes/Readers/VTKReader.h new file mode 100644 index 0000000000000000000000000000000000000000..7b52df0bc92401a1187c17feb0636a4cfe305789 --- /dev/null +++ b/src/TNL/Meshes/Readers/VTKReader.h @@ -0,0 +1,434 @@ +/*************************************************************************** + VTKReader.h - description + ------------------- + begin : Feb 25, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <fstream> +#include <sstream> +#include <map> +#include <vector> + +#include <TNL/Meshes/MeshBuilder.h> +#include <TNL/Meshes/Readers/EntityShape.h> + +namespace TNL { +namespace Meshes { +namespace Readers { + +class VTKReader +{ +public: + bool detectMesh( const String& fileName ) + { + this->reset(); + this->fileName = fileName; + + std::ifstream inputFile( fileName.getString() ); + if( ! inputFile ) { + std::cerr << "Failed to open the file " << fileName << "." << std::endl; + return false; + } + + if( ! parseHeader( inputFile ) ) + return false; + + if( dataset != "UNSTRUCTURED_GRID" ) { + std::cerr << "VTKReader: the dataset '" << dataset << "' is not supported." << std::endl; + return false; + } + + // TODO: implement binary parsing + if( dataType == "BINARY" ) { + std::cerr << "VTKReader: parsing of BINARY data is not implemented yet." << std::endl; + return false; + } + + std::string line, aux; + std::istringstream iss; + + // parse points section + if( ! findSection( inputFile, "POINTS" ) ) { + std::cerr << "VTKReader: unable to find the POINTS section, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + iss.clear(); + iss.str( line ); + iss >> aux; + long int numberOfVertices; + iss >> numberOfVertices; + iss >> realType; + + // read points + long int verticesRead = 0; + worldDimension = 0; + while( verticesRead < numberOfVertices ) { + if( ! inputFile ) { + std::cerr << "VTKReader: unable to read enough vertices, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + + // read the coordinates and compute the world dimension + iss.clear(); + iss.str( line ); + for( int i = 0; i < 3; i++ ) { + double aux; + iss >> aux; + if( ! iss ) { + std::cerr << "VTKReader: unable to read " << i << "th component of the vertex number " << verticesRead << "." << std::endl; + return false; + } + if( aux != 0.0 ) + worldDimension = std::max( worldDimension, i + 1 ); + } + + verticesRead++; + } + + // skip to the CELL_TYPES section + if( ! findSection( inputFile, "CELL_TYPES" ) ) { + std::cerr << "VTKReader: unable to find the CELL_TYPES section, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + iss.clear(); + iss.str( line ); + iss >> aux; + long int numberOfEntities; + iss >> numberOfEntities; + + // read entity types + long int entitiesRead = 0; + std::map< int, EntityShape > entityTypes; + while( entitiesRead < numberOfEntities ) { + if( ! inputFile ) { + std::cerr << "VTKReader: unable to read enough entity types, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + + // get entity type + int typeId; + iss.clear(); + iss.str( line ); + iss >> typeId; + const EntityShape type = (EntityShape) typeId; + const int dimension = getEntityDimension( type ); + + // check entity type + if( entityTypes.find( dimension ) == entityTypes.cend() ) + entityTypes.emplace( std::make_pair( dimension, type ) ); + else if( entityTypes[ dimension ] != type ) { + std::cerr << "Mixed unstructured meshes are not supported. There are elements of dimension " << dimension + << " with type " << entityTypes[ dimension ] << " and " << type << ". " + << "The type of all entities with the same dimension must be the same." << std::endl; + this->reset(); + return false; + } + + entitiesRead++; + } + + // set meshDimension and cellShape + meshDimension = 0; + for( auto it : entityTypes ) + if( it.first > meshDimension ) { + meshDimension = it.first; + cellShape = it.second; + } + + return true; + } + + template< typename MeshType > + bool readMesh( const String& fileName, MeshType& mesh ) + { + using MeshBuilder = MeshBuilder< MeshType >; + using IndexType = typename MeshType::GlobalIndexType; + using PointType = typename MeshType::PointType; + using CellSeedType = typename MeshBuilder::CellSeedType; + + const EntityShape cellType = TopologyToEntityShape< typename MeshType::template EntityTraits< MeshType::getMeshDimension() >::EntityTopology >::shape; + MeshBuilder meshBuilder; + + std::ifstream inputFile( fileName.getString() ); + if( ! inputFile ) { + std::cerr << "Failed to open the file " << fileName << "." << std::endl; + return false; + } + + if( ! parseHeader( inputFile ) ) + return false; + const auto positionAfterHeading = inputFile.tellg(); + + if( dataset != "UNSTRUCTURED_GRID" ) { + std::cerr << "VTKReader: the dataset '" << dataset << "' is not supported." << std::endl; + return false; + } + + // TODO: implement binary parsing + if( dataType == "BINARY" ) { + std::cerr << "VTKReader: parsing of BINARY data is not implemented yet." << std::endl; + return false; + } + + std::string line, aux; + std::istringstream iss; + + // parse the points section + if( ! findSection( inputFile, "POINTS" ) ) { + std::cerr << "VTKReader: unable to find the POINTS section, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + iss.clear(); + iss.str( line ); + iss >> aux; + IndexType numberOfVertices; + iss >> numberOfVertices; + + // allocate vertices + meshBuilder.setPointsCount( numberOfVertices ); + + // read points + for( IndexType vertexIndex = 0; vertexIndex < numberOfVertices; vertexIndex++ ) { + if( ! inputFile ) { + std::cerr << "VTKReader: unable to read enough vertices, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + + // read the coordinates + iss.clear(); + iss.str( line ); + PointType p; + for( int i = 0; i < p.size; i++ ) { + iss >> p[ i ]; + if( ! iss ) { + std::cerr << "VTKReader: unable to read " << i << "th component of the vertex number " << vertexIndex << "." << std::endl; + return false; + } + } + meshBuilder.setPoint( vertexIndex, p ); + } + + // find to the CELL_TYPES section + if( ! findSection( inputFile, "CELL_TYPES", positionAfterHeading ) ) { + std::cerr << "VTKReader: unable to find the CELL_TYPES section, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + iss.clear(); + iss.str( line ); + iss >> aux; + IndexType numberOfEntities; + iss >> numberOfEntities; + + // read entity types, count cells + std::vector< EntityShape > entityTypes; + entityTypes.resize( numberOfEntities ); + IndexType numberOfCells = 0; + for( IndexType entityIndex = 0; entityIndex < numberOfEntities; entityIndex++ ) { + if( ! inputFile ) { + std::cerr << "VTKReader: unable to read enough entity types, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + + // get entity type + int typeId; + iss.clear(); + iss.str( line ); + iss >> typeId; + entityTypes[ entityIndex ] = (EntityShape) typeId; + const int dimension = getEntityDimension( entityTypes[ entityIndex ] ); + if( dimension == MeshType::getMeshDimension() ) + numberOfCells++; + } + + meshBuilder.setCellsCount( numberOfCells ); + + // find to the CELLS section + if( ! findSection( inputFile, "CELLS", positionAfterHeading ) ) { + std::cerr << "VTKReader: unable to find the CELLS section, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + + // read cells + IndexType cellIndex = 0; + for( IndexType entityIndex = 0; entityIndex < numberOfEntities; entityIndex++ ) { + if( ! inputFile ) { + std::cerr << "VTKReader: unable to read enough entities, the file may be invalid or corrupted." << std::endl; + return false; + } + getline( inputFile, line ); + + if( entityTypes[ entityIndex ] == cellType ) { + iss.clear(); + iss.str( line ); + int vid; + iss >> vid; // ignore number of subvertices + CellSeedType& seed = meshBuilder.getCellSeed( cellIndex++ ); + for( int v = 0; v < CellSeedType::getCornersCount(); v++ ) { + iss >> vid; + if( ! iss ) + return false; + seed.setCornerId( v, vid ); + } + } + } + + // no cells found + if( cellIndex == 0 ) + return false; + + return meshBuilder.build( mesh ); + } + + String + getMeshType() const + { + return "Meshes::Mesh"; + } + + int getMeshDimension() const + { + return this->meshDimension; + } + + int + getWorldDimension() const + { + return worldDimension; + } + + EntityShape + getCellShape() const + { + return cellShape; + } + + String + getRealType() const + { + return realType.c_str(); + } + + String + getGlobalIndexType() const + { + // not stored in the VTK file + return "int"; + } + + String + getLocalIndexType() const + { + // not stored in the VTK file + return "short int"; + } + + String + getIdType() const + { + // not stored in the VTK file + return "int"; + } + +protected: + // output of parseHeader + std::string dataType; + std::string dataset; + + String fileName; + int meshDimension, worldDimension; + EntityShape cellShape = EntityShape::Vertex; + std::string realType; + + void reset() + { + fileName = ""; + meshDimension = worldDimension = 0; + cellShape = EntityShape::Vertex; + realType = ""; + } + + bool parseHeader( std::istream& str ) + { + std::string line; + std::istringstream iss; + + // check header + getline( str, line ); + if( line != "# vtk DataFile Version 2.0" ) { + std::cerr << "VTKReader: unsupported VTK header: '" << line << "'." << std::endl; + return false; + } + + // skip title + if( ! str ) + return false; + getline( str, line ); + + // parse data type + if( ! str ) + return false; + getline( str, dataType ); + if( dataType != "ASCII" && dataType != "BINARY" ) { + std::cerr << "VTKReader: unknown data type: '" << dataType << "'." << std::endl; + return false; + } + + // parse dataset + if( ! str ) + return false; + getline( str, line ); + iss.clear(); + iss.str( line ); + std::string tmp; + iss >> tmp; + if( tmp != "DATASET" ) { + std::cerr << "VTKReader: wrong dataset specification: '" << line << "'." << std::endl; + return false; + } + iss >> dataset; + + return true; + } + + bool findSection( std::istream& str, const std::string& section, std::ios::pos_type begin = -1 ) + { + std::string line, aux; + std::istringstream iss; + + if( begin >= 0 ) + str.seekg( begin ); + + while( str ) { + std::ios::pos_type currentPosition = str.tellg(); + getline( str, line ); + iss.clear(); + iss.str( line ); + iss >> aux; + if( aux == section ) { + str.seekg( currentPosition ); + return true; + } + } + + return false; + } +}; + +} // namespace Readers +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Readers/VTKReader_libvtk.h b/src/TNL/Meshes/Readers/VTKReader_libvtk.h new file mode 100644 index 0000000000000000000000000000000000000000..a8d317eaaa96e340ea63988ac5308ead358ece27 --- /dev/null +++ b/src/TNL/Meshes/Readers/VTKReader_libvtk.h @@ -0,0 +1,331 @@ +/*************************************************************************** + VTKReader_libvtk.h - description + ------------------- + begin : Nov 6, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <fstream> +#include <istream> +#include <vector> +#include <map> +#include <unordered_map> +#include <type_traits> + +#include <TNL/Containers/StaticVector.h> +#include <TNL/Meshes/MeshBuilder.h> +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> +#include <TNL/Meshes/Readers/EntityShape.h> + +#ifdef HAVE_VTK +#include <vtkSmartPointer.h> +#include <vtkCell.h> +#include <vtkUnstructuredGrid.h> +#include <vtkUnstructuredGridReader.h> +#endif + +namespace TNL { +namespace Meshes { +namespace Readers { + +// types used in VTK +using VTKRealType = double; +#ifdef HAVE_VTK +using VTKIndexType = vtkIdType; +#else +using VTKIndexType = int; +#endif +// wrapper type for physical coordinates to preserve my sanity +using VTKPointType = Containers::StaticVector< 3, VTKRealType >; + +template< typename Index = int > +class VTKReader_libvtk +{ +public: + using IndexType = Index; + + bool + detectMesh( const String& fileName ) + { + resetAll(); + if( ! loadVTKFile( fileName ) ) { + resetAll(); + return false; + } + reset(); + return true; + } + + template< typename MeshType > + bool + readMesh( const String& fileName, MeshType& mesh ) + { + static_assert( std::is_same< IndexType, typename MeshType::GlobalIndexType >::value, "VTKReader_libvtk::IndexType and MeshType::GlobalIndexType must be the same type." ); + + resetAll(); + if( ! loadVTKFile( fileName ) ) { + resetAll(); + return false; + } + + // GOTCHA: The unary "+" is a workaround due to odr-use of undefined static data member. See: + // https://stackoverflow.com/questions/39646958/constexpr-static-member-before-after-c17 + // https://stackoverflow.com/questions/272900/undefined-reference-to-static-class-member/272996#272996 + TNL_ASSERT_EQ( this->worldDimension, + MeshType::Config::worldDimension, "world dimensions do not match" ); + TNL_ASSERT_EQ( this->meshDimension, + MeshType::Config::meshDimension, "mesh dimensions do not match" ); + const int subvertices = Topologies::Subtopology< typename MeshType::Config::CellTopology, 0 >::count; + TNL_ASSERT_EQ( this->verticesInEntities.at( this->meshDimension ), subvertices, "numbers of cell subvertices do not match" ); + + using MeshBuilder = MeshBuilder< MeshType >; + using VertexIndexType = typename MeshType::MeshTraitsType::template EntityTraits< 0 >::GlobalIndexType; + using CellIndexType = typename MeshType::MeshTraitsType::template EntityTraits< MeshType::Config::meshDimension >::GlobalIndexType; + + const VertexIndexType numberOfPoints = this->pointsData.size(); + const CellIndexType numberOfCells = this->entityIdMappings.at( this->meshDimension ).size(); + + MeshBuilder meshBuilder; + meshBuilder.setPointsCount( numberOfPoints ); + meshBuilder.setCellsCount( numberOfCells ); + + for( VertexIndexType i = 0; i < numberOfPoints; i++ ) { + typename MeshType::PointType p; + for( int j = 0; j < p.size; j++ ) + p[ j ] = this->pointsData.at( i )[ j ]; + meshBuilder.setPoint( i, p ); + } + + const auto& cellIdMap = this->entityIdMappings.at( this->meshDimension ); + for( CellIndexType i = 0; i < numberOfCells; i++ ) { + const VTKIndexType vtkCellIndex = cellIdMap.at( i ); + const auto& vtkCellSeeds = this->entitySeeds.at( vtkCellIndex ); + using CellSeedType = typename MeshBuilder::CellSeedType; + TNL_ASSERT_EQ( CellSeedType::getCornersCount(), vtkCellSeeds.size(), "wrong number of subvertices" ); + CellSeedType& seed = meshBuilder.getCellSeed( i ); + for( int v = 0; v < CellSeedType::getCornersCount(); v++ ) { + seed.setCornerId( v, vtkCellSeeds[ v ] ); + } + } + + // drop all data from the VTK file since it's not needed anymore + this->resetAll(); + + return meshBuilder.build( mesh ); + } + + String + getMeshType() const + { + // we can read only the UNSTRUCTURED_GRID dataset + return "Meshes::Mesh"; + } + + int + getWorldDimension() const + { + return this->worldDimension; + } + + int + getMeshDimension() const + { + return this->meshDimension; + } + + EntityShape + getCellShape() const + { + return this->entityTypes.at( this->meshDimension ); + } + +// int +// getVerticesInCell() const +// { +// return this->verticesInEntities.at( this->getMeshDimension() ); +// } + +// EntityShape +// getEntityType( int entityDimension ) const +// { +// return this->entityTypes.at( entityDimension ); +// } + + String + getRealType() const + { + // TODO: how to extract it from the VTK object? +// return "float"; + return "double"; + } + + String + getGlobalIndexType() const + { + // not stored in the VTK file + return "int"; + } + + String + getLocalIndexType() const + { + // not stored in the VTK file + return "short int"; + } + + String + getIdType() const + { + // not stored in the VTK file + return "int"; + } + +protected: + int worldDimension = 0; + int meshDimension = 0; + + // maps vertex indices to physical coordinates + std::unordered_map< VTKIndexType, VTKPointType > pointsData; + + // maps entity dimension to the number of vertices in the entity + std::map< int, int > verticesInEntities; + + // type for mapping TNL entity indices to VTK cell indices + using TNL2VTKindexmap = std::unordered_map< IndexType, VTKIndexType >; + // maps dimension to maps of TNL entity IDs to corresponding VTK cell IDs + std::unordered_map< int, TNL2VTKindexmap > entityIdMappings; + + // maps VTK cell indices to entity seeds (set of indices of subvertices) + std::unordered_map< VTKIndexType, std::vector< VTKIndexType > > entitySeeds; + + // maps dimension to VTK type of the entity with given dimension + std::unordered_map< int, EntityShape > entityTypes; + + void reset() + { + pointsData.clear(); + verticesInEntities.clear(); + entityIdMappings.clear(); + entitySeeds.clear(); + } + + void resetAll() + { + reset(); + worldDimension = 0; + meshDimension = 0; + entityTypes.clear(); + } + + bool loadVTKFile( const String& fileName ) + { +#ifdef HAVE_VTK + vtkSmartPointer< vtkUnstructuredGridReader > vtkReader + = vtkSmartPointer<vtkUnstructuredGridReader>::New(); + vtkReader->SetFileName( fileName.getString() ); + vtkReader->Update(); + + if( ! vtkReader->IsFileUnstructuredGrid() ) { + std::cerr << "The file '" << fileName << "' is not a VTK Legacy file with an UNSTRUCTURED_GRID dataset type." << std::endl; + return false; + } + + auto& vtkMesh = *vtkReader->GetOutput(); + + /* To determine the mesh type, we need: + * - world dimension (default 1D, if some 2nd coordinate is non-zero -> 2D, some 3rd coordinate non-zero -> 3D) + * - mesh dimension (highest dimension of the entities present in mesh) + * - check that it is homogeneous - all entities of the same dimension should have the same number of vertices and type + * - types of entities for each dimension + * + * To initialize the mesh, we need: + * - points data (vertex indices and world coordinates) + * - cell seeds (indices of vertices composing each cell) + */ + const VTKIndexType numberOfPoints = vtkMesh.GetNumberOfPoints(); + const VTKIndexType numberOfCells = vtkMesh.GetNumberOfCells(); + + if( numberOfPoints == 0 ) { + std::cerr << "There are no points data in the file '" << fileName << "'." << std::endl; + return false; + } + + if( numberOfCells == 0 ) { + std::cerr << "There are no cells data in the file '" << fileName << "'." << std::endl; + return false; + } + + for( VTKIndexType i = 0; i < numberOfPoints; i++ ) { + VTKRealType* p = vtkMesh.GetPoint( i ); + + // get world dimension + for( int j = 0; j < 3; j++ ) + if( p[ j ] != 0.0 ) + this->worldDimension = std::max( this->worldDimension, j + 1 ); + + // copy points data + this->pointsData[ i ] = VTKPointType( p[ 0 ], p[ 1 ], p[ 2 ] ); + } + + for( VTKIndexType i = 0; i < numberOfCells; i++ ) { + vtkCell* cell = vtkMesh.GetCell( i ); + const int dimension = cell->GetCellDimension(); + const int points = cell->GetNumberOfPoints(); + const EntityShape type = (EntityShape) cell->GetCellType(); + + // number of vertices in entities + if( this->verticesInEntities.find( dimension ) == this->verticesInEntities.cend() ) + this->verticesInEntities[ dimension ] = points; + else if( this->verticesInEntities[ dimension ] != points ) { + std::cerr << "Mixed unstructured meshes are not supported. There are elements of dimension " << dimension + << " with " << this->verticesInEntities[ dimension ] << " vertices and with " << points + << " vertices. The number of vertices per entity must be constant." << std::endl; + this->reset(); + return false; + } + + // entity types + if( this->entityTypes.find( dimension ) == this->entityTypes.cend() ) + this->entityTypes.emplace( std::make_pair( dimension, type ) ); + else if( this->entityTypes[ dimension ] != type ) { + std::cerr << "Mixed unstructured meshes are not supported. There are elements of dimension " << dimension + << " with type " << this->entityTypes[ dimension ] << " and " << type + << ". The type of all entities with the same dimension must be the same." << std::endl; + this->reset(); + return false; + } + + // mapping between TNL and VTK indices + auto& map = this->entityIdMappings[ dimension ]; + map[ map.size() ] = i; + + // copy seed + auto& seed = this->entitySeeds[ i ]; + for( int j = 0; j < points; j++ ) + seed.push_back( cell->GetPointId( j ) ); + } + + // std::map is sorted, so the last key is the maximum + this->meshDimension = this->verticesInEntities.rbegin()->first; + + if( this->meshDimension > this->worldDimension ) { + std::cerr << "Invalid mesh: world dimension is " << this->worldDimension + << ", but mesh dimension is " << this->meshDimension << "." << std::endl; + this->reset(); + return false; + } + + return true; +#else + std::cerr << "The VTKReader_libvtk needs to be compiled with the VTK library." << std::endl; + return false; +#endif + } +}; + +} // namespace Readers +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/CMakeLists.txt b/src/TNL/Meshes/Topologies/CMakeLists.txt index 26d1753a352df8e6d3b363f456b4f42ed1f24aa5..797662306a257537a98fd9c756818be02e1923c6 100644 --- a/src/TNL/Meshes/Topologies/CMakeLists.txt +++ b/src/TNL/Meshes/Topologies/CMakeLists.txt @@ -1,9 +1,11 @@ -SET( headers MeshEdgeTopology.h - MeshEntityTopology.h - MeshHexahedronTopology.h - MeshQuadrilateralTopology.h - MeshTetrahedronTopology.h - MeshTriangleTopology.h - MeshVertexTopology.h ) +SET( headers Edge.h + Hexahedron.h + Quadrilateral.h + Simplex.h + SubentityVertexMap.h + Tetrahedron.h + Triangle.h + Vertex.h +) INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Topologies ) diff --git a/src/TNL/Meshes/Topologies/MeshEdgeTopology.h b/src/TNL/Meshes/Topologies/Edge.h similarity index 54% rename from src/TNL/Meshes/Topologies/MeshEdgeTopology.h rename to src/TNL/Meshes/Topologies/Edge.h index 34e8778baa434e444a50e01068d06812e44992d1..4c4b8269e51a7de9f709f28868b6fc09d517f757 100644 --- a/src/TNL/Meshes/Topologies/MeshEdgeTopology.h +++ b/src/TNL/Meshes/Topologies/Edge.h @@ -1,8 +1,8 @@ /*************************************************************************** - MeshEdgeTopology.h - description + Edge.h - description ------------------- begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -16,25 +16,32 @@ #pragma once -#include <TNL/Meshes/Topologies/MeshEntityTopology.h> -#include <TNL/Meshes/Topologies/MeshVertexTopology.h> +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> +#include <TNL/Meshes/Topologies/Vertex.h> namespace TNL { namespace Meshes { +namespace Topologies { -struct MeshEdgeTopology +struct Edge { - static const int dimensions = 1; + static constexpr int dimension = 1; + + static String getType() + { + return "Topologies::Edge"; + } }; template<> -struct MeshSubtopology< MeshEdgeTopology, 0 > +struct Subtopology< Edge, 0 > { - typedef MeshVertexTopology Topology; + typedef Vertex Topology; - static const int count = 2; + static constexpr int count = 2; }; +} // namespace Topologies } // namespace Meshes } // namespace TNL diff --git a/src/TNL/Meshes/Topologies/Hexahedron.h b/src/TNL/Meshes/Topologies/Hexahedron.h new file mode 100644 index 0000000000000000000000000000000000000000..db922f3b5bc487a7160e74c471597826e1461584 --- /dev/null +++ b/src/TNL/Meshes/Topologies/Hexahedron.h @@ -0,0 +1,185 @@ +/*************************************************************************** + Hexahedron.h - description + ------------------- + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/Topologies/Quadrilateral.h> + +namespace TNL { +namespace Meshes { +namespace Topologies { + +struct Hexahedron +{ + static constexpr int dimension = 3; + + static String getType() + { + return "Topologies::Hexahedron"; + } +}; + +template<> +struct Subtopology< Hexahedron, 0 > +{ + typedef Vertex Topology; + + static constexpr int count = 8; +}; + +template<> +struct Subtopology< Hexahedron, 1 > +{ + typedef Edge Topology; + + static constexpr int count = 12; +}; + +template<> +struct Subtopology< Hexahedron, 2 > +{ + typedef Quadrilateral Topology; + + static constexpr int count = 6; +}; + +/**** + * Indexing of the vertices follows the VTK file format + * + * 7+---------------------------+6 + * /| /| + * / | / | + * / | / | + * / | / | + * 4+---------------------------+5 | + * | | | | + * | | | | + * | 3+----------------------|----+2 + * | / | / + * | / | / + * | / | / + * |/ |/ + * 0+---------------------------+1 + * + * + * The edges are indexed as follows: + * + * +---------------------------+ + * /| 10 /| + * 11/ | / | + * / | /9 | + * / 7| / |6 + * +---------------------------+ | + * | | 8 | | + * | | | | + * | +----------------------|----+ + * 4| / 2 |5 / + * | 3/ | / + * | / | /1 + * |/ |/ + * +---------------------------+ + * 0 + * + * The faces are indexed as follows (the indexed are positioned to + * the opposite corners of given face): + * + * +---------------------------+ + * /|5 3/| + * /4| /2| + * / | / | + * / | 5 / | + * +---------------------------+ | + * |1 | | | + * | |3 | | + * | +----------------------|----+ + * | / | 0/ + * | / | / + * |4/ |2/ + * |/0 1|/ + * +---------------------------+ + * + */ + +template<> struct SubentityVertexMap< Hexahedron, Edge, 0, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 0, 1> { enum { index = 1 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 1, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 1, 1> { enum { index = 2 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 2, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 2, 1> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 3, 0> { enum { index = 3 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 3, 1> { enum { index = 0 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 4, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 4, 1> { enum { index = 4 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 5, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 5, 1> { enum { index = 5 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 6, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 6, 1> { enum { index = 6 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 7, 0> { enum { index = 3 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 7, 1> { enum { index = 7 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 8, 0> { enum { index = 4 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 8, 1> { enum { index = 5 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 9, 0> { enum { index = 5 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 9, 1> { enum { index = 6 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 10, 0> { enum { index = 6 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 10, 1> { enum { index = 7 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Edge, 11, 0> { enum { index = 7 }; }; +template<> struct SubentityVertexMap< Hexahedron, Edge, 11, 1> { enum { index = 4 }; }; + + +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 1> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 2> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 3> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 1> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 2> { enum { index = 5 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 3> { enum { index = 4 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 1> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 2> { enum { index = 6 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 3> { enum { index = 5 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 1> { enum { index = 3 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 2> { enum { index = 7 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 3> { enum { index = 6 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 0> { enum { index = 3 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 1> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 2> { enum { index = 4 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 3> { enum { index = 7 }; }; + +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 0> { enum { index = 4 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 1> { enum { index = 5 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 2> { enum { index = 6 }; }; +template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 3> { enum { index = 7 }; }; + +} // namespace Topologies +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/MeshEntityTopology.h b/src/TNL/Meshes/Topologies/MeshEntityTopology.h deleted file mode 100644 index 589bec5db38d2cc7a406b8abd3092251f8247628..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/Topologies/MeshEntityTopology.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - MeshEntityTopology.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -namespace TNL { -namespace Meshes{ - -template< typename MeshEntityTopology, - int SubentityDimension > -struct MeshSubtopology -{ -}; - -template< typename MeshEntityTopology, - typename SubentityTopology, - int SubentityIndex, - int SubentityVertexIndex > -struct tnlSubentityVertex; - - -template< typename MeshConfig, - int Dimension > -class MeshEntityTopology -{ - public: - - typedef typename MeshSubtopology< typename MeshConfig::CellTopology, - Dimension >::Topology Topology; -}; - -template< typename MeshConfig > -class MeshEntityTopology< MeshConfig, - MeshConfig::CellTopology::dimensions > -{ - public: - - typedef typename MeshConfig::CellTopology Topology; -}; - -} // namespace Meshes -} // namespace TNL \ No newline at end of file diff --git a/src/TNL/Meshes/Topologies/MeshHexahedronTopology.h b/src/TNL/Meshes/Topologies/MeshHexahedronTopology.h deleted file mode 100644 index 4dc1ff3acae2a5579885bf00963150d86cc52844..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/Topologies/MeshHexahedronTopology.h +++ /dev/null @@ -1,178 +0,0 @@ -/*************************************************************************** - MeshHexahedronTopology.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/Topologies/MeshQuadrilateralTopology.h> - -namespace TNL { -namespace Meshes { - -struct MeshHexahedronTopology -{ - static const int dimensions = 3; -}; - -template<> -struct MeshSubtopology< MeshHexahedronTopology, 0 > -{ - typedef MeshVertexTopology Topology; - - static const int count = 8; -}; - -template<> -struct MeshSubtopology< MeshHexahedronTopology, 1 > -{ - typedef MeshEdgeTopology Topology; - - static const int count = 12; -}; - -template<> -struct MeshSubtopology< MeshHexahedronTopology, 2 > -{ - typedef MeshQuadrilateralTopology Topology; - - static const int count = 6; -}; - -/**** - * Indexing of the vertices follows the VTK file format - * - * 7+---------------------------+6 - * /| /| - * / | / | - * / | / | - * / | / | - * 4+---------------------------+5 | - * | | | | - * | | | | - * | 3+----------------------|----+2 - * | / | / - * | / | / - * | / | / - * |/ |/ - * 0+---------------------------+1 - * - * - * The edges are indexed as follows: - * - * +---------------------------+ - * /| 10 /| - * 11/ | / | - * / | /9 | - * / 7| / |6 - * +---------------------------+ | - * | | 8 | | - * | | | | - * | +----------------------|----+ - * 4| / 2 |5 / - * | 3/ | / - * | / | /1 - * |/ |/ - * +---------------------------+ - * 0 - * - * The faces are indexed as follows (the indexed are positioned to - * the opposite corners of given face): - * - * +---------------------------+ - * /|5 3/| - * /4| /2| - * / | / | - * / | 5 / | - * +---------------------------+ | - * |1 | | | - * | |3 | | - * | +----------------------|----+ - * | / | 0/ - * | / | / - * |4/ |2/ - * |/0 1|/ - * +---------------------------+ - * - */ - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 0, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 0, 1> { enum { index = 1 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 1, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 1, 1> { enum { index = 2 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 2, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 2, 1> { enum { index = 3 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 3, 0> { enum { index = 3 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 3, 1> { enum { index = 0 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 4, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 4, 1> { enum { index = 4 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 5, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 5, 1> { enum { index = 5 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 6, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 6, 1> { enum { index = 6 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 7, 0> { enum { index = 3 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 7, 1> { enum { index = 7 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 8, 0> { enum { index = 4 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 8, 1> { enum { index = 5 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 9, 0> { enum { index = 5 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 9, 1> { enum { index = 6 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 10, 0> { enum { index = 6 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 10, 1> { enum { index = 7 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 11, 0> { enum { index = 7 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 11, 1> { enum { index = 4 }; }; - - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 1> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 2> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 3> { enum { index = 3 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 1> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 2> { enum { index = 5 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 3> { enum { index = 4 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 1> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 2> { enum { index = 6 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 3> { enum { index = 5 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 1> { enum { index = 3 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 2> { enum { index = 7 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 3> { enum { index = 6 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 0> { enum { index = 3 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 1> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 2> { enum { index = 4 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 3> { enum { index = 7 }; }; - -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 0> { enum { index = 4 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 1> { enum { index = 5 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 2> { enum { index = 6 }; }; -template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 3> { enum { index = 7 }; }; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/MeshQuadrilateralTopology.h b/src/TNL/Meshes/Topologies/MeshQuadrilateralTopology.h deleted file mode 100644 index 4dd844e4c9c0b3bd195c9f3387f8bbfa7d3557e2..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/Topologies/MeshQuadrilateralTopology.h +++ /dev/null @@ -1,87 +0,0 @@ -/*************************************************************************** - MeshQuadrilateralTopology.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/Topologies/MeshEdgeTopology.h> - -namespace TNL { -namespace Meshes { - -struct MeshQuadrilateralTopology -{ - static const int dimensions = 2; -}; - - -template<> -struct MeshSubtopology< MeshQuadrilateralTopology, 0 > -{ - typedef MeshVertexTopology Topology; - - static const int count = 4; -}; - -template<> -struct MeshSubtopology< MeshQuadrilateralTopology, 1 > -{ - typedef MeshEdgeTopology Topology; - - static const int count = 4; -}; - - -/**** - * Indexing of the vertices follows the VTK file format - * - * 3 2 - * +-------------------+ - * | | - * | | - * | | - * | | - * | | - * +-------------------+ - * 0 1 - * - * The edges are indexed as follows: - * - * 2 - * +-------------------+ - * | | - * | | - * 3 | | 1 - * | | - * | | - * +-------------------+ - * 0 - * - */ - -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 0, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 0, 1> { enum { index = 1 }; }; - -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 1, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 1, 1> { enum { index = 2 }; }; - -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 2, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 2, 1> { enum { index = 3 }; }; - -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 3, 0> { enum { index = 3 }; }; -template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 3, 1> { enum { index = 0 }; }; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/MeshSimplexTopology.h b/src/TNL/Meshes/Topologies/MeshSimplexTopology.h deleted file mode 100644 index 2120a71c7a120ab996e4b68777bcea99bfad5e22..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/Topologies/MeshSimplexTopology.h +++ /dev/null @@ -1,189 +0,0 @@ -/*************************************************************************** - MeshSimplexTopology.h - description - ------------------- - begin : Aug 29, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - - -#pragma once - -namespace TNL { -namespace Meshes { - -template< int dimensions_ > -class MeshSimplexTopology -{ - public: - static const int dimensions = dimensions_; -}; - -template< unsigned int n, unsigned int k > -class tnlStaticNumCombinations; - -template<unsigned int n, unsigned int k, unsigned int combinationIndex, unsigned int valueIndex> -class tnlCombinationValue; - -template< int dimensions, - int subtopologyDim > -class MeshSubtopology< MeshSimplexTopology< dimensions >, subtopologyDim > -{ - static_assert( 0 < subtopologyDim && subtopologyDim < dim, "invalid subtopology dimension" ); - - static const int topologyVertexCount = MeshSubtopology< MeshSimplexTopology< dimensions >, 0 >::count; - static const int subtopologyVertexCount = MeshSubtopology< MeshSimplexTopology< subtopologyDim >, 0>::count; - - public: - typedef MeshSimplexTopology< subtopologyDim > Topology; - - static const int count = tnlNumCombinations< topologyVertexCount, subtopologyVertexCount >::value; -}; - -template< int dimensions > -class MeshSubtopology< MeshSimplexTopology< dimensions >, 0 > -{ - static_assert(0 < dim, "invalid dimension"); - - public: - typedef MeshVertexTopology Topology; - - static const int count = dim + 1; -}; - - -template< int dimensions, - typename Subtopology, - int subtopologyIndex, - int vertexIndex > -struct tnlSubentityVertex< MeshSimplexTopology< dimensions >, Subtopology, subtopologyIndex, vertexIndex > -{ - private: - static const int subtopologyCount = Subtopology< MeshSimplexTopology< dimensions >, Subtopology::dimensions >::count; - static const int topologyVertexCount = Subtopology< MeshSimplex< dimensions >, 0 >::count; - static const int subtopologyVertexCount = Subtopology< Subtopology, 0 >::count; - - static_assert(1 < dimensions, "subtopology vertex can be specified for topologies of dimension 2 or higher"); - static_assert(0 <= subtopologyIndex && subtopologyIndex < subtopologyCount, "invalid subtopology index"); - static_assert(0 <= vertexIndex && vertexIndex < subtopologyVertexCount, "invalid subtopology vertex index"); - - public: - static const int index = CombinationValue< topologyVertexCount, subtopologyVertexCount, subtopologyIndex, vertexIndex>::value; -}; - -template< unsigned int n, unsigned int k > -class tnlStaticNumCombinations -{ - static_assert(0 < k && k < n, "invalid argument"); - - public: - static const unsigned int value = tnlNumCombinations< n - 1, k - 1 >::value + tnlNumCombinations< n - 1, k >::value; -}; - -// Nummber of combinations (n choose k) -template< unsigned int n > -class tnlNumCombinations< n, 0 > -{ - static_assert(0 <= n, "invalid argument"); - - public: - static const unsigned int value = 1; -}; - -template< unsigned int n > -class tnlNumCombinations< n, n > -{ - static_assert(0 < n, "invalid argument"); - - public: - static const unsigned int value = 1; -}; - -// Compile-time generation of combinations -// Combinations are generated in lexicographical order. The following example shows generation of 2-combinations from set {0, 1, 2}: -// 0, 1 <-> CombinationValue<3, 2, 0, 0>::VALUE, CombinationValue<3, 2, 0, 1>::VALUE -// 0, 2 <-> CombinationValue<3, 2, 1, 0>::VALUE, CombinationValue<3, 2, 1, 1>::VALUE -// 1, 2 <-> CombinationValue<3, 2, 2, 0>::VALUE, CombinationValue<3, 2, 2, 1>::VALUE -template< unsigned int n, - unsigned int k, - unsigned int combinationIndex > -class tnlCombinationIncrement; - -template< unsigned int n, - unsigned int k, - unsigned int combinationIndex, - unsigned int valueIndex > -class tnlCombinationValue -{ - static_assert( combinationIndex < NumCombinations< n, k >::value, "invalid combination index" ); - static_assert( valueIndex < k, "invalid value index" ); - - static const unsigned int incrementValueIndex = tnlCombinationIncrement< n, k, combinationIndex - 1>::valueIndex; - - public: - static const unsigned int value = ( valueIndex < incrementValueIndex ? tnlCombinationValue< n, k, combinationIndex - 1, valueIndex >::value : - tnlCombinationValue< n, k, combinationIndex - 1, incrementValueIndex >::value + - valueIndex - incrementValueIndex + 1); -}; - -template< unsigned int n, - unsigned int k, - unsigned int valueIndex > -class tnlCombinationValue< n, k, 0, valueIndex > -{ - static_assert( valueIndex < k, "invalid value index" ); - - static const unsigned int incrementValueIndex = tnlCombinationIncrement< n, k, 0 >::valueIndex; - - public: - static const unsigned int value = valueIndex; -}; - -// The CombinationIncrement class determines value index of the particular combination which will be incremented when generating the next combination -template< unsigned int n, - unsigned int k, - unsigned int combinationIndex, - unsigned int valueIndex > -class tnlCombinationIncrementImpl -{ - static_assert( combinationIndex < tnlNumCombinations< n, k >::value - 1, "nothing to increment" ); - - static const bool incrementPossible = ( tnlCombinationValue< n, k, combinationIndex, valueIndex >::value + k - valueIndex < n ); - - public: - static const int valueIndex = ( incrementPossible ? valueIndex : tnlCombinationIncrementImpl< n, k, combinationIndex, valueIndex - 1 >::valueIndex ); -}; - -template< unsigned int n, - unsigned int k, - unsigned int combinationIndex > -class tnlCombinationIncrementImpl< n, k, combinationIndex, 0 > -{ - static_assert( combinationIndex < tnlNumCombinations<n, k>::value - 1, "nothing to increment" ); - - public: - static const int valueIndex = 0; -}; - -template< unsigned int n, - unsigned int k, - unsigned int combinationIndex > -class tnlCombinationIncrement -{ - static_assert( combinationIndex < tnlNumCombinations< n, k >::value - 1, "nothing to increment" ); - - public: - static const unsigned int valueIndex = tnlCombinationIncrementImpl< n, k, combinationIndex, k - 1 >::valueIndex; -}; - -} // namespace Meshes -} // namespace TNL - diff --git a/src/TNL/Meshes/Topologies/MeshSubtopology.h b/src/TNL/Meshes/Topologies/MeshSubtopology.h deleted file mode 100644 index df9d813302025b4f6373f6ff4dc2f032b72a96ba..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/Topologies/MeshSubtopology.h +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************** - MeshSubtopology.h - description - ------------------- - begin : Aug 29, 2015 - copyright : (C) 2015 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -namespace TNL { -namespace Meshes { - -template< typename Topology, - int dimensions > -class MeshSubtopology; - -template< typename Topology, - typename Subtopology, - int subtopologyIndex, - int vertexIndex > -struct MeshSubtopologyVertex; - -} // namespace Meshes -} // namespace TNL - diff --git a/src/TNL/Meshes/Topologies/MeshTetrahedronTopology.h b/src/TNL/Meshes/Topologies/MeshTetrahedronTopology.h deleted file mode 100644 index 4f0067c255af28cf33d2dc4c5140053dbc8c8052..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/Topologies/MeshTetrahedronTopology.h +++ /dev/null @@ -1,90 +0,0 @@ -/*************************************************************************** - MeshTetrahedronTopology.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/Topologies/MeshTriangleTopology.h> - -namespace TNL { -namespace Meshes { - -struct MeshTetrahedronTopology -{ - static const int dimensions = 3; -}; - -template<> -struct MeshSubtopology< MeshTetrahedronTopology, 0 > -{ - typedef MeshVertexTopology Topology; - - static const int count = 4; -}; - -template<> -struct MeshSubtopology< MeshTetrahedronTopology, 1 > -{ - typedef MeshEdgeTopology Topology; - - static const int count = 6; -}; - -template<> -struct MeshSubtopology< MeshTetrahedronTopology, 2 > -{ - typedef MeshTriangleTopology Topology; - - static const int count = 4; -}; - - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 1> { enum { index = 2 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 1> { enum { index = 0 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 1> { enum { index = 1 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 1> { enum { index = 3 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 1> { enum { index = 3 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 1> { enum { index = 3 }; }; - - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 1> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 2> { enum { index = 2 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 1> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 2> { enum { index = 3 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 1> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 2> { enum { index = 3 }; }; - -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 1> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 2> { enum { index = 3 }; }; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/MeshTriangleTopology.h b/src/TNL/Meshes/Topologies/MeshTriangleTopology.h deleted file mode 100644 index 0305c4355cc289548bf8fe3381f9fd08c71b513a..0000000000000000000000000000000000000000 --- a/src/TNL/Meshes/Topologies/MeshTriangleTopology.h +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************** - MeshTriangleTopology.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -/*** - * Authors: - * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz - * Zabka Vitezslav, zabkav@gmail.com - */ - -#pragma once - -#include <TNL/Meshes/Topologies/MeshEdgeTopology.h> - -namespace TNL { -namespace Meshes { - -struct MeshTriangleTopology -{ - static const int dimensions = 2; -}; - - -template<> -struct MeshSubtopology< MeshTriangleTopology, 0 > -{ - typedef MeshVertexTopology Topology; - - static const int count = 3; -}; - -template<> -struct MeshSubtopology< MeshTriangleTopology, 1 > -{ - typedef MeshEdgeTopology Topology; - - static const int count = 3; -}; - - -template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 0> { enum { index = 1 }; }; -template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 1> { enum { index = 2 }; }; - -template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 0> { enum { index = 2 }; }; -template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 1> { enum { index = 0 }; }; - -template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 0> { enum { index = 0 }; }; -template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 1> { enum { index = 1 }; }; - -} // namespace Meshes -} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/Quadrilateral.h b/src/TNL/Meshes/Topologies/Quadrilateral.h new file mode 100644 index 0000000000000000000000000000000000000000..6b5d4eb54b68f01f6fef9932cd66c3c897d1d72d --- /dev/null +++ b/src/TNL/Meshes/Topologies/Quadrilateral.h @@ -0,0 +1,94 @@ +/*************************************************************************** + Quadrilateral.h - description + ------------------- + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/Topologies/Edge.h> + +namespace TNL { +namespace Meshes { +namespace Topologies { + +struct Quadrilateral +{ + static constexpr int dimension = 2; + + static String getType() + { + return "Topologies::Quadrilateral"; + } +}; + + +template<> +struct Subtopology< Quadrilateral, 0 > +{ + typedef Vertex Topology; + + static constexpr int count = 4; +}; + +template<> +struct Subtopology< Quadrilateral, 1 > +{ + typedef Edge Topology; + + static constexpr int count = 4; +}; + + +/**** + * Indexing of the vertices follows the VTK file format + * + * 3 2 + * +-------------------+ + * | | + * | | + * | | + * | | + * | | + * +-------------------+ + * 0 1 + * + * The edges are indexed as follows: + * + * 2 + * +-------------------+ + * | | + * | | + * 3 | | 1 + * | | + * | | + * +-------------------+ + * 0 + * + */ + +template<> struct SubentityVertexMap< Quadrilateral, Edge, 0, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Quadrilateral, Edge, 0, 1> { enum { index = 1 }; }; + +template<> struct SubentityVertexMap< Quadrilateral, Edge, 1, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Quadrilateral, Edge, 1, 1> { enum { index = 2 }; }; + +template<> struct SubentityVertexMap< Quadrilateral, Edge, 2, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Quadrilateral, Edge, 2, 1> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Quadrilateral, Edge, 3, 0> { enum { index = 3 }; }; +template<> struct SubentityVertexMap< Quadrilateral, Edge, 3, 1> { enum { index = 0 }; }; + +} // namespace Topologies +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/Simplex.h b/src/TNL/Meshes/Topologies/Simplex.h new file mode 100644 index 0000000000000000000000000000000000000000..bbdf39b27c73f46f91064df1590dfd7f1c86efd0 --- /dev/null +++ b/src/TNL/Meshes/Topologies/Simplex.h @@ -0,0 +1,205 @@ +/*************************************************************************** + Simplex.h - description + ------------------- + begin : Aug 29, 2015 + copyright : (C) 2015 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + + +#pragma once + +#include <TNL/Meshes/Topologies/SubentityVertexMap.h> +#include <TNL/Meshes/Topologies/Vertex.h> + +namespace TNL { +namespace Meshes { +namespace Topologies { + +template< int dimension_ > +class Simplex +{ + public: + static constexpr int dimension = dimension_; + + static String getType() + { + return String( "Topologies::Simplex< " ) + String( dimension ) + " >"; + } +}; + +namespace SimplexDetails { + template< unsigned int n, unsigned int k > + class NumCombinations; + + template<unsigned int n, unsigned int k, unsigned int combinationIndex, unsigned int valueIndex> + class CombinationValue; +} + +template< int dimension, + int subtopologyDim > +class Subtopology< Simplex< dimension >, subtopologyDim > +{ + static_assert( 0 < subtopologyDim && subtopologyDim < dimension, "invalid subtopology dimension" ); + + static constexpr int topologyVertexCount = Subtopology< Simplex< dimension >, 0 >::count; + static constexpr int subtopologyVertexCount = Subtopology< Simplex< subtopologyDim >, 0>::count; + + public: + typedef Simplex< subtopologyDim > Topology; + + static constexpr int count = SimplexDetails::NumCombinations< topologyVertexCount, subtopologyVertexCount >::value; +}; + +template< int dimension > +class Subtopology< Simplex< dimension >, 0 > +{ + static_assert(0 < dimension, "invalid dimension"); + + public: + typedef Vertex Topology; + + static constexpr int count = dimension + 1; +}; + + +template< int dimension, + typename Subtopology, + int subtopologyIndex, + int vertexIndex > +struct SubentityVertexMap< Simplex< dimension >, Subtopology, subtopologyIndex, vertexIndex > +{ + private: + static constexpr int subtopologyCount = Topologies::Subtopology< Simplex< dimension >, Subtopology::dimension >::count; + static constexpr int topologyVertexCount = Topologies::Subtopology< Simplex< dimension >, 0 >::count; + static constexpr int subtopologyVertexCount = Topologies::Subtopology< Subtopology, 0 >::count; + + static_assert(1 < dimension, "subtopology vertex can be specified for topologies of dimension 2 or higher"); + static_assert(0 <= subtopologyIndex && subtopologyIndex < subtopologyCount, "invalid subtopology index"); + static_assert(0 <= vertexIndex && vertexIndex < subtopologyVertexCount, "invalid subtopology vertex index"); + + public: + static constexpr int index = SimplexDetails::CombinationValue< topologyVertexCount, subtopologyVertexCount, subtopologyIndex, vertexIndex>::value; +}; + +template< unsigned int n, unsigned int k > +class NumCombinations +{ + static_assert(0 < k && k < n, "invalid argument"); + + public: + static const unsigned int value = NumCombinations< n - 1, k - 1 >::value + NumCombinations< n - 1, k >::value; +}; + + +namespace SimplexDetails { + +// Nummber of combinations (n choose k) +template< unsigned int n > +class NumCombinations< n, 0 > +{ + static_assert(0 <= n, "invalid argument"); + + public: + static const unsigned int value = 1; +}; + +template< unsigned int n > +class NumCombinations< n, n > +{ + static_assert(0 < n, "invalid argument"); + + public: + static const unsigned int value = 1; +}; + +// Compile-time generation of combinations +// Combinations are generated in lexicographical order. The following example shows generation of 2-combinations from set {0, 1, 2}: +// 0, 1 <-> CombinationValue<3, 2, 0, 0>::VALUE, CombinationValue<3, 2, 0, 1>::VALUE +// 0, 2 <-> CombinationValue<3, 2, 1, 0>::VALUE, CombinationValue<3, 2, 1, 1>::VALUE +// 1, 2 <-> CombinationValue<3, 2, 2, 0>::VALUE, CombinationValue<3, 2, 2, 1>::VALUE +template< unsigned int n, + unsigned int k, + unsigned int combinationIndex > +class CombinationIncrement; + +template< unsigned int n, + unsigned int k, + unsigned int combinationIndex, + unsigned int valueIndex > +class CombinationValue +{ + static_assert( combinationIndex < NumCombinations< n, k >::value, "invalid combination index" ); + static_assert( valueIndex < k, "invalid value index" ); + + static const unsigned int incrementValueIndex = CombinationIncrement< n, k, combinationIndex - 1>::valueIndex; + + public: + static const unsigned int value = ( valueIndex < incrementValueIndex ? CombinationValue< n, k, combinationIndex - 1, valueIndex >::value : + CombinationValue< n, k, combinationIndex - 1, incrementValueIndex >::value + + valueIndex - incrementValueIndex + 1); +}; + +template< unsigned int n, + unsigned int k, + unsigned int valueIndex > +class CombinationValue< n, k, 0, valueIndex > +{ + static_assert( valueIndex < k, "invalid value index" ); + + static const unsigned int incrementValueIndex = CombinationIncrement< n, k, 0 >::valueIndex; + + public: + static const unsigned int value = valueIndex; +}; + +// The CombinationIncrement class determines value index of the particular combination which will be incremented when generating the next combination +template< unsigned int n, + unsigned int k, + unsigned int combinationIndex, + unsigned int valueIndex_ > +class CombinationIncrementImpl +{ + static_assert( combinationIndex < NumCombinations< n, k >::value - 1, "nothing to increment" ); + + static const bool incrementPossible = ( CombinationValue< n, k, combinationIndex, valueIndex_ >::value + k - valueIndex_ < n ); + + public: + static constexpr int valueIndex = ( incrementPossible ? valueIndex_ : CombinationIncrementImpl< n, k, combinationIndex, valueIndex_ - 1 >::valueIndex ); +}; + +template< unsigned int n, + unsigned int k, + unsigned int combinationIndex > +class CombinationIncrementImpl< n, k, combinationIndex, 0 > +{ + static_assert( combinationIndex < NumCombinations<n, k>::value - 1, "nothing to increment" ); + + public: + static constexpr int valueIndex = 0; +}; + +template< unsigned int n, + unsigned int k, + unsigned int combinationIndex > +class CombinationIncrement +{ + static_assert( combinationIndex < NumCombinations< n, k >::value - 1, "nothing to increment" ); + + public: + static const unsigned int valueIndex = CombinationIncrementImpl< n, k, combinationIndex, k - 1 >::valueIndex; +}; + +} // namespace SimplexDetails + +} // namespace Topologies +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityIntegrityChecker.h b/src/TNL/Meshes/Topologies/SubentityVertexMap.h similarity index 50% rename from src/TNL/Meshes/MeshDetails/MeshEntityIntegrityChecker.h rename to src/TNL/Meshes/Topologies/SubentityVertexMap.h index 2eabfa69e9e72a2b9e3a96aa4c8a3d11d87eaa19..89b5fb57e002f33ab897034927c79889ec1105c5 100644 --- a/src/TNL/Meshes/MeshDetails/MeshEntityIntegrityChecker.h +++ b/src/TNL/Meshes/Topologies/SubentityVertexMap.h @@ -1,8 +1,8 @@ /*************************************************************************** - MeshEntityIntegrityChecker.h - description + SubentityVertexMap.h - description ------------------- - begin : Mar 20, 2014 - copyright : (C) 2014 by Tomas Oberhuber + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -17,19 +17,23 @@ #pragma once namespace TNL { -namespace Meshes { +namespace Meshes{ +namespace Topologies { -template< typename MeshEntity > -class MeshEntityIntegrityChecker +template< typename EntityTopology, + int SubentityDimension > +struct Subtopology { - public: - - static bool checkEntity( const MeshEntity& entity ) - { - return true; - } +}; +template< typename EntityTopology, + typename SubentityTopology, + int SubentityIndex, + int SubentityVertexIndex > +struct SubentityVertexMap +{ }; +} // namespace Topologies } // namespace Meshes } // namespace TNL diff --git a/src/TNL/Meshes/Topologies/Tetrahedron.h b/src/TNL/Meshes/Topologies/Tetrahedron.h new file mode 100644 index 0000000000000000000000000000000000000000..7722f5ef688ad41cd3b594e8ec3a5484aae17b9e --- /dev/null +++ b/src/TNL/Meshes/Topologies/Tetrahedron.h @@ -0,0 +1,98 @@ +/*************************************************************************** + Tetrahedron.h - description + ------------------- + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/Topologies/Triangle.h> + +namespace TNL { +namespace Meshes { +namespace Topologies { + +struct Tetrahedron +{ + static constexpr int dimension = 3; + + static String getType() + { + return "Topologies::Tetrahedron"; + } +}; + +template<> +struct Subtopology< Tetrahedron, 0 > +{ + typedef Vertex Topology; + + static constexpr int count = 4; +}; + +template<> +struct Subtopology< Tetrahedron, 1 > +{ + typedef Edge Topology; + + static constexpr int count = 6; +}; + +template<> +struct Subtopology< Tetrahedron, 2 > +{ + typedef Triangle Topology; + + static constexpr int count = 4; +}; + + +template<> struct SubentityVertexMap< Tetrahedron, Edge, 0, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Edge, 0, 1> { enum { index = 2 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Edge, 1, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Edge, 1, 1> { enum { index = 0 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Edge, 2, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Edge, 2, 1> { enum { index = 1 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Edge, 3, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Edge, 3, 1> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Edge, 4, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Edge, 4, 1> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Edge, 5, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Edge, 5, 1> { enum { index = 3 }; }; + + +// i-th subvertex is the opposite vertex of i-th subface +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 1> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 2> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 1> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 2> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 1> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 2> { enum { index = 3 }; }; + +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 1> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 2> { enum { index = 2 }; }; + +} // namespace Topologies +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/Triangle.h b/src/TNL/Meshes/Topologies/Triangle.h new file mode 100644 index 0000000000000000000000000000000000000000..11d1c8a846c360f22d46fb676f411146d33662bd --- /dev/null +++ b/src/TNL/Meshes/Topologies/Triangle.h @@ -0,0 +1,64 @@ +/*************************************************************************** + Triangle.h - description + ------------------- + begin : Feb 11, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <TNL/Meshes/Topologies/Edge.h> + +namespace TNL { +namespace Meshes { +namespace Topologies { + +struct Triangle +{ + static constexpr int dimension = 2; + + static String getType() + { + return "Topologies::Triangle"; + } +}; + + +template<> +struct Subtopology< Triangle, 0 > +{ + typedef Vertex Topology; + + static constexpr int count = 3; +}; + +template<> +struct Subtopology< Triangle, 1 > +{ + typedef Edge Topology; + + static constexpr int count = 3; +}; + + +template<> struct SubentityVertexMap< Triangle, Edge, 0, 0> { enum { index = 1 }; }; +template<> struct SubentityVertexMap< Triangle, Edge, 0, 1> { enum { index = 2 }; }; + +template<> struct SubentityVertexMap< Triangle, Edge, 1, 0> { enum { index = 2 }; }; +template<> struct SubentityVertexMap< Triangle, Edge, 1, 1> { enum { index = 0 }; }; + +template<> struct SubentityVertexMap< Triangle, Edge, 2, 0> { enum { index = 0 }; }; +template<> struct SubentityVertexMap< Triangle, Edge, 2, 1> { enum { index = 1 }; }; + +} // namespace Topologies +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Topologies/MeshVertexTopology.h b/src/TNL/Meshes/Topologies/Vertex.h similarity index 63% rename from src/TNL/Meshes/Topologies/MeshVertexTopology.h rename to src/TNL/Meshes/Topologies/Vertex.h index 5c70978f74687cf8999dd91b1ae811d1e8db9410..cff78e37d6e64f3798791e26510864aaed44955c 100644 --- a/src/TNL/Meshes/Topologies/MeshVertexTopology.h +++ b/src/TNL/Meshes/Topologies/Vertex.h @@ -1,8 +1,8 @@ /*************************************************************************** - MeshVertexTopology.h - description + Vertex.h - description ------------------- begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -16,13 +16,22 @@ #pragma once +#include <TNL/String.h> + namespace TNL { namespace Meshes { +namespace Topologies { -struct MeshVertexTopology +struct Vertex { - static const int dimensions = 0; + static constexpr int dimension = 0; + + static String getType() + { + return "Topologies::Vertex"; + } }; +} // namespace Topologies } // namespace Meshes } // namespace TNL diff --git a/src/TNL/Meshes/Traverser.h b/src/TNL/Meshes/Traverser.h index c9c647cd7314d800c4a56739945284530945b575..ce0e0bf99d818b696c94ed8791dad5717dcb3cde 100644 --- a/src/TNL/Meshes/Traverser.h +++ b/src/TNL/Meshes/Traverser.h @@ -2,7 +2,7 @@ Traverser.h - description ------------------- begin : Jul 28, 2014 - copyright : (C) 2014 by Tomas Oberhuber + copyright : (C) 2014 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,17 +10,68 @@ #pragma once +#include <TNL/SharedPointer.h> +#include <TNL/Meshes/Mesh.h> + namespace TNL { namespace Meshes { template< typename Mesh, typename MeshEntity, int EntitiesDimension = MeshEntity::getEntityDimension() > -class Traverser{}; +class Traverser +{ + public: + using MeshType = Mesh; + using MeshPointer = SharedPointer< MeshType >; + using DeviceType = typename MeshType::DeviceType; + + template< typename UserData, + typename EntitiesProcessor > + void processBoundaryEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const; + + template< typename UserData, + typename EntitiesProcessor > + void processInteriorEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const; + + template< typename UserData, + typename EntitiesProcessor > + void processAllEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const; +}; + +template< typename MeshConfig, + typename MeshEntity, + int EntitiesDimension > +class Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension > +{ + public: + using MeshType = Mesh< MeshConfig, Devices::Cuda >; + using MeshPointer = SharedPointer< MeshType >; + using DeviceType = typename MeshType::DeviceType; + + template< typename UserData, + typename EntitiesProcessor > + void processBoundaryEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const; + + template< typename UserData, + typename EntitiesProcessor > + void processInteriorEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const; + + template< typename UserData, + typename EntitiesProcessor > + void processAllEntities( const MeshPointer& meshPointer, + SharedPointer< UserData, DeviceType >& userDataPointer ) const; +}; } // namespace Meshes } // namespace TNL +#include <TNL/Meshes/MeshDetails/Traverser_impl.h> #include <TNL/Meshes/GridDetails/Traverser_Grid1D.h> #include <TNL/Meshes/GridDetails/Traverser_Grid2D.h> #include <TNL/Meshes/GridDetails/Traverser_Grid3D.h> diff --git a/src/TNL/Meshes/TypeResolver/CMakeLists.txt b/src/TNL/Meshes/TypeResolver/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..83c105cd54b89b17e8cecd0a29b030e14fa820b6 --- /dev/null +++ b/src/TNL/Meshes/TypeResolver/CMakeLists.txt @@ -0,0 +1,9 @@ +SET( headers GridTypeResolver.h + GridTypeResolver_impl.h + MeshTypeResolver.h + MeshTypeResolver_impl.h + TypeResolver.h + TypeResolver_impl.h +) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/TypeResolver ) diff --git a/src/TNL/Meshes/TypeResolver/GridTypeResolver.h b/src/TNL/Meshes/TypeResolver/GridTypeResolver.h new file mode 100644 index 0000000000000000000000000000000000000000..498ae0f589cb28a40c31b0f382f0e620f1a96a4b --- /dev/null +++ b/src/TNL/Meshes/TypeResolver/GridTypeResolver.h @@ -0,0 +1,103 @@ +/*************************************************************************** + GridTypeResolver.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <type_traits> + +#include <TNL/Meshes/BuildConfigTags.h> + +namespace TNL { +namespace Meshes { + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +class GridTypeResolver +{ +public: + + static bool run( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + +protected: + + static bool resolveGridDimension( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // NOTE: We could disable the grids only by the GridTag, but doing the + // resolution for all subtypes is more flexible and also pretty + // good optimization of compilation times. + + // Overload for disabled grid dimensions + template< int MeshDimension, + typename = typename std::enable_if< ! BuildConfigTags::GridDimensionTag< ConfigTag, MeshDimension >::enabled >::type, + typename = void > + static bool resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled grid dimensions + template< int MeshDimension, + typename = typename std::enable_if< BuildConfigTags::GridDimensionTag< ConfigTag, MeshDimension >::enabled >::type > + static bool resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled real types + template< int MeshDimension, + typename Real, + typename = typename std::enable_if< ! BuildConfigTags::GridRealTag< ConfigTag, Real >::enabled >::type, + typename = void > + static bool resolveIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled real types + template< int MeshDimension, + typename Real, + typename = typename std::enable_if< BuildConfigTags::GridRealTag< ConfigTag, Real >::enabled >::type > + static bool resolveIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled index types + template< int MeshDimension, + typename Real, + typename Index, + typename = typename std::enable_if< ! BuildConfigTags::GridIndexTag< ConfigTag, Index >::enabled >::type, + typename = void > + static bool resolveGridType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled index types + template< int MeshDimension, + typename Real, + typename Index, + typename = typename std::enable_if< BuildConfigTags::GridIndexTag< ConfigTag, Index >::enabled >::type > + static bool resolveGridType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled grid types + template< typename GridType, + typename = typename std::enable_if< ! BuildConfigTags::GridTag< ConfigTag, GridType >::enabled >::type, + typename = void > + static bool resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled grid types + template< typename GridType, + typename = typename std::enable_if< BuildConfigTags::GridTag< ConfigTag, GridType >::enabled >::type > + static bool resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); +}; + +} // namespace Meshes +} // namespace TNL + +#include <TNL/Meshes/TypeResolver/GridTypeResolver_impl.h> diff --git a/src/TNL/Meshes/TypeResolver/GridTypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/GridTypeResolver_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..20f40c26820e611b3055879ec96445e13656f802 --- /dev/null +++ b/src/TNL/Meshes/TypeResolver/GridTypeResolver_impl.h @@ -0,0 +1,201 @@ +/*************************************************************************** + GridTypeResolver_impl.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <utility> + +#include <TNL/String.h> +#include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/TypeResolver/GridTypeResolver.h> + +namespace TNL { +namespace Meshes { + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +run( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + return resolveGridDimension( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveGridDimension( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + if( reader.getMeshDimension() == 1 ) + return resolveReal< 1 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getMeshDimension() == 2 ) + return resolveReal< 2 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getMeshDimension() == 3 ) + return resolveReal< 3 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + std::cerr << "Unsupported mesh dimension: " << reader.getMeshDimension() << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< int MeshDimension, + typename, typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The grid dimension " << MeshDimension << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< int MeshDimension, + typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + if( reader.getRealType() == "float" ) + return resolveIndex< MeshDimension, float >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getRealType() == "double" ) + return resolveIndex< MeshDimension, double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getRealType() == "long-double" ) + return resolveIndex< MeshDimension, long double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + std::cerr << "Unsupported real type: " << reader.getRealType() << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< int MeshDimension, + typename Real, + typename, typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The grid real type " << getType< Real >() << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< int MeshDimension, + typename Real, + typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + if( reader.getGlobalIndexType() == "short int" ) + return resolveGridType< MeshDimension, Real, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getGlobalIndexType() == "int" ) + return resolveGridType< MeshDimension, Real, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getGlobalIndexType() == "long int" ) + return resolveGridType< MeshDimension, Real, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + std::cerr << "Unsupported index type: " << reader.getRealType() << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< int MeshDimension, + typename Real, + typename Index, + typename, typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveGridType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The grid index type " << getType< Index >() << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< int MeshDimension, + typename Real, + typename Index, + typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveGridType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + using GridType = Meshes::Grid< MeshDimension, Real, Device, Index >; + return resolveTerminate< GridType >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename GridType, + typename, typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The mesh type " << TNL::getType< GridType >() << " is disabled in the build configuration." << std::endl; + return false; +}; + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename GridType, + typename > +bool +GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + return ProblemSetter< GridType >::run( std::forward<ProblemSetterArgs>(problemSetterArgs)... ); +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/TypeResolver/MeshTypeResolver.h b/src/TNL/Meshes/TypeResolver/MeshTypeResolver.h new file mode 100644 index 0000000000000000000000000000000000000000..dfdb0ad1ed312e8a4841361644f5bdb97ee37dd2 --- /dev/null +++ b/src/TNL/Meshes/TypeResolver/MeshTypeResolver.h @@ -0,0 +1,184 @@ +/*************************************************************************** + MeshTypeResolver.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <type_traits> + +#include <TNL/Meshes/BuildConfigTags.h> + +namespace TNL { +namespace Meshes { + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +class MeshTypeResolver +{ +public: + + static bool run( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + +protected: + + static bool resolveCellTopology( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // NOTE: We could disable the meshes only by the MeshTag, but doing the + // resolution for all subtypes is more flexible and also pretty + // good optimization of compilation times. + + // Overload for disabled cell topologies + template< typename CellTopology, + typename = typename std::enable_if< ! BuildConfigTags::MeshCellTopologyTag< ConfigTag, CellTopology >::enabled >::type, + typename = void > + static bool resolveWorldDimension( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled cell topologies + template< typename CellTopology, + typename = typename std::enable_if< BuildConfigTags::MeshCellTopologyTag< ConfigTag, CellTopology >::enabled >::type > + static bool resolveWorldDimension( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled world dimensions + template< typename CellTopology, + int WorldDimension, + typename = typename std::enable_if< ! BuildConfigTags::MeshWorldDimensionTag< ConfigTag, CellTopology, WorldDimension >::enabled >::type, + typename = void > + static bool resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled world dimensions + template< typename CellTopology, + int WorldDimension, + typename = typename std::enable_if< BuildConfigTags::MeshWorldDimensionTag< ConfigTag, CellTopology, WorldDimension >::enabled >::type > + static bool resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled real types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename = typename std::enable_if< ! BuildConfigTags::MeshRealTag< ConfigTag, Real >::enabled >::type, + typename = void > + static bool resolveGlobalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled real types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename = typename std::enable_if< BuildConfigTags::MeshRealTag< ConfigTag, Real >::enabled >::type > + static bool resolveGlobalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled global index types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename = typename std::enable_if< ! BuildConfigTags::MeshGlobalIndexTag< ConfigTag, GlobalIndex >::enabled >::type, + typename = void > + static bool resolveLocalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled global index types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename = typename std::enable_if< BuildConfigTags::MeshGlobalIndexTag< ConfigTag, GlobalIndex >::enabled >::type > + static bool resolveLocalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled local index types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename = typename std::enable_if< ! BuildConfigTags::MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled >::type, + typename = void > + static bool resolveId( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled local index types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename = typename std::enable_if< BuildConfigTags::MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled >::type > + static bool resolveId( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled id types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename Id, + typename = typename std::enable_if< ! BuildConfigTags::MeshIdTag< ConfigTag, GlobalIndex, Id >::enabled >::type, + typename = void > + static bool resolveMeshType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled id types + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename Id, + typename = typename std::enable_if< BuildConfigTags::MeshIdTag< ConfigTag, GlobalIndex, Id >::enabled >::type > + static bool resolveMeshType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for disabled mesh types + template< typename MeshConfig, + typename = typename std::enable_if< ! BuildConfigTags::MeshDeviceTag< ConfigTag, Device >::enabled || + ! BuildConfigTags::MeshTag< ConfigTag, + Device, + typename MeshConfig::CellTopology, + MeshConfig::worldDimension, + typename MeshConfig::RealType, + typename MeshConfig::GlobalIndexType, + typename MeshConfig::LocalIndexType, + typename MeshConfig::IdType + >::enabled >::type, + typename = void > + static bool resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); + + // Overload for enabled mesh types + template< typename MeshConfig, + typename = typename std::enable_if< BuildConfigTags::MeshDeviceTag< ConfigTag, Device >::enabled && + BuildConfigTags::MeshTag< ConfigTag, + Device, + typename MeshConfig::CellTopology, + MeshConfig::worldDimension, + typename MeshConfig::RealType, + typename MeshConfig::GlobalIndexType, + typename MeshConfig::LocalIndexType, + typename MeshConfig::IdType + >::enabled >::type > + static bool resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ); +}; + +} // namespace Meshes +} // namespace TNL + +#include <TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h> diff --git a/src/TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..46c4e9c58f30f3d7abf9c04de6071d64f5e34977 --- /dev/null +++ b/src/TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h @@ -0,0 +1,358 @@ +/*************************************************************************** + MeshTypeResolver_impl.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <utility> + +#include <TNL/String.h> +#include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/TypeResolver/MeshTypeResolver.h> +#include <TNL/Meshes/Readers/EntityShape.h> + +namespace TNL { +namespace Meshes { + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +run( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + return resolveCellTopology( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveCellTopology( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + using Readers::EntityShape; + switch( reader.getCellShape() ) + { + case EntityShape::Line: + return resolveWorldDimension< Topologies::Edge >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + case EntityShape::Triangle: + return resolveWorldDimension< Topologies::Triangle >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + case EntityShape::Quad: + return resolveWorldDimension< Topologies::Quadrilateral >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + case EntityShape::Tetra: + return resolveWorldDimension< Topologies::Tetrahedron >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + case EntityShape::Hexahedron: + return resolveWorldDimension< Topologies::Hexahedron >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + default: + std::cerr << "unsupported cell topology: " << reader.getCellShape() << std::endl; + return false; + } +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + typename, typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveWorldDimension( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The cell topology " << CellTopology::getType() << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveWorldDimension( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + switch( reader.getWorldDimension() ) + { + case 1: + return resolveReal< CellTopology, 1 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + case 2: + return resolveReal< CellTopology, 2 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + case 3: + return resolveReal< CellTopology, 3 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + default: + std::cerr << "unsupported world dimension: " << reader.getWorldDimension() << std::endl; + return false; + } +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename, typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The combination of world dimension (" << WorldDimension + << ") and mesh dimension (" << CellTopology::dimension + << ") is either invalid or disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveReal( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + if( reader.getRealType() == "float" ) + return resolveGlobalIndex< CellTopology, WorldDimension, float >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getRealType() == "double" ) + return resolveGlobalIndex< CellTopology, WorldDimension, double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getRealType() == "long-double" ) + return resolveGlobalIndex< CellTopology, WorldDimension, long double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + std::cerr << "Unsupported real type: " << reader.getRealType() << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename, typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveGlobalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The mesh real type " << getType< Real >() << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveGlobalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + if( reader.getGlobalIndexType() == "short int" ) + return resolveLocalIndex< CellTopology, WorldDimension, Real, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getGlobalIndexType() == "int" ) + return resolveLocalIndex< CellTopology, WorldDimension, Real, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getGlobalIndexType() == "long int" ) + return resolveLocalIndex< CellTopology, WorldDimension, Real, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + std::cerr << "Unsupported global index type: " << reader.getGlobalIndexType() << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename, typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveLocalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The mesh global index type " << getType< GlobalIndex >() << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveLocalIndex( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + if( reader.getLocalIndexType() == "short int" ) + return resolveId< CellTopology, WorldDimension, Real, GlobalIndex, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getLocalIndexType() == "int" ) + return resolveId< CellTopology, WorldDimension, Real, GlobalIndex, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getLocalIndexType() == "long int" ) + return resolveId< CellTopology, WorldDimension, Real, GlobalIndex, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + std::cerr << "Unsupported local index type: " << reader.getLocalIndexType() << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename, typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveId( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The mesh local index type " << getType< LocalIndex >() << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveId( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + if( reader.getIdType() == "short int" ) + return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getIdType() == "int" ) + return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getIdType() == "long int" ) + return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + if( reader.getIdType() == "void" ) + return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, void >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + std::cerr << "Unsupported id type: " << reader.getIdType() << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename Id, + typename, typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveMeshType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The mesh id type " << getType< Id >() << " is disabled in the build configuration." << std::endl; + return false; +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename CellTopology, + int WorldDimension, + typename Real, + typename GlobalIndex, + typename LocalIndex, + typename Id, + typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveMeshType( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + using MeshConfig = typename BuildConfigTags::MeshConfigTemplateTag< ConfigTag >::template MeshConfig< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, Id >; + return resolveTerminate< MeshConfig >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); +} + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename MeshConfig, + typename, typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cerr << "The mesh config type " << TNL::getType< MeshConfig >() << " is disabled in the build configuration for device " << Device::getDeviceType() << "." << std::endl; + return false; +}; + +template< typename Reader, + typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > + template< typename MeshConfig, + typename > +bool +MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: +resolveTerminate( const Reader& reader, + ProblemSetterArgs&&... problemSetterArgs ) +{ + using MeshType = Meshes::Mesh< MeshConfig, Device >; + return ProblemSetter< MeshType >::run( std::forward<ProblemSetterArgs>(problemSetterArgs)... ); +}; + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/TypeResolver/TypeResolver.h b/src/TNL/Meshes/TypeResolver/TypeResolver.h new file mode 100644 index 0000000000000000000000000000000000000000..a04391af61acc23c1bdc43a12ac3243dbe4b9c25 --- /dev/null +++ b/src/TNL/Meshes/TypeResolver/TypeResolver.h @@ -0,0 +1,34 @@ +/*************************************************************************** + MeshResolver.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/String.h> + +namespace TNL { +namespace Meshes { + +/* + * This function does the following (in pseudo-code): + * + * using MeshType = [black magic] + * return ProblemSetter< MeshType >::run( problemSetterArgs... ); + */ +template< typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +bool resolveMeshType( const String& fileName, + ProblemSetterArgs&&... problemSetterArgs ); + +} // namespace Meshes +} // namespace TNL + +#include <TNL/Meshes/TypeResolver/TypeResolver_impl.h> diff --git a/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..82767a0f02e2862eba1bf0c0849d3367e5806ace --- /dev/null +++ b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h @@ -0,0 +1,175 @@ +/*************************************************************************** + MeshResolver_impl.h - description + ------------------- + begin : Nov 22, 2016 + copyright : (C) 2016 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <string> +#include <utility> + +#include <TNL/Meshes/TypeResolver/TypeResolver.h> +#include <TNL/Meshes/Readers/TNLReader.h> +#include <TNL/Meshes/Readers/NetgenReader.h> +#include <TNL/Meshes/Readers/VTKReader.h> +#include <TNL/Meshes/TypeResolver/GridTypeResolver.h> +#include <TNL/Meshes/TypeResolver/MeshTypeResolver.h> + +// TODO: implement this in TNL::String +inline bool ends_with( const std::string& value, const std::string& ending ) +{ + if (ending.size() > value.size()) + return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + +namespace TNL { +namespace Meshes { + +/* + * TODO: + * The variadic template parameter pack ProblemSetterArgs will not be necessary + * in C++14 as it will be possible to use generic lambda functions to pass + * parameters to the ProblemSetter: + * + * // wrapper for MeshTypeResolver + * template< typename MeshType > + * using ProblemSetterWrapper = ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag > >; + * + * bool run( const Config::ParameterContainer& parameters ) + * { + * const String& meshFileName = parameters.getParameter< String >( "mesh" ); + * auto wrapper = []( auto&& mesh ) { + * return ProblemSetterWrapper< decltype(mesh) >::run( parameters ); + * }; + * return MeshTypeResolver< ConfigTag, Device, wrapper >::run( meshFileName ); + * } + */ +template< typename ConfigTag, + typename Device, + template< typename MeshType > class ProblemSetter, + typename... ProblemSetterArgs > +bool resolveMeshType( const String& fileName_, + ProblemSetterArgs&&... problemSetterArgs ) +{ + std::cout << "Detecting mesh from file " << fileName_ << " ..." << std::endl; + std::string fileName( fileName_.getString() ); + if( ends_with( fileName, ".tnl" ) ) { + Readers::TNLReader reader; + if( ! reader.detectMesh( fileName_ ) ) + return false; + if( reader.getMeshType() == "Meshes::Grid" ) + return GridTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: + run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + else if( reader.getMeshType() == "Meshes::Mesh" ) + return MeshTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: + run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + else { + std::cerr << "The mesh type " << reader.getMeshType() << " is not supported in the TNL reader." << std::endl; + return false; + } + } + else if( ends_with( fileName, ".ng" ) ) { + // FIXME: The Netgen files don't store the real, global index, local index and id types. + // The reader has some defaults, but they might be disabled by the BuildConfigTags - in + // this case we should use the first enabled type. + Readers::NetgenReader reader; + if( ! reader.detectMesh( fileName_ ) ) + return false; + if( reader.getMeshType() == "Meshes::Mesh" ) + return MeshTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: + run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + else { + std::cerr << "The mesh type " << reader.getMeshType() << " is not supported in the Netgen reader." << std::endl; + return false; + } + } + else if( ends_with( fileName, ".vtk" ) ) { + // FIXME: The VTK files don't store the global index, local index and id types. + // The reader has some defaults, but they might be disabled by the BuildConfigTags - in + // this case we should use the first enabled type. + Readers::VTKReader reader; + if( ! reader.detectMesh( fileName_ ) ) + return false; + if( reader.getMeshType() == "Meshes::Mesh" ) + return MeshTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >:: + run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... ); + else { + std::cerr << "The mesh type " << reader.getMeshType() << " is not supported in the VTK reader." << std::endl; + return false; + } + } + else { + std::cerr << "File '" << fileName << "' has unknown extension. Supported extensions are '.tnl', '.vtk' and '.ng'." << std::endl; + return false; + } +} + +// TODO: reorganize +template< typename MeshConfig, typename Device > +bool +loadMesh( const String& fileName_, Mesh< MeshConfig, Device >& mesh ) +{ + std::cout << "Loading mesh from file " << fileName_ << " ..." << std::endl; + std::string fileName( fileName_.getString() ); + bool status = true; + + if( ends_with( fileName, ".tnl" ) ) + status = mesh.load( fileName_ ); + else if( ends_with( fileName, ".ng" ) ) { + Readers::NetgenReader reader; + status = reader.readMesh( fileName_, mesh ); + } + else if( ends_with( fileName, ".vtk" ) ) { + Readers::VTKReader reader; + status = reader.readMesh( fileName_, mesh ); + } + else { + std::cerr << "File '" << fileName << "' has unknown extension. Supported extensions are '.tnl', '.vtk' and '.ng'." << std::endl; + return false; + } + + if( ! status ) + { + std::cerr << "I am not able to load the mesh from the file " << fileName_ << ". " + "Perhaps the mesh stored in the file is not supported by the mesh " + "passed to the loadMesh function? The mesh type is " + << mesh.getType() << std::endl; + return false; + } + return true; +} + +template< typename MeshConfig > +bool +loadMesh( const String& fileName, Mesh< MeshConfig, Devices::Cuda >& mesh ) +{ + Mesh< MeshConfig, Devices::Host > hostMesh; + if( ! loadMesh( fileName, hostMesh ) ) + return false; + mesh = hostMesh; + return true; +} + +template< int Dimension, typename Real, typename Device, typename Index > +bool +loadMesh( const String& fileName, Grid< Dimension, Real, Device, Index >& mesh ) +{ + std::cout << "Loading mesh from file " << fileName << " ..." << std::endl; + if( ! mesh.load( fileName ) ) + { + std::cerr << "I am not able to load the grid from the file " << fileName << ". " + "You may create it with tools like tnl-grid-setup." + << std::endl; + return false; + } + return true; +} + +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Writers/AsymptoteWriter.h b/src/TNL/Meshes/Writers/AsymptoteWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..96d138b9678ef9d884551ae9e1d1859d0c48a7b1 --- /dev/null +++ b/src/TNL/Meshes/Writers/AsymptoteWriter.h @@ -0,0 +1,163 @@ +/*************************************************************************** + AsymptoteWriter.h - description + ------------------- + begin : Oct 22, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/Grid.h> + +namespace TNL { +namespace Meshes { +namespace Writers { + +template< typename Mesh > +class AsymptoteWriter +{ + static_assert( Mesh::getMeshDimension() <= 3, "The Asymptote format supports only 1D, 2D and 3D meshes." ); + +public: + static void writeAllEntities( const Mesh& mesh, std::ostream& str ) + { + throw "not implemented"; + } + + template< int EntityDimension = Mesh::getMeshDimension() > + static void writeEntities( const Mesh& mesh, std::ostream& str ) + { + throw "not implemented"; + } +}; + +template< typename Real, typename Device, typename Index > +class AsymptoteWriter< Grid< 2, Real, Device, Index > > +{ + using Mesh = Grid< 2, Real, Device, Index >; + using CoordinatesType = typename Mesh::CoordinatesType; + using PointType = typename Mesh::PointType; + +public: + static void writeAllEntities( const Mesh& mesh, std::ostream& str ) + { + str << "size( " + << mesh.getProportions(). x() << "cm , " + << mesh.getProportions(). y() << "cm );" + << std::endl << std::endl; + typename Mesh::Vertex vertex( mesh ); + CoordinatesType& vertexCoordinates = vertex.getCoordinates(); + PointType v; + for( Index j = 0; j < mesh.dimensions. y(); j ++ ) + { + str << "draw( "; + vertexCoordinates.x() = 0; + vertexCoordinates.y() = j; + v = vertex.getCenter(); + str << "( " << v. x() << ", " << v. y() << " )"; + for( Index i = 0; i < mesh.dimensions. x(); i ++ ) + { + vertexCoordinates.x() = i + 1; + vertexCoordinates.y() = j; + v = vertex.getCenter(); + str << "--( " << v. x() << ", " << v. y() << " )"; + } + str << " );" << std::endl; + } + str << std::endl; + for( Index i = 0; i < mesh.dimensions. x(); i ++ ) + { + str << "draw( "; + vertexCoordinates.x() = i; + vertexCoordinates.y() = 0; + v = vertex.getCenter(); + str << "( " << v. x() << ", " << v. y() << " )"; + for( Index j = 0; j < mesh.dimensions. y(); j ++ ) + { + vertexCoordinates.x() = i; + vertexCoordinates.y() = j + 1; + v = vertex.getCenter(); + str << "--( " << v. x() << ", " << v. y() << " )"; + } + str << " );" << std::endl; + } + str << std::endl; + + typename Mesh::Cell cell( mesh ); + CoordinatesType& cellCoordinates = cell.getCoordinates(); + const Real cellMeasure = mesh.getSpaceSteps().x() * mesh.getSpaceSteps().y(); + for( Index i = 0; i < mesh.dimensions. x(); i ++ ) + for( Index j = 0; j < mesh.dimensions. y(); j ++ ) + { + cellCoordinates.x() = i; + cellCoordinates.y() = j; + v = vertex.getCenter(); + str << "label( scale(0.33) * Label( \"$" << std::setprecision( 3 ) << cellMeasure << std::setprecision( 8 ) + << "$\" ), ( " << v. x() << ", " << v. y() << " ), S );" << std::endl; + } + + for( Index i = 0; i < mesh.dimensions. x(); i ++ ) + for( Index j = 0; j < mesh.dimensions. y(); j ++ ) + { + PointType v1, v2, c; + + /**** + * East edge normal + */ + /*v1 = mesh.getPoint( CoordinatesType( i + 1, j ), v1 ); + v2 = mesh.getPoint( CoordinatesType( i + 1, j + 1 ), v2 ); + c = ( ( Real ) 0.5 ) * ( v1 + v2 ); + mesh.getEdgeNormal< 1, 0 >( CoordinatesType( i, j ), v ); + v *= 0.5; + str << "draw( ( " << c. x() << ", " << c. y() << " )--( " + << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl; + */ + /**** + * West edge normal + */ + /*mesh.getPoint< -1, -1 >( CoordinatesType( i, j ), v1 ); + mesh.getPoint< -1, 1 >( CoordinatesType( i, j ), v2 ); + c = ( ( Real ) 0.5 ) * ( v1 + v2 ); + mesh.getEdgeNormal< -1, 0 >( CoordinatesType( i, j ), v ); + v *= 0.5; + str << "draw( ( " << c. x() << ", " << c. y() << " )--( " + << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl; + */ + /**** + * North edge normal + */ + /*mesh.getPoint< 1, 1 >( CoordinatesType( i, j ), v1 ); + mesh.getPoint< -1, 1 >( CoordinatesType( i, j ), v2 ); + c = ( ( Real ) 0.5 ) * ( v1 + v2 ); + mesh.getEdgeNormal< 0, 1 >( CoordinatesType( i, j ), v ); + v *= 0.5; + str << "draw( ( " << c. x() << ", " << c. y() << " )--( " + << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl; + */ + /**** + * South edge normal + */ + /*mesh.getPoint< 1, -1 >( CoordinatesType( i, j ), v1 ); + mesh.getPoint< -1, -1 >( CoordinatesType( i, j ), v2 ); + c = ( ( Real ) 0.5 ) * ( v1 + v2 ); + mesh.getEdgeNormal< 0, -1 >( CoordinatesType( i, j ), v ); + v *= 0.5; + str << "draw( ( " << c. x() << ", " << c. y() << " )--( " + << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl; + */ + } + } + + template< int EntityDimension = Mesh::getMeshDimension() > + static void writeEntities( const Mesh& mesh, std::ostream& str ) + { + throw "not implemented"; + } +}; + +} // namespace Writers +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Writers/CMakeLists.txt b/src/TNL/Meshes/Writers/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b06a95b0cf7aea43bd9e4d1b3b8fe1d1aded0385 --- /dev/null +++ b/src/TNL/Meshes/Writers/CMakeLists.txt @@ -0,0 +1,7 @@ +SET( headers AsymptoteWriter.h + NetgenWriter.h + VTKWriter.h + VTKWriter_impl.h +) + +INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Writers ) diff --git a/src/TNL/Meshes/Writers/NetgenWriter.h b/src/TNL/Meshes/Writers/NetgenWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..7a3a86f9230ba317505c71d850ed8c86cef87267 --- /dev/null +++ b/src/TNL/Meshes/Writers/NetgenWriter.h @@ -0,0 +1,70 @@ +/*************************************************************************** + MeshWriterNetgen.h - description + ------------------- + begin : Feb 22, 2014 + copyright : (C) 2014 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +/*** + * Authors: + * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz + * Zabka Vitezslav, zabkav@gmail.com + */ + +#pragma once + +#include <ostream> +#include <iomanip> + +#include <TNL/String.h> + +namespace TNL { +namespace Meshes { +namespace Writers { + +template< typename Mesh > +class NetgenWriter +{ + using GlobalIndexType = typename Mesh::GlobalIndexType; + using PointType = typename Mesh::PointType; + using Cell = typename Mesh::Cell; + static constexpr int meshDimension = Mesh::getMeshDimension(); + +public: + static void writeMesh( const Mesh& mesh, std::ostream& str ) + { + str << std::setprecision( 6 ); + str << std::fixed; + + const GlobalIndexType numberOfVertices = mesh.template getEntitiesCount< typename Mesh::Vertex >(); + str << numberOfVertices << std::endl; + for( GlobalIndexType i = 0; i < numberOfVertices; i++ ) + { + const PointType& point = mesh.template getEntity< typename Mesh::Vertex >( i ).getPoint(); + str << " "; + for( int d = 0; d < meshDimension; d++ ) + str << " " << point[ d ]; + str << std::endl; + } + + const GlobalIndexType numberOfCells = mesh.template getEntitiesCount< typename Mesh::Cell >(); + str << numberOfCells << std::endl; + for( GlobalIndexType cellIdx = 0; cellIdx < numberOfCells; cellIdx++ ) + { + const Cell& cell = mesh.template getEntity< typename Mesh::Cell >( cellIdx ); + str << " 1"; + for( int cellVertexIdx = 0; + cellVertexIdx < meshDimension + 1; + cellVertexIdx++ ) + str << " " << cell.getVertexIndex( cellVertexIdx ); + str << "\n"; + } + } +}; + +} // namespace Writers +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Meshes/Writers/VTKWriter.h b/src/TNL/Meshes/Writers/VTKWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..4d5ad00e82b259c68849847dd9219d1e2d637588 --- /dev/null +++ b/src/TNL/Meshes/Writers/VTKWriter.h @@ -0,0 +1,60 @@ +/*************************************************************************** + VTKWriter.h - description + ------------------- + begin : Mar 04, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <limits> + +#include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/Mesh.h> + +namespace TNL { +namespace Meshes { +namespace Writers { + +namespace __impl { + +template< typename Mesh, int EntityDimension > struct MeshEntitiesVTKWriter; +template< typename Mesh, int EntityDimension > struct MeshEntityTypesVTKWriter; + +} // namespace __impl + +template< typename Mesh > +class VTKWriter +{ + static_assert( Mesh::getMeshDimension() <= 3, "The VTK format supports only 1D, 2D and 3D meshes." ); + // TODO: check also world dimension when grids allow it +// static_assert( Mesh::getWorldDimension() <= 3, "The VTK format supports only 1D, 2D and 3D meshes." ); + + template< int EntityDimension > + using EntitiesWriter = __impl::MeshEntitiesVTKWriter< Mesh, EntityDimension >; + + template< int EntityDimension > + using EntityTypesWriter = __impl::MeshEntityTypesVTKWriter< Mesh, EntityDimension >; + +public: + using Index = typename Mesh::GlobalIndexType; + + static void writeAllEntities( const Mesh& mesh, std::ostream& str ); + + template< int EntityDimension = Mesh::getMeshDimension() > + static void writeEntities( const Mesh& mesh, std::ostream& str ); + +protected: + static void writeHeader( const Mesh& mesh, std::ostream& str ); + + static void writePoints( const Mesh& mesh, std::ostream& str ); +}; + +} // namespace Writers +} // namespace Meshes +} // namespace TNL + +#include <TNL/Meshes/Writers/VTKWriter_impl.h> diff --git a/src/TNL/Meshes/Writers/VTKWriter_impl.h b/src/TNL/Meshes/Writers/VTKWriter_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..456429a5a083c58428e5c45b89015d5261e58826 --- /dev/null +++ b/src/TNL/Meshes/Writers/VTKWriter_impl.h @@ -0,0 +1,475 @@ +/*************************************************************************** + VTKWriter.h - description + ------------------- + begin : Mar 04, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/Writers/VTKWriter.h> +#include <TNL/Meshes/Readers/EntityShape.h> + +namespace TNL { +namespace Meshes { +namespace Writers { + +namespace __impl { + +template< typename Entity > +struct VerticesPerEntity +{ + static constexpr int count = Entity::getVerticesCount(); +}; + +template< typename MeshConfig, typename Device > +struct VerticesPerEntity< MeshEntity< MeshConfig, Device, Topologies::Vertex > > +{ + static constexpr int count = 1; +}; + +template< typename Grid, typename Config > +struct VerticesPerEntity< GridEntity< Grid, 0, Config > > +{ + static constexpr int count = 1; +}; + +template< typename Grid, typename Config > +struct VerticesPerEntity< GridEntity< Grid, 1, Config > > +{ + static constexpr int count = 2; +}; + +template< typename Grid, typename Config > +struct VerticesPerEntity< GridEntity< Grid, 2, Config > > +{ + static constexpr int count = 4; +}; + +template< typename Grid, typename Config > +struct VerticesPerEntity< GridEntity< Grid, 3, Config > > +{ + static constexpr int count = 8; +}; + + +template< typename GridEntity > +struct GridEntityShape {}; + +template< typename Grid, typename Config > +struct GridEntityShape< GridEntity< Grid, 0, Config > > +{ + static constexpr Readers::EntityShape shape = Readers::EntityShape::Vertex; +}; + +template< typename Grid, typename Config > +struct GridEntityShape< GridEntity< Grid, 1, Config > > +{ + static constexpr Readers::EntityShape shape = Readers::EntityShape::Line; +}; + +template< typename Grid, typename Config > +struct GridEntityShape< GridEntity< Grid, 2, Config > > +{ + static constexpr Readers::EntityShape shape = Readers::EntityShape::Pixel; +}; + +template< typename Grid, typename Config > +struct GridEntityShape< GridEntity< Grid, 3, Config > > +{ + static constexpr Readers::EntityShape shape = Readers::EntityShape::Voxel; +}; + + +template< typename Mesh > +typename Mesh::GlobalIndexType +getAllMeshEntitiesCount( const Mesh& mesh, DimensionTag< 0 > ) +{ + using EntityType = typename Mesh::template EntityType< 0 >; + return mesh.template getEntitiesCount< EntityType >(); +} + +// TODO: specialization for disabled entities +template< typename Mesh, + typename DimensionTag = Meshes::DimensionTag< Mesh::getMeshDimension() > > +typename Mesh::GlobalIndexType +getAllMeshEntitiesCount( const Mesh& mesh, DimensionTag = DimensionTag() ) +{ + using EntityType = typename Mesh::template EntityType< DimensionTag::value >; + return mesh.template getEntitiesCount< EntityType >() + + getAllMeshEntitiesCount( mesh, typename DimensionTag::Decrement() ); +} + + +template< typename Mesh > +typename Mesh::GlobalIndexType +getCellsListSize( const Mesh& mesh, DimensionTag< 0 > ) +{ + using EntityType = typename Mesh::template EntityType< 0 >; + return mesh.template getEntitiesCount< EntityType >() * 2; +} + +// TODO: specialization for disabled entities +template< typename Mesh, + typename DimensionTag = Meshes::DimensionTag< Mesh::getMeshDimension() > > +typename Mesh::GlobalIndexType +getCellsListSize( const Mesh& mesh, DimensionTag = DimensionTag() ) +{ + using EntityType = typename Mesh::template EntityType< DimensionTag::value >; + const auto verticesPerEntity = VerticesPerEntity< EntityType >::count; + return ( mesh.template getEntitiesCount< EntityType >() * ( verticesPerEntity + 1 ) ) + + getCellsListSize( mesh, typename DimensionTag::Decrement() ); +} + + +// TODO: specialization for disabled entities +// Unstructured meshes, entities +template< typename Mesh, int EntityDimension > +struct MeshEntitiesVTKWriter +{ + static void exec( const Mesh& mesh, std::ostream& str ) + { + using EntityType = typename Mesh::template EntityType< EntityDimension >; + using Index = typename Mesh::GlobalIndexType; + + const Index entitiesCount = mesh.template getEntitiesCount< EntityType >(); + const Index verticesPerEntity = VerticesPerEntity< EntityType >::count;; + for( Index i = 0; i < entitiesCount; i++ ) { + const auto& entity = mesh.template getEntity< EntityType >( i ); + str << verticesPerEntity; + for( Index j = 0; j < verticesPerEntity; j++ ) + str << " " << entity.template getSubentityIndex< 0 >( j ); + str << "\n"; + } + } +}; + +// Unstructured meshes, vertices +template< typename Mesh > +struct MeshEntitiesVTKWriter< Mesh, 0 > +{ + static void exec( const Mesh& mesh, std::ostream& str ) + { + using EntityType = typename Mesh::template EntityType< 0 >; + using Index = typename Mesh::GlobalIndexType; + + const Index entitiesCount = mesh.template getEntitiesCount< EntityType >(); + const Index verticesPerEntity = 1; + for( Index i = 0; i < entitiesCount; i++ ) { + str << verticesPerEntity << " " << i << "\n"; + } + } +}; + +// 1D grids, cells +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1 > +{ + using MeshType = Meshes::Grid< 1, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) + str << "2 " << i << " " << i+1 << "\n"; + } +}; + +// 1D grids, vertices +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0 > +{ + using MeshType = Meshes::Grid< 1, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex i = 0; i < mesh.getDimensions().x() + 1; i++ ) + str << "1 " << i << "\n"; + } +}; + +// 2D grids, cells +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2 > +{ + using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) + str << "4 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " + << j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " + << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " + << (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\n"; + } +}; + +// 2D grids, faces +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1 > +{ + using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ ) + str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " + << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << "\n"; + + for( MeshIndex j = 0; j < (mesh.getDimensions().y()+1); j++ ) + for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) + str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " + << j * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\n"; + } +}; + +// 2D grids, vertices +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0 > +{ + using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ ) + for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ ) + str << "1 " << j * mesh.getDimensions().x() + i << "\n"; + } +}; + +// 3D grids, cells +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3 > +{ + using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ ) + for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) + str << "8 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\n"; + } +}; + +// 3D grids, faces +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2 > +{ + using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ ) + for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ ) + str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << "\n"; + + for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ ) + for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) + str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\n"; + + for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ ) + for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) + str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\n"; + } +}; + +// 3D grids, edges +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1 > +{ + using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ ) + for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) + str << "2 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\n"; + + for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ ) + for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ ) + str << "2 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << "\n"; + + for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ ) + for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ ) + for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ ) + str << "2 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " " + << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << "\n"; + } +}; + +// 3D grids, vertices +template< typename MeshReal, + typename Device, + typename MeshIndex > +struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0 > +{ + using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + for( MeshIndex k = 0; k < ( mesh.getDimensions().z() + 1 ); k++ ) + for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ ) + for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ ) + str << "1 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << "\n"; + } +}; + + +// TODO: specialization for disabled entities +template< typename Mesh, int EntityDimension > +struct MeshEntityTypesVTKWriter +{ + static void exec( const Mesh& mesh, std::ostream& str ) + { + using EntityType = typename Mesh::template EntityType< EntityDimension >; + using Index = typename Mesh::GlobalIndexType; + + const Index entitiesCount = mesh.template getEntitiesCount< EntityType >(); + for( Index i = 0; i < entitiesCount; i++ ) { + const int type = (int) Meshes::Readers::TopologyToEntityShape< typename EntityType::EntityTopology >::shape; + str << type << "\n"; + } + } +}; + +template< int Dimension, + typename MeshReal, + typename Device, + typename MeshIndex, + int EntityDimension > +struct MeshEntityTypesVTKWriter< Grid< Dimension, MeshReal, Device, MeshIndex >, EntityDimension > +{ + using MeshType = Grid< Dimension, MeshReal, Device, MeshIndex >; + + static void exec( const MeshType& mesh, std::ostream& str ) + { + using EntityType = typename MeshType::template EntityType< EntityDimension >; + + const MeshIndex entitiesCount = mesh.template getEntitiesCount< EntityType >(); + for( MeshIndex i = 0; i < entitiesCount; i++ ) { + const int type = (int) __impl::GridEntityShape< EntityType >::shape; + str << type << "\n"; + } + } +}; + +} // namespace __impl + +template< typename Mesh > +void +VTKWriter< Mesh >::writeAllEntities( const Mesh& mesh, std::ostream& str ) +{ + writeHeader( mesh, str ); + writePoints( mesh, str ); + + const Index allEntitiesCount = __impl::getAllMeshEntitiesCount( mesh ); + const Index cellsListSize = __impl::getCellsListSize( mesh ); + + str << std::endl << "CELLS " << allEntitiesCount << " " << cellsListSize << std::endl; + StaticFor< int, 0, Mesh::getMeshDimension() + 1, EntitiesWriter >::exec( mesh, str ); + + str << std::endl << "CELL_TYPES " << allEntitiesCount << std::endl; + StaticFor< int, 0, Mesh::getMeshDimension() + 1, EntityTypesWriter >::exec( mesh, str ); +} + +template< typename Mesh > + template< int EntityDimension > +void +VTKWriter< Mesh >::writeEntities( const Mesh& mesh, std::ostream& str ) +{ + writeHeader( mesh, str ); + writePoints( mesh, str ); + + using EntityType = typename Mesh::template EntityType< EntityDimension >; + const Index entitiesCount = mesh.template getEntitiesCount< EntityType >(); + const Index verticesPerEntity = __impl::VerticesPerEntity< EntityType >::count; + const Index cellsListSize = entitiesCount * ( verticesPerEntity + 1 ); + + str << std::endl << "CELLS " << entitiesCount << " " << cellsListSize << std::endl; + EntitiesWriter< EntityDimension >::exec( mesh, str ); + + str << std::endl << "CELL_TYPES " << entitiesCount << std::endl; + EntityTypesWriter< EntityDimension >::exec( mesh, str ); +} + +template< typename Mesh > +void +VTKWriter< Mesh >::writeHeader( const Mesh& mesh, std::ostream& str ) +{ + str << "# vtk DataFile Version 2.0\n" + << "TNL DATA\n" + << "ASCII\n" + << "DATASET UNSTRUCTURED_GRID\n"; +} + +template< typename Mesh > +void +VTKWriter< Mesh >::writePoints( const Mesh& mesh, std::ostream& str ) +{ + const Index verticesCount = mesh.template getEntitiesCount< typename Mesh::Vertex >(); + + str << "POINTS " << verticesCount << " " << getType< typename Mesh::RealType >() << std::endl; + str.precision( std::numeric_limits< typename Mesh::RealType >::digits10 ); + + for( Index i = 0; i < verticesCount; i++ ) { + const auto& vertex = mesh.template getEntity< typename Mesh::Vertex >( i ); + const auto& point = vertex.getPoint(); + for( Index j = 0; j < point.size; j++ ) { + str << point[ j ]; + if( j < point.size - 1 ) + str << " "; + } + // VTK needs zeros for unused dimensions + for( Index j = 0; j < 3 - point.size; j++ ) + str << " 0"; + str << "\n"; + } +} + +} // namespace Writers +} // namespace Meshes +} // namespace TNL diff --git a/src/TNL/Operators/Advection/LaxFridrichs.h b/src/TNL/Operators/Advection/LaxFridrichs.h index 9dff03402a5bfef768e8ca608bd8dbbd10a38998..5bd51aa72efcaf9b9203f3f54894c9479282ce5f 100644 --- a/src/TNL/Operators/Advection/LaxFridrichs.h +++ b/src/TNL/Operators/Advection/LaxFridrichs.h @@ -31,14 +31,14 @@ class LaxFridrichs< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, Real, Index, typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType; typedef SharedPointer< MeshType > MeshPointer; - static const int Dimensions = MeshType::getMeshDimension(); + static const int Dimension = MeshType::getMeshDimension(); typedef typename MeshType::CoordinatesType CoordinatesType; typedef Real RealType; typedef Device DeviceType; typedef Index IndexType; typedef Functions::MeshFunction< MeshType > MeshFunctionType; typedef VelocityFunction VelocityFunctionType; - typedef Functions::VectorField< Dimensions, VelocityFunctionType > VelocityFieldType; + typedef Functions::VectorField< Dimension, VelocityFunctionType > VelocityFieldType; typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer; static void configSetup( Config::ConfigDescription& config, @@ -123,14 +123,14 @@ class LaxFridrichs< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, Real, Index, typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType; typedef SharedPointer< MeshType > MeshPointer; - static const int Dimensions = MeshType::getMeshDimension(); + static const int Dimension = MeshType::getMeshDimension(); typedef typename MeshType::CoordinatesType CoordinatesType; typedef Real RealType; typedef Device DeviceType; typedef Index IndexType; typedef Functions::MeshFunction< MeshType > MeshFunctionType; typedef VelocityFunction VelocityFunctionType; - typedef Functions::VectorField< Dimensions, VelocityFunctionType > VelocityFieldType; + typedef Functions::VectorField< Dimension, VelocityFunctionType > VelocityFieldType; typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer; static void configSetup( Config::ConfigDescription& config, @@ -221,14 +221,14 @@ class LaxFridrichs< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, Real, Index, typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType; typedef SharedPointer< MeshType > MeshPointer; - static const int Dimensions = MeshType::getMeshDimension(); + static const int Dimension = MeshType::getMeshDimension(); typedef typename MeshType::CoordinatesType CoordinatesType; typedef Real RealType; typedef Device DeviceType; typedef Index IndexType; typedef Functions::MeshFunction< MeshType > MeshFunctionType; typedef VelocityFunction VelocityFunctionType; - typedef Functions::VectorField< Dimensions, VelocityFunctionType > VelocityFieldType; + typedef Functions::VectorField< Dimension, VelocityFunctionType > VelocityFieldType; typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer; static void configSetup( Config::ConfigDescription& config, diff --git a/src/TNL/Operators/diffusion/LinearDiffusion.h b/src/TNL/Operators/diffusion/LinearDiffusion.h index ff9c05f03238eb5e10869f4a1dc2d8a6cd2d821a..e31113800f1c790ee630e7a99ae8d046fe039a5c 100644 --- a/src/TNL/Operators/diffusion/LinearDiffusion.h +++ b/src/TNL/Operators/diffusion/LinearDiffusion.h @@ -54,7 +54,7 @@ class LinearDiffusion< Meshes::Grid< 1,MeshReal, Device, MeshIndex >, Real, Inde static const int Dimension = MeshType::getMeshDimension(); - static constexpr int getDimension() { return Dimension; } + static constexpr int getMeshDimension() { return Dimension; } static String getType(); @@ -105,7 +105,7 @@ class LinearDiffusion< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, Real, Ind static const int Dimension = MeshType::getMeshDimension(); - static constexpr int getDimension() { return Dimension; } + static constexpr int getMeshDimension() { return Dimension; } static String getType(); @@ -155,7 +155,7 @@ class LinearDiffusion< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, Real, Ind static const int Dimension = MeshType::getMeshDimension(); - static constexpr int getDimension() { return Dimension; } + static constexpr int getMeshDimension() { return Dimension; } static String getType(); diff --git a/src/TNL/Operators/fdm/BackwardFiniteDifference.h b/src/TNL/Operators/fdm/BackwardFiniteDifference.h index d816499f1e733c4a6cbca7f1a3dc1c0fefe3d320..cceaa807f49961d3efe1cfda844c13ff3daa435e 100644 --- a/src/TNL/Operators/fdm/BackwardFiniteDifference.h +++ b/src/TNL/Operators/fdm/BackwardFiniteDifference.h @@ -48,7 +48,7 @@ class BackwardFiniteDifference< Meshes::Grid< Dimension, MeshReal, MeshDevice, M typedef Index IndexType; typedef ExactDifference< Dimension, XDifference, YDifference, ZDifference > ExactOperatorType; - static constexpr int getDimension() { return Dimension; } + static constexpr int getMeshDimension() { return Dimension; } static String getType() { diff --git a/src/TNL/Operators/fdm/CentralFiniteDifference.h b/src/TNL/Operators/fdm/CentralFiniteDifference.h index 90c9a5887897dd2664e2936514bb9255089c9e2c..feecc62e77800c94b63417aad765b0c404d58a22 100644 --- a/src/TNL/Operators/fdm/CentralFiniteDifference.h +++ b/src/TNL/Operators/fdm/CentralFiniteDifference.h @@ -48,7 +48,7 @@ class CentralFiniteDifference< Meshes::Grid< Dimension, MeshReal, MeshDevice, Me typedef Index IndexType; typedef ExactDifference< Dimension, XDifference, YDifference, ZDifference > ExactOperatorType; - //static constexpr int getDimension() { return Dimension; } + //static constexpr int getMeshDimension() { return Dimension; } static String getType() { diff --git a/src/TNL/Operators/fdm/ForwardFiniteDifference.h b/src/TNL/Operators/fdm/ForwardFiniteDifference.h index 9c75e05dadd03213494d1229fe814771ca0f540d..53602afec21eb7bc1dc416c7647306297895643e 100644 --- a/src/TNL/Operators/fdm/ForwardFiniteDifference.h +++ b/src/TNL/Operators/fdm/ForwardFiniteDifference.h @@ -49,7 +49,7 @@ class ForwardFiniteDifference< Meshes::Grid< Dimension, MeshReal, MeshDevice, Me typedef Index IndexType; typedef ExactDifference< Dimension, XDifference, YDifference, ZDifference > ExactOperatorType; - static constexpr int getDimension() { return Dimension; } + static constexpr int getMeshDimension() { return Dimension; } static String getType() { diff --git a/src/TNL/Solvers/BuildConfigTags.h b/src/TNL/Solvers/BuildConfigTags.h index e89aa9d925c7bfe748ec8ab1f98bbc8408787d18..7824f4a18ed44b2cfbb17c1ded32179806bb6fa1 100644 --- a/src/TNL/Solvers/BuildConfigTags.h +++ b/src/TNL/Solvers/BuildConfigTags.h @@ -10,7 +10,6 @@ #pragma once -#include <TNL/Meshes/Grid.h> #include <TNL/Solvers/ODE/Merson.h> #include <TNL/Solvers/ODE/Euler.h> #include <TNL/Solvers/Linear/SOR.h> @@ -26,7 +25,7 @@ namespace TNL { namespace Solvers { -class DefaultBuildConfigTag{}; +class DefaultBuildConfigTag {}; /**** * All devices are enabled by default. Those which are not available @@ -53,29 +52,10 @@ template< typename ConfigTag, typename Index > struct ConfigTagIndex{ enum { ena /**** * The mesh type will be resolved by the Solver by default. + * (The detailed mesh configuration is in TNL/Meshes/BuildConfigTags.h) */ template< typename ConfigTag > struct ConfigTagMeshResolve{ enum { enabled = true }; }; -/**** - * 1, 2, and 3 dimensions are enabled by default - */ -template< typename ConfigTag, int Dimension > struct ConfigTagDimension{ enum { enabled = ( Dimension > 0 && Dimension <= 3 ) }; }; - -/**** - * Up to the exceptions enlisted below, all mesh types are disabled by default. - */ -template< typename ConfigTag, typename MeshType > struct ConfigTagMesh{ enum { enabled = false }; }; - -/**** - * Use of Grid is enabled for allowed dimensions and Real, Device and Index types. - */ -template< typename ConfigTag, int Dimension, typename Real, typename Device, typename Index > - struct ConfigTagMesh< ConfigTag, Meshes::Grid< Dimension, Real, Device, Index > > - { enum { enabled = ConfigTagDimension< ConfigTag, Dimension >::enabled && - ConfigTagReal< ConfigTag, Real >::enabled && - ConfigTagDevice< ConfigTag, Device >::enabled && - ConfigTagIndex< ConfigTag, Index >::enabled }; }; - /**** * All time discretisations (explicit, semi-impicit and implicit ) are * enabled by default. diff --git a/src/TNL/Solvers/CMakeLists.txt b/src/TNL/Solvers/CMakeLists.txt index e9cf7268d584ef8228fa371bc82234a48bf5f255..e648956cdb6f9535e77da8ae1e2a3f0e8b6a6818 100644 --- a/src/TNL/Solvers/CMakeLists.txt +++ b/src/TNL/Solvers/CMakeLists.txt @@ -7,8 +7,6 @@ SET( headers IterativeSolver.h IterativeSolver_impl.h BuildConfigTags.h FastBuildConfigTag.h - MeshTypeResolver.h - MeshTypeResolver_impl.h Solver.h Solver_impl.h SolverStarter.h diff --git a/src/TNL/Solvers/FastBuildConfigTag.h b/src/TNL/Solvers/FastBuildConfigTag.h index 45ab71b8d84b447a178f3a1c338b1a9f4cf050ca..18e0d80adadff0256668c72d115a9ae707144a13 100644 --- a/src/TNL/Solvers/FastBuildConfigTag.h +++ b/src/TNL/Solvers/FastBuildConfigTag.h @@ -11,50 +11,59 @@ #pragma once #include <TNL/Solvers/BuildConfigTags.h> +#include <TNL/Meshes/BuildConfigTags.h> namespace TNL { namespace Solvers { -class FastBuildConfig +class FastBuildConfigTag { public: - static void print() { std::cerr << "FastBuildConfig" << std::endl; } + static void print() { std::cerr << "FastBuildConfigTag" << std::endl; } }; /**** * Turn off support for float and long double. */ -template<> struct ConfigTagReal< FastBuildConfig, float > { enum { enabled = false }; }; -template<> struct ConfigTagReal< FastBuildConfig, long double > { enum { enabled = false }; }; +template<> struct ConfigTagReal< FastBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct ConfigTagReal< FastBuildConfigTag, long double > { enum { enabled = false }; }; /**** * Turn off support for short int and long int indexing. */ -template<> struct ConfigTagIndex< FastBuildConfig, short int >{ enum { enabled = false }; }; -template<> struct ConfigTagIndex< FastBuildConfig, long int >{ enum { enabled = false }; }; - -/**** - * Use of Grid is enabled for allowed dimensions and Real, Device and Index types. - */ -template< int Dimension, typename Real, typename Device, typename Index > - struct ConfigTagMesh< FastBuildConfig, Meshes::Grid< Dimension, Real, Device, Index > > - { enum { enabled = ConfigTagDimension< FastBuildConfig, Dimension >::enabled && - ConfigTagReal< FastBuildConfig, Real >::enabled && - ConfigTagDevice< FastBuildConfig, Device >::enabled && - ConfigTagIndex< FastBuildConfig, Index >::enabled }; }; +template<> struct ConfigTagIndex< FastBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct ConfigTagIndex< FastBuildConfigTag, long int >{ enum { enabled = false }; }; /**** * Please, chose your preferred time discretisation here. */ -template<> struct ConfigTagTimeDiscretisation< FastBuildConfig, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; }; -template<> struct ConfigTagTimeDiscretisation< FastBuildConfig, SemiImplicitTimeDiscretisationTag >{ enum { enabled = true }; }; -template<> struct ConfigTagTimeDiscretisation< FastBuildConfig, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; }; +template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; }; +template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, SemiImplicitTimeDiscretisationTag >{ enum { enabled = true }; }; +template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; }; /**** * Only the Runge-Kutta-Merson solver is enabled by default. */ -//template<> struct ConfigTagExplicitSolver< FastBuildConfig, ExplicitEulerSolverTag >{ enum { enabled = false }; }; +//template<> struct ConfigTagExplicitSolver< FastBuildConfigTag, ExplicitEulerSolverTag >{ enum { enabled = false }; }; } // namespace Solvers + +namespace Meshes { +namespace BuildConfigTags { + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< Solvers::FastBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< Solvers::FastBuildConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< Solvers::FastBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< Solvers::FastBuildConfigTag, long int >{ enum { enabled = false }; }; + +} // namespace BuildConfigTags +} // namespace Meshes } // namespace TNL diff --git a/src/TNL/Solvers/MeshTypeResolver.h b/src/TNL/Solvers/MeshTypeResolver.h deleted file mode 100644 index d24bd8afa89c8d56257dd7d8d38684a7b853e210..0000000000000000000000000000000000000000 --- a/src/TNL/Solvers/MeshTypeResolver.h +++ /dev/null @@ -1,133 +0,0 @@ -/*************************************************************************** - MeshTypeResolver.h - description - ------------------- - begin : Nov 28, 2013 - copyright : (C) 2013 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/Config/ParameterContainer.h> - -namespace TNL { -namespace Solvers { - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag, - bool ResolveMesh = ConfigTagMeshResolve< ConfigTag >::enabled > -class MeshTypeResolver -{ -}; - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > -class MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, false > -{ - public: - - static bool run( const Config::ParameterContainer& parameters ); -}; - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > -class MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true > -{ - public: - - static bool run( const Config::ParameterContainer& parameters ); - - protected: - - static bool resolveMeshDimension( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); - - // Overload for disabled dimensions - template< int MeshDimension, - typename = typename std::enable_if< ! ConfigTagDimension<ConfigTag,MeshDimension>::enabled >::type, - typename = void > - static bool resolveMeshRealType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); - - // Overload for enabled dimensions - template< int MeshDimension, - typename = typename std::enable_if< ConfigTagDimension<ConfigTag,MeshDimension>::enabled >::type > - static bool resolveMeshRealType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); - - // Overload for disabled real types - template< int MeshDimension, - typename MeshRealType, - typename = typename std::enable_if< ! ConfigTagReal<ConfigTag, MeshRealType>::enabled >::type, - typename = void > - static bool resolveMeshIndexType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); - - // Overload for enabled real types - template< int MeshDimension, - typename MeshRealType, - typename = typename std::enable_if< ConfigTagReal<ConfigTag, MeshRealType>::enabled >::type > - static bool resolveMeshIndexType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); - - // Overload for disabled index types - template< int MeshDimension, - typename MeshRealType, - typename MeshIndexType, - typename = typename std::enable_if< ! ConfigTagIndex<ConfigTag, MeshIndexType>::enabled >::type, - typename = void > - static bool resolveMeshType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); - - // Overload for enabled index types - template< int MeshDimension, - typename MeshRealType, - typename MeshIndexType, - typename = typename std::enable_if< ConfigTagIndex<ConfigTag, MeshIndexType>::enabled >::type > - static bool resolveMeshType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); - - - - template< int Dimension, bool DimensionSupport, typename MeshTypeResolver > - friend class MeshTypeResolverDimensionSupportChecker; -}; - -/*template< int Dimension, bool DimensionSupport, typename MeshTypeResolver > -class MeshTypeResolverDimensionSupportChecker -{ -}; - -template< int Dimension, typename MeshTypeResolver > -class MeshTypeResolverDimensionSupportChecker< Dimension, true, MeshTypeResolver > -{ - public: - - static bool checkDimension( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); -}; - -template< int Dimension, typename MeshTypeResolver > -class MeshTypeResolverDimensionSupportChecker< Dimension, false, MeshTypeResolver > -{ - public: - - static bool checkDimension( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ); -};*/ - -} // namespace Solvers -} // namespace TNL - -#include <TNL/Solvers/MeshTypeResolver_impl.h> diff --git a/src/TNL/Solvers/MeshTypeResolver_impl.h b/src/TNL/Solvers/MeshTypeResolver_impl.h deleted file mode 100644 index c342c58f34204e5e42f163c637bf60aaed2f2df6..0000000000000000000000000000000000000000 --- a/src/TNL/Solvers/MeshTypeResolver_impl.h +++ /dev/null @@ -1,242 +0,0 @@ -/*************************************************************************** - MeshTypeResolver_impl.h - description - ------------------- - begin : Nov 28, 2013 - copyright : (C) 2013 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/String.h> -#include <TNL/Meshes/Grid.h> -#include <TNL/Meshes/DummyMesh.h> -#include <TNL/Solvers/SolverStarter.h> - -namespace TNL { -namespace Solvers { - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename MeshType, - typename ConfigTag, - bool MeshTypeSupported = ConfigTagMesh< ConfigTag, MeshType >::enabled > -class MeshResolverTerminator{}; - - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > -bool MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, false >::run( const Config::ParameterContainer& parameters ) -{ - return ProblemSetter< Real, - Device, - Index, - Meshes::DummyMesh< Real, Device, Index >, - ConfigTag, - SolverStarter< ConfigTag > >::template run< Real, Device, Index, ConfigTag >( parameters ); -}; - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > -bool MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::run( const Config::ParameterContainer& parameters ) -{ - const String& meshFileName = parameters.getParameter< String >( "mesh" ); - - String meshType; - if( ! getObjectType( meshFileName, meshType ) ) - { - std::cerr << "I am not able to detect the mesh type from the file " << meshFileName << "." << std::endl; - return EXIT_FAILURE; - } - std::cout << meshType << " detected in " << meshFileName << " file." << std::endl; - Containers::List< String > parsedMeshType; - if( ! parseObjectType( meshType, parsedMeshType ) ) - { - std::cerr << "Unable to parse the mesh type " << meshType << "." << std::endl; - return false; - } - return resolveMeshDimension( parameters, parsedMeshType ); -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > -bool -MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >:: -resolveMeshDimension( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ) -{ - int dimensions = atoi( parsedMeshType[ 1 ].getString() ); - - if( dimensions == 1 ) - return resolveMeshRealType< 1 >( parameters, parsedMeshType ); - if( dimensions == 2 ) - return resolveMeshRealType< 2 >( parameters, parsedMeshType ); - if( dimensions == 3 ) - return resolveMeshRealType< 3 >( parameters, parsedMeshType ); - std::cerr << "Dimension higher than 3 are not supported." << std::endl; - return false; -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > - template< int MeshDimension, typename, typename > -bool -MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >:: -resolveMeshRealType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ) -{ - std::cerr << "Mesh dimension " << MeshDimension << " is not supported." << std::endl; - return false; -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > - template< int MeshDimension, typename > -bool -MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >:: -resolveMeshRealType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ) -{ - if( parsedMeshType[ 2 ] == "float" ) - return resolveMeshIndexType< MeshDimension, float >( parameters, parsedMeshType ); - if( parsedMeshType[ 2 ] == "double" ) - return resolveMeshIndexType< MeshDimension, double >( parameters, parsedMeshType ); - if( parsedMeshType[ 2 ] == "long-double" ) - return resolveMeshIndexType< MeshDimension, long double >( parameters, parsedMeshType ); - std::cerr << "The type '" << parsedMeshType[ 2 ] << "' is not allowed for real type." << std::endl; - return false; -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > - template< int MeshDimension, - typename MeshRealType, - typename, typename > -bool -MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >:: -resolveMeshIndexType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ) -{ - std::cerr << "The type '" << parsedMeshType[ 4 ] << "' is not allowed for real type." << std::endl; - return false; -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > - template< int MeshDimension, - typename MeshRealType, - typename > -bool -MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >:: -resolveMeshIndexType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ) -{ - if( parsedMeshType[ 4 ] == "short int" ) - return resolveMeshType< MeshDimension, MeshRealType, short int >( parameters, parsedMeshType ); - if( parsedMeshType[ 4 ] == "int" ) - return resolveMeshType< MeshDimension, MeshRealType, int >( parameters, parsedMeshType ); - if( parsedMeshType[ 4 ] == "long int" ) - return resolveMeshType< MeshDimension, MeshRealType, long int >( parameters, parsedMeshType ); - std::cerr << "The type '" << parsedMeshType[ 4 ] << "' is not allowed for indexing type." << std::endl; - return false; -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > - template< int MeshDimension, - typename MeshRealType, - typename MeshIndexType, - typename, typename > -bool -MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >:: -resolveMeshType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ) -{ - std::cerr << "The type '" << parsedMeshType[ 4 ] << "' is not allowed for indexing type." << std::endl; - return false; -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename ConfigTag > - template< int MeshDimension, - typename MeshRealType, - typename MeshIndexType, - typename > -bool -MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >:: -resolveMeshType( const Config::ParameterContainer& parameters, - const Containers::List< String >& parsedMeshType ) -{ - if( parsedMeshType[ 0 ] == "Meshes::Grid" ) - { - typedef Meshes::Grid< MeshDimension, MeshRealType, Device, MeshIndexType > MeshType; - return MeshResolverTerminator< ProblemSetter, Real, Device, Index, MeshType, ConfigTag >::run( parameters ); - } - std::cerr << "Unknown mesh type " << parsedMeshType[ 0 ] << "." << std::endl; - return false; -} - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename MeshType, - typename ConfigTag > -class MeshResolverTerminator< ProblemSetter, Real, Device, Index, MeshType, ConfigTag, false > -{ - public: - static bool run( const Config::ParameterContainer& parameters ) - { - std::cerr << "The mesh type " << TNL::getType< MeshType >() << " is not supported." << std::endl; - return false; - }; -}; - -template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, - typename Real, - typename Device, - typename Index, - typename MeshType, - typename ConfigTag > -class MeshResolverTerminator< ProblemSetter, Real, Device, Index, MeshType, ConfigTag, true > -{ - public: - static bool run( const Config::ParameterContainer& parameters ) - { - return ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag > >::run( parameters ); - } -}; - -} // namespace Solvers -} // namespace TNL diff --git a/src/TNL/Solvers/ODE/ExplicitSolver.h b/src/TNL/Solvers/ODE/ExplicitSolver.h index 36a7118314a442029bd4a7c1fbe6312d42065af9..7ac4f14ecd4bc1eb0ae827a3f67dfd2de4dd1628 100644 --- a/src/TNL/Solvers/ODE/ExplicitSolver.h +++ b/src/TNL/Solvers/ODE/ExplicitSolver.h @@ -19,6 +19,7 @@ #include <TNL/Config/ConfigDescription.h> #include <TNL/Config/ParameterContainer.h> #include <TNL/SharedPointer.h> +#include <TNL/Containers/Vector.h> namespace TNL { namespace Solvers { diff --git a/src/TNL/Solvers/PDE/CMakeLists.txt b/src/TNL/Solvers/PDE/CMakeLists.txt index 8b5021374834c72d41411df38b20afdd67d62a5d..98f367667d351e9f5dfbcc82b8e0b6a4502acdd2 100644 --- a/src/TNL/Solvers/PDE/CMakeLists.txt +++ b/src/TNL/Solvers/PDE/CMakeLists.txt @@ -4,6 +4,7 @@ SET( headers BackwardTimeDiscretisation.h ExplicitTimeStepper_impl.h ExplicitUpdater.h LinearSystemAssembler.h + MeshDependentTimeSteps.h NoTimeDiscretisation.h PDESolver.h PDESolver_impl.h diff --git a/src/TNL/Solvers/PDE/MeshDependentTimeSteps.h b/src/TNL/Solvers/PDE/MeshDependentTimeSteps.h new file mode 100644 index 0000000000000000000000000000000000000000..143c4b7f02755057238ca878c52b75ae0a57a32e --- /dev/null +++ b/src/TNL/Solvers/PDE/MeshDependentTimeSteps.h @@ -0,0 +1,93 @@ +/*************************************************************************** + MeshDependentTimeSteps.h - description + ------------------- + begin : Jan 26, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/Mesh.h> + +namespace TNL { +namespace Solvers { +namespace PDE { + +template< typename Mesh, typename Real > +class MeshDependentTimeSteps +{ +}; + +template< int Dimension, + typename MeshReal, + typename Device, + typename MeshIndex, + typename Real > +class MeshDependentTimeSteps< TNL::Meshes::Grid< Dimension, MeshReal, Device, MeshIndex >, Real > +{ +public: + using MeshType = TNL::Meshes::Grid< Dimension, MeshReal, Device, MeshIndex >; + + bool setTimeStepOrder( const Real& timeStepOrder ) + { + if( timeStepOrder < 0 ) { + std::cerr << "The time step order for PDESolver must be zero or positive value." << std::endl; + return false; + } + this->timeStepOrder = timeStepOrder; + return true; + } + + const Real& getTimeStepOrder() const + { + return timeStepOrder; + } + + Real getRefinedTimeStep( const MeshType& mesh, const Real& timeStep ) + { + return timeStep * std::pow( mesh.getSmallestSpaceStep(), this->timeStepOrder ); + } + +protected: + Real timeStepOrder = 0.0; +}; + +template< typename MeshConfig, + typename Device, + typename Real > +class MeshDependentTimeSteps< TNL::Meshes::Mesh< MeshConfig, Device >, Real > +{ +public: + using MeshType = TNL::Meshes::Mesh< MeshConfig >; + + bool setTimeStepOrder( const Real& timeStepOrder ) + { + if( timeStepOrder != 0.0 ) { + std::cerr << "Mesh-dependent time stepping is not available on unstructured meshes, so the time step order must be 0." << std::endl; + return false; + } + this->timeStepOrder = timeStepOrder; + return true; + } + + const Real& getTimeStepOrder() const + { + return timeStepOrder; + } + + Real getRefinedTimeStep( const MeshType& mesh, const Real& timeStep ) + { + return timeStep; + } + +protected: + Real timeStepOrder = 0.0; +}; + +} // namespace PDE +} // namespace Solvers +} // namespace TNL diff --git a/src/TNL/Solvers/PDE/TimeDependentPDESolver.h b/src/TNL/Solvers/PDE/TimeDependentPDESolver.h index 8b400c994e1b05d560e41c1123aaf3d73c702753..af4889ac329fa032bc71bf355e0044327f79c5bb 100644 --- a/src/TNL/Solvers/PDE/TimeDependentPDESolver.h +++ b/src/TNL/Solvers/PDE/TimeDependentPDESolver.h @@ -15,6 +15,7 @@ #include <TNL/Logger.h> #include <TNL/SharedPointer.h> #include <TNL/Solvers/PDE/PDESolver.h> +#include <TNL/Solvers/PDE/MeshDependentTimeSteps.h> namespace TNL { namespace Solvers { @@ -23,8 +24,11 @@ namespace PDE { template< typename Problem, typename DiscreteSolver, typename TimeStepper > -class TimeDependentPDESolver : public PDESolver< typename Problem::RealType, - typename Problem::IndexType > +class TimeDependentPDESolver + : public PDESolver< typename Problem::RealType, + typename Problem::IndexType >, + public MeshDependentTimeSteps< typename Problem::MeshType, + typename TimeStepper::RealType > { public: @@ -68,10 +72,6 @@ class TimeDependentPDESolver : public PDESolver< typename Problem::RealType, const RealType& getTimeStep() const; - bool setTimeStepOrder( const RealType& timeStepOrder ); - - const RealType& getTimeStepOrder() const; - bool setSnapshotPeriod( const RealType& period ); const RealType& getSnapshotPeriod() const; @@ -94,7 +94,7 @@ class TimeDependentPDESolver : public PDESolver< typename Problem::RealType, ProblemType* problem; - RealType initialTime, finalTime, snapshotPeriod, timeStep, timeStepOrder; + RealType initialTime, finalTime, snapshotPeriod, timeStep; }; } // namespace PDE diff --git a/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h b/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h index 991789e8abf1898c5af82653de4875db1d5153e3..a8a01aa9c506e288cedb2d0f366cbbd3d7de366a 100644 --- a/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h +++ b/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h @@ -11,6 +11,7 @@ #pragma once #include "TimeDependentPDESolver.h" +#include <TNL/Meshes/TypeResolver/TypeResolver.h> namespace TNL { namespace Solvers { @@ -25,8 +26,7 @@ TimeDependentPDESolver() initialTime( 0.0 ), finalTime( 0.0 ), snapshotPeriod( 0.0 ), - timeStep( 1.0 ), - timeStepOrder( 0.0 ) + timeStep( 1.0 ) { } @@ -62,15 +62,8 @@ setup( const Config::ParameterContainer& parameters, * Load the mesh from the mesh file */ const String& meshFile = parameters.getParameter< String >( "mesh" ); - std::cout << "Loading a mesh from the file " << meshFile << "..."; - if( ! this->meshPointer->load( meshFile ) ) - { - std::cerr << std::endl; - std::cerr << "I am not able to load the mesh from the file " << meshFile << "." << std::endl; - std::cerr << " You may create it with tools like tnl-grid-setup or tnl-mesh-convert." << std::endl; + if( ! Meshes::loadMesh( meshFile, *meshPointer ) ) return false; - } - std::cout << " [ OK ] " << std::endl; /**** * Setup the problem @@ -107,11 +100,14 @@ setup( const Config::ParameterContainer& parameters, /**** * Initialize the time discretisation */ - this->setFinalTime( parameters.getParameter< double >( "final-time" ) ); - this->setInitialTime( parameters.getParameter< double >( "initial-time" ) ); - this->setSnapshotPeriod( parameters.getParameter< double >( "snapshot-period" ) ); - this->setTimeStep( parameters.getParameter< double >( "time-step") ); - this->setTimeStepOrder( parameters.getParameter< double >( "time-step-order" ) ); + bool status = true; + status &= this->setFinalTime( parameters.getParameter< double >( "final-time" ) ); + this->setInitialTime( parameters.getParameter< double >( "initial-time" ) ); + status &= this->setSnapshotPeriod( parameters.getParameter< double >( "snapshot-period" ) ); + status &= this->setTimeStep( parameters.getParameter< double >( "time-step") ); + status &= this->setTimeStepOrder( parameters.getParameter< double >( "time-step-order" ) ); + if( ! status ) + return false; /**** * Set-up the discrete solver @@ -143,7 +139,7 @@ writeProlog( Logger& logger, meshPointer->writeProlog( logger ); logger.writeSeparator(); logger.writeParameter< String >( "Time discretisation:", "time-discretisation", parameters ); - logger.writeParameter< double >( "Initial time step:", this->timeStep * std::pow( meshPointer->getSmallestSpaceStep(), this->timeStepOrder ) ); + logger.writeParameter< double >( "Initial time step:", this->getRefinedTimeStep( this->meshPointer.getData(), this->timeStep ) ); logger.writeParameter< double >( "Initial time:", "initial-time", parameters ); logger.writeParameter< double >( "Final time:", "final-time", parameters ); logger.writeParameter< double >( "Snapshot period:", "snapshot-period", parameters ); @@ -275,32 +271,6 @@ getTimeStep() const return this->timeStep; } -template< typename Problem, - typename DiscreteSolver, - typename TimeStepper > -bool -TimeDependentPDESolver< Problem, DiscreteSolver, TimeStepper >:: -setTimeStepOrder( const RealType& timeStepOrder ) -{ - if( timeStepOrder < 0 ) - { - std::cerr << "The time step order for TimeDependentPDESolver must be zero or positive value." << std::endl; - return false; - } - this->timeStepOrder = timeStepOrder; - return true; -} - -template< typename Problem, - typename DiscreteSolver, - typename TimeStepper > -const typename Problem::RealType& -TimeDependentPDESolver< Problem, DiscreteSolver, TimeStepper >:: -getTimeStepOrder() const -{ - return this->timeStepOrder; -} - template< typename Problem, typename DiscreteSolver, typename TimeStepper > @@ -336,7 +306,7 @@ solve() */ this->timeStepper.setProblem( * ( this->problem ) ); this->timeStepper.init( this->meshPointer ); - this->timeStepper.setTimeStep( this->timeStep * std::pow( this->meshPointer.getData().getSmallestSpaceStep(), this->timeStepOrder ) ); + this->timeStepper.setTimeStep( this->getRefinedTimeStep( this->meshPointer.getData(), this->timeStep ) ); while( step < allSteps ) { RealType tau = min( this->snapshotPeriod, diff --git a/src/TNL/Solvers/SolverConfig_impl.h b/src/TNL/Solvers/SolverConfig_impl.h index 69b895b50164449e8aa255ea52800d314e3e0da5..9da689521d3b0b5b5c0b752e309f89eab8eca8b6 100644 --- a/src/TNL/Solvers/SolverConfig_impl.h +++ b/src/TNL/Solvers/SolverConfig_impl.h @@ -11,6 +11,7 @@ #pragma once #include <TNL/tnlConfig.h> +#include <TNL/Solvers/SolverConfig.h> #include <TNL/Solvers/BuildConfigTags.h> #include <TNL/Solvers/DummyProblem.h> #include <TNL/Solvers/PDE/ExplicitTimeStepper.h> diff --git a/src/TNL/Solvers/SolverInitiator.h b/src/TNL/Solvers/SolverInitiator.h index 329c4f6d533ad32a21610d9967bdda1625d1893b..40a6d9cddd773c29e58813b996d813373af60b67 100644 --- a/src/TNL/Solvers/SolverInitiator.h +++ b/src/TNL/Solvers/SolverInitiator.h @@ -17,8 +17,8 @@ namespace TNL { namespace Solvers { -template< template< typename Real, typename Device, typename Index, typename MeshType, typename MeshConfig, typename SolverStarter > class ProblemSetter, - typename MeshConfig > +template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, + typename ConfigTag > class SolverInitiator : public Object { public: diff --git a/src/TNL/Solvers/SolverInitiator_impl.h b/src/TNL/Solvers/SolverInitiator_impl.h index 1b5ddc1a3bd15ccd16cb4bcfa7bc6940f7342134..4736e585705f9c785dfe828cb823e8473d66db4b 100644 --- a/src/TNL/Solvers/SolverInitiator_impl.h +++ b/src/TNL/Solvers/SolverInitiator_impl.h @@ -8,16 +8,20 @@ /* See Copyright Notice in tnl/Copyright */ +#include <TNL/Solvers/SolverInitiator.h> + +#include <TNL/Devices/Host.h> +#include <TNL/Devices/Cuda.h> +#include <TNL/Devices/MIC.h> #include <TNL/Config/ParameterContainer.h> -#include <TNL/Solvers/MeshTypeResolver.h> +#include <TNL/Meshes/TypeResolver/TypeResolver.h> #include <TNL/Solvers/BuildConfigTags.h> #include <TNL/Solvers/Linear/SOR.h> #include <TNL/Solvers/Linear/CG.h> #include <TNL/Solvers/Linear/BICGStab.h> #include <TNL/Solvers/Linear/GMRES.h> -#include <TNL/Devices/Host.h> -#include <TNL/Devices/Cuda.h> -#include <TNL/Devices/MIC.h> +#include <TNL/Solvers/SolverStarter.h> +#include <TNL/Meshes/DummyMesh.h> namespace TNL { namespace Solvers { @@ -26,14 +30,14 @@ template< template< typename Real, typename Device, typename Index, typename Mes typename Real, typename ConfigTag, bool enabled = ConfigTagReal< ConfigTag, Real >::enabled > -class SolverInitiatorRealResolver{}; +class SolverInitiatorRealResolver {}; template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, typename Real, typename Device, typename ConfigTag, bool enabled = ConfigTagDevice< ConfigTag, Device >::enabled > -class SolverInitiatorDeviceResolver{}; +class SolverInitiatorDeviceResolver {}; template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, typename Real, @@ -41,7 +45,16 @@ template< template< typename Real, typename Device, typename Index, typename Mes typename Index, typename ConfigTag, bool enabled = ConfigTagIndex< ConfigTag, Index >::enabled > -class SolverInitiatorIndexResolver{}; +class SolverInitiatorIndexResolver {}; + +template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, + typename Real, + typename Device, + typename Index, + typename ConfigTag, + bool enabled = ConfigTagMeshResolve< ConfigTag >::enabled > +class SolverInitiatorMeshResolver {}; + template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, typename ConfigTag > @@ -60,6 +73,7 @@ bool SolverInitiator< ProblemSetter, ConfigTag > :: run( const Config::Parameter return false; }; + template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, typename Real, typename ConfigTag > @@ -96,6 +110,7 @@ class SolverInitiatorRealResolver< ProblemSetter, Real, ConfigTag, false > } }; + template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, typename Real, typename Device, @@ -133,6 +148,7 @@ class SolverInitiatorDeviceResolver< ProblemSetter, Real, Device, ConfigTag, fal } }; + template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, typename Real, typename Device, @@ -158,10 +174,48 @@ class SolverInitiatorIndexResolver< ProblemSetter, Real, Device, Index, ConfigTa public: static bool run( const Config::ParameterContainer& parameters ) { - return MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag >::run( parameters ); + return SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag >::run( parameters ); + } +}; + + +template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, + typename Real, + typename Device, + typename Index, + typename ConfigTag > +class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, false > +{ + public: + static bool run( const Config::ParameterContainer& parameters ) + { + return ProblemSetter< Real, + Device, + Index, + Meshes::DummyMesh< Real, Device, Index >, + ConfigTag, + SolverStarter< ConfigTag > >::template run< Real, Device, Index, ConfigTag >( parameters ); + } +}; + +template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter, + typename Real, + typename Device, + typename Index, + typename ConfigTag > +class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, true > +{ + // wrapper for MeshTypeResolver + template< typename MeshType > + using ProblemSetterWrapper = ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag > >; + + public: + static bool run( const Config::ParameterContainer& parameters ) + { + const String& meshFileName = parameters.getParameter< String >( "mesh" ); + return Meshes::resolveMeshType< ConfigTag, Device, ProblemSetterWrapper >( meshFileName, parameters ); } }; } // namespace Solvers } // namespace TNL - diff --git a/src/TNL/Solvers/SolverStarter.h b/src/TNL/Solvers/SolverStarter.h index 8cfbe25ced0ba46f786e464858b76570e280e1d7..aa4604e5f58d11e498366844a534d11d983c736b 100644 --- a/src/TNL/Solvers/SolverStarter.h +++ b/src/TNL/Solvers/SolverStarter.h @@ -18,7 +18,7 @@ namespace TNL { namespace Solvers { -template< typename MeshConfig > +template< typename ConfigTag > class SolverStarter { public: diff --git a/src/TNL/param-types.h b/src/TNL/param-types.h index b73383165d5d023e02c4cc943dc0489b57b6e892..e245ec5c995b2c1f233fdc005a7c74bd53cfeac5 100644 --- a/src/TNL/param-types.h +++ b/src/TNL/param-types.h @@ -18,6 +18,7 @@ namespace TNL { template< typename T > String getType() { return T::getType(); }; +template<> inline String getType< void >() { return String( "void" ); }; template<> inline String getType< bool >() { return String( "bool" ); }; template<> inline String getType< short int >() { return String( "short int" ); }; template<> inline String getType< int >() { return String( "int" ); }; diff --git a/src/Tools/CMakeLists.txt b/src/Tools/CMakeLists.txt index e313ef1f6ee5af61953807ae8d3eab51daa6d18d..c32d49043510fb36b06f3fac0ea8763de34c9e8e 100644 --- a/src/Tools/CMakeLists.txt +++ b/src/Tools/CMakeLists.txt @@ -7,8 +7,11 @@ CONFIGURE_FILE( "tnl-bindir.in" "${PROJECT_TOOLS_PATH}/tnl-bindir" @ONLY ) ADD_EXECUTABLE(tnl-grid-setup tnl-grid-setup.cpp ) target_link_libraries (tnl-grid-setup tnl ) -#ADD_EXECUTABLE(tnl-mesh-convert tnl-mesh-convert.cpp ) -#target_link_libraries (tnl-mesh-convert tnl ) +ADD_EXECUTABLE(tnl-grid-to-mesh tnl-grid-to-mesh.cpp ) +target_link_libraries (tnl-grid-to-mesh tnl ) + +ADD_EXECUTABLE(tnl-mesh-converter tnl-mesh-converter.cpp ) +target_link_libraries (tnl-mesh-converter tnl ) ADD_EXECUTABLE(tnl-init tnl-init.cpp ) target_link_libraries (tnl-init tnl ) @@ -42,7 +45,8 @@ INSTALL( TARGETS tnl-init tnl-view tnl-diff tnl-grid-setup - #tnl-mesh-convert + tnl-grid-to-mesh + tnl-mesh-converter tnl-dicom-reader tnl-image-converter tnl-curve2gnuplot diff --git a/src/Tools/tnl-grid-to-mesh.cpp b/src/Tools/tnl-grid-to-mesh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cd56244676ce70f700775943cfe970105ed95cd --- /dev/null +++ b/src/Tools/tnl-grid-to-mesh.cpp @@ -0,0 +1,216 @@ +#include <TNL/Meshes/TypeResolver/TypeResolver.h> + +struct GridToMeshConfigTag {}; + +namespace TNL { +namespace Meshes { +namespace BuildConfigTags { + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< GridToMeshConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< GridToMeshConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< GridToMeshConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< GridToMeshConfigTag, long int >{ enum { enabled = false }; }; + +/**** + * Unstructured meshes are disabled, only grids can be on input. + */ + +} // namespace BuildConfigTags +} // namespace Meshes +} // namespace TNL + + +// FIXME: can't be deduced from GridType +using LocalIndexType = short int; + +template< typename Mesh > +struct MeshCreator +{ + using MeshType = Mesh; + + static bool run( const Mesh& meshIn, Mesh& meshOut ) + { + std::cerr << "Got a mesh on the input." << std::endl; + return false; + } +}; + +template< typename Real, typename Device, typename Index > +struct MeshCreator< TNL::Meshes::Grid< 1, Real, Device, Index > > +{ + using GridType = TNL::Meshes::Grid< 1, Real, Device, Index >; + using CellTopology = TNL::Meshes::Topologies::Edge; + using MeshConfig = TNL::Meshes::DefaultConfig< CellTopology, + CellTopology::dimension, + typename GridType::RealType, + typename GridType::GlobalIndexType, + LocalIndexType, + typename GridType::GlobalIndexType >; + using MeshType = TNL::Meshes::Mesh< MeshConfig >; + + static bool run( const GridType& grid, MeshType& mesh ) + { + const Index numberOfVertices = grid.template getEntitiesCount< typename GridType::Vertex >(); + const Index numberOfCells = grid.template getEntitiesCount< typename GridType::Cell >(); + + TNL::Meshes::MeshBuilder< MeshType > meshBuilder; + meshBuilder.setPointsCount( numberOfVertices ); + meshBuilder.setCellsCount( numberOfCells ); + + for( Index i = 0; i < numberOfVertices; i++ ) { + const auto vertex = grid.template getEntity< typename GridType::Vertex >( i ); + meshBuilder.setPoint( i, vertex.getCenter() ); + } + + for( Index i = 0; i < numberOfCells; i++ ) { + const auto cell = grid.template getEntity< typename GridType::Cell >( i ); + const auto neighbors = cell.template getNeighborEntities< 0 >(); + meshBuilder.getCellSeed( i ).setCornerId( 0, neighbors.template getEntityIndex< -1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 1, neighbors.template getEntityIndex< 1 >() ); + } + + return meshBuilder.build( mesh ); + } +}; + +template< typename Real, typename Device, typename Index > +struct MeshCreator< TNL::Meshes::Grid< 2, Real, Device, Index > > +{ + using GridType = TNL::Meshes::Grid< 2, Real, Device, Index >; + using CellTopology = TNL::Meshes::Topologies::Quadrilateral; + using MeshConfig = TNL::Meshes::DefaultConfig< CellTopology, + CellTopology::dimension, + typename GridType::RealType, + typename GridType::GlobalIndexType, + LocalIndexType, + typename GridType::GlobalIndexType >; + using MeshType = TNL::Meshes::Mesh< MeshConfig >; + + static bool run( const GridType& grid, MeshType& mesh ) + { + const Index numberOfVertices = grid.template getEntitiesCount< typename GridType::Vertex >(); + const Index numberOfCells = grid.template getEntitiesCount< typename GridType::Cell >(); + + TNL::Meshes::MeshBuilder< MeshType > meshBuilder; + meshBuilder.setPointsCount( numberOfVertices ); + meshBuilder.setCellsCount( numberOfCells ); + + for( Index i = 0; i < numberOfVertices; i++ ) { + const auto vertex = grid.template getEntity< typename GridType::Vertex >( i ); + meshBuilder.setPoint( i, vertex.getCenter() ); + } + + for( Index i = 0; i < numberOfCells; i++ ) { + const auto cell = grid.template getEntity< typename GridType::Cell >( i ); + const auto neighbors = cell.template getNeighborEntities< 0 >(); + meshBuilder.getCellSeed( i ).setCornerId( 0, neighbors.template getEntityIndex< -1, -1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 1, neighbors.template getEntityIndex< 1, -1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 2, neighbors.template getEntityIndex< 1, 1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 3, neighbors.template getEntityIndex< -1, 1 >() ); + } + + return meshBuilder.build( mesh ); + } +}; + +template< typename Real, typename Device, typename Index > +struct MeshCreator< TNL::Meshes::Grid< 3, Real, Device, Index > > +{ + using GridType = TNL::Meshes::Grid< 3, Real, Device, Index >; + using CellTopology = TNL::Meshes::Topologies::Hexahedron; + using MeshConfig = TNL::Meshes::DefaultConfig< CellTopology, + CellTopology::dimension, + typename GridType::RealType, + typename GridType::GlobalIndexType, + LocalIndexType, + typename GridType::GlobalIndexType >; + using MeshType = TNL::Meshes::Mesh< MeshConfig >; + + static bool run( const GridType& grid, MeshType& mesh ) + { + const Index numberOfVertices = grid.template getEntitiesCount< typename GridType::Vertex >(); + const Index numberOfCells = grid.template getEntitiesCount< typename GridType::Cell >(); + + TNL::Meshes::MeshBuilder< MeshType > meshBuilder; + meshBuilder.setPointsCount( numberOfVertices ); + meshBuilder.setCellsCount( numberOfCells ); + + for( Index i = 0; i < numberOfVertices; i++ ) { + const auto vertex = grid.template getEntity< typename GridType::Vertex >( i ); + meshBuilder.setPoint( i, vertex.getCenter() ); + } + + for( Index i = 0; i < numberOfCells; i++ ) { + const auto cell = grid.template getEntity< typename GridType::Cell >( i ); + const auto neighbors = cell.template getNeighborEntities< 0 >(); + meshBuilder.getCellSeed( i ).setCornerId( 0, neighbors.template getEntityIndex< -1, -1, -1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 1, neighbors.template getEntityIndex< 1, -1, -1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 2, neighbors.template getEntityIndex< 1, 1, -1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 3, neighbors.template getEntityIndex< -1, 1, -1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 4, neighbors.template getEntityIndex< -1, -1, 1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 5, neighbors.template getEntityIndex< 1, -1, 1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 6, neighbors.template getEntityIndex< 1, 1, 1 >() ); + meshBuilder.getCellSeed( i ).setCornerId( 7, neighbors.template getEntityIndex< -1, 1, 1 >() ); + } + + return meshBuilder.build( mesh ); + } +}; + +template< typename Grid > +struct GridConverter +{ + static bool run( const TNL::String& fileName, const TNL::String& outputFileName ) + { + using MeshCreator = MeshCreator< Grid >; + using Mesh = typename MeshCreator::MeshType; + + Grid grid; + Mesh mesh; + + TNL::Meshes::Readers::TNLReader reader; + if( ! reader.readMesh( fileName, grid ) ) { + std::cerr << "Failed to load grid from file '" << fileName << "'." << std::endl; + return false; + } + + if( ! MeshCreator::run( grid, mesh ) ) { + std::cerr << "Unable to build mesh from grid." << std::endl; + return false; + } + + if( ! mesh.save( outputFileName ) ) { + std::cerr << "Failed to save the mesh to file '" << outputFileName << "'." << std::endl; + return false; + } + + return true; + } +}; + +int +main( int argc, char* argv[] ) +{ + using namespace TNL; + + if( argc < 3 ) { + std::cerr << "Usage: " << argv[ 0 ] << " input-grid.tnl output-mesh.tnl" << std::endl; + return EXIT_FAILURE; + } + + String fileName( argv[ 1 ] ); + String outputFileName( argv[ 2 ] ); + + return ! Meshes::resolveMeshType< GridToMeshConfigTag, Devices::Host, GridConverter > + ( fileName, + fileName, // passed to GridConverter::run + outputFileName + ); +} diff --git a/src/Tools/tnl-mesh-convert.cpp b/src/Tools/tnl-mesh-convert.cpp deleted file mode 100644 index d7de402bc72bc3cc84bd03452837cb7bff40833d..0000000000000000000000000000000000000000 --- a/src/Tools/tnl-mesh-convert.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************** - tnl-mesh-convert.cpp - description - ------------------- - begin : Feb 19, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#ifndef __INTEL_COMPILER -#include "tnl-mesh-convert.h" -#endif -#include <TNL/Config/ParameterContainer.h> - -void configSetup( Config::ConfigDescription& config ) -{ - config.addDelimiter ( "General settings:" ); - config.addRequiredEntry< String >( "input-file", "Input file with the mesh." ); - config.addEntry< String >( "output-file", "Output mesh file in TNL or VTK format.", "mesh.tnl" ); - //config.addEntry< String >( "output-format", "Output mesh file format.", "vtk" ); - config.addEntry< int >( "verbose", "Set the verbosity of the program.", 1 ); - config.addEntry< String >( "mesh-name", "The mesh name.", "tnl-mesh" ); -} - -int main( int argc, char* argv[] ) -{ - Config::ParameterContainer parameters; - Config::ConfigDescription conf_desc; - - configSetup( conf_desc ); - - if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) - { - conf_desc.printUsage( argv[ 0 ] ); - return EXIT_FAILURE; - } -#ifndef __INTEL_COMPILER - if( ! convertMesh( parameters ) ) - return EXIT_FAILURE; -#endif - return EXIT_SUCCESS; -} - - diff --git a/src/Tools/tnl-mesh-convert.h b/src/Tools/tnl-mesh-convert.h deleted file mode 100644 index a45e8d0e4b11d14cf5ad7af0a82404b2f6f01162..0000000000000000000000000000000000000000 --- a/src/Tools/tnl-mesh-convert.h +++ /dev/null @@ -1,123 +0,0 @@ -/*************************************************************************** - tnl-mesh-convert.h - description - ------------------- - begin : Feb 19, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#ifndef TNL_MESH_CONVERT_H_ -#define TNL_MESH_CONVERT_H_ - -#include <TNL/Config/ParameterContainer.h> -#include <TNL/Meshes/MeshDetails/MeshReaderNetgen.h> -#include <TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h> -#include <TNL/Meshes/MeshConfigBase.h> -#include <TNL/Meshes/Topologies/MeshTriangleTopology.h> -#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h> -#include <TNL/Meshes/Mesh.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshInitializer.h> -#include <TNL/Meshes/MeshDetails/MeshIntegrityChecker.h> -#include <TNL/FileName.h> - -using namespace TNL; -using namespace TNL::Meshes; - -template< typename MeshReader, - typename MeshType > -bool convertMesh( const Config::ParameterContainer& parameters ) -{ - const String& inputFileName = parameters.getParameter< String >( "input-file" ); - const String& outputFileName = parameters.getParameter< String >( "output-file" ); - const String outputFileExt = getFileExtension( outputFileName ); - - MeshType mesh; - if( ! MeshReader::readMesh( inputFileName, mesh, true ) ) - return false; - /*MeshInitializer< typename MeshType::Config > meshInitializer; - meshInitializer.setVerbose( true ); - if( ! meshInitializer.initMesh( mesh ) ) - return false; - if( ! MeshIntegrityChecker< MeshType >::checkMesh( mesh ) ) - return false;*/ - std::cout << mesh << std::endl; - std::cout << "Writing the mesh to a file " << outputFileName << "." << std::endl; - if( outputFileExt == "tnl" ) - { - if( ! mesh.save( outputFileName ) ) - { - std::cerr << "I am not able to write the mesh into the file " << outputFileName << "." << std::endl; - return false; - } - return true; - } - if( outputFileExt == "vtk" ) - { - if( ! MeshWriterVTKLegacy::write( outputFileName, mesh, true ) ) - { - std::cerr << "I am not able to write the mesh into the file " << outputFileName << "." << std::endl; - return false; - } - return true; - } - return false; -} - -bool readNetgenMesh( const Config::ParameterContainer& parameters ) -{ - const String& inputFileName = parameters.getParameter< String >( "input-file" ); - - MeshReaderNetgen meshReader; - if( ! meshReader.detectMesh( inputFileName ) ) - return false; - - std::cout << "Reading mesh with " << meshReader.getDimension() << " dimensions..." << std::endl; - - if( meshReader.getDimension() == 2 ) - { - if( meshReader.getVerticesInCell() == 3 ) - { - typedef Mesh< MeshConfigBase< MeshTriangleTopology > > MeshType; - std::cout << "Mesh consisting of triangles was detected ... " << std::endl; - return convertMesh< MeshReaderNetgen, MeshType >( parameters ); - } - if( meshReader.getVerticesInCell() == 4 ) - { - typedef Mesh< MeshConfigBase< MeshQuadrilateralTopology > > MeshType; - std::cout << "Mesh consisting of quadrilaterals was detected ... " << std::endl; - return convertMesh< MeshReaderNetgen, MeshType >( parameters ); - } - } - if( meshReader.getDimension() == 3 ) - { - if( meshReader.getVerticesInCell() == 4 ) - { - typedef Mesh< MeshConfigBase< MeshTetrahedronTopology > > MeshType; - std::cout << "Mesh consisting of tetrahedrons was detected ... " << std::endl; - return convertMesh< MeshReaderNetgen, MeshType >( parameters ); - } - if( meshReader.getVerticesInCell() == 8 ) - { - typedef Mesh< MeshConfigBase< MeshHexahedronTopology > > MeshType; - std::cout << "Mesh consisting of hexahedrons was detected ... " << std::endl; - return convertMesh< MeshReaderNetgen, MeshType >( parameters ); - } - } - std::cerr << "Wrong mesh dimensions were detected ( " << meshReader.getDimension() << " )." << std::endl; - return false; -} - -bool convertMesh( const Config::ParameterContainer& parameters ) -{ - String inputFileName = parameters.getParameter< String >( "input-file" ); - - const String fileExt = getFileExtension( inputFileName ); - if( fileExt == "ng" ) - return readNetgenMesh( parameters ); - return false; -} - - -#endif /* TNL_MESH_CONVERT_H_ */ diff --git a/src/Tools/tnl-mesh-converter.cpp b/src/Tools/tnl-mesh-converter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0bc4e050f9e1e2ec66f88695f08673e3937bbde8 --- /dev/null +++ b/src/Tools/tnl-mesh-converter.cpp @@ -0,0 +1,131 @@ +/*************************************************************************** + tnl-mesh-converter.cpp - description + ------------------- + begin : Oct 24, 2017 + copyright : (C) 2017 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#include <TNL/Config/ParameterContainer.h> +#include <TNL/Meshes/TypeResolver/TypeResolver.h> +#include <TNL/Meshes/Writers/VTKWriter.h> +#include <TNL/Meshes/Writers/NetgenWriter.h> + +using namespace TNL; + +struct MeshConverterConfigTag {}; + +namespace TNL { +namespace Meshes { +namespace BuildConfigTags { + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< MeshConverterConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< MeshConverterConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< MeshConverterConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< MeshConverterConfigTag, long int >{ enum { enabled = false }; }; + +/**** + * Unstructured meshes. + */ +template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Edge > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Triangle > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Quadrilateral > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Hexahedron > { enum { enabled = true }; }; + +// Meshes are enabled only for the world dimension equal to the cell dimension. +template< typename CellTopology, int WorldDimension > +struct MeshWorldDimensionTag< MeshConverterConfigTag, CellTopology, WorldDimension > +{ enum { enabled = ( WorldDimension == CellTopology::dimension ) }; }; + +// Meshes are enabled only for types explicitly listed below. +template< typename Real > struct MeshRealTag< MeshConverterConfigTag, Real > { enum { enabled = false }; }; +template< typename GlobalIndex > struct MeshGlobalIndexTag< MeshConverterConfigTag, GlobalIndex > { enum { enabled = false }; }; +template< typename LocalIndex > struct MeshLocalIndexTag< MeshConverterConfigTag, LocalIndex > { enum { enabled = false }; }; +template< typename GlobalIndex, typename Id > struct MeshIdTag< MeshConverterConfigTag, GlobalIndex, Id > { enum { enabled = false }; }; +template<> struct MeshRealTag< MeshConverterConfigTag, double > { enum { enabled = true }; }; +template<> struct MeshGlobalIndexTag< MeshConverterConfigTag, int > { enum { enabled = true }; }; +template<> struct MeshLocalIndexTag< MeshConverterConfigTag, short int > { enum { enabled = true }; }; +template< typename GlobalIndex > struct MeshIdTag< MeshConverterConfigTag, GlobalIndex, void > { enum { enabled = false }; }; +template< typename GlobalIndex > struct MeshIdTag< MeshConverterConfigTag, GlobalIndex, GlobalIndex > { enum { enabled = true }; }; + +} // namespace BuildConfigTags +} // namespace Meshes +} // namespace TNL + + +template< typename Mesh > +struct MeshConverter +{ + static bool run( const String& inputFileName, const String& outputFileName, const String& outputFormat ) + { + Mesh mesh; + if( ! loadMesh( inputFileName, mesh ) ) { + std::cerr << "Failed to load mesh from file '" << inputFileName << "'." << std::endl; + return false; + } + + if( outputFormat == "tnl" ) { + if( ! mesh.save( outputFileName ) ) { + std::cerr << "Failed to save the mesh to file '" << outputFileName << "'." << std::endl; + return false; + } + } + else if( outputFormat == "vtk" ) { + using VTKWriter = Meshes::Writers::VTKWriter< Mesh >; + std::fstream file( outputFileName.getString() ); + VTKWriter::template writeEntities< Mesh::getMeshDimension() >( mesh, file ); + } + // FIXME: NetgenWriter is not specialized for grids +// else if( outputFormat == "netgen" ) { +// using NetgenWriter = Meshes::Writers::NetgenWriter< Mesh >; +// std::fstream file( outputFileName.getString() ); +// NetgenWriter::writeMesh( mesh, file ); +// } + + return true; + } +}; + +void configSetup( Config::ConfigDescription& config ) +{ + config.addDelimiter( "General settings:" ); + config.addRequiredEntry< String >( "input-file", "Input file with the mesh." ); + config.addRequiredEntry< String >( "output-file", "Output mesh file in TNL or VTK format." ); + config.addEntry< String >( "output-format", "Output mesh file format." ); + config.addEntryEnum( "tnl" ); + config.addEntryEnum( "vtk" ); +// config.addEntryEnum( "netgen" ); +} + +int main( int argc, char* argv[] ) +{ + Config::ParameterContainer parameters; + Config::ConfigDescription conf_desc; + + configSetup( conf_desc ); + + if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) { + return EXIT_FAILURE; + } + + const String inputFileName = parameters.getParameter< String >( "input-file" ); + const String outputFileName = parameters.getParameter< String >( "output-file" ); + const String outputFormat = parameters.getParameter< String >( "output-format" ); + + return ! Meshes::resolveMeshType< MeshConverterConfigTag, Devices::Host, MeshConverter > + ( inputFileName, + inputFileName, // passed to MeshConverter::run + outputFileName, + outputFormat + ); +} diff --git a/src/Tools/tnl-view.cpp b/src/Tools/tnl-view.cpp index 4a5865ac610e5d0713899f9a72678ab878f13d76..453586e65caf917d8952cda8180f5ac811e8aec7 100644 --- a/src/Tools/tnl-view.cpp +++ b/src/Tools/tnl-view.cpp @@ -15,6 +15,52 @@ #include <TNL/Config/ParameterContainer.h> #include <TNL/Meshes/DummyMesh.h> #include <TNL/Meshes/Grid.h> +#include <TNL/Meshes/TypeResolver/TypeResolver.h> + +struct TNLViewBuildConfigTag {}; + +namespace TNL { +namespace Meshes { +namespace BuildConfigTags { + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< TNLViewBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< TNLViewBuildConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< TNLViewBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< TNLViewBuildConfigTag, long int >{ enum { enabled = false }; }; + +/**** + * Unstructured meshes. + */ +template<> struct MeshCellTopologyTag< TNLViewBuildConfigTag, Topologies::Edge > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< TNLViewBuildConfigTag, Topologies::Triangle > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< TNLViewBuildConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; }; + +// Meshes are enabled only for the world dimension equal to the cell dimension. +template< typename CellTopology, int WorldDimension > +struct MeshWorldDimensionTag< TNLViewBuildConfigTag, CellTopology, WorldDimension > +{ enum { enabled = ( WorldDimension == CellTopology::dimension ) }; }; + +// Meshes are enabled only for types explicitly listed below. +template< typename Real > struct MeshRealTag< TNLViewBuildConfigTag, Real > { enum { enabled = false }; }; +template< typename GlobalIndex > struct MeshGlobalIndexTag< TNLViewBuildConfigTag, GlobalIndex > { enum { enabled = false }; }; +template< typename LocalIndex > struct MeshLocalIndexTag< TNLViewBuildConfigTag, LocalIndex > { enum { enabled = false }; }; +template< typename GlobalIndex, typename Id > struct MeshIdTag< TNLViewBuildConfigTag, GlobalIndex, Id > { enum { enabled = false }; }; +template<> struct MeshRealTag< TNLViewBuildConfigTag, double > { enum { enabled = true }; }; +template<> struct MeshGlobalIndexTag< TNLViewBuildConfigTag, int > { enum { enabled = true }; }; +template<> struct MeshLocalIndexTag< TNLViewBuildConfigTag, short int > { enum { enabled = true }; }; +template< typename GlobalIndex > struct MeshIdTag< TNLViewBuildConfigTag, GlobalIndex, void > { enum { enabled = false }; }; +template< typename GlobalIndex > struct MeshIdTag< TNLViewBuildConfigTag, GlobalIndex, GlobalIndex > { enum { enabled = true }; }; + +} // namespace BuildConfigTags +} // namespace Meshes +} // namespace TNL void setupConfig( Config::ConfigDescription& config ) { @@ -55,64 +101,10 @@ int main( int argc, char* argv[] ) if( ! parseCommandLine( argc, argv, conf_desc, parameters ) ) return EXIT_FAILURE; - - int verbose = parameters. getParameter< int >( "verbose" ); - String meshFile = parameters. getParameter< String >( "mesh" ); - if( meshFile == "" ) - { - //if( ! processFiles< DummyMesh< double, Devices::Host, int > >( parameters ) ) - // return EXIT_FAILURE; - //return EXIT_SUCCESS; - } - String meshType; - if( ! getObjectType( meshFile, meshType ) ) - { - std::cerr << "I am not able to detect the mesh type from the file " << meshFile << "." << std::endl; - return EXIT_FAILURE; - } - std::cout << meshType << " detected in " << meshFile << " file." << std::endl; - Containers::List< String > parsedMeshType; - if( ! parseObjectType( meshType, parsedMeshType ) ) - { - std::cerr << "Unable to parse the mesh type " << meshType << "." << std::endl; - return EXIT_FAILURE; - } - if( parsedMeshType[ 0 ] == "Meshes::Grid" || - parsedMeshType[ 0 ] == "tnlGrid" ) // TODO: remove deprecated type name - { - int dimensions = atoi( parsedMeshType[ 1 ].getString() ); - if( dimensions == 1 ) - { - typedef Meshes::Grid< 1, double, Devices::Host, int > MeshType; - if( ! processFiles< MeshType >( parameters ) ) - return EXIT_FAILURE; - } - if( dimensions == 2 ) - { - typedef Meshes::Grid< 2, double, Devices::Host, int > MeshType; - if( ! processFiles< MeshType >( parameters ) ) - return EXIT_FAILURE; - } - if( dimensions == 3 ) - { - typedef Meshes::Grid< 3, double, Devices::Host, int > MeshType; - if( ! processFiles< MeshType >( parameters ) ) - return EXIT_FAILURE; - } - return EXIT_SUCCESS; - } - if( parsedMeshType[ 0 ] == "Meshes::Mesh" ) - { - /*String meshFile = parameters. getParameter< String >( "mesh" ); - struct MeshConfig : public MeshConfigBase< 2 > - { - typedef MeshTriangleTopology CellType; - }; - Mesh< MeshConfig > mesh; - if( ! mesh.load( meshFile ) ) - return EXIT_FAILURE; - if( ! MeshWriterNetgen::writeMesh( "tnl-mesh.ng", mesh, true ) ) - return EXIT_FAILURE;*/ - } - return EXIT_FAILURE; + String meshFile = parameters.getParameter< String >( "mesh" ); + return ! TNL::Meshes::resolveMeshType< TNLViewBuildConfigTag, + Devices::Host, + FilesProcessor > + ( meshFile, + parameters ); } diff --git a/src/Tools/tnl-view.h b/src/Tools/tnl-view.h index c4d25f1d5520d2886be390bc41763c1f338e45aa..42f4fd1b300cf7c738efdac37713a77534ce3611 100644 --- a/src/Tools/tnl-view.h +++ b/src/Tools/tnl-view.h @@ -117,7 +117,8 @@ bool setMeshFunctionRealType( const MeshPointer& meshPointer, template< typename MeshPointer, int EntityDimension, - int VectorFieldSize > + int VectorFieldSize, + typename = typename std::enable_if< EntityDimension <= MeshPointer::ObjectType::getMeshDimension() >::type > bool setMeshEntityType( const MeshPointer& meshPointer, const String& inputFileName, const Containers::List< String >& parsedObjectType, @@ -133,69 +134,27 @@ bool setMeshEntityType( const MeshPointer& meshPointer, return false; } -template< typename MeshReal, - typename MeshIndex, - int VectorFieldSize > -bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 1, MeshReal, Devices::Host, MeshIndex > >& meshPointer, - const String& inputFileName, - const Containers::List< String >& parsedObjectType, - const Config::ParameterContainer& parameters ) -{ - typedef Meshes::Grid< 1, MeshReal, Devices::Host, MeshIndex > Mesh; - typedef SharedPointer< Mesh > MeshPointer; - int meshEntityDimension = atoi( parsedObjectType[ 2 ].getString() ); - switch( meshEntityDimension ) - { - case 0: - return setMeshEntityType< MeshPointer, 0, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); - break; - case 1: - return setMeshEntityType< MeshPointer, 1, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); - break; - default: - std::cerr << "Unsupported mesh functions entity dimension count " << meshEntityDimension << "." << std::endl; - return false; - } -} - -template< typename MeshReal, - typename MeshIndex, - int VectorFieldSize > -bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 2, MeshReal, Devices::Host, MeshIndex > >& meshPointer, - const String& inputFileName, - const Containers::List< String >& parsedObjectType, - const Config::ParameterContainer& parameters ) +template< typename MeshPointer, + int EntityDimension, + int VectorFieldSize, + typename = typename std::enable_if< ( EntityDimension > MeshPointer::ObjectType::getMeshDimension() ) >::type, + typename = void > +bool setMeshEntityType( const MeshPointer& meshPointer, + const String& inputFileName, + const Containers::List< String >& parsedObjectType, + const Config::ParameterContainer& parameters ) { - typedef Meshes::Grid< 2, MeshReal, Devices::Host, MeshIndex > Mesh; - typedef SharedPointer< Mesh > MeshPointer; - int meshEntityDimension = atoi( parsedObjectType[ 2 ].getString() ); - switch( meshEntityDimension ) - { - case 0: - return setMeshEntityType< MeshPointer, 0, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); - break; - case 1: - return setMeshEntityType< MeshPointer, 1, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); - break; - case 2: - return setMeshEntityType< MeshPointer, 2, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); - break; - default: - std::cerr << "Unsupported mesh functions entity dimension count " << meshEntityDimension << "." << std::endl; - return false; - } + std::cerr << "Unsupported mesh functions entity dimension: " << EntityDimension << "." << std::endl; + return false; } -template< typename MeshReal, - typename MeshIndex, - int VectorFieldSize > -bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 3, MeshReal, Devices::Host, MeshIndex > >& meshPointer, - const String& inputFileName, - const Containers::List< String >& parsedObjectType, - const Config::ParameterContainer& parameters ) +template< int VectorFieldSize, + typename MeshPointer > +bool setMeshEntityDimension( const MeshPointer& meshPointer, + const String& inputFileName, + const Containers::List< String >& parsedObjectType, + const Config::ParameterContainer& parameters ) { - typedef Meshes::Grid< 3, MeshReal, Devices::Host, MeshIndex > Mesh; - typedef SharedPointer< Mesh > MeshPointer; int meshEntityDimension = atoi( parsedObjectType[ 2 ].getString() ); switch( meshEntityDimension ) { @@ -212,7 +171,7 @@ bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 3, MeshReal, Dev return setMeshEntityType< MeshPointer, 3, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); break; default: - std::cerr << "Unsupported mesh functions entity dimension count " << meshEntityDimension << "." << std::endl; + std::cerr << "Unsupported mesh functions entity dimension: " << meshEntityDimension << "." << std::endl; return false; } } @@ -229,9 +188,7 @@ bool setMeshFunction( const MeshPointer& meshPointer, std::cerr << "Incompatible mesh type for the mesh function " << inputFileName << "." << std::endl; return false; } - typedef typename MeshPointer::ObjectType::RealType RealType; - typedef typename MeshPointer::ObjectType::IndexType IndexType; - return setMeshEntityDimension< RealType, IndexType, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); + return setMeshEntityDimension< VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters ); } template< typename MeshPointer > @@ -307,14 +264,14 @@ bool convertObject( const MeshPointer& meshPointer, grid. setDomain( PointType( 0.0 ), PointType( 1.0 ) ); grid. setDimensions( CoordinatesType( multiVector. getDimensions() ) ); const Real spaceStep = grid. getSpaceSteps(). x(); - if( ! grid. write( multiVector, outputFileName, outputFormat ) ) +// if( ! grid. write( multiVector, outputFileName, outputFormat ) ) return false; } return true; } template< typename MeshPointer, typename Element, typename Real, typename Index > -bool setDimensions( const MeshPointer& meshPointer, +bool setDimension( const MeshPointer& meshPointer, const String& inputFileName, const Containers::List< String >& parsedObjectType, const Config::ParameterContainer& parameters ) @@ -358,9 +315,9 @@ bool setIndexType( const MeshPointer& meshPointer, indexType = parsedObjectType[ 3 ]; if( indexType == "int" ) - return setDimensions< MeshPointer, Element, Real, int >( meshPointer, inputFileName, parsedObjectType, parameters ); + return setDimension< MeshPointer, Element, Real, int >( meshPointer, inputFileName, parsedObjectType, parameters ); if( indexType == "long-int" ) - return setDimensions< MeshPointer, Element, Real, long int >( meshPointer, inputFileName, parsedObjectType, parameters ); + return setDimension< MeshPointer, Element, Real, long int >( meshPointer, inputFileName, parsedObjectType, parameters ); std::cerr << "Unknown index type " << indexType << "." << std::endl; return false; } @@ -456,83 +413,82 @@ bool setElementType( const MeshPointer& meshPointer, } template< typename Mesh > -bool processFiles( const Config::ParameterContainer& parameters ) +struct FilesProcessor { - int verbose = parameters. getParameter< int >( "verbose"); - String meshFile = parameters. getParameter< String >( "mesh" ); - - typedef SharedPointer< Mesh > MeshPointer; - MeshPointer meshPointer; - - if( meshFile != "" ) - if( ! meshPointer->load( meshFile ) ) - { - std::cerr << "I am not able to load mesh from the file " << meshFile << "." << std::endl; - return false; - } - meshPointer->writeMesh( "mesh.asy", "asymptote" ); - - bool checkOutputFile = parameters. getParameter< bool >( "check-output-file" ); - Containers::List< String > inputFiles = parameters. getParameter< Containers::List< String > >( "input-files" ); - bool error( false ); -//#ifdef HAVE_OPENMP -//#pragma omp parallel for -//#endif - for( int i = 0; i < inputFiles. getSize(); i ++ ) + static bool run( const Config::ParameterContainer& parameters ) { - if( verbose ) - std::cout << "Processing file " << inputFiles[ i ] << " ... " << std::flush; - - String outputFormat = parameters. getParameter< String >( "output-format" ); - String outputFileName; - if( ! getOutputFileName( inputFiles[ i ], - outputFormat, - outputFileName ) ) - { - error = true; - continue; - } - if( checkOutputFile && fileExists( outputFileName ) ) + int verbose = parameters. getParameter< int >( "verbose"); + String meshFile = parameters. getParameter< String >( "mesh" ); + + typedef SharedPointer< Mesh > MeshPointer; + MeshPointer meshPointer; + + if( meshFile != "" ) + if( ! loadMesh( meshFile, *meshPointer ) ) + return false; + + bool checkOutputFile = parameters. getParameter< bool >( "check-output-file" ); + Containers::List< String > inputFiles = parameters. getParameter< Containers::List< String > >( "input-files" ); + bool error( false ); + //#ifdef HAVE_OPENMP + //#pragma omp parallel for + //#endif + for( int i = 0; i < inputFiles. getSize(); i ++ ) { if( verbose ) - std::cout << " file already exists. Skipping. \r" << std::flush; - continue; - } + std::cout << "Processing file " << inputFiles[ i ] << " ... " << std::flush; - String objectType; - if( ! getObjectType( inputFiles[ i ], objectType ) ) - std::cerr << "unknown object ... SKIPPING!" << std::endl; - else - { - if( verbose ) - std::cout << objectType << " detected ... "; - - Containers::List< String > parsedObjectType; - if( ! parseObjectType( objectType, parsedObjectType ) ) + String outputFormat = parameters. getParameter< String >( "output-format" ); + String outputFileName; + if( ! getOutputFileName( inputFiles[ i ], + outputFormat, + outputFileName ) ) { - std::cerr << "Unable to parse object type " << objectType << "." << std::endl; error = true; continue; } - if( parsedObjectType[ 0 ] == "Containers::MultiVector" || - parsedObjectType[ 0 ] == "Containers::Vector" || - parsedObjectType[ 0 ] == "tnlMultiVector" || // TODO: remove deprecated type names - parsedObjectType[ 0 ] == "tnlSharedMultiVector" || // - parsedObjectType[ 0 ] == "tnlSharedVector" || // - parsedObjectType[ 0 ] == "tnlVector" ) // - setElementType< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters ); - if( parsedObjectType[ 0 ] == "Functions::MeshFunction" || - parsedObjectType[ 0 ] == "tnlMeshFunction" ) // TODO: remove deprecated type names - setMeshFunction< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters ); - if( parsedObjectType[ 0 ] == "Functions::VectorField" ) - setVectorFieldSize< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters ); - if( verbose ) - std::cout << "[ OK ]. " << std::endl; + if( checkOutputFile && fileExists( outputFileName ) ) + { + if( verbose ) + std::cout << " file already exists. Skipping. \r" << std::flush; + continue; + } + + String objectType; + if( ! getObjectType( inputFiles[ i ], objectType ) ) + std::cerr << "unknown object ... SKIPPING!" << std::endl; + else + { + if( verbose ) + std::cout << objectType << " detected ... "; + + Containers::List< String > parsedObjectType; + if( ! parseObjectType( objectType, parsedObjectType ) ) + { + std::cerr << "Unable to parse object type " << objectType << "." << std::endl; + error = true; + continue; + } + if( parsedObjectType[ 0 ] == "Containers::MultiVector" || + parsedObjectType[ 0 ] == "Containers::Vector" || + parsedObjectType[ 0 ] == "tnlMultiVector" || // TODO: remove deprecated type names + parsedObjectType[ 0 ] == "tnlSharedMultiVector" || // + parsedObjectType[ 0 ] == "tnlSharedVector" || // + parsedObjectType[ 0 ] == "tnlVector" ) // + setElementType< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters ); + if( parsedObjectType[ 0 ] == "Functions::MeshFunction" || + parsedObjectType[ 0 ] == "tnlMeshFunction" ) // TODO: remove deprecated type names + setMeshFunction< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters ); + if( parsedObjectType[ 0 ] == "Functions::VectorField" ) + setVectorFieldSize< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters ); + if( verbose ) + std::cout << "[ OK ]. " << std::endl; + } } + if( verbose ) + std::cout << std::endl; + return ! error; } - if( verbose ) - std::cout << std::endl; - return ! error; -} +}; #endif /* TNL_VIEW_H_ */ diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt index 21fef2e5607ea0f6c08d53e8f4d966fb4f236f98..3e17aad5d338f543c176d399e1df62b08f2fd1e8 100644 --- a/src/UnitTests/CMakeLists.txt +++ b/src/UnitTests/CMakeLists.txt @@ -3,6 +3,7 @@ if( WITH_TESTS STREQUAL "yes" ) ADD_SUBDIRECTORY( Containers ) ADD_SUBDIRECTORY( Matrices ) ADD_SUBDIRECTORY( Mpi ) +ADD_SUBDIRECTORY( Meshes ) ADD_EXECUTABLE( UniquePointerTest UniquePointerTest.cpp ) TARGET_COMPILE_OPTIONS( UniquePointerTest PRIVATE ${CXX_TESTS_FLAGS} ) diff --git a/src/UnitTests/Containers/CMakeLists.txt b/src/UnitTests/Containers/CMakeLists.txt index 477a161bc1eaa8070dfc29c37367632a4e907f7d..58832b04d4108ede4165995ac9bb818b806afe7d 100644 --- a/src/UnitTests/Containers/CMakeLists.txt +++ b/src/UnitTests/Containers/CMakeLists.txt @@ -81,3 +81,6 @@ ADD_TEST( StaticArrayTest ${EXECUTABLE_OUTPUT_PATH}/StaticArrayTest${CMAKE_EXECU ADD_TEST( VectorTest ${EXECUTABLE_OUTPUT_PATH}/VectorTest${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( StaticVectorTest ${EXECUTABLE_OUTPUT_PATH}/StaticVectorTest${CMAKE_EXECUTABLE_SUFFIX} ) #ADD_TEST( MultiArrayTest ${EXECUTABLE_OUTPUT_PATH}/MultiArrayTest${CMAKE_EXECUTABLE_SUFFIX} ) + + +ADD_SUBDIRECTORY( Multimaps ) diff --git a/src/UnitTests/Containers/Multimaps/CMakeLists.txt b/src/UnitTests/Containers/Multimaps/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5fb63a52191ede8885ca920420a991175f867823 --- /dev/null +++ b/src/UnitTests/Containers/Multimaps/CMakeLists.txt @@ -0,0 +1,14 @@ +ADD_EXECUTABLE( MultimapTest MultimapTest.cpp ) +TARGET_COMPILE_OPTIONS( MultimapTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( MultimapTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + +ADD_EXECUTABLE( StaticMultimapTest StaticMultimapTest.cpp ) +TARGET_COMPILE_OPTIONS( StaticMultimapTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( StaticMultimapTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + +ADD_TEST( MultimapTest ${EXECUTABLE_OUTPUT_PATH}/MultimapTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( StaticMultimapTest ${EXECUTABLE_OUTPUT_PATH}/MultimapTest${CMAKE_EXECUTABLE_SUFFIX} ) diff --git a/src/UnitTests/Containers/Multimaps/MultimapTest.cpp b/src/UnitTests/Containers/Multimaps/MultimapTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95fe0d68df1cb1bdf003bfb07189e20c5aba8a4b --- /dev/null +++ b/src/UnitTests/Containers/Multimaps/MultimapTest.cpp @@ -0,0 +1,154 @@ +#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h> + +using namespace TNL; + +using IndexType = int; +using Device = Devices::Host; +using LocalIndexType = short; + +#ifdef HAVE_GTEST +#include <gtest/gtest.h> + +TEST( MultimapTest, TestTypedefs ) +{ + using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >; + const bool same_index = std::is_same< typename MultimapType::IndexType, IndexType >::value; + ASSERT_TRUE( same_index ); + const bool same_device = std::is_same< typename MultimapType::DeviceType, Device >::value; + ASSERT_TRUE( same_device ); + const bool same_localindex = std::is_same< typename MultimapType::LocalIndexType, LocalIndexType >::value; + ASSERT_TRUE( same_localindex ); +} + +TEST( MultimapTest, TestSettingSizes ) +{ + using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >; + + IndexType inputs = 10; + LocalIndexType valuesGlobalMax = 3; + LocalIndexType valuesLocalMax = 2; + + MultimapType map; + map.setKeysRange( inputs ); + ASSERT_EQ( map.getKeysRange(), inputs ); + + typename MultimapType::ValuesAllocationVectorType allocationRanges; + allocationRanges.setSize( inputs ); + allocationRanges.setValue( valuesGlobalMax ); + allocationRanges[ 0 ] = 0; + allocationRanges[ 1 ] = 1; + map.allocate( allocationRanges ); + + for( IndexType i = 0; i < inputs; i++ ) { + auto values = map.getValues( i ); + const auto constValues = ( (const MultimapType) map ).getValues( i ); + + // uninitialized should be equal to the value from the allocation vector + ASSERT_EQ( values.getSize(), allocationRanges[ i ] ); + ASSERT_EQ( constValues.getSize(), allocationRanges[ i ] ); + + // setting lower sizes + values.setSize( valuesLocalMax ); + ASSERT_EQ( values.getSize(), valuesLocalMax ); + ASSERT_EQ( constValues.getSize(), valuesLocalMax ); + + // setting global max + values.setSize( valuesGlobalMax ); + ASSERT_EQ( values.getSize(), valuesGlobalMax ); + ASSERT_EQ( constValues.getSize(), valuesGlobalMax ); + } +} + +TEST( MultimapTest, TestSettingValues ) +{ + using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >; + + IndexType inputs = 10; + LocalIndexType allocatedValues = 2; + + MultimapType map; + map.setKeysRange( inputs ); + ASSERT_EQ( map.getKeysRange(), inputs ); + + typename MultimapType::ValuesAllocationVectorType allocationRanges; + allocationRanges.setSize( inputs ); + allocationRanges.setValue( allocatedValues ); + map.allocate( allocationRanges ); + + for( IndexType i = 0; i < inputs; i++ ) { + auto values = map.getValues( i ); + const auto constValues = ( (const MultimapType) map ).getValues( i ); + + values.setSize( allocatedValues ); + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) + values.setValue( o, i + o ); + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) { + ASSERT_EQ( values.getValue( o ), i + o ); + ASSERT_EQ( values[ o ], i + o ); + ASSERT_EQ( constValues.getValue( o ), i + o ); + ASSERT_EQ( constValues[ o ], i + o ); + } + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) + values[ o ] = i * o; + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) { + ASSERT_EQ( values.getValue( o ), i * o ); + ASSERT_EQ( values[ o ], i * o ); + ASSERT_EQ( constValues.getValue( o ), i * o ); + ASSERT_EQ( constValues[ o ], i * o ); + } + } +} + +TEST( MultimapTest, TestSaveAndLoad ) +{ + using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >; + + IndexType inputs = 10; + LocalIndexType allocatedValues = 2; + + MultimapType map, map2; + map.setKeysRange( inputs ); + ASSERT_EQ( map.getKeysRange(), inputs ); + + typename MultimapType::ValuesAllocationVectorType allocationRanges; + allocationRanges.setSize( inputs ); + allocationRanges.setValue( allocatedValues ); + map.allocate( allocationRanges ); + + for( IndexType i = 0; i < inputs; i++ ) { + auto values = map.getValues( i ); + for( LocalIndexType o = 0; o < allocatedValues; o++ ) + values.setValue( o, i + o ); + } + + ASSERT_TRUE( map.save( "multimap-test.tnl" ) ); + ASSERT_TRUE( map2.load( "multimap-test.tnl" ) ); + + EXPECT_EQ( map, map2 ); + EXPECT_EQ( map.getKeysRange(), map2.getKeysRange() ); + + for( IndexType i = 0; i < inputs; i++ ) { + auto values = map.getValues( i ); + auto values2 = map2.getValues( i ); + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) { + ASSERT_EQ( values[ o ], i + o ); + ASSERT_EQ( values2[ o ], i + o ); + } + } +} +#endif + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Containers/Multimaps/StaticMultimapTest.cpp b/src/UnitTests/Containers/Multimaps/StaticMultimapTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3ea42293e0d048b43257c2179018c0de418683e --- /dev/null +++ b/src/UnitTests/Containers/Multimaps/StaticMultimapTest.cpp @@ -0,0 +1,105 @@ +#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h> + +using namespace TNL; + +using IndexType = int; +using Device = Devices::Host; +using LocalIndexType = short; + +#ifdef HAVE_GTEST +#include <gtest/gtest.h> + +TEST( MultimapTest, TestTypedefs ) +{ + using MultimapType = TNL::StaticEllpackIndexMultimap< 4, IndexType, Device, LocalIndexType >; + const bool same_index = std::is_same< typename MultimapType::IndexType, IndexType >::value; + ASSERT_TRUE( same_index ); + const bool same_device = std::is_same< typename MultimapType::DeviceType, Device >::value; + ASSERT_TRUE( same_device ); + const bool same_localindex = std::is_same< typename MultimapType::LocalIndexType, LocalIndexType >::value; + ASSERT_TRUE( same_localindex ); +} + +TEST( MultimapTest, TestSettingValues ) +{ + using MultimapType = TNL::StaticEllpackIndexMultimap< 4, IndexType, Device, LocalIndexType >; + + const IndexType inputs = 10; + const LocalIndexType allocatedValues = 4; + + MultimapType map; + map.setKeysRange( inputs ); + ASSERT_EQ( map.getKeysRange(), inputs ); + map.allocate(); + + for( IndexType i = 0; i < inputs; i++ ) { + auto values = map.getValues( i ); + const auto constValues = ( (const MultimapType) map ).getValues( i ); + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) + values.setValue( o, i + o ); + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) { + ASSERT_EQ( values.getValue( o ), i + o ); + ASSERT_EQ( values[ o ], i + o ); + ASSERT_EQ( constValues.getValue( o ), i + o ); + ASSERT_EQ( constValues[ o ], i + o ); + } + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) + values[ o ] = i * o; + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) { + ASSERT_EQ( values.getValue( o ), i * o ); + ASSERT_EQ( values[ o ], i * o ); + ASSERT_EQ( constValues.getValue( o ), i * o ); + ASSERT_EQ( constValues[ o ], i * o ); + } + } +} + +TEST( MultimapTest, TestSaveAndLoad ) +{ + using MultimapType = TNL::StaticEllpackIndexMultimap< 4, IndexType, Device, LocalIndexType >; + + const IndexType inputs = 10; + const LocalIndexType allocatedValues = 4; + + MultimapType map, map2; + map.setKeysRange( inputs ); + ASSERT_EQ( map.getKeysRange(), inputs ); + map.allocate(); + + for( IndexType i = 0; i < inputs; i++ ) { + auto values = map.getValues( i ); + for( LocalIndexType o = 0; o < allocatedValues; o++ ) + values.setValue( o, i + o ); + } + + ASSERT_TRUE( map.save( "multimap-test.tnl" ) ); + ASSERT_TRUE( map2.load( "multimap-test.tnl" ) ); + + EXPECT_EQ( map, map2 ); + EXPECT_EQ( map.getKeysRange(), map2.getKeysRange() ); + + for( IndexType i = 0; i < inputs; i++ ) { + auto values = map.getValues( i ); + auto values2 = map2.getValues( i ); + + for( LocalIndexType o = 0; o < allocatedValues; o++ ) { + ASSERT_EQ( values[ o ], i + o ); + ASSERT_EQ( values2[ o ], i + o ); + } + } +} +#endif + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Meshes/BoundaryTagsTest.cpp b/src/UnitTests/Meshes/BoundaryTagsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..274ef974b78a2c41fa27ca08654723778bb95f9b --- /dev/null +++ b/src/UnitTests/Meshes/BoundaryTagsTest.cpp @@ -0,0 +1,11 @@ +#include "BoundaryTagsTest.h" + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Meshes/BoundaryTagsTest.h b/src/UnitTests/Meshes/BoundaryTagsTest.h new file mode 100644 index 0000000000000000000000000000000000000000..b7eccf5f24b16927a4cd211b876f24bd5d9512ed --- /dev/null +++ b/src/UnitTests/Meshes/BoundaryTagsTest.h @@ -0,0 +1,117 @@ +#pragma once + +#ifdef HAVE_GTEST +#include <gtest/gtest.h> + +#include <vector> + +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/MeshEntity.h> +#include <TNL/Meshes/DefaultConfig.h> +#include <TNL/Meshes/Topologies/Quadrilateral.h> +#include <TNL/Meshes/MeshBuilder.h> + +namespace BoundaryTagsTest { + +using namespace TNL; +using namespace TNL::Meshes; + +using RealType = double; +using Device = Devices::Host; +using IndexType = int; + +class TestQuadrilateralMeshConfig : public DefaultConfig< Topologies::Quadrilateral > +{ +public: + static constexpr bool entityStorage( int dimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return ( SubentityDimensions % 2 != 0 ); } + template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; } + template< typename EntityTopology > static constexpr bool boundaryTagsStorage( EntityTopology ) { return true; } +}; + +TEST( MeshTest, RegularMeshOfQuadrilateralsTest ) +{ + using QuadrilateralMeshEntityType = MeshEntity< TestQuadrilateralMeshConfig, Devices::Host, Topologies::Quadrilateral >; + using EdgeMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 1 >::SubentityType; + using VertexMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 0 >::SubentityType; + + using PointType = typename VertexMeshEntityType::PointType; + ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) ); + + const IndexType xSize( 3 ), ySize( 4 ); + const RealType width( 1.0 ), height( 1.0 ); + const RealType hx( width / ( RealType ) xSize ), + hy( height / ( RealType ) ySize ); + const IndexType numberOfCells = xSize * ySize; + const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ); + + typedef Mesh< TestQuadrilateralMeshConfig > TestQuadrilateralMesh; + TestQuadrilateralMesh mesh, mesh2; + MeshBuilder< TestQuadrilateralMesh > meshBuilder; + meshBuilder.setPointsCount( numberOfVertices ); + meshBuilder.setCellsCount( numberOfCells ); + + /**** + * Setup vertices + */ + for( IndexType j = 0; j <= ySize; j++ ) + for( IndexType i = 0; i <= xSize; i++ ) + meshBuilder.setPoint( j * ( xSize + 1 ) + i, PointType( i * hx, j * hy ) ); + + /**** + * Setup cells + */ + IndexType cellIdx( 0 ); + for( IndexType j = 0; j < ySize; j++ ) + for( IndexType i = 0; i < xSize; i++ ) + { + const IndexType vertex0 = j * ( xSize + 1 ) + i; + const IndexType vertex1 = j * ( xSize + 1 ) + i + 1; + const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i + 1; + const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i; + + meshBuilder.getCellSeed( cellIdx ).setCornerId( 0, vertex0 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 1, vertex1 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 2, vertex2 ); + meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 3, vertex3 ); + } + + ASSERT_TRUE( meshBuilder.build( mesh ) ); + + std::vector< IndexType > boundaryCells = {0, 1, 2, 3, 5, 6, 8, 9, 10, 11}; + std::vector< IndexType > interiorCells = {4, 7}; + + // Test boundary cells + EXPECT_EQ( mesh.template getBoundaryEntitiesCount< 2 >(), (int) boundaryCells.size() ); + for( size_t i = 0; i < boundaryCells.size(); i++ ) { + EXPECT_TRUE( mesh.template isBoundaryEntity< 2 >( boundaryCells[ i ] ) ); + EXPECT_EQ( mesh.template getBoundaryEntityIndex< 2 >( i ), boundaryCells[ i ] ); + } + // Test interior cells + EXPECT_EQ( mesh.template getInteriorEntitiesCount< 2 >(), (int) interiorCells.size() ); + for( size_t i = 0; i < interiorCells.size(); i++ ) { + EXPECT_FALSE( mesh.template isBoundaryEntity< 2 >( interiorCells[ i ] ) ); + EXPECT_EQ( mesh.template getInteriorEntityIndex< 2 >( i ), interiorCells[ i ] ); + } + + std::vector< IndexType > boundaryFaces = {0, 3, 4, 7, 8, 12, 15, 19, 22, 25, 26, 28, 29, 30}; + std::vector< IndexType > interiorFaces = {1, 2, 5, 6, 9, 10, 11, 13, 14, 16, 17, 18, 20, 21, 23, 24, 27}; + + // Test boundary faces + EXPECT_EQ( mesh.template getBoundaryEntitiesCount< 1 >(), (int) boundaryFaces.size() ); + for( size_t i = 0; i < boundaryFaces.size(); i++ ) { + EXPECT_TRUE( mesh.template isBoundaryEntity< 1 >( boundaryFaces[ i ] ) ); + EXPECT_EQ( mesh.template getBoundaryEntityIndex< 1 >( i ), boundaryFaces[ i ] ); + } + // Test interior faces + EXPECT_EQ( mesh.template getInteriorEntitiesCount< 1 >(), (int) interiorFaces.size() ); + for( size_t i = 0; i < interiorFaces.size(); i++ ) { + EXPECT_FALSE( mesh.template isBoundaryEntity< 1 >( interiorFaces[ i ] ) ); + EXPECT_EQ( mesh.template getInteriorEntityIndex< 1 >( i ), interiorFaces[ i ] ); + } +} + +} // namespace BoundaryTagsTest + +#endif diff --git a/src/UnitTests/Meshes/CMakeLists.txt b/src/UnitTests/Meshes/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..97cdc0333d747c2e6162a6b9ecb115b6c91a001a --- /dev/null +++ b/src/UnitTests/Meshes/CMakeLists.txt @@ -0,0 +1,74 @@ +ADD_EXECUTABLE( BoundaryTagsTest BoundaryTagsTest.cpp ) +TARGET_COMPILE_OPTIONS( BoundaryTagsTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( BoundaryTagsTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + +if( BUILD_CUDA AND ${CMAKE_CXX_COMPILER} MATCHES ".*clang\\+\\+" ) + CUDA_ADD_EXECUTABLE( MeshTest MeshTest.cu + OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( MeshTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + + CUDA_ADD_EXECUTABLE( MeshOrderingTest MeshOrderingTest.cu + OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( MeshOrderingTest + ${GTEST_BOTH_LIBRARIES} + tnl ) +else() + ADD_EXECUTABLE( MeshTest MeshTest.cpp ) + TARGET_COMPILE_OPTIONS( MeshTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( MeshTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + + ADD_EXECUTABLE( MeshOrderingTest MeshOrderingTest.cpp ) + TARGET_COMPILE_OPTIONS( MeshOrderingTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( MeshOrderingTest + ${GTEST_BOTH_LIBRARIES} + tnl ) +endif() + +ADD_EXECUTABLE( MeshEntityTest MeshEntityTest.cpp ) +TARGET_COMPILE_OPTIONS( MeshEntityTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( MeshEntityTest + ${GTEST_BOTH_LIBRARIES} + tnl ) + + +ADD_TEST( BoundaryTagsTest ${EXECUTABLE_OUTPUT_PATH}/BoundaryTagsTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( MeshTest ${EXECUTABLE_OUTPUT_PATH}/MeshTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( MeshOrderingTest ${EXECUTABLE_OUTPUT_PATH}/MeshOrderingTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( MeshEntityTest ${EXECUTABLE_OUTPUT_PATH}/MeshEntityTest${CMAKE_EXECUTABLE_SUFFIX} ) + + + +## +## Tests with VTK +## + +find_package( VTK ) +if( VTK_FOUND ) + include(${VTK_USE_FILE}) + + AddCompilerFlag( "-DHAVE_VTK " ) + SET( VTK_COMMON_LIBRARIES vtkCommonCore ; vtkIOLegacy ) +endif( VTK_FOUND ) + +# FIXME: compilation fails with nvcc (CUDA 9.0) +#if( BUILD_CUDA AND ${CMAKE_CXX_COMPILER} MATCHES ".*clang\\+\\+" ) +# CUDA_ADD_EXECUTABLE( MeshReaderTest MeshReaderTest.cu +# OPTIONS ${CXX_TESTS_FLAGS} ) +# TARGET_LINK_LIBRARIES( MeshReaderTest +# ${GTEST_BOTH_LIBRARIES} +# ${VTK_COMMON_LIBRARIES} +# tnl ) +#else() + ADD_EXECUTABLE( MeshReaderTest MeshReaderTest.cpp ) + TARGET_COMPILE_OPTIONS( MeshReaderTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( MeshReaderTest + ${GTEST_BOTH_LIBRARIES} + ${VTK_COMMON_LIBRARIES} + tnl ) +#endif() diff --git a/src/UnitTests/Meshes/MeshEntityTest.cpp b/src/UnitTests/Meshes/MeshEntityTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3f87a32bf81d05898c1451dc88488b71df8dc31 --- /dev/null +++ b/src/UnitTests/Meshes/MeshEntityTest.cpp @@ -0,0 +1,11 @@ +#include "MeshEntityTest.h" + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Meshes/MeshEntityTest.h b/src/UnitTests/Meshes/MeshEntityTest.h new file mode 100644 index 0000000000000000000000000000000000000000..5360fd6a8b9151972c798f8f2abb97bf6e31d6eb --- /dev/null +++ b/src/UnitTests/Meshes/MeshEntityTest.h @@ -0,0 +1,794 @@ +#pragma once + +#ifdef HAVE_GTEST +#include <gtest/gtest.h> + +#include <TNL/Meshes/MeshEntity.h> +#include <TNL/Meshes/DefaultConfig.h> +#include <TNL/Meshes/Topologies/Vertex.h> +#include <TNL/Meshes/Topologies/Edge.h> +#include <TNL/Meshes/Topologies/Triangle.h> +#include <TNL/Meshes/Topologies/Tetrahedron.h> + +namespace MeshEntityTest { + +using namespace TNL; +using namespace TNL::Meshes; + +using RealType = double; +using Device = Devices::Host; +using IndexType = int; + +using TestEdgeMeshConfig = DefaultConfig< Topologies::Edge, 2, RealType, IndexType, IndexType, void >; + +class TestTriangleMeshConfig : public DefaultConfig< Topologies::Triangle > +{ +public: + template< typename EntityTopology > + static constexpr bool subentityStorage( EntityTopology entity, int subentityDimensions ) + { + return true; + } + + template< typename EntityTopology > + static constexpr bool superentityStorage( EntityTopology entity, int superentityDimensions ) + { + return true; + } +}; + +class TestTetrahedronMeshConfig : public DefaultConfig< Topologies::Tetrahedron > +{ +public: + template< typename EntityTopology > + static constexpr bool subentityStorage( EntityTopology entity, int subentityDimensions ) + { + return true; + } + + template< typename EntityTopology > + static constexpr bool superentityStorage( EntityTopology entity, int superentityDimensions ) + { + return true; + } +}; + +template< typename MeshConfig, typename EntityTopology, int Dimensions > +using SubentityStorage = typename MeshSubentityTraits< MeshConfig, Devices::Host, EntityTopology, Dimensions >::StorageNetworkType; + +template< typename MeshConfig, typename EntityTopology, int Dimensions > +using SuperentityStorage = typename MeshSuperentityTraits< MeshConfig, Devices::Host, EntityTopology, Dimensions >::StorageNetworkType; + +// stupid wrapper around MeshEntity to expose protected members needed for tests +template< typename MeshConfig, typename EntityTopology > +class TestMeshEntity + : public MeshEntity< MeshConfig, Devices::Host, EntityTopology > +{ + using BaseType = MeshEntity< MeshConfig, Devices::Host, EntityTopology >; + +public: + template< int Subdimensions, typename Storage > + void bindSubentitiesStorageNetwork( const Storage& storage ) + { + BaseType::template bindSubentitiesStorageNetwork< Subdimensions >( storage ); + } + + template< int Subdimensions > + void setSubentityIndex( const typename BaseType::LocalIndexType& localIndex, + const typename BaseType::GlobalIndexType& globalIndex ) + { + BaseType::template setSubentityIndex< Subdimensions >( localIndex, globalIndex ); + } + + using BaseType::bindSuperentitiesStorageNetwork; + using BaseType::setNumberOfSuperentities; + using BaseType::setSuperentityIndex; + using BaseType::setIndex; +}; + +template< typename Entity > +void generalTestSubentities( const Entity& entity ) +{ + Entity copy1( entity ); + Entity copy2 = entity; + + // check that subentity accessors have been rebound, at least for the 0th subvertex + EXPECT_EQ( copy1.template getSubentityIndex< 0 >( 0 ), entity.template getSubentityIndex< 0 >( 0 ) ); + EXPECT_EQ( copy2.template getSubentityIndex< 0 >( 0 ), entity.template getSubentityIndex< 0 >( 0 ) ); +} + +template< typename Entity > +void generalTestSuperentities( const Entity& entity ) +{ + Entity copy1( entity ); + Entity copy2 = entity; + + // check that subentity accessors have been rebound, at least for the 0th superentity + EXPECT_EQ( copy1.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ), entity.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ) ); + EXPECT_EQ( copy2.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ), entity.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ) ); +} + +TEST( MeshEntityTest, VertexMeshEntityTest ) +{ + using EdgeMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, Topologies::Edge >; + using VertexMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, typename EdgeMeshEntityType::SubentityTraits< 0 >::SubentityTopology >; + + using PointType = typename VertexMeshEntityType::PointType; + EXPECT_EQ( PointType::getType(), ( Containers::StaticVector< 2, RealType >::getType() ) ); + + VertexMeshEntityType vertexEntity; + PointType point; + point.x() = 1.0; + point.y() = 2.0; + vertexEntity.setPoint( point ); + EXPECT_EQ( vertexEntity.getPoint(), point ); +} + +TEST( MeshEntityTest, EdgeMeshEntityTest ) +{ + using EdgeMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, Topologies::Edge >; + using VertexMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, typename EdgeMeshEntityType::SubentityTraits< 0 >::SubentityTopology >; + static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." ); + + using PointType = typename VertexMeshEntityType::PointType; + EXPECT_EQ( PointType::getType(), ( Containers::StaticVector< 2, RealType >::getType() ) ); + + /**** + * + * Here we test the following simple example: + * + + point2 + |\ + | \ + | \ + | \ + + .... + edge1 edge0 + .... + + + | \ + | \ + --------------------- + point0 edge2 point1 + + */ + + PointType point0( 0.0, 0.0 ), + point1( 1.0, 0.0 ), + point2( 0.0, 1.0 ); + + Containers::StaticArray< 3, VertexMeshEntityType > vertexEntities; + vertexEntities[ 0 ].setPoint( point0 ); + vertexEntities[ 1 ].setPoint( point1 ); + vertexEntities[ 2 ].setPoint( point2 ); + + EXPECT_EQ( vertexEntities[ 0 ].getPoint(), point0 ); + EXPECT_EQ( vertexEntities[ 1 ].getPoint(), point1 ); + EXPECT_EQ( vertexEntities[ 2 ].getPoint(), point2 ); + + Containers::StaticArray< 3, EdgeMeshEntityType > edgeEntities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities; + edgeVertexSubentities.setKeysRange( 3 ); + edgeVertexSubentities.allocate(); + + edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, 0 ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, 1 ); + edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, 1 ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, 2 ); + edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, 2 ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, 0 ); + edgeEntities[ 0 ].setIndex( 0 ); + edgeEntities[ 1 ].setIndex( 1 ); + edgeEntities[ 2 ].setIndex( 2 ); + + EXPECT_EQ( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 0 ) ].getPoint(), point0 ); + EXPECT_EQ( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 1 ) ].getPoint(), point1 ); + EXPECT_EQ( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 0 ) ].getPoint(), point1 ); + EXPECT_EQ( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 1 ) ].getPoint(), point2 ); + EXPECT_EQ( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 0 ) ].getPoint(), point2 ); + EXPECT_EQ( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 1 ) ].getPoint(), point0 ); + + + generalTestSubentities( edgeEntities[ 0 ] ); + generalTestSubentities( edgeEntities[ 1 ] ); + generalTestSubentities( edgeEntities[ 2 ] ); +} + +TEST( MeshEntityTest, TriangleMeshEntityTest ) +{ + using TriangleMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, Topologies::Triangle >; + using EdgeMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityTopology >; + using VertexMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityTopology >; + + static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." ); + static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." ); + + using PointType = typename VertexMeshEntityType::PointType; + EXPECT_EQ( PointType::getType(), ( Containers::StaticVector< 2, RealType >::getType() ) ); + + /**** + * We set-up the same situation as in the test above + */ + PointType point0( 0.0, 0.0 ), + point1( 1.0, 0.0 ), + point2( 0.0, 1.0 ); + + Containers::StaticArray< 3, VertexMeshEntityType > vertexEntities; + vertexEntities[ 0 ].setPoint( point0 ); + vertexEntities[ 1 ].setPoint( point1 ); + vertexEntities[ 2 ].setPoint( point2 ); + + EXPECT_EQ( vertexEntities[ 0 ].getPoint(), point0 ); + EXPECT_EQ( vertexEntities[ 1 ].getPoint(), point1 ); + EXPECT_EQ( vertexEntities[ 2 ].getPoint(), point2 ); + + Containers::StaticArray< 3, EdgeMeshEntityType > edgeEntities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities; + edgeVertexSubentities.setKeysRange( 3 ); + edgeVertexSubentities.allocate(); + + edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 0 >::index ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 1 >::index ); + edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 0 >::index ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 1 >::index ); + edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 0 >::index ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 1 >::index ); + + EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 1 >::index ) ); + EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 1 >::index ) ); + EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 1 >::index ) ); + + TriangleMeshEntityType triangleEntity; + SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 1 > triangleEdgeSubentities; + triangleVertexSubentities.setKeysRange( 1 ); + triangleEdgeSubentities.setKeysRange( 1 ); + triangleVertexSubentities.allocate(); + triangleEdgeSubentities.allocate(); + + triangleEntity.template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) ); + triangleEntity.template setSubentityIndex< 0 >( 0 , 0 ); + triangleEntity.template setSubentityIndex< 0 >( 1 , 1 ); + triangleEntity.template setSubentityIndex< 0 >( 2 , 2 ); + + EXPECT_EQ( triangleEntity.template getSubentityIndex< 0 >( 0 ), 0 ); + EXPECT_EQ( triangleEntity.template getSubentityIndex< 0 >( 1 ), 1 ); + EXPECT_EQ( triangleEntity.template getSubentityIndex< 0 >( 2 ), 2 ); + + triangleEntity.template bindSubentitiesStorageNetwork< 1 >( triangleEdgeSubentities.getValues( 0 ) ); + triangleEntity.template setSubentityIndex< 1 >( 0 , 0 ); + triangleEntity.template setSubentityIndex< 1 >( 1 , 1 ); + triangleEntity.template setSubentityIndex< 1 >( 2 , 2 ); + + EXPECT_EQ( triangleEntity.template getSubentityIndex< 1 >( 0 ), 0 ); + EXPECT_EQ( triangleEntity.template getSubentityIndex< 1 >( 1 ), 1 ); + EXPECT_EQ( triangleEntity.template getSubentityIndex< 1 >( 2 ), 2 ); +} + +TEST( MeshEntityTest, TetrahedronMeshEntityTest ) +{ + using TetrahedronMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, Topologies::Tetrahedron >; + using TriangleMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, typename TetrahedronMeshEntityType::SubentityTraits< 2 >::SubentityTopology >; + using EdgeMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, typename TetrahedronMeshEntityType::SubentityTraits< 1 >::SubentityTopology >; + using VertexMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, typename TetrahedronMeshEntityType::SubentityTraits< 0 >::SubentityTopology >; + + static_assert( TetrahedronMeshEntityType::SubentityTraits< 2 >::storageEnabled, "Testing tetrahedron entity does not store triangles as required." ); + static_assert( TetrahedronMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing tetrahedron entity does not store edges as required." ); + static_assert( TetrahedronMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing tetrahedron entity does not store vertices as required." ); + static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." ); + static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." ); + + using PointType = typename VertexMeshEntityType::PointType; + EXPECT_EQ( PointType::getType(), ( Containers::StaticVector< 3, RealType >::getType() ) ); + + /**** + * We set-up similar situation as above but with + * tetrahedron. + */ + PointType point0( 0.0, 0.0, 0.0), + point1( 1.0, 0.0, 0.0 ), + point2( 0.0, 1.0, 0.0 ), + point3( 0.0, 0.0, 1.0 ); + + Containers::StaticArray< Topologies::Subtopology< Topologies::Tetrahedron, 0 >::count, + VertexMeshEntityType > vertexEntities; + + vertexEntities[ 0 ].setPoint( point0 ); + vertexEntities[ 1 ].setPoint( point1 ); + vertexEntities[ 2 ].setPoint( point2 ); + vertexEntities[ 3 ].setPoint( point3 ); + + EXPECT_EQ( vertexEntities[ 0 ].getPoint(), point0 ); + EXPECT_EQ( vertexEntities[ 1 ].getPoint(), point1 ); + EXPECT_EQ( vertexEntities[ 2 ].getPoint(), point2 ); + EXPECT_EQ( vertexEntities[ 3 ].getPoint(), point3 ); + + Containers::StaticArray< Topologies::Subtopology< Topologies::Tetrahedron, 1 >::count, + EdgeMeshEntityType > edgeEntities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities; + edgeVertexSubentities.setKeysRange( 6 ); + edgeVertexSubentities.allocate(); + + edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 0 >::index ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 1 >::index ); + edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 0 >::index ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 1 >::index ); + edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 0 >::index ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 1 >::index ); + edgeEntities[ 3 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 3 ) ); + edgeEntities[ 3 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 0 >::index ); + edgeEntities[ 3 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 1 >::index ); + edgeEntities[ 4 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 4 ) ); + edgeEntities[ 4 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 0 >::index ); + edgeEntities[ 4 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 1 >::index ); + edgeEntities[ 5 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 5 ) ); + edgeEntities[ 5 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 0 >::index ); + edgeEntities[ 5 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 1 >::index ); + + EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 1 >::index ) ); + EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 1 >::index ) ); + EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 1 >::index ) ); + EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 1 >::index ) ); + EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 1 >::index ) ); + EXPECT_EQ( edgeEntities[ 5 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 0 >::index ) ); + EXPECT_EQ( edgeEntities[ 5 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 1 >::index ) ); + + Containers::StaticArray< Topologies::Subtopology< Topologies::Tetrahedron, 2 >::count, + TriangleMeshEntityType > triangleEntities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities; + triangleVertexSubentities.setKeysRange( 4 ); + triangleVertexSubentities.allocate(); + + triangleEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) ); + triangleEntities[ 0 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 0 >::index ); + triangleEntities[ 0 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 1 >::index ); + triangleEntities[ 0 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 2 >::index ); + triangleEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 1 ) ); + triangleEntities[ 1 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 0 >::index ); + triangleEntities[ 1 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 1 >::index ); + triangleEntities[ 1 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 2 >::index ); + triangleEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 2 ) ); + triangleEntities[ 2 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 0 >::index ); + triangleEntities[ 2 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 1 >::index ); + triangleEntities[ 2 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 2 >::index ); + triangleEntities[ 3 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 3 ) ); + triangleEntities[ 3 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 3, 0 >::index ); + triangleEntities[ 3 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 3, 1 >::index ); + triangleEntities[ 3 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 3, 2 >::index ); + + EXPECT_EQ( triangleEntities[ 0 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 0 >::index ) ); + EXPECT_EQ( triangleEntities[ 0 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 1 >::index ) ); + EXPECT_EQ( triangleEntities[ 0 ].getVertexIndex( 2 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 2 >::index ) ); + EXPECT_EQ( triangleEntities[ 1 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 0 >::index ) ); + EXPECT_EQ( triangleEntities[ 1 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 1 >::index ) ); + EXPECT_EQ( triangleEntities[ 1 ].getVertexIndex( 2 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 2 >::index ) ); + EXPECT_EQ( triangleEntities[ 2 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 0 >::index ) ); + EXPECT_EQ( triangleEntities[ 2 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 1 >::index ) ); + EXPECT_EQ( triangleEntities[ 2 ].getVertexIndex( 2 ), ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 2 >::index ) ); + + TetrahedronMeshEntityType tetrahedronEntity; + SubentityStorage< TestTriangleMeshConfig, Topologies::Tetrahedron, 0 > tetrahedronVertexSubentities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Tetrahedron, 1 > tetrahedronEdgeSubentities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Tetrahedron, 2 > tetrahedronTriangleSubentities; + tetrahedronVertexSubentities.setKeysRange( 1 ); + tetrahedronEdgeSubentities.setKeysRange( 1 ); + tetrahedronTriangleSubentities.setKeysRange( 1 ); + tetrahedronVertexSubentities.allocate(); + tetrahedronEdgeSubentities.allocate(); + tetrahedronTriangleSubentities.allocate(); + + tetrahedronEntity.template bindSubentitiesStorageNetwork< 0 >( tetrahedronVertexSubentities.getValues( 0 ) ); + tetrahedronEntity.template setSubentityIndex< 0 >( 0, 0 ); + tetrahedronEntity.template setSubentityIndex< 0 >( 1, 1 ); + tetrahedronEntity.template setSubentityIndex< 0 >( 2, 2 ); + tetrahedronEntity.template setSubentityIndex< 0 >( 3, 3 ); + + EXPECT_EQ( tetrahedronEntity.getVertexIndex( 0 ), 0 ); + EXPECT_EQ( tetrahedronEntity.getVertexIndex( 1 ), 1 ); + EXPECT_EQ( tetrahedronEntity.getVertexIndex( 2 ), 2 ); + EXPECT_EQ( tetrahedronEntity.getVertexIndex( 3 ), 3 ); + + tetrahedronEntity.template bindSubentitiesStorageNetwork< 2 >( tetrahedronTriangleSubentities.getValues( 0 ) ); + tetrahedronEntity.template setSubentityIndex< 2 >( 0, 0 ); + tetrahedronEntity.template setSubentityIndex< 2 >( 1, 1 ); + tetrahedronEntity.template setSubentityIndex< 2 >( 2, 2 ); + tetrahedronEntity.template setSubentityIndex< 2 >( 3, 3 ); + + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 0 ), 0 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 1 ), 1 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 2 ), 2 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 3 ), 3 ); + + tetrahedronEntity.template bindSubentitiesStorageNetwork< 1 >( tetrahedronEdgeSubentities.getValues( 0 ) ); + tetrahedronEntity.template setSubentityIndex< 1 >( 0, 0 ); + tetrahedronEntity.template setSubentityIndex< 1 >( 1, 1 ); + tetrahedronEntity.template setSubentityIndex< 1 >( 2, 2 ); + tetrahedronEntity.template setSubentityIndex< 1 >( 3, 3 ); + tetrahedronEntity.template setSubentityIndex< 1 >( 4, 4 ); + tetrahedronEntity.template setSubentityIndex< 1 >( 5, 5 ); + + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 0 ), 0 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 1 ), 1 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 2 ), 2 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 3 ), 3 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 4 ), 4 ); + EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 5 ), 5 ); + + + generalTestSubentities( edgeEntities[ 0 ] ); + generalTestSubentities( edgeEntities[ 1 ] ); + generalTestSubentities( edgeEntities[ 2 ] ); + generalTestSubentities( tetrahedronEntity ); +} + +TEST( MeshEntityTest, TwoTrianglesMeshEntityTest ) +{ + using TriangleMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, Topologies::Triangle >; + using EdgeMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityTopology >; + using VertexMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityTopology >; + + static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." ); + static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." ); + + using PointType = typename VertexMeshEntityType::PointType; + EXPECT_EQ( PointType::getType(), ( Containers::StaticVector< 2, RealType >::getType() ) ); + + /**** + * We set-up the following situation + point2 edge3 point3 + |\-------------------| + | \ | + | \ triangle1 | + | \ | + + .... + edge1 edge0 edge4 + .... + + + | triangle0 \ | + | \ | + ---------------------| + point0 edge2 point1 + */ + + PointType point0( 0.0, 0.0 ), + point1( 1.0, 0.0 ), + point2( 0.0, 1.0 ), + point3( 1.0, 1.0 ); + + Containers::StaticArray< 4, VertexMeshEntityType > vertexEntities; + vertexEntities[ 0 ].setPoint( point0 ); + vertexEntities[ 1 ].setPoint( point1 ); + vertexEntities[ 2 ].setPoint( point2 ); + vertexEntities[ 3 ].setPoint( point3 ); + + EXPECT_EQ( vertexEntities[ 0 ].getPoint(), point0 ); + EXPECT_EQ( vertexEntities[ 1 ].getPoint(), point1 ); + EXPECT_EQ( vertexEntities[ 2 ].getPoint(), point2 ); + EXPECT_EQ( vertexEntities[ 3 ].getPoint(), point3 ); + + Containers::StaticArray< 5, EdgeMeshEntityType > edgeEntities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities; + edgeVertexSubentities.setKeysRange( 5 ); + edgeVertexSubentities.allocate(); + + edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, 1 ); + edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, 2 ); + edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, 2 ); + edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, 0 ); + edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, 0 ); + edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, 1 ); + edgeEntities[ 3 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 3 ) ); + edgeEntities[ 3 ].template setSubentityIndex< 0 >( 0, 2 ); + edgeEntities[ 3 ].template setSubentityIndex< 0 >( 1, 3 ); + edgeEntities[ 4 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 4 ) ); + edgeEntities[ 4 ].template setSubentityIndex< 0 >( 0, 3 ); + edgeEntities[ 4 ].template setSubentityIndex< 0 >( 1, 1 ); + + EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 0 ), 1 ); + EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 1 ), 2 ); + EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 0 ), 2 ); + EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 1 ), 0 ); + EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 0 ), 0 ); + EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 1 ), 1 ); + EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 0 ), 2 ); + EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 1 ), 3 ); + EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 0 ), 3 ); + EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 1 ), 1 ); + + Containers::StaticArray< 2, TriangleMeshEntityType > triangleEntities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 1 > triangleEdgeSubentities; + triangleVertexSubentities.setKeysRange( 2 ); + triangleVertexSubentities.allocate(); + triangleEdgeSubentities.setKeysRange( 2 ); + triangleEdgeSubentities.allocate(); + + triangleEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) ); + triangleEntities[ 0 ].template setSubentityIndex< 0 >( 0 , 0 ); + triangleEntities[ 0 ].template setSubentityIndex< 0 >( 1 , 1 ); + triangleEntities[ 0 ].template setSubentityIndex< 0 >( 2 , 2 ); + triangleEntities[ 0 ].template bindSubentitiesStorageNetwork< 1 >( triangleEdgeSubentities.getValues( 0 ) ); + triangleEntities[ 0 ].template setSubentityIndex< 1 >( 0 , 0 ); + triangleEntities[ 0 ].template setSubentityIndex< 1 >( 1 , 1 ); + triangleEntities[ 0 ].template setSubentityIndex< 1 >( 2 , 2 ); + triangleEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 1 ) ); + triangleEntities[ 1 ].template setSubentityIndex< 0 >( 0 , 1 ); + triangleEntities[ 1 ].template setSubentityIndex< 0 >( 1 , 2 ); + triangleEntities[ 1 ].template setSubentityIndex< 0 >( 2 , 3 ); + triangleEntities[ 1 ].template bindSubentitiesStorageNetwork< 1 >( triangleEdgeSubentities.getValues( 1 ) ); + triangleEntities[ 1 ].template setSubentityIndex< 1 >( 0 , 3 ); + triangleEntities[ 1 ].template setSubentityIndex< 1 >( 1 , 4 ); + triangleEntities[ 1 ].template setSubentityIndex< 1 >( 2 , 0 ); + + EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 0 ), 0 ); + EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 1 ), 1 ); + EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 2 ), 2 ); + EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 0 ), 0 ); + EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 1 ), 1 ); + EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 2 ), 2 ); + EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 0 ), 1 ); + EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 1 ), 2 ); + EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 2 ), 3 ); + EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 0 ), 3 ); + EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 1 ), 4 ); + EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 2 ), 0 ); + + + /* + * Tests for the superentities layer. + */ + SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 1 > vertexEdgeSuperentities; + vertexEdgeSuperentities.setKeysRange( 4 ); + vertexEdgeSuperentities.allocate( 3 ); + + vertexEntities[ 0 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 0 ) ); + vertexEntities[ 0 ].template setNumberOfSuperentities< 1 >( 2 ); + vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 0, 2 ); + vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 1, 1 ); + + EXPECT_EQ( vertexEntities[ 0 ].template getSuperentitiesCount< 1 >(), 2 ); + EXPECT_EQ( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 0 ), 2 ); + EXPECT_EQ( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 1 ), 1 ); + + vertexEntities[ 1 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 1 ) ); + vertexEntities[ 1 ].template setNumberOfSuperentities< 1 >( 3 ); + vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 0, 0 ); + vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 1, 2 ); + vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 2, 4 ); + + EXPECT_EQ( vertexEntities[ 1 ].template getSuperentitiesCount< 1 >(), 3 ); + EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 0 ), 0 ); + EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 1 ), 2 ); + EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 2 ), 4 ); + + + SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 2 > vertexCellSuperentities; + vertexCellSuperentities.setKeysRange( 4 ); + vertexCellSuperentities.allocate( 2 ); + + vertexEntities[ 1 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 1 ) ); + vertexEntities[ 1 ].template setNumberOfSuperentities< 2 >( 2 ); + vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 0, 0 ); + vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 1, 1 ); + + EXPECT_EQ( vertexEntities[ 1 ].template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 0 ), 0 ); + EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 1 ), 1 ); + + + SuperentityStorage< TestTriangleMeshConfig, Topologies::Edge, 2 > edgeCellSuperentities; + edgeCellSuperentities.setKeysRange( 5 ); + edgeCellSuperentities.allocate( 2 ); + + edgeEntities[ 0 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 0 ) ); + edgeEntities[ 0 ].template setNumberOfSuperentities< 2 >( 2 ); + edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 0, 0 ); + edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 1, 1 ); + + EXPECT_EQ( edgeEntities[ 0 ].template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( edgeEntities[ 0 ].template getSuperentityIndex< 2 >( 0 ), 0 ); + EXPECT_EQ( edgeEntities[ 0 ].template getSuperentityIndex< 2 >( 1 ), 1 ); + + + generalTestSuperentities( vertexEntities[ 0 ] ); + generalTestSuperentities( vertexEntities[ 1 ] ); + generalTestSuperentities( edgeEntities[ 0 ] ); + generalTestSubentities( edgeEntities[ 0 ] ); + generalTestSubentities( edgeEntities[ 1 ] ); + generalTestSubentities( edgeEntities[ 2 ] ); + generalTestSubentities( edgeEntities[ 3 ] ); + generalTestSubentities( edgeEntities[ 4 ] ); + generalTestSubentities( triangleEntities[ 0 ] ); + generalTestSubentities( triangleEntities[ 1 ] ); +} + +TEST( MeshEntityTest, OneTriangleComparisonTest ) +{ + using TriangleMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, Topologies::Triangle >; + using EdgeMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityTopology >; + using VertexMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityTopology >; + + static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." ); + static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." ); + + using PointType = typename VertexMeshEntityType::PointType; + EXPECT_EQ( PointType::getType(), ( Containers::StaticVector< 2, RealType >::getType() ) ); + + PointType point0( 0.0, 0.0 ), + point1( 1.0, 0.0 ), + point2( 0.0, 1.0 ); + + Containers::StaticArray< 3, VertexMeshEntityType > vertices; + vertices[ 0 ].setPoint( point0 ); + vertices[ 1 ].setPoint( point1 ); + vertices[ 2 ].setPoint( point2 ); + + Containers::StaticArray< 3, EdgeMeshEntityType > edges; + SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities; + edgeVertexSubentities.setKeysRange( 3 ); + edgeVertexSubentities.allocate(); + + edges[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) ); + edges[ 0 ].template setSubentityIndex< 0 >( 0, 1 ); + edges[ 0 ].template setSubentityIndex< 0 >( 1, 2 ); + edges[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) ); + edges[ 1 ].template setSubentityIndex< 0 >( 0, 2 ); + edges[ 1 ].template setSubentityIndex< 0 >( 1, 0 ); + edges[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) ); + edges[ 2 ].template setSubentityIndex< 0 >( 0, 0 ); + edges[ 2 ].template setSubentityIndex< 0 >( 1, 1 ); + + TriangleMeshEntityType triangle; + SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities; + SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 1 > triangleEdgeSubentities; + triangleVertexSubentities.setKeysRange( 1 ); + triangleEdgeSubentities.setKeysRange( 1 ); + triangleVertexSubentities.allocate(); + triangleEdgeSubentities.allocate(); + + triangle.template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) ); + triangle.template setSubentityIndex< 0 >( 0 , 0 ); + triangle.template setSubentityIndex< 0 >( 1 , 1 ); + triangle.template setSubentityIndex< 0 >( 2 , 2 ); + triangle.template bindSubentitiesStorageNetwork< 1 >( triangleVertexSubentities.getValues( 0 ) ); + triangle.template setSubentityIndex< 1 >( 0 , 0 ); + triangle.template setSubentityIndex< 1 >( 1 , 1 ); + triangle.template setSubentityIndex< 1 >( 2 , 2 ); + + + SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 1 > vertexEdgeSuperentities; + vertexEdgeSuperentities.setKeysRange( 3 ); + vertexEdgeSuperentities.allocate( 2 ); + + vertices[ 0 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 0 ) ); + vertices[ 0 ].template setNumberOfSuperentities< 1 >( 2 ); + vertices[ 0 ].template setSuperentityIndex< 1 >( 0, 2 ); + vertices[ 0 ].template setSuperentityIndex< 1 >( 1, 1 ); + + vertices[ 1 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 1 ) ); + vertices[ 1 ].template setNumberOfSuperentities< 1 >( 2 ); + vertices[ 1 ].template setSuperentityIndex< 1 >( 0, 0 ); + vertices[ 1 ].template setSuperentityIndex< 1 >( 1, 2 ); + + vertices[ 2 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 2 ) ); + vertices[ 2 ].template setNumberOfSuperentities< 1 >( 2 ); + vertices[ 2 ].template setSuperentityIndex< 1 >( 0, 0 ); + vertices[ 2 ].template setSuperentityIndex< 1 >( 1, 1 ); + + + SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 2 > vertexCellSuperentities; + vertexCellSuperentities.setKeysRange( 3 ); + vertexCellSuperentities.allocate( 1 ); + + vertices[ 0 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 0 ) ); + vertices[ 0 ].template setNumberOfSuperentities< 2 >( 1 ); + vertices[ 0 ].template setSuperentityIndex< 2 >( 0, 0 ); + + vertices[ 1 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 1 ) ); + vertices[ 1 ].template setNumberOfSuperentities< 2 >( 1 ); + vertices[ 1 ].template setSuperentityIndex< 2 >( 0, 0 ); + + vertices[ 2 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 2 ) ); + vertices[ 2 ].template setNumberOfSuperentities< 2 >( 1 ); + vertices[ 2 ].template setSuperentityIndex< 2 >( 0, 0 ); + + + SuperentityStorage< TestTriangleMeshConfig, Topologies::Edge, 2 > edgeCellSuperentities; + edgeCellSuperentities.setKeysRange( 3 ); + edgeCellSuperentities.allocate( 1 ); + + edges[ 0 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 0 ) ); + edges[ 0 ].template setNumberOfSuperentities< 2 >( 1 ); + edges[ 0 ].template setSuperentityIndex< 2 >( 0, 0 ); + + edges[ 1 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 1 ) ); + edges[ 1 ].template setNumberOfSuperentities< 2 >( 1 ); + edges[ 1 ].template setSuperentityIndex< 2 >( 0, 0 ); + + edges[ 2 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 2 ) ); + edges[ 2 ].template setNumberOfSuperentities< 2 >( 1 ); + edges[ 2 ].template setSuperentityIndex< 2 >( 0, 0 ); + + + /* + * Tests for MeshEntity::operator== + */ + EXPECT_EQ( vertices[ 0 ], vertices[ 0 ] ); + EXPECT_NE( vertices[ 0 ], vertices[ 1 ] ); + vertices[ 0 ].setPoint( point1 ); + vertices[ 0 ].template setSuperentityIndex< 1 >( 0, 0 ); + vertices[ 0 ].template setSuperentityIndex< 1 >( 1, 2 ); + EXPECT_EQ( vertices[ 0 ], vertices[ 1 ] ); + vertices[ 0 ].template setSuperentityIndex< 2 >( 0, 1 ); + EXPECT_NE( vertices[ 0 ], vertices[ 1 ] ); + vertices[ 1 ].template setSuperentityIndex< 2 >( 0, 1 ); + EXPECT_EQ( vertices[ 0 ], vertices[ 1 ] ); + + EXPECT_EQ( edges[ 0 ], edges[ 0 ] ); + EXPECT_NE( edges[ 0 ], edges[ 1 ] ); + edges[ 0 ].template setSubentityIndex< 0 >( 0, 2 ); + edges[ 0 ].template setSubentityIndex< 0 >( 1, 0 ); + EXPECT_EQ( edges[ 0 ], edges[ 1 ] ); + edges[ 0 ].template setSuperentityIndex< 2 >( 0, 1 ); + EXPECT_NE( edges[ 0 ], edges[ 1 ] ); + edges[ 1 ].template setSuperentityIndex< 2 >( 0, 1 ); + EXPECT_EQ( edges[ 0 ], edges[ 1 ] ); + + + /* + * Tests for copy-assignment + */ + VertexMeshEntityType v1( vertices[ 0 ] ); + EXPECT_EQ( v1, vertices[ 0 ] ); + VertexMeshEntityType v2 = vertices[ 0 ]; + EXPECT_EQ( v2, vertices[ 0 ] ); + + EdgeMeshEntityType e1( edges[ 0 ] ); + EXPECT_EQ( e1, edges[ 0 ] ); + EdgeMeshEntityType e2 = edges[ 0 ]; + EXPECT_EQ( e2, edges[ 0 ] ); + + TriangleMeshEntityType t1( triangle ); + EXPECT_EQ( t1, triangle ); + TriangleMeshEntityType t2 = triangle; + EXPECT_EQ( t2, triangle ); +} + +} // namespace MeshEntityTest + +#endif diff --git a/src/UnitTests/Meshes/MeshOrderingTest.cpp b/src/UnitTests/Meshes/MeshOrderingTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc03c92cc71ee9d8fa3ca554651e20ff19b170c2 --- /dev/null +++ b/src/UnitTests/Meshes/MeshOrderingTest.cpp @@ -0,0 +1,11 @@ +#include "MeshOrderingTest.h" + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Meshes/MeshOrderingTest.cu b/src/UnitTests/Meshes/MeshOrderingTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..fc03c92cc71ee9d8fa3ca554651e20ff19b170c2 --- /dev/null +++ b/src/UnitTests/Meshes/MeshOrderingTest.cu @@ -0,0 +1,11 @@ +#include "MeshOrderingTest.h" + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Meshes/MeshOrderingTest.h b/src/UnitTests/Meshes/MeshOrderingTest.h new file mode 100644 index 0000000000000000000000000000000000000000..054e4309eedd85563d95bf18ba5e9de74beff01d --- /dev/null +++ b/src/UnitTests/Meshes/MeshOrderingTest.h @@ -0,0 +1,328 @@ +#pragma once + +#ifdef HAVE_GTEST +#include <gtest/gtest.h> + +#include <array> + +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/MeshEntity.h> +#include <TNL/Meshes/DefaultConfig.h> +#include <TNL/Meshes/Topologies/Triangle.h> +#include <TNL/Meshes/MeshBuilder.h> + +namespace MeshOrderingTest { + +using namespace TNL; +using namespace TNL::Meshes; + +class TestTriangleMeshConfig + : public DefaultConfig< Topologies::Triangle, 2, double, int, short int, int > +{ +public: + static constexpr bool entityStorage( int dimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; } + //template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return true; } + template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; } +}; + +template< typename Device > +bool buildTriangleMesh( Mesh< TestTriangleMeshConfig, Device >& mesh ) +{ + using TriangleMesh = Mesh< TestTriangleMeshConfig, Device >; + using TriangleMeshEntityType = typename TriangleMesh::template EntityType< 2 >; + using EdgeMeshEntityType = typename TriangleMesh::template EntityType< 1 >; + using VertexMeshEntityType = typename TriangleMesh::template EntityType< 0 >; + + static_assert( TriangleMeshEntityType::template SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." ); + static_assert( TriangleMeshEntityType::template SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::template SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::template SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::template SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::template SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." ); + + using PointType = typename VertexMeshEntityType::PointType; + static_assert( std::is_same< PointType, Containers::StaticVector< 2, double > >::value, "" ); + + /**** + * We set-up the following situation + point2 edge3 point3 + |\-------------------| + | \ | + | \ triangle1 | + | \ | + + .... + edge1 edge0 edge4 + .... + + + | triangle0 \ | + | \ | + ---------------------| + point0 edge2 point1 + */ + + PointType point0( 0.0, 0.0 ), + point1( 1.0, 0.0 ), + point2( 0.0, 1.0 ), + point3( 1.0, 1.0 ); + + MeshBuilder< TriangleMesh > meshBuilder; + meshBuilder.setPointsCount( 4 ); + meshBuilder.setPoint( 0, point0 ); + meshBuilder.setPoint( 1, point1 ); + meshBuilder.setPoint( 2, point2 ); + meshBuilder.setPoint( 3, point3 ); + + meshBuilder.setCellsCount( 2 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 2, 2 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 0, 1 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 1, 2 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 2, 3 ); + return meshBuilder.build( mesh ); +} + +template< typename PermutationVector > +void testMesh( const Mesh< TestTriangleMeshConfig, Devices::Host >& mesh, + const PermutationVector& vertexPermutation, + const PermutationVector& edgePermutation, + const PermutationVector& cellPermutation ) +{ + using MeshType = Mesh< TestTriangleMeshConfig, Devices::Host >; + using PointType = typename MeshType::PointType; + + ASSERT_EQ( vertexPermutation.getSize(), 4 ); + ASSERT_EQ( edgePermutation.getSize(), 5 ); + ASSERT_EQ( cellPermutation.getSize(), 2 ); + + EXPECT_EQ( mesh.getEntitiesCount< 0 >(), 4 ); + EXPECT_EQ( mesh.getEntitiesCount< 1 >(), 5 ); + EXPECT_EQ( mesh.getEntitiesCount< 2 >(), 2 ); + + // test points + PointType point0( 0.0, 0.0 ), + point1( 1.0, 0.0 ), + point2( 0.0, 1.0 ), + point3( 1.0, 1.0 ); + + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).getPoint(), point0 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).getPoint(), point1 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).getPoint(), point2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).getPoint(), point3 ); + + + // test getIndex + for( int i = 0; i < 4; i++ ) + EXPECT_EQ( mesh.template getEntity< 0 >( i ).getIndex(), i ); + for( int i = 0; i < 5; i++ ) + EXPECT_EQ( mesh.template getEntity< 1 >( i ).getIndex(), i ); + for( int i = 0; i < 2; i++ ) + EXPECT_EQ( mesh.template getEntity< 2 >( i ).getIndex(), i ); + + + // test subentities + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).getVertexIndex( 0 ), vertexPermutation[ 1 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).getVertexIndex( 1 ), vertexPermutation[ 2 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).getVertexIndex( 0 ), vertexPermutation[ 2 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).getVertexIndex( 1 ), vertexPermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).getVertexIndex( 0 ), vertexPermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).getVertexIndex( 1 ), vertexPermutation[ 1 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).getVertexIndex( 0 ), vertexPermutation[ 2 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).getVertexIndex( 1 ), vertexPermutation[ 3 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).getVertexIndex( 0 ), vertexPermutation[ 3 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).getVertexIndex( 1 ), vertexPermutation[ 1 ] ); + + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 0 >( 0 ), vertexPermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 0 >( 1 ), vertexPermutation[ 1 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 0 >( 2 ), vertexPermutation[ 2 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 1 >( 0 ), edgePermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 1 >( 1 ), edgePermutation[ 1 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 1 >( 2 ), edgePermutation[ 2 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 0 >( 0 ), vertexPermutation[ 1 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 0 >( 1 ), vertexPermutation[ 2 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 0 >( 2 ), vertexPermutation[ 3 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 1 >( 0 ), edgePermutation[ 3 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 1 >( 1 ), edgePermutation[ 4 ] ); + EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 1 >( 2 ), edgePermutation[ 0 ] ); + + + // test superentities + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentitiesCount< 1 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentityIndex< 1 >( 0 ), edgePermutation[ 1 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentityIndex< 1 >( 1 ), edgePermutation[ 2 ] ); + + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentitiesCount< 1 >(), 3 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 1 >( 0 ), edgePermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 1 >( 1 ), edgePermutation[ 2 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 1 >( 2 ), edgePermutation[ 4 ] ); + + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentitiesCount< 1 >(), 3 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 1 >( 0 ), edgePermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 1 >( 1 ), edgePermutation[ 1 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 1 >( 2 ), edgePermutation[ 3 ] ); + + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentitiesCount< 1 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentityIndex< 1 >( 0 ), edgePermutation[ 3 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentityIndex< 1 >( 1 ), edgePermutation[ 4 ] ); + + + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentitiesCount< 2 >(), 1 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 0 ] ); + + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 2 >( 1 ), cellPermutation[ 1 ] ); + + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 2 >( 1 ), cellPermutation[ 1 ] ); + + ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentitiesCount< 2 >(), 1 ); + EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 1 ] ); + + + ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 0 ] ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).template getSuperentityIndex< 2 >( 1 ), cellPermutation[ 1 ] ); + + ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).template getSuperentitiesCount< 2 >(), 1 ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 0 ] ); + + ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).template getSuperentitiesCount< 2 >(), 1 ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 0 ] ); + + ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).template getSuperentitiesCount< 2 >(), 1 ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 1 ] ); + + ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).template getSuperentitiesCount< 2 >(), 1 ); + EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).template getSuperentityIndex< 2 >( 0 ), cellPermutation[ 1 ] ); + + + // test boundary tags + const std::vector< int > boundaryFaces = {1, 2, 3, 4}; + const std::vector< int > interiorFaces = {0}; + EXPECT_EQ( mesh.template getBoundaryEntitiesCount< 1 >(), (int) boundaryFaces.size() ); + for( size_t i = 0; i < boundaryFaces.size(); i++ ) { + EXPECT_TRUE( mesh.template isBoundaryEntity< 1 >( edgePermutation[ boundaryFaces[ i ] ] ) ); + // boundary indices are always sorted so we can't test this +// EXPECT_EQ( mesh.template getBoundaryEntityIndex< 1 >( i ), edgePermutation[ boundaryFaces[ i ] ] ); + } + // Test interior faces + EXPECT_EQ( mesh.template getInteriorEntitiesCount< 1 >(), (int) interiorFaces.size() ); + for( size_t i = 0; i < interiorFaces.size(); i++ ) { + EXPECT_FALSE( mesh.template isBoundaryEntity< 1 >( edgePermutation[ interiorFaces[ i ] ] ) ); + // boundary indices are always sorted so we can't test this +// EXPECT_EQ( mesh.template getInteriorEntityIndex< 1 >( i ), edgePermutation[ interiorFaces[ i ] ] ); + } +} + +// hack due to TNL::Containers::Vector not supporting initilizer lists +const std::array< int, 4 > _vertexIdentity { { 0, 1, 2, 3 } }; +const std::array< int, 5 > _edgeIdentity { { 0, 1, 2, 3, 4 } }; +const std::array< int, 2 > _cellIdentity { { 0, 1 } }; + +const std::array< int, 4 > _vertexPermutation { { 3, 2, 0, 1 } }; +const std::array< int, 5 > _edgePermutation { { 2, 0, 4, 1, 3 } }; +const std::array< int, 2 > _cellPermutation { { 1, 0 } }; + +const std::array< int, 4 > _vertexInversePermutation { { 2, 3, 1, 0 } }; +const std::array< int, 5 > _edgeInversePermutation { { 1, 3, 0, 4, 2 } }; +const std::array< int, 2 > _cellInversePermutation { { 1, 0 } }; + +template< typename TNLVector, typename STDArray > +void setPermutation( TNLVector& perm, const STDArray& stdperm ) +{ + perm.setSize( stdperm.size() ); + for( int i = 0; i < perm.getSize(); i++ ) + perm.setElement( i, stdperm[ i ] ); +} + +TEST( MeshOrderingTest, OrderingOnHost ) +{ + using MeshHost = Mesh< TestTriangleMeshConfig, Devices::Host >; + + MeshHost mesh; + ASSERT_TRUE( buildTriangleMesh( mesh ) ); + + using PermutationVector = typename MeshHost::GlobalIndexVector; + PermutationVector vertexIdentity, edgeIdentity, cellIdentity, + vertexPermutation, edgePermutation, cellPermutation, + vertexInversePermutation, edgeInversePermutation, cellInversePermutation; + setPermutation( vertexIdentity, _vertexIdentity ); + setPermutation( edgeIdentity, _edgeIdentity ); + setPermutation( cellIdentity, _cellIdentity ); + setPermutation( vertexPermutation, _vertexPermutation ); + setPermutation( edgePermutation, _edgePermutation ); + setPermutation( cellPermutation, _cellPermutation ); + setPermutation( vertexInversePermutation, _vertexInversePermutation ); + setPermutation( edgeInversePermutation, _edgeInversePermutation ); + setPermutation( cellInversePermutation, _cellInversePermutation ); + + mesh.template reorderEntities< 0 >( vertexPermutation, vertexInversePermutation ); + testMesh( mesh, vertexInversePermutation, edgeIdentity, cellIdentity ); + + mesh.template reorderEntities< 2 >( cellPermutation, cellInversePermutation ); + testMesh( mesh, vertexInversePermutation, edgeIdentity, cellInversePermutation ); + + mesh.template reorderEntities< 1 >( edgePermutation, edgeInversePermutation ); + testMesh( mesh, vertexInversePermutation, edgeInversePermutation, cellInversePermutation ); +}; + +#ifdef HAVE_CUDA +TEST( MeshOrderingTest, OrderingOnCuda ) +{ + using MeshHost = Mesh< TestTriangleMeshConfig, Devices::Host >; + using MeshCuda = Mesh< TestTriangleMeshConfig, Devices::Cuda >; + + MeshHost meshHost; + MeshCuda mesh; + ASSERT_TRUE( buildTriangleMesh( meshHost ) ); + mesh = meshHost; + + using PermutationCuda = typename MeshCuda::GlobalIndexVector; + PermutationCuda vertexIdentity, edgeIdentity, cellIdentity, + vertexPermutation, edgePermutation, cellPermutation, + vertexInversePermutation, edgeInversePermutation, cellInversePermutation; + setPermutation( vertexIdentity, _vertexIdentity ); + setPermutation( edgeIdentity, _edgeIdentity ); + setPermutation( cellIdentity, _cellIdentity ); + setPermutation( vertexPermutation, _vertexPermutation ); + setPermutation( edgePermutation, _edgePermutation ); + setPermutation( cellPermutation, _cellPermutation ); + setPermutation( vertexInversePermutation, _vertexInversePermutation ); + setPermutation( edgeInversePermutation, _edgeInversePermutation ); + setPermutation( cellInversePermutation, _cellInversePermutation ); + + mesh.template reorderEntities< 0 >( vertexPermutation, vertexInversePermutation ); + mesh.template reorderEntities< 1 >( edgePermutation, edgeInversePermutation ); + mesh.template reorderEntities< 2 >( cellPermutation, cellInversePermutation ); + + // test is on host + { + // local scope so we can use the same names + using PermutationVector = typename MeshHost::GlobalIndexVector; + PermutationVector vertexIdentity, edgeIdentity, cellIdentity, + vertexPermutation, edgePermutation, cellPermutation, + vertexInversePermutation, edgeInversePermutation, cellInversePermutation; + setPermutation( vertexIdentity, _vertexIdentity ); + setPermutation( edgeIdentity, _edgeIdentity ); + setPermutation( cellIdentity, _cellIdentity ); + setPermutation( vertexPermutation, _vertexPermutation ); + setPermutation( edgePermutation, _edgePermutation ); + setPermutation( cellPermutation, _cellPermutation ); + setPermutation( vertexInversePermutation, _vertexInversePermutation ); + setPermutation( edgeInversePermutation, _edgeInversePermutation ); + setPermutation( cellInversePermutation, _cellInversePermutation ); + + meshHost = mesh; + testMesh( meshHost, vertexInversePermutation, edgeInversePermutation, cellInversePermutation ); + } +}; +#endif + +} // namespace MeshOrderingTest + +#endif diff --git a/src/UnitTests/Meshes/MeshReaderTest.cpp b/src/UnitTests/Meshes/MeshReaderTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac1b0314a166f798dd4c518b278844c2ecbcb964 --- /dev/null +++ b/src/UnitTests/Meshes/MeshReaderTest.cpp @@ -0,0 +1 @@ +#include "MeshReaderTest.h" diff --git a/src/UnitTests/Meshes/MeshReaderTest.cu b/src/UnitTests/Meshes/MeshReaderTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..ac1b0314a166f798dd4c518b278844c2ecbcb964 --- /dev/null +++ b/src/UnitTests/Meshes/MeshReaderTest.cu @@ -0,0 +1 @@ +#include "MeshReaderTest.h" diff --git a/src/UnitTests/Meshes/MeshReaderTest.h b/src/UnitTests/Meshes/MeshReaderTest.h new file mode 100644 index 0000000000000000000000000000000000000000..64fe92cc190656001ed066fa46d4a2e917bd4239 --- /dev/null +++ b/src/UnitTests/Meshes/MeshReaderTest.h @@ -0,0 +1,194 @@ +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/DefaultConfig.h> +#include <TNL/Meshes/BuildConfigTags.h> +#include <TNL/Meshes/TypeResolver/TypeResolver.h> + +#ifdef HAVE_VTK +#include <TNL/Meshes/Readers/VTKReader_libvtk.h> +#endif + +#include <TNL/Debugging/MemoryUsage.h> + +#include "MeshTest.h" + +// TODO: remove this after refactoring with clang-rename +#include "MeshEntityTest.h" +#include "BoundaryTagsTest.h" + +using namespace TNL; +using namespace TNL::Meshes; + + +template< typename Cell, + int WorldDimension = Cell::dimension, + typename Real = double, + typename GlobalIndex = int, + typename LocalIndex = GlobalIndex, + typename Id = void > +struct MyMeshConfig + : public DefaultConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id > +{ + static constexpr bool entityStorage( int dimension ) + { + return true; +// return dimension == 0 || dimension == Cell::dimension; + } + + template< typename EntityTopology > + static constexpr bool subentityStorage( EntityTopology, int SubentityDimension ) + { +// return entityStorage( EntityTopology::dimension ); + return entityStorage( EntityTopology::dimension ) && + SubentityDimension == 0; + } + + template< typename EntityTopology > + static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimension ) + { + return false; + } + + template< typename EntityTopology > + static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension ) + { +// return entityStorage( EntityTopology::dimension ); + return entityStorage( EntityTopology::dimension ) && + SuperentityDimension == Cell::dimension; + } + + template< typename EntityTopology > + static constexpr bool boundaryTagsStorage( EntityTopology ) + { + using BaseType = DefaultConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id >; + using FaceTopology = typename Topologies::Subtopology< Cell, BaseType::meshDimension - 1 >::Topology; + return entityStorage( BaseType::meshDimension - 1 ) && + superentityStorage( FaceTopology(), BaseType::meshDimension ) && + ( EntityTopology::dimension >= BaseType::meshDimension - 1 || subentityStorage( FaceTopology(), EntityTopology::dimension ) ); + //return false; + } +}; + + +// specialization of BuildConfigTags +struct MyBuildConfigTag {}; + +namespace TNL { +namespace Meshes { +namespace BuildConfigTags { + +// disable grids +template< int Dimension, typename Real, typename Device, typename Index > +struct GridTag< MyBuildConfigTag, Grid< Dimension, Real, Device, Index > > +{ enum { enabled = false }; }; + +// enable all cell topologies +template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Edge > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Triangle > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Quadrilateral > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; }; +template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Hexahedron > { enum { enabled = true }; }; + +template< typename CellTopology, int WorldDimension > +struct MeshWorldDimensionTag< MyBuildConfigTag, CellTopology, WorldDimension > +{ enum { enabled = ( WorldDimension == CellTopology::dimension ) }; }; + +template< typename Real > struct MeshRealTag< MyBuildConfigTag, Real > { enum { enabled = false }; }; +template<> struct MeshRealTag< MyBuildConfigTag, float > { enum { enabled = true }; }; +template<> struct MeshRealTag< MyBuildConfigTag, double > { enum { enabled = true }; }; + +template< typename GlobalIndex > struct MeshGlobalIndexTag< MyBuildConfigTag, GlobalIndex > { enum { enabled = false }; }; +template<> struct MeshGlobalIndexTag< MyBuildConfigTag, int > { enum { enabled = true }; }; + +template< typename LocalIndex > struct MeshLocalIndexTag< MyBuildConfigTag, LocalIndex > { enum { enabled = false }; }; +template<> struct MeshLocalIndexTag< MyBuildConfigTag, short int > { enum { enabled = true }; }; + +template<> +struct MeshConfigTemplateTag< MyBuildConfigTag > +{ + template< typename Cell, int WorldDimension, typename Real, typename GlobalIndex, typename LocalIndex, typename Id > + using MeshConfig = MyMeshConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id >; +}; + +} // namespace BuildConfigTags +} // namespace Meshes +} // namespace TNL + + +template< typename MeshType > +class MeshTester +{ +public: + static bool run( const String& fileName ) + { + std::cout << "pre-init\t"; + Debugging::printMemoryUsage(); + +#ifdef HAVE_VTK + MeshType mesh_libvtk; + Readers::VTKReader_libvtk<> reader; + if( ! reader.readMesh( fileName, mesh_libvtk ) ) + return false; + + std::cout << "libvtk vertices: " << mesh_libvtk.template getEntitiesCount< 0 >() << std::endl; + std::cout << "libvtk faces: " << mesh_libvtk.template getEntitiesCount< MeshType::getMeshDimension() - 1 >() << std::endl; + std::cout << "libvtk cells: " << mesh_libvtk.template getEntitiesCount< MeshType::getMeshDimension() >() << std::endl; +#endif + + Timer timer; + timer.start(); + + MeshType mesh; + if( ! loadMesh( fileName, mesh ) ) + return false; + + timer.stop(); + std::cout << "Loading took " << timer.getRealTime() << " seconds." << std::endl; + + std::cout << "vertices: " << mesh.template getEntitiesCount< 0 >() << std::endl; + std::cout << "faces: " << mesh.template getEntitiesCount< MeshType::getMeshDimension() - 1 >() << std::endl; + std::cout << "cells: " << mesh.template getEntitiesCount< MeshType::getMeshDimension() >() << std::endl; + + std::cout << "post-init\t"; + Debugging::printMemoryUsage(); + +#ifdef HAVE_VTK + std::cout << "mesh_libvtk == mesh: " << std::boolalpha << (mesh_libvtk == mesh) << std::endl; + if( mesh_libvtk != mesh ) { + std::cerr << "mesh_libvtk:\n" << mesh_libvtk << "\n\nmesh:\n" << mesh << std::endl; + return false; + } +#endif + +#ifdef HAVE_GTEST + std::cout << "Running basic I/O tests..." << std::endl; + MeshTest::testFinishedMesh( mesh ); +#endif +// mesh.save( "mesh-test.tnl" ); + + return true; + } +}; + +int main( int argc, char* argv[] ) +{ + if( argc < 2 ) { + std::cerr << "Usage: " << argv[ 0 ] << " filename.[tnl|ng|vtk] ..." << std::endl; + return EXIT_FAILURE; + } + + bool result = true; + + for( int i = 1; i < argc; i++ ) { + String fileName = argv[ i ]; + + result &= resolveMeshType< MyBuildConfigTag, Devices::Host, MeshTester > + ( fileName, + fileName // passed to MeshTester::run + ); + } + + std::cout << "final\t"; + Debugging::printMemoryUsage(); + + return ! result; +} diff --git a/src/UnitTests/Meshes/MeshTest.cpp b/src/UnitTests/Meshes/MeshTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93004f18d5245073d8d6811c1253acfd6cf7a509 --- /dev/null +++ b/src/UnitTests/Meshes/MeshTest.cpp @@ -0,0 +1,11 @@ +#include "MeshTest.h" + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Meshes/MeshTest.cu b/src/UnitTests/Meshes/MeshTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..93004f18d5245073d8d6811c1253acfd6cf7a509 --- /dev/null +++ b/src/UnitTests/Meshes/MeshTest.cu @@ -0,0 +1,11 @@ +#include "MeshTest.h" + +int main( int argc, char* argv[] ) +{ +#ifdef HAVE_GTEST + ::testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +#else + return EXIT_FAILURE; +#endif +} diff --git a/src/UnitTests/Meshes/MeshTest.h b/src/UnitTests/Meshes/MeshTest.h new file mode 100644 index 0000000000000000000000000000000000000000..3835df28d5cae1ac07d952ed861474561f03c4f9 --- /dev/null +++ b/src/UnitTests/Meshes/MeshTest.h @@ -0,0 +1,811 @@ +#pragma once + +#ifdef HAVE_GTEST +#include <gtest/gtest.h> + +#include <sstream> + +#include <TNL/Meshes/Mesh.h> +#include <TNL/Meshes/MeshEntity.h> +#include <TNL/Meshes/DefaultConfig.h> +#include <TNL/Meshes/Topologies/Vertex.h> +#include <TNL/Meshes/Topologies/Edge.h> +#include <TNL/Meshes/Topologies/Triangle.h> +#include <TNL/Meshes/Topologies/Quadrilateral.h> +#include <TNL/Meshes/Topologies/Tetrahedron.h> +#include <TNL/Meshes/Topologies/Hexahedron.h> +#include <TNL/Meshes/MeshBuilder.h> + +namespace MeshTest { + +using namespace TNL; +using namespace TNL::Meshes; + +using RealType = double; +using Device = Devices::Host; +using IndexType = int; + +class TestTriangleMeshConfig : public DefaultConfig< Topologies::Triangle > +{ +public: + static constexpr bool entityStorage( int dimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; } + //template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return true; } + template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; } +}; + +class TestQuadrilateralMeshConfig : public DefaultConfig< Topologies::Quadrilateral > +{ +public: + static constexpr bool entityStorage( int dimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return ( SubentityDimensions % 2 != 0 ); } + template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; } +}; + +class TestTetrahedronMeshConfig : public DefaultConfig< Topologies::Tetrahedron > +{ +public: + static constexpr bool entityStorage( int dimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return ( SubentityDimensions % 2 != 0 ); } + template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; } +}; + +class TestHexahedronMeshConfig : public DefaultConfig< Topologies::Hexahedron > +{ +public: + static constexpr bool entityStorage( int dimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; } + template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return ( SubentityDimensions % 2 != 0 ); } + template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; } +}; + +template< typename Object1, typename Object2 > +void compareStringRepresentation( const Object1& obj1, const Object2& obj2 ) +{ + std::stringstream str1, str2; + str1 << obj1; + str2 << obj2; + EXPECT_EQ( str1.str(), str2.str() ); +} + +template< typename Object > +void testCopyAssignment( const Object& obj ) +{ + static_assert( std::is_copy_constructible< Object >::value, "" ); + static_assert( std::is_copy_assignable< Object >::value, "" ); + + Object new_obj_1( obj ); + EXPECT_EQ( new_obj_1, obj ); + Object new_obj_2; + new_obj_2 = obj; + EXPECT_EQ( new_obj_2, obj ); +} + +template< typename Mesh > +void testMeshOnCuda( const Mesh& mesh ) +{ +#ifdef HAVE_CUDA + using DeviceMesh = Meshes::Mesh< typename Mesh::Config, Devices::Cuda >; + + // test host->CUDA copy + DeviceMesh dmesh1( mesh ); + EXPECT_EQ( dmesh1, mesh ); + DeviceMesh dmesh2; + dmesh2 = mesh; + EXPECT_EQ( dmesh2, mesh ); + + // test CUDA->CUDA copy + testCopyAssignment( dmesh1 ); + + // copy CUDA->host copy + Mesh mesh2( dmesh1 ); + EXPECT_EQ( mesh2, mesh ); + Mesh mesh3; + mesh3 = dmesh1; + EXPECT_EQ( mesh2, mesh ); + + // test load from file to CUDA + ASSERT_TRUE( mesh.save( "mesh.tnl" ) ); + ASSERT_TRUE( dmesh1.load( "mesh.tnl" ) ); + EXPECT_EQ( dmesh1, mesh ); + + // test save into file from CUDA + ASSERT_TRUE( dmesh1.save( "mesh.tnl" ) ); + ASSERT_TRUE( mesh2.load( "mesh.tnl" ) ); + EXPECT_EQ( mesh2, mesh ); + + EXPECT_EQ( std::remove( "mesh.tnl" ), 0 ); +#endif +} + +template< typename Mesh > +void testEntities( const Mesh& mesh ) +{ + using IndexType = typename Mesh::GlobalIndexType; + + // test that superentity accessors have been correctly bound + for( IndexType i = 0; i < mesh.template getEntitiesCount< 0 >(); i++ ) { + auto v1 = mesh.template getEntity< 0 >( i ); + auto& v2 = mesh.template getEntity< 0 >( i ); + EXPECT_EQ( v1, v2 ); + EXPECT_EQ( v1.template getSuperentitiesCount< Mesh::getMeshDimension() >(), + v2.template getSuperentitiesCount< Mesh::getMeshDimension() >() ); + for( IndexType s = 0; s < v1.template getSuperentitiesCount< Mesh::getMeshDimension() >(); s++ ) + EXPECT_EQ( v1.template getSuperentityIndex< Mesh::getMeshDimension() >( s ), + v2.template getSuperentityIndex< Mesh::getMeshDimension() >( s ) ); + } + + // test that subentity accessors have been correctly bound + for( IndexType i = 0; i < mesh.template getEntitiesCount< Mesh::getMeshDimension() >(); i++ ) { + auto c1 = mesh.template getEntity< Mesh::getMeshDimension() >( i ); + auto& c2 = mesh.template getEntity< Mesh::getMeshDimension() >( i ); + EXPECT_EQ( c1, c2 ); + EXPECT_EQ( c1.template getSubentitiesCount< 0 >(), + c2.template getSubentitiesCount< 0 >() ); + for( IndexType s = 0; s < c1.template getSubentitiesCount< 0 >(); s++ ) + EXPECT_EQ( c1.template getSubentityIndex< 0 >( s ), + c2.template getSubentityIndex< 0 >( s ) ); + } +} + +template< typename Mesh > +void testFinishedMesh( const Mesh& mesh ) +{ + Mesh mesh2; + ASSERT_TRUE( mesh.save( "mesh.tnl" ) ); + ASSERT_TRUE( mesh2.load( "mesh.tnl" ) ); + EXPECT_EQ( std::remove( "mesh.tnl" ), 0 ); + ASSERT_EQ( mesh, mesh2 ); + compareStringRepresentation( mesh, mesh2 ); + testCopyAssignment( mesh ); + testMeshOnCuda( mesh ); + testEntities( mesh ); +} + +TEST( MeshTest, TwoTrianglesTest ) +{ + using TriangleMeshEntityType = MeshEntity< TestTriangleMeshConfig, Devices::Host, Topologies::Triangle >; + using EdgeMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityType; + using VertexMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityType; + + static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." ); + static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." ); + static_assert( EdgeMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." ); + static_assert( VertexMeshEntityType::SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." ); + + using PointType = typename VertexMeshEntityType::PointType; + ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) ); + + /**** + * We set-up the following situation + point2 edge3 point3 + |\-------------------| + | \ | + | \ triangle1 | + | \ | + + .... + edge1 edge0 edge4 + .... + + + | triangle0 \ | + | \ | + ---------------------| + point0 edge2 point1 + */ + + PointType point0( 0.0, 0.0 ), + point1( 1.0, 0.0 ), + point2( 0.0, 1.0 ), + point3( 1.0, 1.0 ); + + typedef Mesh< TestTriangleMeshConfig > TriangleTestMesh; + TriangleTestMesh mesh; + MeshBuilder< TriangleTestMesh > meshBuilder; + meshBuilder.setPointsCount( 4 ); + meshBuilder.setPoint( 0, point0 ); + meshBuilder.setPoint( 1, point1 ); + meshBuilder.setPoint( 2, point2 ); + meshBuilder.setPoint( 3, point3 ); + + meshBuilder.setCellsCount( 2 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 2, 2 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 0, 1 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 1, 2 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 2, 3 ); + ASSERT_TRUE( meshBuilder.build( mesh ) ); + + EXPECT_EQ( mesh.getEntitiesCount< 2 >(), 2 ); + EXPECT_EQ( mesh.getEntitiesCount< 1 >(), 5 ); + EXPECT_EQ( mesh.getEntitiesCount< 0 >(), 4 ); + + EXPECT_EQ( mesh.template getEntity< 0 >( 0 ).getPoint(), point0 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).getPoint(), point1 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 2 ).getPoint(), point2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 3 ).getPoint(), point3 ); + + EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).getVertexIndex( 0 ), 1 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).getVertexIndex( 1 ), 2 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 1 ).getVertexIndex( 0 ), 2 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 1 ).getVertexIndex( 1 ), 0 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 2 ).getVertexIndex( 0 ), 0 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 2 ).getVertexIndex( 1 ), 1 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 3 ).getVertexIndex( 0 ), 2 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 3 ).getVertexIndex( 1 ), 3 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 4 ).getVertexIndex( 0 ), 3 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 4 ).getVertexIndex( 1 ), 1 ); + + EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 0 >( 0 ), 0 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 0 >( 1 ), 1 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 0 >( 2 ), 2 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 1 >( 0 ), 0 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 1 >( 1 ), 1 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 1 >( 2 ), 2 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 0 >( 0 ), 1 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 0 >( 1 ), 2 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 0 >( 2 ), 3 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 1 >( 0 ), 3 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 1 >( 1 ), 4 ); + EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 1 >( 2 ), 0 ); + + /* + * Tests for the superentities layer. + */ + ASSERT_EQ( mesh.template getEntity< 0 >( 0 ).template getSuperentitiesCount< 1 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 0 ).template getSuperentityIndex< 1 >( 0 ), 1 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 0 ).template getSuperentityIndex< 1 >( 1 ), 2 ); + + ASSERT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentitiesCount< 1 >(), 3 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 1 >( 0 ), 0 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 1 >( 1 ), 2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 1 >( 2 ), 4 ); + + ASSERT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 2 >( 0 ), 0 ); + EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 2 >( 1 ), 1 ); + + ASSERT_EQ( mesh.template getEntity< 1 >( 0 ).template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).template getSuperentityIndex< 2 >( 0 ), 0 ); + EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).template getSuperentityIndex< 2 >( 1 ), 1 ); + + + testFinishedMesh( mesh ); +}; + +TEST( MeshTest, TetrahedronsTest ) +{ + using TetrahedronMeshEntityType = MeshEntity< TestTetrahedronMeshConfig, Devices::Host, Topologies::Tetrahedron >; + using TriangleMeshEntityType = typename TetrahedronMeshEntityType::SubentityTraits< 2 >::SubentityType; + using EdgeMeshEntityType = typename TetrahedronMeshEntityType::SubentityTraits< 1 >::SubentityType; + using VertexMeshEntityType = typename TetrahedronMeshEntityType::SubentityTraits< 0 >::SubentityType; + + using PointType = typename VertexMeshEntityType::PointType; + ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 3, RealType >::getType() ) ); + + typedef Mesh< TestTetrahedronMeshConfig > TestTetrahedronMesh; + TestTetrahedronMesh mesh; + MeshBuilder< TestTetrahedronMesh > meshBuilder; + meshBuilder.setPointsCount( 13 ); + meshBuilder.setPoint( 0, PointType( 0.000000, 0.000000, 0.000000 ) ); + meshBuilder.setPoint( 1, PointType( 0.000000, 0.000000, 8.000000 ) ); + meshBuilder.setPoint( 2, PointType( 0.000000, 8.000000, 0.000000 ) ); + meshBuilder.setPoint( 3, PointType( 15.000000, 0.000000, 0.000000 ) ); + meshBuilder.setPoint( 4, PointType( 0.000000, 8.000000, 8.000000 ) ); + meshBuilder.setPoint( 5, PointType( 15.000000, 0.000000, 8.000000 ) ); + meshBuilder.setPoint( 6, PointType( 15.000000, 8.000000, 0.000000 ) ); + meshBuilder.setPoint( 7, PointType( 15.000000, 8.000000, 8.000000 ) ); + meshBuilder.setPoint( 8, PointType( 7.470740, 8.000000, 8.000000 ) ); + meshBuilder.setPoint( 9, PointType( 7.470740, 0.000000, 8.000000 ) ); + meshBuilder.setPoint( 10, PointType( 7.504125, 8.000000, 0.000000 ) ); + meshBuilder.setPoint( 11, PointType( 7.212720, 0.000000, 0.000000 ) ); + meshBuilder.setPoint( 12, PointType( 11.184629, 3.987667, 3.985835 ) ); + + /**** + * Setup the following tetrahedrons: + * ( Generated by Netgen ) + * + * 12 8 7 5 + * 12 7 8 10 + * 12 11 8 9 + * 10 11 2 8 + * 12 7 6 5 + * 9 12 5 8 + * 12 11 9 3 + * 9 4 11 8 + * 12 9 5 3 + * 1 2 0 11 + * 8 11 2 4 + * 1 2 11 4 + * 9 4 1 11 + * 10 11 8 12 + * 12 6 7 10 + * 10 11 12 3 + * 12 6 3 5 + * 12 3 6 10 + */ + + meshBuilder.setCellsCount( 18 ); + // 12 8 7 5 + meshBuilder.getCellSeed( 0 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 1, 8 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 2, 7 ); + meshBuilder.getCellSeed( 0 ).setCornerId( 3, 5 ); + + // 12 7 8 10 + meshBuilder.getCellSeed( 1 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 1, 7 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 2, 8 ); + meshBuilder.getCellSeed( 1 ).setCornerId( 3, 10 ); + + // 12 11 8 9 + meshBuilder.getCellSeed( 2 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 2 ).setCornerId( 1, 11 ); + meshBuilder.getCellSeed( 2 ).setCornerId( 2, 8 ); + meshBuilder.getCellSeed( 2 ).setCornerId( 3, 9 ); + + // 10 11 2 8 + meshBuilder.getCellSeed( 3 ).setCornerId( 0, 10 ); + meshBuilder.getCellSeed( 3 ).setCornerId( 1, 11 ); + meshBuilder.getCellSeed( 3 ).setCornerId( 2, 2 ); + meshBuilder.getCellSeed( 3 ).setCornerId( 3, 8 ); + + // 12 7 6 5 + meshBuilder.getCellSeed( 4 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 4 ).setCornerId( 1, 7 ); + meshBuilder.getCellSeed( 4 ).setCornerId( 2, 6 ); + meshBuilder.getCellSeed( 4 ).setCornerId( 3, 5 ); + + // 9 12 5 8 + meshBuilder.getCellSeed( 5 ).setCornerId( 0, 9 ); + meshBuilder.getCellSeed( 5 ).setCornerId( 1, 12 ); + meshBuilder.getCellSeed( 5 ).setCornerId( 2, 5 ); + meshBuilder.getCellSeed( 5 ).setCornerId( 3, 8 ); + + // 12 11 9 3 + meshBuilder.getCellSeed( 6 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 6 ).setCornerId( 1, 11 ); + meshBuilder.getCellSeed( 6 ).setCornerId( 2, 9 ); + meshBuilder.getCellSeed( 6 ).setCornerId( 3, 3 ); + + // 9 4 11 8 + meshBuilder.getCellSeed( 7 ).setCornerId( 0, 9 ); + meshBuilder.getCellSeed( 7 ).setCornerId( 1, 4 ); + meshBuilder.getCellSeed( 7 ).setCornerId( 2, 11 ); + meshBuilder.getCellSeed( 7 ).setCornerId( 3, 8 ); + + // 12 9 5 3 + meshBuilder.getCellSeed( 8 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 8 ).setCornerId( 1, 9 ); + meshBuilder.getCellSeed( 8 ).setCornerId( 2, 5 ); + meshBuilder.getCellSeed( 8 ).setCornerId( 3, 3 ); + + // 1 2 0 11 + meshBuilder.getCellSeed( 9 ).setCornerId( 0, 1 ); + meshBuilder.getCellSeed( 9 ).setCornerId( 1, 2 ); + meshBuilder.getCellSeed( 9 ).setCornerId( 2, 0 ); + meshBuilder.getCellSeed( 9 ).setCornerId( 3, 11 ); + + // 8 11 2 4 + meshBuilder.getCellSeed( 10 ).setCornerId( 0, 8 ); + meshBuilder.getCellSeed( 10 ).setCornerId( 1, 11 ); + meshBuilder.getCellSeed( 10 ).setCornerId( 2, 2 ); + meshBuilder.getCellSeed( 10 ).setCornerId( 3, 4 ); + + // 1 2 11 4 + meshBuilder.getCellSeed( 11 ).setCornerId( 0, 1 ); + meshBuilder.getCellSeed( 11 ).setCornerId( 1, 2 ); + meshBuilder.getCellSeed( 11 ).setCornerId( 2, 11 ); + meshBuilder.getCellSeed( 11 ).setCornerId( 3, 4 ); + + // 9 4 1 11 + meshBuilder.getCellSeed( 12 ).setCornerId( 0, 9 ); + meshBuilder.getCellSeed( 12 ).setCornerId( 1, 4 ); + meshBuilder.getCellSeed( 12 ).setCornerId( 2, 1 ); + meshBuilder.getCellSeed( 12 ).setCornerId( 3, 11 ); + + // 10 11 8 12 + meshBuilder.getCellSeed( 13 ).setCornerId( 0, 10 ); + meshBuilder.getCellSeed( 13 ).setCornerId( 1, 11 ); + meshBuilder.getCellSeed( 13 ).setCornerId( 2, 8 ); + meshBuilder.getCellSeed( 13 ).setCornerId( 3, 12 ); + + // 12 6 7 10 + meshBuilder.getCellSeed( 14 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 14 ).setCornerId( 1, 6 ); + meshBuilder.getCellSeed( 14 ).setCornerId( 2, 7 ); + meshBuilder.getCellSeed( 14 ).setCornerId( 3, 10 ); + + // 10 11 12 3 + meshBuilder.getCellSeed( 15 ).setCornerId( 0, 10 ); + meshBuilder.getCellSeed( 15 ).setCornerId( 1, 11 ); + meshBuilder.getCellSeed( 15 ).setCornerId( 2, 12 ); + meshBuilder.getCellSeed( 15 ).setCornerId( 3, 3 ); + + // 12 6 3 5 + meshBuilder.getCellSeed( 16 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 16 ).setCornerId( 1, 6 ); + meshBuilder.getCellSeed( 16 ).setCornerId( 2, 3 ); + meshBuilder.getCellSeed( 16 ).setCornerId( 3, 5 ); + + // 12 3 6 10 + meshBuilder.getCellSeed( 17 ).setCornerId( 0, 12 ); + meshBuilder.getCellSeed( 17 ).setCornerId( 1, 3 ); + meshBuilder.getCellSeed( 17 ).setCornerId( 2, 6 ); + meshBuilder.getCellSeed( 17 ).setCornerId( 3, 10 ); + + ASSERT_TRUE( meshBuilder.build( mesh ) ); + + testFinishedMesh( mesh ); +} + +TEST( MeshTest, RegularMeshOfTrianglesTest ) +{ + using TriangleMeshEntityType = MeshEntity< TestTriangleMeshConfig, Devices::Host, Topologies::Triangle >; + using EdgeMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityType; + using VertexMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityType; + + using PointType = typename VertexMeshEntityType::PointType; + ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) ); + + const IndexType xSize( 5 ), ySize( 5 ); + const RealType width( 1.0 ), height( 1.0 ); + const RealType hx( width / ( RealType ) xSize ), + hy( height / ( RealType ) ySize ); + const IndexType numberOfCells = 2 * xSize * ySize; + const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ); + + typedef Mesh< TestTriangleMeshConfig > TestTriangleMesh; + Mesh< TestTriangleMeshConfig > mesh; + MeshBuilder< TestTriangleMesh > meshBuilder; + meshBuilder.setPointsCount( numberOfVertices ); + meshBuilder.setCellsCount( numberOfCells ); + + /**** + * Setup vertices + */ + for( IndexType j = 0; j <= ySize; j++ ) + for( IndexType i = 0; i <= xSize; i++ ) + meshBuilder.setPoint( j * ( xSize + 1 ) + i, PointType( i * hx, j * hy ) ); + + /**** + * Setup cells + */ + IndexType cellIdx( 0 ); + for( IndexType j = 0; j < ySize; j++ ) + for( IndexType i = 0; i < xSize; i++ ) + { + const IndexType vertex0 = j * ( xSize + 1 ) + i; + const IndexType vertex1 = j * ( xSize + 1 ) + i + 1; + const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i; + const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i + 1; + + meshBuilder.getCellSeed( cellIdx ).setCornerId( 0, vertex0 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 1, vertex1 ); + meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex2 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 0, vertex1 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 1, vertex2 ); + meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex3 ); + } + + ASSERT_TRUE( meshBuilder.build( mesh ) ); + + // Test cells -> vertices subentities + cellIdx = 0; + for( IndexType j = 0; j < ySize; j++ ) + for( IndexType i = 0; i < xSize; i++ ) + { + const IndexType vertex0 = j * ( xSize + 1 ) + i; + const IndexType vertex1 = j * ( xSize + 1 ) + i + 1; + const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i; + const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i + 1; + + const TriangleMeshEntityType& leftCell = mesh.template getEntity< 2 >( cellIdx++ ); + EXPECT_EQ( leftCell.template getSubentityIndex< 0 >( 0 ), vertex0 ); + EXPECT_EQ( leftCell.template getSubentityIndex< 0 >( 1 ), vertex1 ); + EXPECT_EQ( leftCell.template getSubentityIndex< 0 >( 2 ), vertex2 ); + + const TriangleMeshEntityType& rightCell = mesh.template getEntity< 2 >( cellIdx++ ); + EXPECT_EQ( rightCell.template getSubentityIndex< 0 >( 0 ), vertex1 ); + EXPECT_EQ( rightCell.template getSubentityIndex< 0 >( 1 ), vertex2 ); + EXPECT_EQ( rightCell.template getSubentityIndex< 0 >( 2 ), vertex3 ); + } + + // Test vertices -> cells superentities + for( IndexType j = 0; j <= ySize; j++ ) + for( IndexType i = 0; i <= xSize; i++ ) + { + const IndexType vertexIndex = j * ( xSize + 1 ) + i; + const VertexMeshEntityType& vertex = mesh.template getEntity< 0 >( vertexIndex ); + + if( ( i == 0 && j == 0 ) || ( i == xSize && j == ySize ) ) { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 2 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 1 ); + } + else if( ( i == 0 && j == ySize ) || ( i == xSize && j == 0 ) ) { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 3 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 2 ); + } + else if( i == 0 || i == xSize || j == 0 || j == ySize ) { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 4 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 3 ); + } + else { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 6 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 6 ); + } + } + + testFinishedMesh( mesh ); +} + +TEST( MeshTest, RegularMeshOfQuadrilateralsTest ) +{ + using QuadrilateralMeshEntityType = MeshEntity< TestQuadrilateralMeshConfig, Devices::Host, Topologies::Quadrilateral >; + using EdgeMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 1 >::SubentityType; + using VertexMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 0 >::SubentityType; + + using PointType = typename VertexMeshEntityType::PointType; + ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) ); + + const IndexType xSize( 3 ), ySize( 4 ); + const RealType width( 1.0 ), height( 1.0 ); + const RealType hx( width / ( RealType ) xSize ), + hy( height / ( RealType ) ySize ); + const IndexType numberOfCells = xSize * ySize; + const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ); + + typedef Mesh< TestQuadrilateralMeshConfig > TestQuadrilateralMesh; + TestQuadrilateralMesh mesh; + MeshBuilder< TestQuadrilateralMesh > meshBuilder; + meshBuilder.setPointsCount( numberOfVertices ); + meshBuilder.setCellsCount( numberOfCells ); + + /**** + * Setup vertices + */ + for( IndexType j = 0; j <= ySize; j++ ) + for( IndexType i = 0; i <= xSize; i++ ) + meshBuilder.setPoint( j * ( xSize + 1 ) + i, PointType( i * hx, j * hy ) ); + + /**** + * Setup cells + */ + IndexType cellIdx( 0 ); + for( IndexType j = 0; j < ySize; j++ ) + for( IndexType i = 0; i < xSize; i++ ) + { + const IndexType vertex0 = j * ( xSize + 1 ) + i; + const IndexType vertex1 = j * ( xSize + 1 ) + i + 1; + const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i + 1; + const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i; + + meshBuilder.getCellSeed( cellIdx ).setCornerId( 0, vertex0 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 1, vertex1 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 2, vertex2 ); + meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 3, vertex3 ); + } + + ASSERT_TRUE( meshBuilder.build( mesh ) ); + + // Test cells -> vertices subentities + cellIdx = 0; + for( IndexType j = 0; j < ySize; j++ ) + for( IndexType i = 0; i < xSize; i++ ) + { + const IndexType vertex0 = j * ( xSize + 1 ) + i; + const IndexType vertex1 = j * ( xSize + 1 ) + i + 1; + const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i + 1; + const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i; + + const QuadrilateralMeshEntityType& cell = mesh.template getEntity< 2 >( cellIdx++ ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 0 ), vertex0 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 1 ), vertex1 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 2 ), vertex2 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 3 ), vertex3 ); + } + + // Test vertices -> cells superentities + for( IndexType j = 0; j <= ySize; j++ ) + for( IndexType i = 0; i <= xSize; i++ ) + { + const IndexType vertexIndex = j * ( xSize + 1 ) + i; + const VertexMeshEntityType& vertex = mesh.template getEntity< 0 >( vertexIndex ); + + if( ( i == 0 || i == xSize ) && ( j == 0 || j == ySize ) ) { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 2 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 0 ), ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) ); + } + else if( i == 0 || i == xSize || j == 0 || j == ySize ) { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 3 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 2 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 0 ), ( j - ( j == ySize || i == 0 || i == xSize ) ) * xSize + i - ( i == xSize ) - ( j == 0 || j == ySize ) ); + EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 1 ), ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) ); + } + else { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 4 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 4 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 0 ), ( j - 1 ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 1 ), ( j - 1 ) * xSize + i ); + EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 2 ), ( j ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 3 ), ( j ) * xSize + i ); + } + } + + testFinishedMesh( mesh ); +} + +TEST( MeshTest, RegularMeshOfHexahedronsTest ) +{ + using HexahedronMeshEntityType = MeshEntity< TestHexahedronMeshConfig, Devices::Host, Topologies::Hexahedron >; + using QuadrilateralMeshEntityType = typename HexahedronMeshEntityType::SubentityTraits< 2 >::SubentityType; + using EdgeMeshEntityType = typename HexahedronMeshEntityType::SubentityTraits< 1 >::SubentityType; + using VertexMeshEntityType = typename HexahedronMeshEntityType::SubentityTraits< 0 >::SubentityType; + + using PointType = typename VertexMeshEntityType::PointType; + ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 3, RealType >::getType() ) ); + + const IndexType xSize( 3 ), ySize( 4 ), zSize( 5 ); + const RealType width( 1.0 ), height( 1.0 ), depth( 1.0 ); + const RealType hx( width / ( RealType ) xSize ), + hy( height / ( RealType ) ySize ), + hz( depth / ( RealType ) zSize ); + const IndexType numberOfCells = xSize * ySize * zSize; + const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ) * ( zSize + 1 ); + + typedef Mesh< TestHexahedronMeshConfig > TestHexahedronMesh; + TestHexahedronMesh mesh; + MeshBuilder< TestHexahedronMesh > meshBuilder; + meshBuilder.setPointsCount( numberOfVertices ); + meshBuilder.setCellsCount( numberOfCells ); + + /**** + * Setup vertices + */ + for( IndexType k = 0; k <= zSize; k++ ) + for( IndexType j = 0; j <= ySize; j++ ) + for( IndexType i = 0; i <= xSize; i++ ) + meshBuilder.setPoint( k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i, PointType( i * hx, j * hy, k * hz ) ); + + /**** + * Setup cells + */ + IndexType cellIdx( 0 ); + for( IndexType k = 0; k < zSize; k++ ) + for( IndexType j = 0; j < ySize; j++ ) + for( IndexType i = 0; i < xSize; i++ ) + { + const IndexType vertex0 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i; + const IndexType vertex1 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1; + const IndexType vertex2 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1; + const IndexType vertex3 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i; + const IndexType vertex4 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i; + const IndexType vertex5 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1; + const IndexType vertex6 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1; + const IndexType vertex7 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i; + + meshBuilder.getCellSeed( cellIdx ).setCornerId( 0, vertex0 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 1, vertex1 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 2, vertex2 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 3, vertex3 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 4, vertex4 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 5, vertex5 ); + meshBuilder.getCellSeed( cellIdx ).setCornerId( 6, vertex6 ); + meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 7, vertex7 ); + } + + ASSERT_TRUE( meshBuilder.build( mesh ) ); + + // Test cells -> vertices subentities + cellIdx = 0; + for( IndexType k = 0; k < zSize; k++ ) + for( IndexType j = 0; j < ySize; j++ ) + for( IndexType i = 0; i < xSize; i++ ) + { + const IndexType vertex0 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i; + const IndexType vertex1 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1; + const IndexType vertex2 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1; + const IndexType vertex3 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i; + const IndexType vertex4 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i; + const IndexType vertex5 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1; + const IndexType vertex6 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1; + const IndexType vertex7 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i; + + const HexahedronMeshEntityType& cell = mesh.template getEntity< 3 >( cellIdx++ ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 0 ), vertex0 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 1 ), vertex1 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 2 ), vertex2 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 3 ), vertex3 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 4 ), vertex4 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 5 ), vertex5 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 6 ), vertex6 ); + EXPECT_EQ( cell.template getSubentityIndex< 0 >( 7 ), vertex7 ); + } + + // Test vertices -> cells superentities + for( IndexType k = 0; k < zSize; k++ ) + for( IndexType j = 0; j <= ySize; j++ ) + for( IndexType i = 0; i <= xSize; i++ ) + { + const IndexType vertexIndex = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i; + const VertexMeshEntityType& vertex = mesh.template getEntity< 0 >( vertexIndex ); + + if( ( i == 0 || i == xSize ) && ( j == 0 || j == ySize ) && ( k == 0 || k == zSize ) ) { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 3 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 3 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) ); + } + else if( i == 0 || i == xSize || j == 0 || j == ySize || k == 0 || k == zSize ) { + if( ( i != 0 && i != xSize && j != 0 && j != ySize ) || + ( i != 0 && i != xSize && k != 0 && k != zSize ) || + ( j != 0 && j != ySize && k != 0 && k != zSize ) ) + { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 5 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 8 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 4 ); + if( k == 0 || k == zSize ) { + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j - 1 ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j - 1 ) * xSize + i ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j ) * xSize + i ); + } + else if( j == 0 || j == ySize ) { + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - 1 ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ), ( k - 1 ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ), ( k ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ), ( k ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i ); + } + else { + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - 1 ) * xSize * ySize + ( j - 1 ) * xSize + i - ( i == xSize ) ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ), ( k - 1 ) * xSize * ySize + ( j ) * xSize + i - ( i == xSize ) ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ), ( k ) * xSize * ySize + ( j - 1 ) * xSize + i - ( i == xSize ) ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ), ( k ) * xSize * ySize + ( j ) * xSize + i - ( i == xSize ) ); + } + } + else { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 4 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 5 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 2 ); + if( k != 0 && k != zSize ) { + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - 1 ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ), ( k ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) ); + } + else if( j != 0 && j != ySize ) { + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j - 1 ) * xSize + i - ( i == xSize ) ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j ) * xSize + i - ( i == xSize ) ); + } + else { + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ), ( k - ( k == zSize ) ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i ); + } + } + } + else { + EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 6 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 12 ); + EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 8 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ), ( k - 1 ) * xSize * ySize + ( j - 1 ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ), ( k - 1 ) * xSize * ySize + ( j - 1 ) * xSize + i ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ), ( k - 1 ) * xSize * ySize + ( j ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ), ( k - 1 ) * xSize * ySize + ( j ) * xSize + i ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 4 ), ( k ) * xSize * ySize + ( j - 1 ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 5 ), ( k ) * xSize * ySize + ( j - 1 ) * xSize + i ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 6 ), ( k ) * xSize * ySize + ( j ) * xSize + i - 1 ); + EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 7 ), ( k ) * xSize * ySize + ( j ) * xSize + i ); + } + } + + testFinishedMesh( mesh ); +} + +} // namespace MeshTest + +#endif diff --git a/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp b/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp index 7f62d6df15b3daef7c67a59706b196f78c9af91b..77dbc74663330dd2d8d4d7fa32576d99c933c485 100644 --- a/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp +++ b/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp @@ -21,6 +21,8 @@ using namespace TNL::Functions; using namespace TNL::Devices; +#define FILENAME "./test-file.tnl" + //=====================================TEST CLASS============================================== template <int dim> @@ -60,9 +62,9 @@ class TestSaveAndLoadMeshfunction linearFunctionEvaluator.evaluateAllEntities(localMeshFunctionptr , linearFunctionPtr); File file; - file.open( String( "./test-file.tnl"), IOMode::write ); - localMeshFunctionptr->save(file); - file.close(); + ASSERT_TRUE( file.open( String( FILENAME), IOMode::write )); + ASSERT_TRUE( localMeshFunctionptr->save(file)); + ASSERT_TRUE( file.close() ); //load other meshfunction on same localgrid from created file SharedPointer<MeshType> loadGridptr; @@ -78,15 +80,17 @@ class TestSaveAndLoadMeshfunction loadDof[i]=-1; } - file.open( String( "./test-file.tnl" ), IOMode::read ); - loadMeshFunctionptr->boundLoad(file); - file.close(); + ASSERT_TRUE( file.open( String( FILENAME ), IOMode::read )); + ASSERT_TRUE( loadMeshFunctionptr->boundLoad(file)); + ASSERT_TRUE( file.close()); for(int i=0;i<localDof.getSize();i++) { EXPECT_EQ( localDof[i], loadDof[i]) << "Compare Loaded and evaluated Dof Failed for: "<< i; } + EXPECT_EQ( std::remove( FILENAME ), 0 ); + }; }; diff --git a/tests/benchmarks/CMakeLists.txt b/tests/benchmarks/CMakeLists.txt index b4a926ac3fae4d68feab1d4a2d74f0cba25e6bda..12fe883c8c50bb59fd1724a528197fc3a394cf2f 100644 --- a/tests/benchmarks/CMakeLists.txt +++ b/tests/benchmarks/CMakeLists.txt @@ -3,9 +3,7 @@ ADD_SUBDIRECTORY( heat-equation-benchmark ) IF( BUILD_CUDA ) CUDA_ADD_EXECUTABLE( tnl-benchmark-blas tnl-benchmark-blas.cu ) - if( HAVE_CUBLAS STREQUAL "yes" ) - CUDA_ADD_CUBLAS_TO_TARGET( tnl-benchmark-blas ) - endif() + CUDA_ADD_CUBLAS_TO_TARGET( tnl-benchmark-blas ) TARGET_LINK_LIBRARIES( tnl-benchmark-blas tnl ${CUSPARSE_LIBRARY} ) CUDA_ADD_EXECUTABLE( tnl-benchmark-spmv tnl-benchmark-spmv.cu ) diff --git a/tests/benchmarks/cublasWrappers.h b/tests/benchmarks/cublasWrappers.h index a7520a34d5d13ced796d8b2366b0382887f09a49..6b71a4ed7befc12664440cf5425f5975e6feec0c 100644 --- a/tests/benchmarks/cublasWrappers.h +++ b/tests/benchmarks/cublasWrappers.h @@ -1,7 +1,6 @@ #pragma once #ifdef HAVE_CUDA -#ifdef HAVE_CUBLAS #include <cublas_v2.h> @@ -120,4 +119,3 @@ cublasGscal( cublasHandle_t handle, int n, } #endif -#endif diff --git a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h index 96a18586f5a8f03b149f9227b776dca6396be9e6..8bdf9634ebea6a9951b4bcfea2adcdbbc070d2a9 100644 --- a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h +++ b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h @@ -1,6 +1,7 @@ #pragma once #include <TNL/Solvers/BuildConfigTags.h> +#include <TNL/Meshes/BuildConfigTags.h> namespace TNL { @@ -20,16 +21,6 @@ template<> struct ConfigTagReal< HeatEquationBenchmarkBuildConfigTag, long doubl template<> struct ConfigTagIndex< HeatEquationBenchmarkBuildConfigTag, short int >{ enum { enabled = false }; }; template<> struct ConfigTagIndex< HeatEquationBenchmarkBuildConfigTag, long int >{ enum { enabled = false }; }; -/**** - * Use of Grid is enabled for allowed dimensions and Real, Device and Index types. - */ -template< int Dimension, typename Real, typename Device, typename Index > - struct ConfigTagMesh< HeatEquationBenchmarkBuildConfigTag, Meshes::Grid< Dimension, Real, Device, Index > > - { enum { enabled = ( Dimension == 2 ) && - ConfigTagReal< HeatEquationBenchmarkBuildConfigTag, Real >::enabled && - ConfigTagDevice< HeatEquationBenchmarkBuildConfigTag, Device >::enabled && - ConfigTagIndex< HeatEquationBenchmarkBuildConfigTag, Index >::enabled }; }; - /**** * Please, chose your preferred time discretisation here. */ @@ -44,5 +35,24 @@ template<> struct ConfigTagExplicitSolver< HeatEquationBenchmarkBuildConfigTag, template<> struct ConfigTagExplicitSolver< HeatEquationBenchmarkBuildConfigTag, ExplicitMersonSolverTag >{ enum { enabled = false }; }; } // namespace Solvers -} // namespace TNL +namespace Meshes { +namespace BuildConfigTags { + +template< int Dimensions > struct GridDimensionTag< HeatEquationBenchmarkBuildConfigTag, Dimensions >{ enum { enabled = ( Dimensions == 2 ) }; }; + +/**** + * Turn off support for float and long double. + */ +template<> struct GridRealTag< HeatEquationBenchmarkBuildConfigTag, float > { enum { enabled = false }; }; +template<> struct GridRealTag< HeatEquationBenchmarkBuildConfigTag, long double > { enum { enabled = false }; }; + +/**** + * Turn off support for short int and long int indexing. + */ +template<> struct GridIndexTag< HeatEquationBenchmarkBuildConfigTag, short int >{ enum { enabled = false }; }; +template<> struct GridIndexTag< HeatEquationBenchmarkBuildConfigTag, long int >{ enum { enabled = false }; }; + +} // namespace BuildConfigTags +} // namespace Meshes +} // namespace TNL diff --git a/tests/benchmarks/vector-operations.h b/tests/benchmarks/vector-operations.h index 2a1f51465bc6ecd93820933b01c51dc9d12c2213..cdf2443964a5bb33354de6e0ec0688018c7128a1 100644 --- a/tests/benchmarks/vector-operations.h +++ b/tests/benchmarks/vector-operations.h @@ -18,7 +18,7 @@ #include <TNL/Containers/Vector.h> -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA #include "cublasWrappers.h" #endif @@ -51,7 +51,7 @@ benchmarkVectorOperations( Benchmark & benchmark, Real resultHost, resultDevice; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA cublasHandle_t cublasHandle; cublasCreate( &cublasHandle ); #endif @@ -153,7 +153,7 @@ benchmarkVectorOperations( Benchmark & benchmark, auto absMaxCuda = [&]() { resultDevice = deviceVector.absMax(); }; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA auto absMaxCublas = [&]() { int index = 0; cublasIgamax( cublasHandle, size, @@ -167,10 +167,8 @@ benchmarkVectorOperations( Benchmark & benchmark, benchmark.time( reset1, "CPU (general)", absMaxHostGeneral ); #ifdef HAVE_CUDA benchmark.time( reset1, "GPU", absMaxCuda ); -#ifdef HAVE_CUBLAS benchmark.time( reset1, "cuBLAS", absMaxCublas ); #endif -#endif auto absMinHost = [&]() { @@ -190,7 +188,7 @@ benchmarkVectorOperations( Benchmark & benchmark, auto absMinCuda = [&]() { resultDevice = deviceVector.absMin(); }; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA auto absMinCublas = [&]() { int index = 0; cublasIgamin( cublasHandle, size, @@ -204,10 +202,8 @@ benchmarkVectorOperations( Benchmark & benchmark, benchmark.time( reset1, "CPU (general)", absMinHostGeneral ); #ifdef HAVE_CUDA benchmark.time( reset1, "GPU", absMinCuda ); -#ifdef HAVE_CUBLAS benchmark.time( reset1, "cuBLAS", absMinCublas ); #endif -#endif auto sumHost = [&]() { @@ -252,7 +248,7 @@ benchmarkVectorOperations( Benchmark & benchmark, auto l1normCuda = [&]() { resultDevice = deviceVector.lpNorm( 1.0 ); }; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA auto l1normCublas = [&]() { cublasGasum( cublasHandle, size, deviceVector.getData(), 1, @@ -264,10 +260,8 @@ benchmarkVectorOperations( Benchmark & benchmark, benchmark.time( reset1, "CPU (general)", l1normHostGeneral ); #ifdef HAVE_CUDA benchmark.time( reset1, "GPU", l1normCuda ); -#ifdef HAVE_CUBLAS benchmark.time( reset1, "cuBLAS", l1normCublas ); #endif -#endif auto l2normHost = [&]() { @@ -287,7 +281,7 @@ benchmarkVectorOperations( Benchmark & benchmark, auto l2normCuda = [&]() { resultDevice = deviceVector.lpNorm( 2.0 ); }; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA auto l2normCublas = [&]() { cublasGnrm2( cublasHandle, size, deviceVector.getData(), 1, @@ -299,10 +293,8 @@ benchmarkVectorOperations( Benchmark & benchmark, benchmark.time( reset1, "CPU (general)", l2normHostGeneral ); #ifdef HAVE_CUDA benchmark.time( reset1, "GPU", l2normCuda ); -#ifdef HAVE_CUBLAS benchmark.time( reset1, "cuBLAS", l2normCublas ); #endif -#endif auto l3normHost = [&]() { @@ -348,7 +340,7 @@ benchmarkVectorOperations( Benchmark & benchmark, auto scalarProductCuda = [&]() { resultDevice = deviceVector.scalarProduct( deviceVector2 ); }; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA auto scalarProductCublas = [&]() { cublasGdot( cublasHandle, size, deviceVector.getData(), 1, @@ -361,9 +353,7 @@ benchmarkVectorOperations( Benchmark & benchmark, benchmark.time( reset1, "CPU (general)", scalarProductHostGeneral ); #ifdef HAVE_CUDA benchmark.time( reset1, "GPU", scalarProductCuda ); -#ifdef HAVE_CUBLAS benchmark.time( reset1, "cuBLAS", scalarProductCublas ); -#endif #endif /* @@ -402,7 +392,7 @@ benchmarkVectorOperations( Benchmark & benchmark, auto multiplyCuda = [&]() { deviceVector *= 0.5; }; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA auto multiplyCublas = [&]() { const Real alpha = 0.5; cublasGscal( cublasHandle, size, @@ -414,10 +404,8 @@ benchmarkVectorOperations( Benchmark & benchmark, benchmark.time( reset1, "CPU", multiplyHost ); #ifdef HAVE_CUDA benchmark.time( reset1, "GPU", multiplyCuda ); -#ifdef HAVE_CUBLAS benchmark.time( reset1, "cuBLAS", multiplyCublas ); #endif -#endif auto addVectorHost = [&]() { @@ -426,7 +414,7 @@ benchmarkVectorOperations( Benchmark & benchmark, auto addVectorCuda = [&]() { deviceVector.addVector( deviceVector2 ); }; -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA auto addVectorCublas = [&]() { const Real alpha = 1.0; cublasGaxpy( cublasHandle, size, @@ -439,13 +427,11 @@ benchmarkVectorOperations( Benchmark & benchmark, benchmark.time( reset1, "CPU", addVectorHost ); #ifdef HAVE_CUDA benchmark.time( reset1, "GPU", addVectorCuda ); -#ifdef HAVE_CUBLAS benchmark.time( reset1, "cuBLAS", addVectorCublas ); #endif -#endif -#ifdef HAVE_CUBLAS +#ifdef HAVE_CUDA cublasDestroy( cublasHandle ); #endif diff --git a/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp b/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp index ec475d71e5014fe7e4b71a141477b26887f725b2..89eabd1314015c26f45b175cca92cbe60daf093f 100644 --- a/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp +++ b/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp @@ -12,7 +12,7 @@ #include <TNL/Devices/Host.h> #include <cstdlib> -#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h> +#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h> #include "tnlIndexMultimapTester.h" #include "../../tnlUnitTestStarter.h" diff --git a/tests/unit-tests/mesh/CMakeLists.txt b/tests/unit-tests/mesh/CMakeLists.txt index d21424d8158129d097665bae61176556cae09048..1d2f3cba628067eaeb6de6ffc98bfc7101c0b560 100644 --- a/tests/unit-tests/mesh/CMakeLists.txt +++ b/tests/unit-tests/mesh/CMakeLists.txt @@ -1,17 +1,4 @@ -set( headers tnlGridTester.h - tnlMeshEntityTester.h - tnlMeshTester.h ) +set( headers tnlGridTester.h ) -ADD_EXECUTABLE( tnlGridTest${mpiExt} ${headers} tnlGridTest.cpp ) -TARGET_LINK_LIBRARIES( tnlGridTest${mpiExt} ${CPPUNIT_LIBRARIES} - tnl${mpiExt} ) - -#ADD_EXECUTABLE( tnlMeshEntityTest${mpiExt} ${headers} tnlMeshEntityTest.cpp ) -#TARGET_LINK_LIBRARIES( MeshEntityTest${mpiExt} ${CPPUNIT_LIBRARIES} -# tnl${mpiExt} ) - -ADD_EXECUTABLE( tnlMeshTest${mpiExt} ${headers} tnlMeshTest.cpp ) -TARGET_LINK_LIBRARIES( tnlMeshTest${mpiExt} ${CPPUNIT_LIBRARIES} - tnl${mpiExt} ) - - +ADD_EXECUTABLE( tnlGridTest ${headers} tnlGridTest.cpp ) +TARGET_LINK_LIBRARIES( tnlGridTest ${CPPUNIT_LIBRARIES} tnl ) diff --git a/tests/unit-tests/mesh/tnlMeshEntityTest.cpp b/tests/unit-tests/mesh/tnlMeshEntityTest.cpp deleted file mode 100644 index a5333f1a64f27240e4bebfce95ea322cb765ad0c..0000000000000000000000000000000000000000 --- a/tests/unit-tests/mesh/tnlMeshEntityTest.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************** - MeshEntityTest.cpp - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include <TNL/tnlConfig.h> -#include <TNL/Devices/Host.h> -#include <cstdlib> - -#ifndef HAVE_NOT_CXX11 -#include "MeshEntityTester.h" -#endif -#include "../tnlUnitTestStarter.h" - -int main( int argc, char* argv[] ) -{ -#ifndef HAVE_NOT_CXX11 -#ifdef HAVE_CPPUNIT - if( ! tnlUnitTestStarter :: run< MeshEntityTester< double, Devices::Host, long int > >() - ) - return EXIT_FAILURE; - return EXIT_SUCCESS; -#else - return EXIT_FAILURE; -#endif -#endif -} - - diff --git a/tests/unit-tests/mesh/tnlMeshEntityTester.h b/tests/unit-tests/mesh/tnlMeshEntityTester.h deleted file mode 100644 index a62dd4eefeb73154a114a0491783cf2f9a6e300b..0000000000000000000000000000000000000000 --- a/tests/unit-tests/mesh/tnlMeshEntityTester.h +++ /dev/null @@ -1,494 +0,0 @@ -/*************************************************************************** - MeshEntityTester.h - description - ------------------- - begin : Feb 11, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#ifndef TNLMESHENTITYTESTER_H_ -#define TNLMESHENTITYTESTER_H_ - -#ifdef HAVE_CPPUNIT -#include <cppunit/TestSuite.h> -#include <cppunit/TestResult.h> -#include <cppunit/TestCaller.h> -#include <cppunit/TestCase.h> -#include <cppunit/Message.h> -#include <TNL/Meshes/MeshEntity.h> -#include <TNL/Meshes/MeshDetails/config/MeshConfigBase.h> -#include <TNL/Meshes/Topologies/MeshVertexTopology.h> -#include <TNL/Meshes/Topologies/MeshEdgeTopology.h> -#include <TNL/Meshes/Topologies/MeshTriangleTopology.h> -#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h> - -using namespace TNL; - -//typedef MeshConfigBase< MeshTriangleTopology, 2, double, int, int, void > TestTriangleEntityTopology; -typedef MeshConfigBase< MeshEdgeTopology, 2, double, int, int, void > TestEdgeEntityTopology; -typedef MeshConfigBase< MeshVertexTopology, 2, double, int, int, void > TestVertexEntityTopology; - -class TestTriangleMeshConfig : public MeshConfigBase< MeshTriangleTopology > -{ - public: - - template< typename MeshEntity > - static constexpr bool subentityStorage( MeshEntity entity, int subentityDimension ) - { - return true; - } - - template< typename MeshEntity > - static constexpr bool superentityStorage( MeshEntity entity, int superentityDimension ) - { - return true; - } -}; - -class TestTetrahedronMeshConfig : public MeshConfigBase< MeshTetrahedronTopology > -{ - public: - - template< typename MeshEntity > - static constexpr bool subentityStorage( MeshEntity entity, int subentityDimension ) - { - return true; - } - - template< typename MeshEntity > - static constexpr bool superentityStorage( MeshEntity entity, int superentityDimension ) - { - return true; - } -}; - -template< typename RealType, typename Device, typename IndexType > -class MeshEntityTester : public CppUnit :: TestCase -{ - public: - typedef MeshEntityTester< RealType, Device, IndexType > TesterType; - typedef typename CppUnit::TestCaller< TesterType > TestCallerType; - - MeshEntityTester(){}; - - virtual - ~MeshEntityTester(){}; - - static CppUnit :: Test* suite() - { - CppUnit :: TestSuite* suiteOfTests = new CppUnit :: TestSuite( "MeshEntityTester" ); - CppUnit :: TestResult result; - - suiteOfTests -> addTest( new TestCallerType( "vertexMeshEntityTest", &TesterType::vertexMeshEntityTest ) ); - suiteOfTests -> addTest( new TestCallerType( "edgeMeshEntityTest", &TesterType::edgeMeshEntityTest ) ); - suiteOfTests -> addTest( new TestCallerType( "triangleMeshEntityTest", &TesterType::triangleMeshEntityTest ) ); - suiteOfTests -> addTest( new TestCallerType( "tetrahedronMeshEntityTest", &TesterType::tetrahedronMeshEntityTest ) ); - suiteOfTests -> addTest( new TestCallerType( "twoTrianglesTest", &TesterType::twoTrianglesTest ) ); - - return suiteOfTests; - } - - - void vertexMeshEntityTest() - { - typedef MeshConfigBase< MeshEdgeTopology, 2, RealType, IndexType, IndexType, void > TestEntityTopology; - typedef MeshEntity< TestEntityTopology, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - - CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) ); - VertexMeshEntityType vertexEntity; - PointType point; - - point.x() = 1.0; - point.y() = 2.0; - vertexEntity.setPoint( point ); - CPPUNIT_ASSERT( vertexEntity.getPoint() == point ); - } - - void edgeMeshEntityTest() - { - typedef MeshEntity< TestEdgeEntityTopology, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestEdgeEntityTopology, MeshVertexTopology > VertexMeshEntityType; - - typedef typename VertexMeshEntityType::PointType PointType; - CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) ); - - /**** - * - * Here we test the following simple example: - * - - point2 - |\ - | \ - | \ - | \ - - .... - edge1 edge0 - .... - - - | \ - | \ - --------------------- - point0 edge2 point1 - - */ - - PointType point0( 0.0, 0.0 ), - point1( 1.0, 0.0 ), - point2( 0.0, 1.0 ); - - StaticArray< 3, VertexMeshEntityType > vertexEntities; - vertexEntities[ 0 ].setPoint( point0 ); - vertexEntities[ 1 ].setPoint( point1 ); - vertexEntities[ 2 ].setPoint( point2 ); - - CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 ); - CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 ); - - StaticArray< 3, EdgeMeshEntityType > edgeEntities; - edgeEntities[ 0 ].setVertexIndex( 0, 0 ); - edgeEntities[ 0 ].setVertexIndex( 1, 1 ); - edgeEntities[ 1 ].setVertexIndex( 0, 1 ); - edgeEntities[ 1 ].setVertexIndex( 1, 2 ); - edgeEntities[ 2 ].setVertexIndex( 0, 2 ); - edgeEntities[ 2 ].setVertexIndex( 1, 0 ); - edgeEntities[ 0 ].setId( 0 ); - edgeEntities[ 1 ].setId( 1 ); - edgeEntities[ 2 ].setId( 2 ); - - CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 0 ) ].getPoint() == point0 ); - CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 1 ) ].getPoint() == point1 ); - CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 0 ) ].getPoint() == point1 ); - CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 1 ) ].getPoint() == point2 ); - CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 0 ) ].getPoint() == point2 ); - CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 1 ) ].getPoint() == point0 ); - } - - void triangleMeshEntityTest() - { - typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType; - - static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangular mesh does not store edges as required." ); - static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "" ); - typedef MeshEntity< TestEdgeEntityTopology, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestVertexEntityTopology, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) ); - - /**** - * We set-up the same situation as in the test above - */ - PointType point0( 0.0, 0.0 ), - point1( 1.0, 0.0 ), - point2( 0.0, 1.0 ); - - StaticArray< 3, VertexMeshEntityType > vertexEntities; - vertexEntities[ 0 ].setPoint( point0 ); - vertexEntities[ 1 ].setPoint( point1 ); - vertexEntities[ 2 ].setPoint( point2 ); - - CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 ); - CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 ); - - StaticArray< 3, EdgeMeshEntityType > edgeEntities; - edgeEntities[ 0 ].setVertexIndex( 0, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 0 >::index ); - edgeEntities[ 0 ].setVertexIndex( 1, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 1 >::index ); - edgeEntities[ 1 ].setVertexIndex( 0, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 0 >::index ); - edgeEntities[ 1 ].setVertexIndex( 1, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 1 >::index ); - edgeEntities[ 2 ].setVertexIndex( 0, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 0 >::index ); - edgeEntities[ 2 ].setVertexIndex( 1, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 1 >::index ); - - CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 1 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 1 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 1 >::index ) ); - - TriangleMeshEntityType triangleEntity; - - triangleEntity.template setSubentityIndex< 0 >( 0 , 0 ); - triangleEntity.template setSubentityIndex< 0 >( 1 , 1 ); - triangleEntity.template setSubentityIndex< 0 >( 2 , 2 ); - - CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 0 >( 0 ) == 0 ); - CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 0 >( 1 ) == 1 ); - CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 0 >( 2 ) == 2 ); - - triangleEntity.template setSubentityIndex< 1 >( 0 , 0 ); - triangleEntity.template setSubentityIndex< 1 >( 1 , 1 ); - triangleEntity.template setSubentityIndex< 1 >( 2 , 2 ); - - CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 1 >( 0 ) == 0 ); - CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 1 >( 1 ) == 1 ); - CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 1 >( 2 ) == 2 ); - }; - - void tetrahedronMeshEntityTest() - { - //typedef MeshConfigBase< MeshTetrahedronTopology, 3, RealType, IndexType, IndexType, void > TestTetrahedronEntityTopology; - typedef MeshConfigBase< MeshTriangleTopology, 3, RealType, IndexType, IndexType, void > TestTriangleEntityTopology; - typedef MeshConfigBase< MeshEdgeTopology, 3, RealType, IndexType, IndexType, void > TestEdgeEntityTopology; - typedef MeshConfigBase< MeshVertexTopology, 3, RealType, IndexType, IndexType, void > TestVertexEntityTopology; - - typedef MeshEntity< TestTetrahedronMeshConfig, MeshTetrahedronTopology > TetrahedronMeshEntityType; - typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType; - typedef MeshEntity< TestEdgeEntityTopology, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestVertexEntityTopology, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 3, RealType >::getType() ) ); - - /**** - * We set-up similar situation as above but with - * tetrahedron. - */ - PointType point0( 0.0, 0.0, 0.0), - point1( 1.0, 0.0, 0.0 ), - point2( 0.0, 1.0, 0.0 ), - point3( 0.0, 0.0, 1.0 ); - - StaticArray< MeshSubtopology< MeshTetrahedronTopology, 0 >::count, - VertexMeshEntityType > vertexEntities; - - vertexEntities[ 0 ].setPoint( point0 ); - vertexEntities[ 1 ].setPoint( point1 ); - vertexEntities[ 2 ].setPoint( point2 ); - vertexEntities[ 3 ].setPoint( point3 ); - - CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 ); - CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 ); - CPPUNIT_ASSERT( vertexEntities[ 3 ].getPoint() == point3 ); - - StaticArray< MeshSubtopology< MeshTetrahedronTopology, 1 >::count, - EdgeMeshEntityType > edgeEntities; - edgeEntities[ 0 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 0 >::index ); - edgeEntities[ 0 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 1 >::index ); - edgeEntities[ 1 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 0 >::index ); - edgeEntities[ 1 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 1 >::index ); - edgeEntities[ 2 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 0 >::index ); - edgeEntities[ 2 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 1 >::index ); - edgeEntities[ 3 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 0 >::index ); - edgeEntities[ 3 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 1 >::index ); - edgeEntities[ 4 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 0 >::index ); - edgeEntities[ 4 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 1 >::index ); - edgeEntities[ 5 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 0 >::index ); - edgeEntities[ 5 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 1 >::index ); - - CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 1 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 1 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 1 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 1 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 1 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 5 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 0 >::index ) ); - CPPUNIT_ASSERT( edgeEntities[ 5 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 1 >::index ) ); - - StaticArray< MeshSubtopology< MeshTetrahedronTopology, 2 >::count, - TriangleMeshEntityType > triangleEntities; - triangleEntities[ 0 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 0 >::index ); - triangleEntities[ 0 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 1 >::index ); - triangleEntities[ 0 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 2 >::index ); - triangleEntities[ 1 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 0 >::index ); - triangleEntities[ 1 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 1 >::index ); - triangleEntities[ 1 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 2 >::index ); - triangleEntities[ 2 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 0 >::index ); - triangleEntities[ 2 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 1 >::index ); - triangleEntities[ 2 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 2 >::index ); - triangleEntities[ 3 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 0 >::index ); - triangleEntities[ 3 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 1 >::index ); - triangleEntities[ 3 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 2 >::index ); - - CPPUNIT_ASSERT( triangleEntities[ 0 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 0 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 0 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 1 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 0 ].getVertexIndex( 2 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 2 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 0 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 1 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].getVertexIndex( 2 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 2 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 2 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 0 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 2 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 1 >::index ) ); - CPPUNIT_ASSERT( triangleEntities[ 2 ].getVertexIndex( 2 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 2 >::index ) ); - - TetrahedronMeshEntityType tetrahedronEntity; - tetrahedronEntity.setVertexIndex( 0, 0 ); - tetrahedronEntity.setVertexIndex( 1, 1 ); - tetrahedronEntity.setVertexIndex( 2, 2 ); - tetrahedronEntity.setVertexIndex( 3, 3 ); - - CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 0 ) == 0 ); - CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 1 ) == 1 ); - CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 2 ) == 2 ); - CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 3 ) == 3 ); - - tetrahedronEntity.template setSubentityIndex< 2 >( 0, 0 ); - tetrahedronEntity.template setSubentityIndex< 2 >( 1, 1 ); - tetrahedronEntity.template setSubentityIndex< 2 >( 2, 2 ); - tetrahedronEntity.template setSubentityIndex< 2 >( 3, 3 ); - - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 0 ) == 0 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 1 ) == 1 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 2 ) == 2 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 3 ) == 3 ); - - tetrahedronEntity.template setSubentityIndex< 1 >( 0, 0 ); - tetrahedronEntity.template setSubentityIndex< 1 >( 1, 1 ); - tetrahedronEntity.template setSubentityIndex< 1 >( 2, 2 ); - tetrahedronEntity.template setSubentityIndex< 1 >( 3, 3 ); - tetrahedronEntity.template setSubentityIndex< 1 >( 4, 4 ); - tetrahedronEntity.template setSubentityIndex< 1 >( 5, 5 ); - - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 0 ) == 0 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 1 ) == 1 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 2 ) == 2 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 3 ) == 3 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 4 ) == 4 ); - CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 5 ) == 5 ); - }; - - void twoTrianglesTest() - { - - typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType; - typedef MeshEntity< TestTriangleMeshConfig, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestTriangleMeshConfig, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) ); - - /**** - * We set-up the following situation - point2 edge3 point3 - |\-------------------| - | \ | - | \ triangle1 | - | \ | - - .... - edge1 edge0 edge4 - .... - - - | triangle0 \ | - | \ | - ---------------------| - point0 edge2 point1 - */ - - PointType point0( 0.0, 0.0 ), - point1( 1.0, 0.0 ), - point2( 0.0, 1.0 ), - point3( 1.0, 1.0 ); - - StaticArray< 4, VertexMeshEntityType > vertexEntities; - vertexEntities[ 0 ].setPoint( point0 ); - vertexEntities[ 1 ].setPoint( point1 ); - vertexEntities[ 2 ].setPoint( point2 ); - vertexEntities[ 3 ].setPoint( point3 ); - - CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 ); - CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 ); - CPPUNIT_ASSERT( vertexEntities[ 3 ].getPoint() == point3 ); - - StaticArray< 5, EdgeMeshEntityType > edgeEntities; - edgeEntities[ 0 ].setVertexIndex( 0, 1 ); - edgeEntities[ 0 ].setVertexIndex( 1, 2 ); - edgeEntities[ 1 ].setVertexIndex( 0, 2 ); - edgeEntities[ 1 ].setVertexIndex( 1, 0 ); - edgeEntities[ 2 ].setVertexIndex( 0, 0 ); - edgeEntities[ 2 ].setVertexIndex( 1, 1 ); - edgeEntities[ 3 ].setVertexIndex( 0, 2 ); - edgeEntities[ 3 ].setVertexIndex( 1, 3 ); - edgeEntities[ 4 ].setVertexIndex( 0, 3 ); - edgeEntities[ 4 ].setVertexIndex( 1, 1 ); - - CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 0 ) == 1 ); - CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 1 ) == 2 ); - CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 0 ) == 2 ); - CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 1 ) == 0 ); - CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 0 ) == 0 ); - CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 1 ) == 1 ); - CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 0 ) == 2 ); - CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 1 ) == 3 ); - CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 0 ) == 3 ); - CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 1 ) == 1 ); - - StaticArray< 2, TriangleMeshEntityType > triangleEntities; - - triangleEntities[ 0 ].template setSubentityIndex< 0 >( 0 , 0 ); - triangleEntities[ 0 ].template setSubentityIndex< 0 >( 1 , 1 ); - triangleEntities[ 0 ].template setSubentityIndex< 0 >( 2 , 2 ); - triangleEntities[ 0 ].template setSubentityIndex< 1 >( 0 , 0 ); - triangleEntities[ 0 ].template setSubentityIndex< 1 >( 1 , 1 ); - triangleEntities[ 0 ].template setSubentityIndex< 1 >( 2 , 2 ); - triangleEntities[ 1 ].template setSubentityIndex< 0 >( 0 , 0 ); - triangleEntities[ 1 ].template setSubentityIndex< 0 >( 1 , 2 ); - triangleEntities[ 1 ].template setSubentityIndex< 0 >( 2 , 3 ); - triangleEntities[ 1 ].template setSubentityIndex< 1 >( 0 , 0 ); - triangleEntities[ 1 ].template setSubentityIndex< 1 >( 1 , 3 ); - triangleEntities[ 1 ].template setSubentityIndex< 1 >( 2 , 4 ); - - CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 0 ) == 0 ); - CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 1 ) == 1 ); - CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 2 ) == 2 ); - CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 0 ) == 0 ); - CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 1 ) == 1 ); - CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 2 ) == 2 ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 0 ) == 0 ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 1 ) == 2 ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 2 ) == 3 ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 0 ) == 0 ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 1 ) == 3 ); - CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 2 ) == 4 ); - - /*vertexEntities[ 0 ].template setNumberOfSuperentities< 1 >( 2 ); - vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 0, 2 ); - vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 1, 1 ); - - vertexEntities[ 1 ].template setNumberOfSuperentities< 1 >( 3 ); - vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 0, 0 ); - vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 1, 2 ); - vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 2, 4 ); - - vertexEntities[ 1 ].template setNumberOfSuperentities< 2 >( 2 ); - vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 0, 0 ); - vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 1, 1 );*/ - - CPPUNIT_ASSERT( vertexEntities[ 0 ].template getNumberOfSuperentities< 1 >() == 2 ); - CPPUNIT_ASSERT( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 0 ) == 2 ); - CPPUNIT_ASSERT( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 1 ) == 1 ); - - CPPUNIT_ASSERT( vertexEntities[ 1 ].template getNumberOfSuperentities< 1 >() == 3 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 0 ) == 0 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 1 ) == 2 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 2 ) == 4 ); - - CPPUNIT_ASSERT( vertexEntities[ 1 ].template getNumberOfSuperentities< 2 >() == 2 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 0 ) == 0 ); - CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 1 ) == 1 ); - - /*edgeEntities[ 0 ].template setNumberOfSuperentities< 2 >( 2 ); - edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 0, 0 ); - edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 1, 1 );*/ - - /*CPPUNIT_ASSERT( edgeEntities[ 0 ].template getNumberOfSuperentities< 2 >() == 2 ); - CPPUNIT_ASSERT( edgeEntities[ 0 ].template getSuperentityIndex< 2 >( 0 ) == 0 );*/ - }; - -}; - -#endif - - - -#endif /* TNLMESHENTITYTESTER_H_ */ diff --git a/tests/unit-tests/mesh/tnlMeshTest.cpp b/tests/unit-tests/mesh/tnlMeshTest.cpp deleted file mode 100644 index 554fc0e6f335bffd6e070f5def2b4761a0b4998c..0000000000000000000000000000000000000000 --- a/tests/unit-tests/mesh/tnlMeshTest.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************** - MeshTest.cpp - description - ------------------- - begin : Feb 18, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include <TNL/tnlConfig.h> -#include <TNL/Devices/Host.h> -#include <cstdlib> - -#ifndef HAVE_NOT_CXX11 -#include "tnlMeshTester.h" -#endif -#include "../tnlUnitTestStarter.h" - -int main( int argc, char* argv[] ) -{ -#ifndef HAVE_NOT_CXX11 -#ifdef HAVE_CPPUNIT - MeshTester< double, Devices::Host, long int > t; - //t.regularMeshOfHexahedronsTest(); - if( ! tnlUnitTestStarter :: run< MeshTester< double, Devices::Host, long int > >() - ) - return EXIT_FAILURE; - return EXIT_SUCCESS; -#else - return EXIT_FAILURE; -#endif -#endif -} - - diff --git a/tests/unit-tests/mesh/tnlMeshTester.h b/tests/unit-tests/mesh/tnlMeshTester.h deleted file mode 100644 index 39aaaf43d79776ecc2ae756ffa97005d0c45363f..0000000000000000000000000000000000000000 --- a/tests/unit-tests/mesh/tnlMeshTester.h +++ /dev/null @@ -1,500 +0,0 @@ -/*************************************************************************** - MeshTester.h - description - ------------------- - begin : Feb 18, 2014 - copyright : (C) 2014 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#ifndef TNLMESHTESTER_H_ -#define TNLMESHTESTER_H_ - -#ifdef HAVE_CPPUNIT -#include <cppunit/TestSuite.h> -#include <cppunit/TestResult.h> -#include <cppunit/TestCaller.h> -#include <cppunit/TestCase.h> -#include <cppunit/Message.h> -#include <TNL/Meshes/Mesh.h> -#include <TNL/Meshes/MeshEntity.h> -#include <TNL/Meshes/MeshConfigBase.h> -#include <TNL/Meshes/Topologies/MeshVertexTopology.h> -#include <TNL/Meshes/Topologies/MeshEdgeTopology.h> -#include <TNL/Meshes/Topologies/MeshTriangleTopology.h> -#include <TNL/Meshes/Topologies/MeshQuadrilateralTopology.h> -#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h> -#include <TNL/Meshes/Topologies/MeshHexahedronTopology.h> -#include <TNL/Meshes/MeshDetails/initializer/MeshInitializer.h> -#include <TNL/Meshes/MeshBuilder.h> - -using namespace TNL; -using namespace TNL::Meshes; - -class TestTriangleMeshConfig : public MeshConfigBase< MeshTriangleTopology > -{ - public: - - static constexpr bool entityStorage( int dimensions ) { return true; }; - template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; }; - //template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) { return true; }; - template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; }; -}; - -class TestQuadrilateralMeshConfig : public MeshConfigBase< MeshQuadrilateralTopology > -{ - public: - - static constexpr bool entityStorage( int dimensions ) { return true; }; - template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; }; - template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) { return ( SubentityDimension % 2 != 0 ); }; - template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; }; -}; - -class TestTetrahedronMeshConfig : public MeshConfigBase< MeshTetrahedronTopology > -{ - public: - - static constexpr bool entityStorage( int dimensions ) { return true; }; - template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; }; - template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) { return ( SubentityDimension % 2 != 0 ); }; - template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; }; -}; - -class TestHexahedronMeshConfig : public MeshConfigBase< MeshHexahedronTopology > -{ - public: - - static constexpr bool entityStorage( int dimensions ) { return true; }; - template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; }; - template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) { return ( SubentityDimension % 2 != 0 ); }; - template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; }; -}; - -template< typename RealType, typename Device, typename IndexType > -class MeshTester : public CppUnit :: TestCase -{ - public: - typedef MeshTester< RealType, Device, IndexType > TesterType; - typedef typename CppUnit::TestCaller< TesterType > TestCallerType; - - MeshTester(){}; - - virtual - ~MeshTester(){}; - - static CppUnit :: Test* suite() - { - CppUnit :: TestSuite* suiteOfTests = new CppUnit :: TestSuite( "MeshTester" ); - CppUnit :: TestResult result; - - suiteOfTests->addTest( new TestCallerType( "twoTrianglesTest", &TesterType::twoTrianglesTest ) ); - suiteOfTests->addTest( new TestCallerType( "tetrahedronsTest", &TesterType::tetrahedronsTest ) ); - suiteOfTests->addTest( new TestCallerType( "regularMeshOfTrianglesTest", &TesterType::regularMeshOfTrianglesTest ) ); - suiteOfTests->addTest( new TestCallerType( "regularMeshOfQuadrilateralsTest", &TesterType::regularMeshOfQuadrilateralsTest ) ); - suiteOfTests->addTest( new TestCallerType( "regularMeshOfHexahedronsTest", &TesterType::regularMeshOfHexahedronsTest ) ); - return suiteOfTests; - } - - void twoTrianglesTest() - { - typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType; - typedef MeshEntity< TestTriangleMeshConfig, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestTriangleMeshConfig, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - CPPUNIT_ASSERT( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) ); - - /**** - * We set-up the following situation - point2 edge3 point3 - |\-------------------| - | \ | - | \ triangle1 | - | \ | - - .... - edge1 edge0 edge4 - .... - - - | triangle0 \ | - | \ | - ---------------------| - point0 edge2 point1 - */ - - typedef Mesh< TestTriangleMeshConfig > TriangleTestMesh; - TriangleTestMesh mesh, mesh2; - MeshBuilder< TriangleTestMesh > meshBuilder; - meshBuilder.setPointsCount( 4 ); - meshBuilder.setPoint( 0, PointType( 0.0, 0.0 ) ); - meshBuilder.setPoint( 1, PointType( 1.0, 0.0 ) ); - meshBuilder.setPoint( 2, PointType( 0.0, 1.0 ) ); - meshBuilder.setPoint( 3, PointType( 1.0, 1.0 ) ); - - meshBuilder.setCellsCount( 2 ); - meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 ); - meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 ); - meshBuilder.getCellSeed( 0 ).setCornerId( 2, 2 ); - meshBuilder.getCellSeed( 1 ).setCornerId( 0, 1 ); - meshBuilder.getCellSeed( 1 ).setCornerId( 1, 2 ); - meshBuilder.getCellSeed( 1 ).setCornerId( 2, 3 ); - meshBuilder.build( mesh ); - - CPPUNIT_ASSERT( mesh.getNumberOfEntities< 2 >() == 2 ); - CPPUNIT_ASSERT( mesh.getNumberOfEntities< 1 >() == 5 ); - CPPUNIT_ASSERT( mesh.getNumberOfEntities< 0 >() == 4 ); - - //CPPUNIT_ASSERT( mesh.save( "mesh.tnl" ) ); - //CPPUNIT_ASSERT( mesh2.load( "mesh.tnl" ) ); - //CPPUNIT_ASSERT( mesh == mesh2 ); - - //mesh.print(std::cout ); - //mesh2.print(std::cout ); - }; - - void tetrahedronsTest() - { - typedef MeshEntity< TestTetrahedronMeshConfig, MeshTriangleTopology > TriangleMeshEntityType; - typedef MeshEntity< TestTetrahedronMeshConfig, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestTetrahedronMeshConfig, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - typedef Mesh< TestTetrahedronMeshConfig > TestTetrahedronMesh; - TestTetrahedronMesh mesh; - MeshBuilder< TestTetrahedronMesh > meshBuilder; - meshBuilder.setPointsCount( 13 ); - meshBuilder.setPoint( 0, PointType( 0.000000, 0.000000, 0.000000 ) ); - meshBuilder.setPoint( 1, PointType( 0.000000, 0.000000, 8.000000 ) ); - meshBuilder.setPoint( 2, PointType( 0.000000, 8.000000, 0.000000 ) ); - meshBuilder.setPoint( 3, PointType( 15.000000, 0.000000, 0.000000 ) ); - meshBuilder.setPoint( 4, PointType( 0.000000, 8.000000, 8.000000 ) ); - meshBuilder.setPoint( 5, PointType( 15.000000, 0.000000, 8.000000 ) ); - meshBuilder.setPoint( 6, PointType( 15.000000, 8.000000, 0.000000 ) ); - meshBuilder.setPoint( 7, PointType( 15.000000, 8.000000, 8.000000 ) ); - meshBuilder.setPoint( 8, PointType( 7.470740, 8.000000, 8.000000 ) ); - meshBuilder.setPoint( 9, PointType( 7.470740, 0.000000, 8.000000 ) ); - meshBuilder.setPoint( 10, PointType( 7.504125, 8.000000, 0.000000 ) ); - meshBuilder.setPoint( 11, PointType( 7.212720, 0.000000, 0.000000 ) ); - meshBuilder.setPoint( 12, PointType( 11.184629, 3.987667, 3.985835 ) ); - - /**** - * Setup the following tetrahedrons: - * ( Generated by Netgen ) - * - * 12 8 7 5 - * 12 7 8 10 - * 12 11 8 9 - * 10 11 2 8 - * 12 7 6 5 - * 9 12 5 8 - * 12 11 9 3 - * 9 4 11 8 - * 12 9 5 3 - * 1 2 0 11 - * 8 11 2 4 - * 1 2 11 4 - * 9 4 1 11 - * 10 11 8 12 - * 12 6 7 10 - * 10 11 12 3 - * 12 6 3 5 - * 12 3 6 10 - */ - - meshBuilder.setCellsCount( 18 ); - // 12 8 7 5 - meshBuilder.getCellSeed( 0 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 0 ).setCornerId( 1, 8 ); - meshBuilder.getCellSeed( 0 ).setCornerId( 2, 7 ); - meshBuilder.getCellSeed( 0 ).setCornerId( 3, 5 ); - - // 12 7 8 10 - meshBuilder.getCellSeed( 1 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 1 ).setCornerId( 1, 7 ); - meshBuilder.getCellSeed( 1 ).setCornerId( 2, 8 ); - meshBuilder.getCellSeed( 1 ).setCornerId( 3, 10 ); - - // 12 11 8 9 - meshBuilder.getCellSeed( 2 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 2 ).setCornerId( 1, 11 ); - meshBuilder.getCellSeed( 2 ).setCornerId( 2, 8 ); - meshBuilder.getCellSeed( 2 ).setCornerId( 3, 9 ); - - // 10 11 2 8 - meshBuilder.getCellSeed( 3 ).setCornerId( 0, 10 ); - meshBuilder.getCellSeed( 3 ).setCornerId( 1, 11 ); - meshBuilder.getCellSeed( 3 ).setCornerId( 2, 2 ); - meshBuilder.getCellSeed( 3 ).setCornerId( 3, 8 ); - - // 12 7 6 5 - meshBuilder.getCellSeed( 4 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 4 ).setCornerId( 1, 7 ); - meshBuilder.getCellSeed( 4 ).setCornerId( 2, 6 ); - meshBuilder.getCellSeed( 4 ).setCornerId( 3, 5 ); - - // 9 12 5 8 - meshBuilder.getCellSeed( 5 ).setCornerId( 0, 9 ); - meshBuilder.getCellSeed( 5 ).setCornerId( 1, 12 ); - meshBuilder.getCellSeed( 5 ).setCornerId( 2, 5 ); - meshBuilder.getCellSeed( 5 ).setCornerId( 3, 8 ); - - // 12 11 9 3 - meshBuilder.getCellSeed( 6 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 6 ).setCornerId( 1, 11 ); - meshBuilder.getCellSeed( 6 ).setCornerId( 2, 9 ); - meshBuilder.getCellSeed( 6 ).setCornerId( 3, 3 ); - - // 9 4 11 8 - meshBuilder.getCellSeed( 7 ).setCornerId( 0, 9 ); - meshBuilder.getCellSeed( 7 ).setCornerId( 1, 4 ); - meshBuilder.getCellSeed( 7 ).setCornerId( 2, 11 ); - meshBuilder.getCellSeed( 7 ).setCornerId( 3, 8 ); - - // 12 9 5 3 - meshBuilder.getCellSeed( 8 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 8 ).setCornerId( 1, 9 ); - meshBuilder.getCellSeed( 8 ).setCornerId( 2, 5 ); - meshBuilder.getCellSeed( 8 ).setCornerId( 3, 3 ); - - // 1 2 0 11 - meshBuilder.getCellSeed( 9 ).setCornerId( 0, 1 ); - meshBuilder.getCellSeed( 9 ).setCornerId( 1, 2 ); - meshBuilder.getCellSeed( 9 ).setCornerId( 2, 0 ); - meshBuilder.getCellSeed( 9 ).setCornerId( 3, 11 ); - - // 8 11 2 4 - meshBuilder.getCellSeed( 10 ).setCornerId( 0, 8 ); - meshBuilder.getCellSeed( 10 ).setCornerId( 1, 11 ); - meshBuilder.getCellSeed( 10 ).setCornerId( 2, 2 ); - meshBuilder.getCellSeed( 10 ).setCornerId( 3, 4 ); - - // 1 2 11 4 - meshBuilder.getCellSeed( 11 ).setCornerId( 0, 1 ); - meshBuilder.getCellSeed( 11 ).setCornerId( 1, 2 ); - meshBuilder.getCellSeed( 11 ).setCornerId( 2, 11 ); - meshBuilder.getCellSeed( 11 ).setCornerId( 3, 4 ); - - // 9 4 1 11 - meshBuilder.getCellSeed( 12 ).setCornerId( 0, 9 ); - meshBuilder.getCellSeed( 12 ).setCornerId( 1, 4 ); - meshBuilder.getCellSeed( 12 ).setCornerId( 2, 1 ); - meshBuilder.getCellSeed( 12 ).setCornerId( 3, 11 ); - - // 10 11 8 12 - meshBuilder.getCellSeed( 13 ).setCornerId( 0, 10 ); - meshBuilder.getCellSeed( 13 ).setCornerId( 1, 11 ); - meshBuilder.getCellSeed( 13 ).setCornerId( 2, 8 ); - meshBuilder.getCellSeed( 13 ).setCornerId( 3, 12 ); - - // 12 6 7 10 - meshBuilder.getCellSeed( 14 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 14 ).setCornerId( 1, 6 ); - meshBuilder.getCellSeed( 14 ).setCornerId( 2, 7 ); - meshBuilder.getCellSeed( 14 ).setCornerId( 3, 10 ); - - // 10 11 12 3 - meshBuilder.getCellSeed( 15 ).setCornerId( 0, 10 ); - meshBuilder.getCellSeed( 15 ).setCornerId( 1, 11 ); - meshBuilder.getCellSeed( 15 ).setCornerId( 2, 12 ); - meshBuilder.getCellSeed( 15 ).setCornerId( 3, 3 ); - - // 12 6 3 5 - meshBuilder.getCellSeed( 16 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 16 ).setCornerId( 1, 6 ); - meshBuilder.getCellSeed( 16 ).setCornerId( 2, 3 ); - meshBuilder.getCellSeed( 16 ).setCornerId( 3, 5 ); - - // 12 3 6 10 - meshBuilder.getCellSeed( 17 ).setCornerId( 0, 12 ); - meshBuilder.getCellSeed( 17 ).setCornerId( 1, 3 ); - meshBuilder.getCellSeed( 17 ).setCornerId( 2, 6 ); - meshBuilder.getCellSeed( 17 ).setCornerId( 3, 10 ); - - meshBuilder.build( mesh ); - - /*CPPUNIT_ASSERT( mesh.save( "mesh.tnl" ) ); - CPPUNIT_ASSERT( mesh2.load( "mesh.tnl" ) ); - CPPUNIT_ASSERT( mesh == mesh2 );*/ - //mesh.print(std::cout ); - } - - void regularMeshOfTrianglesTest() - { - typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType; - typedef MeshEntity< TestTriangleMeshConfig, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestTriangleMeshConfig, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - - const IndexType xSize( 5 ), ySize( 5 ); - const RealType width( 1.0 ), height( 1.0 ); - const RealType hx( width / ( RealType ) xSize ), - hy( height / ( RealType ) ySize ); - const IndexType numberOfCells = 2*xSize * ySize; - const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ); - - typedef Mesh< TestTriangleMeshConfig > TestTriangleMesh; - Mesh< TestTriangleMeshConfig > mesh; - MeshBuilder< TestTriangleMesh > meshBuilder; - meshBuilder.setPointsCount( numberOfVertices ); - meshBuilder.setCellsCount( numberOfCells ); - - /**** - * Setup vertices - */ - for( IndexType i = 0; i <= xSize; i++ ) - for( IndexType j = 0; j <= ySize; j++ ) - meshBuilder.setPoint( j*xSize + i, PointType( i * hx, j * hy ) ); - - /**** - * Setup cells - */ - IndexType cellIdx( 0 ); - for( IndexType i = 0; i < xSize; i++ ) - for( IndexType j = 0; j < ySize; j++ ) - { - IndexType vertex0 = j * xSize + i; - IndexType vertex1 = j * xSize + i + 1; - IndexType vertex2 = ( j + 1 ) * xSize + i; - IndexType vertex3 = ( j + 1 ) * xSize + i + 1; - meshBuilder.getCellSeed( cellIdx ).setCornerId( 0, vertex0 ); - meshBuilder.getCellSeed( cellIdx ).setCornerId( 1, vertex1 ); - meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex2 ); - meshBuilder.getCellSeed( cellIdx ).setCornerId( 0, vertex1 ); - meshBuilder.getCellSeed( cellIdx ).setCornerId( 1, vertex2 ); - meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex3 ); - } - - meshBuilder.build( mesh ); - //CPPUNIT_ASSERT( mesh.save( "mesh-test.tnl" ) ); - //CPPUNIT_ASSERT( mesh2.load( "mesh-test.tnl" ) ); - //CPPUNIT_ASSERT( mesh == mesh2 ); - //mesh.print(std::cout ); - } - - void regularMeshOfQuadrilateralsTest() - { -#ifdef UNDEF - typedef MeshEntity< TestQuadrilateralMeshConfig, MeshQuadrilateralTopology > QuadrilateralMeshEntityType; - typedef MeshEntity< TestQuadrilateralMeshConfig, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestQuadrilateralMeshConfig, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - - const IndexType xSize( 5 ), ySize( 5 ); - const RealType width( 1.0 ), height( 1.0 ); - const RealType hx( width / ( RealType ) xSize ), - hy( height / ( RealType ) ySize ); - const IndexType numberOfCells = xSize * ySize; - const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ); - - Mesh< TestQuadrilateralMeshConfig > mesh, mesh2; - mesh.setNumberOfCells( numberOfCells ); - mesh.setNumberOfVertices( numberOfVertices ); - - /**** - * Setup vertices - */ - for( IndexType i = 0; i <= xSize; i++ ) - for( IndexType j = 0; j <= ySize; j++ ) - mesh.setVertex( j*xSize + i, PointType( i * hx, j * hy ) ); - - /**** - * Setup cells - */ - IndexType cellIdx( 0 ); - for( IndexType i = 0; i < xSize; i++ ) - for( IndexType j = 0; j < ySize; j++ ) - { - IndexType vertex0 = j * xSize + i; - IndexType vertex1 = j * xSize + i + 1; - IndexType vertex2 = ( j + 1 ) * xSize + i; - IndexType vertex3 = ( j + 1 ) * xSize + i + 1; - mesh.getEntities< 2 >()[ cellIdx ].getVerticesIndices()[ 0 ] = vertex0; - mesh.getEntities< 2 >()[ cellIdx ].getVerticesIndices()[ 1 ] = vertex1; - mesh.getEntities< 2 >()[ cellIdx ].getVerticesIndices()[ 2 ] = vertex2; - mesh.getEntities< 2 >()[ cellIdx++ ].getVerticesIndices()[ 3 ] = vertex3; - } - - MeshInitializer< TestQuadrilateralMeshConfig > meshInitializer; - //meshInitializer.initMesh( mesh ); - CPPUNIT_ASSERT( mesh.save( "mesh-test.tnl" ) ); - CPPUNIT_ASSERT( mesh2.load( "mesh-test.tnl" ) ); - CPPUNIT_ASSERT( mesh == mesh2 ); - //mesh.print(std::cout ); -#endif - } - - void regularMeshOfHexahedronsTest() - { -#ifdef UNDEF - typedef MeshEntity< TestHexahedronMeshConfig, MeshHexahedronTopology > HexahedronMeshEntityType; - typedef MeshEntity< TestHexahedronMeshConfig, MeshEdgeTopology > EdgeMeshEntityType; - typedef MeshEntity< TestHexahedronMeshConfig, MeshVertexTopology > VertexMeshEntityType; - typedef typename VertexMeshEntityType::PointType PointType; - - const IndexType xSize( 5 ), ySize( 5 ), zSize( 5 ); - const RealType width( 1.0 ), height( 1.0 ), depth( 1.0 ); - const RealType hx( width / ( RealType ) xSize ), - hy( height / ( RealType ) ySize ), - hz( depth / ( RealType ) zSize ); - const IndexType numberOfCells = xSize * ySize * zSize; - const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ) * ( zSize + 1 ); - - Mesh< TestHexahedronMeshConfig > mesh, mesh2; - mesh.setNumberOfCells( numberOfCells ); - mesh.setNumberOfVertices( numberOfVertices ); - - /**** - * Setup vertices - */ - for( IndexType i = 0; i <= xSize; i++ ) - for( IndexType j = 0; j <= ySize; j++ ) - for( IndexType k = 0; k <= zSize; k++ ) - mesh.setVertex( k * xSize * ySize + j * xSize + i, PointType( i * hx, j * hy, k * hz ) ); - - /**** - * Setup cells - */ - IndexType cellIdx( 0 ); - for( IndexType i = 0; i < xSize; i++ ) - for( IndexType j = 0; j < ySize; j++ ) - for( IndexType k = 0; k < zSize; k++ ) - { - IndexType vertex0 = k * xSize * ySize + j * xSize + i; - IndexType vertex1 = k * xSize * ySize + j * xSize + i + 1; - IndexType vertex2 = k * xSize * ySize + ( j + 1 ) * xSize + i; - IndexType vertex3 = k * xSize * ySize + ( j + 1 ) * xSize + i + 1; - IndexType vertex4 = ( k + 1 ) * xSize * ySize + j * xSize + i; - IndexType vertex5 = ( k + 1 ) * xSize * ySize + j * xSize + i + 1; - IndexType vertex6 = ( k + 1 ) * xSize * ySize + ( j + 1 ) * xSize + i; - IndexType vertex7 = ( k + 1 )* xSize * ySize + ( j + 1 ) * xSize + i + 1; - - mesh.getEntities< 3 >()[ cellIdx ].getVerticesIndices()[ 0 ] = vertex0; - mesh.getEntities< 3 >()[ cellIdx ].getVerticesIndices()[ 1 ] = vertex1; - mesh.getEntities< 3 >()[ cellIdx ].getVerticesIndices()[ 2 ] = vertex2; - mesh.getEntities< 3 >()[ cellIdx ].getVerticesIndices()[ 3 ] = vertex3; - mesh.getEntities< 3 >()[ cellIdx ].getVerticesIndices()[ 4 ] = vertex4; - mesh.getEntities< 3 >()[ cellIdx ].getVerticesIndices()[ 5 ] = vertex5; - mesh.getEntities< 3 >()[ cellIdx ].getVerticesIndices()[ 6 ] = vertex6; - mesh.getEntities< 3 >()[ cellIdx++ ].getVerticesIndices()[ 7 ] = vertex7; - } - - MeshInitializer< TestHexahedronMeshConfig > meshInitializer; - //meshInitializer.initMesh( mesh ); - /*CPPUNIT_ASSERT( mesh.save( "mesh-test.tnl" ) ); - CPPUNIT_ASSERT( mesh2.load( "mesh-test.tnl" ) ); - CPPUNIT_ASSERT( mesh == mesh2 );*/ - //mesh.print(std::cout ); -#endif - } - - -}; - -#endif - - - - - -#endif /* TNLMESHTESTER_H_ */ diff --git a/tnlConfig.h.in b/tnlConfig.h.in index 197065ae1ab93b1a09fa22709af278d0563763a4..1775037c4412fdc3e927f9f821b1a9f3b97993fd 100644 --- a/tnlConfig.h.in +++ b/tnlConfig.h.in @@ -5,8 +5,6 @@ @HAVE_SYS_IOCTL_H@ #ifdef HAVE_CUDA - @HAVE_CUBLAS@ - @HAVE_CUSP@ @HAVE_CUSPARSE@