diff --git a/CMakeLists.txt b/CMakeLists.txt index df28e82ba..cfd7fe344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,198 +1,194 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Nicolas Richart # # @date creation: Mon Jun 14 2010 # @date last modification: Fri Jan 22 2016 # # @brief main configuration file # # @section LICENSE # # Copyright (©) 2010-2012, 2014, 2015 EPFL (Ecole Polytechnique Fédérale de # Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des # Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION #------------------------------------------------------------------------------- # _ _ # | | | | # __ _| | ____ _ _ __ | |_ _ _ # / _` | |/ / _` | '_ \| __| | | | # | (_| | < (_| | | | | |_| |_| | # \__,_|_|\_\__,_|_| |_|\__|\__,_| # #=============================================================================== #=============================================================================== # CMake Project #=============================================================================== cmake_minimum_required(VERSION 3.1.3) # add this options before PROJECT keyword set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) project(Akantu) enable_language(CXX) #=============================================================================== # Misc. config for cmake #=============================================================================== set(AKANTU_CMAKE_DIR "${PROJECT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/Modules") set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries.") set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "Enable/Disable output of compile commands during generation" FORCE) mark_as_advanced(BUILD_SHARED_LIBS) if(NOT AKANTU_TARGETS_EXPORT) set(AKANTU_TARGETS_EXPORT AkantuTargets) endif() include(CMakeVersionGenerator) include(CMakePackagesSystem) include(CMakeFlagsHandling) include(AkantuPackagesSystem) include(AkantuMacros) include(AkantuCleaning) #cmake_activate_debug_message() #=============================================================================== # Version Number #=============================================================================== # AKANTU version number. An even minor number corresponds to releases. set(AKANTU_MAJOR_VERSION 3) set(AKANTU_MINOR_VERSION 1) set(AKANTU_PATCH_VERSION 0) define_project_version() #=============================================================================== # Options #=============================================================================== # Debug set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DAKANTU_NDEBUG" CACHE STRING "Flags used by the compiler during release builds" FORCE) #add_flags(cxx "-Wall -Wextra -pedantic -Werror") if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") add_flags(cxx "-Wall -Wextra -pedantic") # -Weffc++ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} -ggdb3" CACHE STRING "Flags used by the compiler during debug builds" FORCE) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT} -ggdb3" CACHE STRING "Flags used by the compiler during debug builds" FORCE) else() add_flags(cxx "-Wall") endif() option(AKANTU_EXAMPLES "Activate examples" OFF) option(AKANTU_TESTS "Activate tests" OFF) set(AKANTU_PREFERRED_PYTHON_VERSION 3 CACHE STRING "Preferred version for python related things") mark_as_advanced(AKANTU_PREFERRED_PYTHON_VERSION) include(AkantuExtraCompilationProfiles) #=============================================================================== # Dependencies #=============================================================================== declare_akantu_types() package_list_packages(${PROJECT_SOURCE_DIR}/packages EXTRA_PACKAGES_FOLDER ${PROJECT_SOURCE_DIR}/extra_packages NO_AUTO_COMPILE_FLAGS) ## meta option \todo better way to do it when multiple package give enable the ## same feature if(AKANTU_SCOTCH) set(AKANTU_PARTITIONER ON) else() set(AKANTU_PARTITIONER OFF) endif() if(AKANTU_MUMPS) set(AKANTU_SOLVER ON) else() set(AKANTU_SOLVER OFF) endif() #=============================================================================== # Akantu library #=============================================================================== add_subdirectory(src) #=============================================================================== # Documentation #=============================================================================== if(AKANTU_DOCUMENTATION_DOXYGEN OR AKANTU_DOCUMENTATION_MANUAL) add_subdirectory(doc) else() set(AKANTU_DOC_EXCLUDE_FILES "${PROJECT_SOURCE_DIR}/doc/manual" CACHE INTERNAL "") endif() +#=============================================================================== +# Python interface +#=============================================================================== +package_is_activated(python_interface _python_act) +if(_python_act) + if(IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}") + set(AKANTU_PYTHON_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) + else() + set(AKANTU_PYTHON_INSTALL_PREFIX "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_PREFIX}") + endif() + add_subdirectory(python) +endif() + #=============================================================================== # Examples and tests #=============================================================================== include(AkantuTestsMacros) include(AkantuExampleMacros) if(AKANTU_TESTS) option(AKANTU_BUILD_ALL_TESTS "Build all tests" ON) find_package(GMSH REQUIRED) - # package_is_activated(pybind11 _pybind11_act) - # if(_pybind11_act) - # find_package(pybind11 CONFIG REQUIRED QUIET) # to get the pybind11_add_module macro - # endif() endif() if(AKANTU_EXAMPLES) find_package(GMSH REQUIRED) add_subdirectory(examples) endif() # tests add_test_tree(test) -#=============================================================================== -# Python interface -#=============================================================================== -package_is_activated(python_interface _python_act) -if(_python_act) - if(IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}") - set(AKANTU_PYTHON_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) - else() - set(AKANTU_PYTHON_INSTALL_PREFIX "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_PREFIX}") - endif() - add_subdirectory(python) -endif() - #=============================================================================== # Install and Packaging #=============================================================================== include(AkantuInstall) option(AKANTU_DISABLE_CPACK "This option commands the generation of extra info for the \"make package\" target" ON) mark_as_advanced(AKANTU_DISABLE_CPACK) if(NOT AKANTU_DISABLE_CPACK) include(AkantuCPack) endif() diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 5584e43a0..dc253b310 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,71 +1,80 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart # # @date creation: Fri Dec 12 2014 # @date last modification: Mon Jan 18 2016 # # @brief CMake file for the python wrapping of akantu # # @section LICENSE # # Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory # (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== set(PYAKANTU_SRCS - py_akantu.cc py_aka_common.cc py_aka_error.cc + py_akantu.cc py_boundary_conditions.cc py_fe_engine.cc + py_group_manager.cc py_mesh.cc - py_parser.cc py_model.cc + py_parser.cc ) +package_is_activated(iohelper _is_activated) +if (_is_activated) + list(APPEND PYAKANTU_SRCS + py_dumpable.cc + ) +endif() + + package_is_activated(solid_mechanics _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model.cc py_material.cc ) endif() package_is_activated(cohesive_element _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model_cohesive.cc ) endif() package_is_activated(heat_transfer _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_heat_transfer_model.cc ) endif() add_library(pyakantu OBJECT ${PYAKANTU_SRCS}) target_link_libraries(pyakantu PUBLIC akantu pybind11) target_include_directories(pyakantu INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(pyakantu PROPERTIES POSITION_INDEPENDENT_CODE TRUE) pybind11_add_module(py11_akantu $) target_link_libraries(py11_akantu PRIVATE pyakantu) set_target_properties(py11_akantu PROPERTIES DEBUG_POSTFIX "") diff --git a/python/py_aka_array.hh b/python/py_aka_array.hh index 09ac23938..67689c65a 100644 --- a/python/py_aka_array.hh +++ b/python/py_aka_array.hh @@ -1,235 +1,238 @@ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; namespace _aka = akantu; namespace akantu { template class Proxy : public VecType { protected: using T = typename VecType::value_type; // deallocate the memory void deallocate() override final {} // allocate the memory void allocate(__attribute__((unused)) UInt size, __attribute__((unused)) UInt nb_component) override final {} // allocate and initialize the memory void allocate(__attribute__((unused)) UInt size, __attribute__((unused)) UInt nb_component, __attribute__((unused)) const T & value) override final {} public: Proxy(T * data, UInt size, UInt nb_component) { this->values = data; this->size_ = size; this->nb_component = nb_component; } Proxy(const Array & src) { this->values = src.storage(); this->size_ = src.size(); this->nb_component = src.getNbComponent(); } ~Proxy() { this->values = nullptr; } void resize(UInt /*size*/, const T & /*val */) override final { AKANTU_EXCEPTION("cannot resize a temporary array"); } void resize(UInt /*new_size*/) override final { AKANTU_EXCEPTION("cannot resize a temporary array"); } void reserve(UInt /*size*/, UInt /*new_size*/) override final { AKANTU_EXCEPTION("cannot resize a temporary array"); } }; template using vec_proxy = Vector; template using mat_proxy = Matrix; template using array_proxy = Proxy>; template struct ProxyType { using type = Proxy; }; template struct ProxyType> { using type = Vector; }; template struct ProxyType> { using type = Matrix; }; template using ProxyType_t = typename ProxyType::type; } // namespace akantu namespace pybind11 { namespace detail { template using array_type = array_t; template void create_proxy(std::unique_ptr<_aka::vec_proxy> & proxy, array_type ref) { proxy = std::make_unique<_aka::vec_proxy>(ref.mutable_data(), ref.shape(0)); } template void create_proxy(std::unique_ptr<_aka::mat_proxy> & proxy, array_type ref) { proxy = std::make_unique<_aka::mat_proxy>(ref.mutable_data(), ref.shape(0), ref.shape(1)); } template void create_proxy(std::unique_ptr<_aka::array_proxy> & proxy, array_type ref) { proxy = std::make_unique<_aka::array_proxy>(ref.mutable_data(), ref.shape(0), ref.shape(1)); } /* ------------------------------------------------------------------------ */ template py::handle aka_array_cast(const _aka::Array & src, py::handle base = handle(), bool writeable = true) { array a; a = array_type({src.size(), src.getNbComponent()}, src.storage(), base); if (not writeable) array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_; return a.release(); } + template + using tensor_type = array_t; + template py::handle aka_array_cast(const _aka::Vector & src, py::handle base = handle(), bool writeable = true) { array a; - a = array_type({src.size()}, src.storage(), base); + a = tensor_type({src.size()}, src.storage(), base); if (not writeable) array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_; return a.release(); } template py::handle aka_array_cast(const _aka::Matrix & src, py::handle base = handle(), bool writeable = true) { array a; - a = array_type({src.size(0), src.size(1)}, src.storage(), base); + a = tensor_type({src.size(0), src.size(1)}, src.storage(), base); if (not writeable) array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_; return a.release(); } /* ------------------------------------------------------------------------ */ template class [[gnu::visibility("default")]] my_type_caster { protected: using T = typename VecType::value_type; using type = VecType; using proxy_type = _aka::ProxyType_t; type value; public: static PYBIND11_DESCR name() { return type_descr(_("Toto")); }; /** * Conversion part 1 (Python->C++) */ bool load(handle src, bool convert) { bool need_copy = not isinstance>(src); auto && fits = [&](auto && aref) { auto && dims = aref.ndim(); if (dims < 1 || dims > 2) return false; return true; }; if (not need_copy) { // We don't need a converting copy, but we also need to check whether // the strides are compatible with the Ref's stride requirements auto aref = py::cast>(src); if (not fits(aref)) { return false; } copy_or_ref = std::move(aref); } else { if (not convert) { return false; } auto copy = array_type::ensure(src); if (not copy) { return false; } if (not fits(copy)) { return false; } copy_or_ref = std::move(array_type::ensure(src)); loader_life_support::add_patient(copy_or_ref); } create_proxy(array_proxy, copy_or_ref); return true; } operator type *() { return array_proxy.get(); } operator type &() { return *array_proxy; } template using cast_op_type = pybind11::detail::cast_op_type<_T>; /** * Conversion part 2 (C++ -> Python) */ static handle cast(const type & src, return_value_policy policy, handle parent) { switch (policy) { case return_value_policy::copy: return aka_array_cast(src); case return_value_policy::reference_internal: return aka_array_cast(src, parent); case return_value_policy::reference: case return_value_policy::automatic: case return_value_policy::automatic_reference: return aka_array_cast(src, none()); default: pybind11_fail("Invalid return_value_policy for ArrayProxy type"); } } protected: std::unique_ptr array_proxy; array_type copy_or_ref; }; /* ------------------------------------------------------------------------ */ // specializations /* ------------------------------------------------------------------------ */ template struct type_caster<_aka::Array> : public my_type_caster<_aka::Array> {}; template struct type_caster<_aka::Vector> : public my_type_caster<_aka::Vector> { }; template struct type_caster<_aka::Matrix> : public my_type_caster<_aka::Matrix> { }; } // namespace detail } // namespace pybind11 diff --git a/python/py_akantu.cc b/python/py_akantu.cc index 4176a4991..d59bf37f2 100644 --- a/python/py_akantu.cc +++ b/python/py_akantu.cc @@ -1,76 +1,89 @@ /* -------------------------------------------------------------------------- */ #include "aka_config.hh" /* -------------------------------------------------------------------------- */ #include "py_aka_common.hh" #include "py_aka_error.hh" #include "py_boundary_conditions.hh" #include "py_fe_engine.hh" +#include "py_group_manager.hh" #include "py_mesh.hh" #include "py_model.hh" #include "py_parser.hh" +#if defined(AKANTU_USE_IOHELPER) +#include "py_dumpable.hh" +#endif + #if defined(AKANTU_SOLID_MECHANICS) #include "py_material.hh" #include "py_solid_mechanics_model.hh" #endif #if defined(AKANTU_HEAT_TRANSFER) #include "py_heat_transfer_model.hh" #endif #if defined(AKANTU_COHESIVE_ELEMENT) #include "py_solid_mechanics_model_cohesive.hh" #endif /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; namespace akantu { void register_all(pybind11::module & mod) { register_initialize(mod); register_enums(mod); register_error(mod); register_functions(mod); register_parser(mod); - register_boundary_conditions(mod); + + register_group_manager(mod); +#if defined(AKANTU_USE_IOHELPER) + register_dumpable(mod); +#endif + register_mesh(mod); + register_fe_engine(mod); + + register_boundary_conditions(mod); register_model(mod); - register_mesh(mod); - +#if defined(AKANTU_HEAT_TRANSFER) + register_heat_transfer_model(mod); +#endif + #if defined(AKANTU_SOLID_MECHANICS) register_solid_mechanics_model(mod); register_material(mod); #endif -#if defined(AKANTU_HEAT_TRANSFER) - register_heat_transfer_model(mod); -#endif - #if defined(AKANTU_COHESIVE_ELEMENT) register_solid_mechanics_model_cohesive(mod); #endif } } // namespace akantu +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ PYBIND11_MODULE(py11_akantu, mod) { mod.doc() = "Akantu python interface"; static py::exception akantu_exception(mod, "Exception"); py::register_exception_translator([](std::exception_ptr p) { try { if (p) std::rethrow_exception(p); } catch (akantu::debug::Exception & e) { if (akantu::debug::debugger.printBacktrace()) akantu::debug::printBacktrace(15); akantu_exception(e.info().c_str()); } }); akantu::register_all(mod); } // Module akantu diff --git a/python/py_mesh.cc b/python/py_dumpable.cc similarity index 50% copy from python/py_mesh.cc copy to python/py_dumpable.cc index 1741c9323..0ee84adef 100644 --- a/python/py_mesh.cc +++ b/python/py_dumpable.cc @@ -1,167 +1,79 @@ /* -------------------------------------------------------------------------- */ #include "py_aka_array.hh" /* -------------------------------------------------------------------------- */ #include -#include -#include #include -#include -#include /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ namespace akantu { -/* -------------------------------------------------------------------------- */ -void register_mesh(py::module & mod) { - - py::module dumper_module("dumper"); - mod.attr("dumper") = dumper_module; - - /* ------------------------------------------------------------------------ */ - py::class_>(dumper_module, - "Field"); - - /* ------------------------------------------------------------------------ */ - py::class_, dumper::Field, - std::shared_ptr>>( - dumper_module, "ElementalFieldUInt", py::multiple_inheritance()) - .def(py::init::field_type &, UInt, GhostType, - ElementKind>(), - py::arg("field"), py::arg("spatial_dimension") = _all_dimensions, - py::arg("ghost_type") = _not_ghost, - py::arg("element_kind") = _ek_not_defined); - - /* ------------------------------------------------------------------------ */ - py::class_(mod, "NodeGroup") - .def("getNodes", - [](NodeGroup & self) -> decltype(auto) { - return self.getNodes(); - }, - py::return_value_policy::reference); - - +void register_dumpable(py::module & mod) { /* ------------------------------------------------------------------------ */ - py::class_(mod, "ElementGroup") - .def("getNodeGroup", - [](ElementGroup & self) -> decltype(auto) { - return self.getNodeGroup(); - }, - py::return_value_policy::reference); - - py::class_(mod, "MeshData") - .def( - "getElementalDataUInt", - [](MeshData & _this, const ID & name) -> ElementTypeMapArray & { - return _this.getElementalData(name); - }, - py::return_value_policy::reference); - py::class_(mod, "Dumpable") .def("registerDumperParaview", &Dumpable::registerDumper, py::arg("dumper_name"), py::arg("file_name"), py::arg("is_default") = false) .def("addDumpMeshToDumper", &Dumpable::addDumpMeshToDumper, py::arg("dumper_name"), py::arg("mesh"), py::arg("dimension"), py::arg("ghost_type") = _not_ghost, py::arg("element_kind") = _ek_regular) .def("addDumpMesh", &Dumpable::addDumpMesh, py::arg("mesh"), py::arg("dimension"), py::arg("ghost_type") = _not_ghost, py::arg("element_kind") = _ek_regular) .def("addDumpField", &Dumpable::addDumpField, py::arg("field_id")) .def("addDumpFieldToDumper", &Dumpable::addDumpFieldToDumper, py::arg("dumper_name"), py::arg("field_id")) .def("addDumpFieldExternal", [](Dumpable & _this, const std::string & field_id, std::shared_ptr field) { return _this.addDumpFieldExternal(field_id, field); }, py::arg("field_id"), py::arg("field")) .def("addDumpFieldExternalToDumper", [](Dumpable & _this, const std::string & dumper_name, const std::string & field_id, std::shared_ptr field) { return _this.addDumpFieldExternalToDumper(dumper_name, field_id, field); }, py::arg("dumper_name"), py::arg("field_id"), py::arg("field")) .def("dump", py::overload_cast<>(&Dumpable::dump)) .def("dump", py::overload_cast(&Dumpable::dump), py::arg("time"), py::arg("step")) .def("dump", py::overload_cast(&Dumpable::dump), py::arg("step")) .def("dump", py::overload_cast(&Dumpable::dump), py::arg("dumper_name"), py::arg("step")) .def("dump", py::overload_cast(&Dumpable::dump), py::arg("dumper_name"), py::arg("time"), py::arg("step")) .def("dump", py::overload_cast(&Dumpable::dump), py::arg("dumper_name")); - py::class_(mod, "GroupManager") - .def("getElementGroup", - [](GroupManager & self, const std::string & name) -> decltype(auto) { - return self.getElementGroup(name); - }, - py::return_value_policy::reference) - .def("createNodeGroup", &GroupManager::createNodeGroup, - py::return_value_policy::reference) - .def("createElementGroup", - py::overload_cast( - &GroupManager::createElementGroup), - py::return_value_policy::reference) - .def("createGroupsFromMeshDataUInt", - &GroupManager::createGroupsFromMeshData) - .def("createElementGroupFromNodeGroup", - &GroupManager::createElementGroupFromNodeGroup, py::arg("name"), - py::arg("node_group"), py::arg("dimension") = _all_dimensions) - .def("getNodeGroup", - [](GroupManager & self, const std::string & name) -> decltype(auto) { - return self.getNodeGroup(name); - }, - py::return_value_policy::reference) - .def("createBoundaryGroupFromGeometry", - &GroupManager::createBoundaryGroupFromGeometry); + /* ------------------------------------------------------------------------ */ + py::module dumper_module("dumper"); + mod.attr("dumper") = dumper_module; - py::class_(mod, "Mesh", - py::multiple_inheritance()) - .def(py::init(), - py::arg("spatial_dimension"), py::arg("id") = "mesh", - py::arg("memory_id") = 0) - .def("read", &Mesh::read, py::arg("filename"), - py::arg("mesh_io_type") = _miot_auto, "read the mesh from a file") - .def("getNodes", - [](Mesh & self) -> decltype(auto) { return self.getNodes(); }, - py::return_value_policy::reference) - .def("getNbNodes", &Mesh::getNbNodes) - .def("distribute", [](Mesh & self) { self.distribute(); }) - .def("getNbElement", - [](Mesh & self, const UInt spatial_dimension, - const GhostType & ghost_type, const ElementKind & kind) { - return self.getNbElement(spatial_dimension, ghost_type, kind); - }, - py::arg("spatial_dimension") = _all_dimensions, - py::arg("ghost_type") = _not_ghost, - py::arg("kind") = _ek_not_defined) - .def("getNbElement", - [](Mesh & self, const ElementType & type, - const GhostType & ghost_type) { - return self.getNbElement(type, ghost_type); - }, - py::arg("type"), py::arg("ghost_type") = _not_ghost) - .def_static("getSpatialDimension", [](ElementType & type) { - return Mesh::getSpatialDimension(type); - }); + /* ------------------------------------------------------------------------ */ + py::class_>(dumper_module, + "Field"); /* ------------------------------------------------------------------------ */ - py::class_(mod, "MeshUtils") - .def_static("buildFacets", &MeshUtils::buildFacets); + py::class_, dumper::Field, + std::shared_ptr>>( + dumper_module, "ElementalFieldUInt", py::multiple_inheritance()) + .def(py::init::field_type &, UInt, GhostType, + ElementKind>(), + py::arg("field"), py::arg("spatial_dimension") = _all_dimensions, + py::arg("ghost_type") = _not_ghost, + py::arg("element_kind") = _ek_not_defined); } + } // namespace akantu diff --git a/python/py_dumpable.hh b/python/py_dumpable.hh new file mode 100644 index 000000000..aa250037b --- /dev/null +++ b/python/py_dumpable.hh @@ -0,0 +1,14 @@ +#ifndef __AKANTU_PY_DUMPABLE_HH__ +#define __AKANTU_PY_DUMPABLE_HH__ + +namespace pybind11 { +struct module; +} // namespace pybind11 + +namespace akantu { + +void register_dumpable(pybind11::module & mod); + +} // namespace akantu + +#endif /* __AKANTU_PY_DUMPABLE_HH__ */ diff --git a/python/py_group_manager.cc b/python/py_group_manager.cc new file mode 100644 index 000000000..c37e04ad8 --- /dev/null +++ b/python/py_group_manager.cc @@ -0,0 +1,57 @@ +/* -------------------------------------------------------------------------- */ +#include "py_aka_array.hh" +/* -------------------------------------------------------------------------- */ +#include +#include +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ +namespace py = pybind11; +/* -------------------------------------------------------------------------- */ + +namespace akantu { + +/* -------------------------------------------------------------------------- */ +void register_group_manager(py::module & mod) { + /* ------------------------------------------------------------------------ */ + py::class_(mod, "NodeGroup") + .def("getNodes", + [](NodeGroup & self) -> decltype(auto) { return self.getNodes(); }, + py::return_value_policy::reference); + + /* ------------------------------------------------------------------------ */ + py::class_(mod, "ElementGroup") + .def("getNodeGroup", + [](ElementGroup & self) -> decltype(auto) { + return self.getNodeGroup(); + }, + py::return_value_policy::reference); + + /* ------------------------------------------------------------------------ */ + py::class_(mod, "GroupManager") + .def("getElementGroup", + [](GroupManager & self, const std::string & name) -> decltype(auto) { + return self.getElementGroup(name); + }, + py::return_value_policy::reference) + .def("createNodeGroup", &GroupManager::createNodeGroup, + py::return_value_policy::reference) + .def("createElementGroup", + py::overload_cast( + &GroupManager::createElementGroup), + py::return_value_policy::reference) + .def("createGroupsFromMeshDataUInt", + &GroupManager::createGroupsFromMeshData) + .def("createElementGroupFromNodeGroup", + &GroupManager::createElementGroupFromNodeGroup, py::arg("name"), + py::arg("node_group"), py::arg("dimension") = _all_dimensions) + .def("getNodeGroup", + [](GroupManager & self, const std::string & name) -> decltype(auto) { + return self.getNodeGroup(name); + }, + py::return_value_policy::reference) + .def("createBoundaryGroupFromGeometry", + &GroupManager::createBoundaryGroupFromGeometry); +} + +} // namespace akantu diff --git a/python/py_group_manager.hh b/python/py_group_manager.hh new file mode 100644 index 000000000..b43335501 --- /dev/null +++ b/python/py_group_manager.hh @@ -0,0 +1,12 @@ +#ifndef __AKANTU_PY_GROUP_MANAGER_HH__ +#define __AKANTU_PY_GROUP_MANAGER_HH__ + +namespace pybind11 { +struct module; +} // namespace pybind11 + +namespace akantu { +void register_group_manager(pybind11::module & mod); +} // namespace akantu + +#endif /* __AKANTU_PY_GROUP_MANAGER_HH__ */ diff --git a/python/py_mesh.cc b/python/py_mesh.cc index 1741c9323..9724f2aae 100644 --- a/python/py_mesh.cc +++ b/python/py_mesh.cc @@ -1,167 +1,60 @@ /* -------------------------------------------------------------------------- */ +#include "aka_config.hh" +/* -------------------------------------------------------------------------- */ #include "py_aka_array.hh" /* -------------------------------------------------------------------------- */ -#include -#include -#include #include #include -#include -/* -------------------------------------------------------------------------- */ -#include /* -------------------------------------------------------------------------- */ -#include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ void register_mesh(py::module & mod) { - - py::module dumper_module("dumper"); - mod.attr("dumper") = dumper_module; - - /* ------------------------------------------------------------------------ */ - py::class_>(dumper_module, - "Field"); - - /* ------------------------------------------------------------------------ */ - py::class_, dumper::Field, - std::shared_ptr>>( - dumper_module, "ElementalFieldUInt", py::multiple_inheritance()) - .def(py::init::field_type &, UInt, GhostType, - ElementKind>(), - py::arg("field"), py::arg("spatial_dimension") = _all_dimensions, - py::arg("ghost_type") = _not_ghost, - py::arg("element_kind") = _ek_not_defined); - - /* ------------------------------------------------------------------------ */ - py::class_(mod, "NodeGroup") - .def("getNodes", - [](NodeGroup & self) -> decltype(auto) { - return self.getNodes(); - }, - py::return_value_policy::reference); - - - /* ------------------------------------------------------------------------ */ - py::class_(mod, "ElementGroup") - .def("getNodeGroup", - [](ElementGroup & self) -> decltype(auto) { - return self.getNodeGroup(); - }, - py::return_value_policy::reference); - py::class_(mod, "MeshData") .def( "getElementalDataUInt", [](MeshData & _this, const ID & name) -> ElementTypeMapArray & { return _this.getElementalData(name); }, py::return_value_policy::reference); - py::class_(mod, "Dumpable") - .def("registerDumperParaview", &Dumpable::registerDumper, - py::arg("dumper_name"), py::arg("file_name"), - py::arg("is_default") = false) - .def("addDumpMeshToDumper", &Dumpable::addDumpMeshToDumper, - py::arg("dumper_name"), py::arg("mesh"), py::arg("dimension"), - py::arg("ghost_type") = _not_ghost, - py::arg("element_kind") = _ek_regular) - .def("addDumpMesh", &Dumpable::addDumpMesh, py::arg("mesh"), - py::arg("dimension"), py::arg("ghost_type") = _not_ghost, - py::arg("element_kind") = _ek_regular) - .def("addDumpField", &Dumpable::addDumpField, py::arg("field_id")) - .def("addDumpFieldToDumper", &Dumpable::addDumpFieldToDumper, - py::arg("dumper_name"), py::arg("field_id")) - .def("addDumpFieldExternal", - [](Dumpable & _this, const std::string & field_id, - std::shared_ptr field) { - return _this.addDumpFieldExternal(field_id, field); - }, - py::arg("field_id"), py::arg("field")) - .def("addDumpFieldExternalToDumper", - [](Dumpable & _this, const std::string & dumper_name, - const std::string & field_id, - std::shared_ptr field) { - return _this.addDumpFieldExternalToDumper(dumper_name, field_id, - field); - }, - py::arg("dumper_name"), py::arg("field_id"), py::arg("field")) - - .def("dump", py::overload_cast<>(&Dumpable::dump)) - .def("dump", py::overload_cast(&Dumpable::dump), - py::arg("time"), py::arg("step")) - .def("dump", py::overload_cast(&Dumpable::dump), py::arg("step")) - .def("dump", - py::overload_cast(&Dumpable::dump), - py::arg("dumper_name"), py::arg("step")) - .def("dump", - py::overload_cast(&Dumpable::dump), - py::arg("dumper_name"), py::arg("time"), py::arg("step")) - .def("dump", py::overload_cast(&Dumpable::dump), - py::arg("dumper_name")); - - py::class_(mod, "GroupManager") - .def("getElementGroup", - [](GroupManager & self, const std::string & name) -> decltype(auto) { - return self.getElementGroup(name); - }, - py::return_value_policy::reference) - .def("createNodeGroup", &GroupManager::createNodeGroup, - py::return_value_policy::reference) - .def("createElementGroup", - py::overload_cast( - &GroupManager::createElementGroup), - py::return_value_policy::reference) - .def("createGroupsFromMeshDataUInt", - &GroupManager::createGroupsFromMeshData) - .def("createElementGroupFromNodeGroup", - &GroupManager::createElementGroupFromNodeGroup, py::arg("name"), - py::arg("node_group"), py::arg("dimension") = _all_dimensions) - .def("getNodeGroup", - [](GroupManager & self, const std::string & name) -> decltype(auto) { - return self.getNodeGroup(name); - }, - py::return_value_policy::reference) - .def("createBoundaryGroupFromGeometry", - &GroupManager::createBoundaryGroupFromGeometry); - py::class_(mod, "Mesh", py::multiple_inheritance()) .def(py::init(), py::arg("spatial_dimension"), py::arg("id") = "mesh", py::arg("memory_id") = 0) .def("read", &Mesh::read, py::arg("filename"), py::arg("mesh_io_type") = _miot_auto, "read the mesh from a file") .def("getNodes", [](Mesh & self) -> decltype(auto) { return self.getNodes(); }, py::return_value_policy::reference) .def("getNbNodes", &Mesh::getNbNodes) .def("distribute", [](Mesh & self) { self.distribute(); }) .def("getNbElement", [](Mesh & self, const UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & kind) { return self.getNbElement(spatial_dimension, ghost_type, kind); }, py::arg("spatial_dimension") = _all_dimensions, py::arg("ghost_type") = _not_ghost, py::arg("kind") = _ek_not_defined) .def("getNbElement", [](Mesh & self, const ElementType & type, const GhostType & ghost_type) { return self.getNbElement(type, ghost_type); }, py::arg("type"), py::arg("ghost_type") = _not_ghost) .def_static("getSpatialDimension", [](ElementType & type) { return Mesh::getSpatialDimension(type); }); /* ------------------------------------------------------------------------ */ py::class_(mod, "MeshUtils") .def_static("buildFacets", &MeshUtils::buildFacets); } } // namespace akantu diff --git a/python/setup.py.in b/python/setup.py.in deleted file mode 100644 index bd7f40535..000000000 --- a/python/setup.py.in +++ /dev/null @@ -1,38 +0,0 @@ -from distutils.core import setup -from distutils.core import setup, Extension -import os -import sys - -os.environ['CC'] = '@CMAKE_CXX_COMPILER@' -os.environ['CXX'] = '@CMAKE_CXX_COMPILER@' - -def cmake_to_list(cmake_list): - if cmake_list == '': - return [] - return cmake_list.split(';') - -# https://stackoverflow.com/a/29634231 -# Remove the "-Wstrict-prototypes" compiler option, which isn't valid for C++. -import distutils.sysconfig -cfg_vars = distutils.sysconfig.get_config_vars() -for key, value in cfg_vars.items(): - if type(value) == str: - cfg_vars[key] = value.replace("-Wstrict-prototypes", "") -# ================================== - -setup( - name='akantu', - license='LGPLv3', - version='@AKANTU_VERSION@', - py_modules=['akantu'], - ext_modules=[Extension( - '_akantu', - cmake_to_list('@_ext_files@'), - include_dirs=cmake_to_list('@_inc_dirs@'), - language='c++', - libraries=cmake_to_list('@_akantu_lib_name@'), - library_dirs=cmake_to_list('@_lib_dirs@'), - runtime_library_dirs=cmake_to_list('@_lib_dirs@'), - extra_compile_args=cmake_to_list('@_flags@') - )] -) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 032391f6e..e9be809e4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,74 +1,73 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Alejandro M. Aragón # @author Nicolas Richart # # @date creation: Fri Sep 03 2010 # @date last modification: Mon Feb 12 2018 # # @brief configuration for tests # # @section LICENSE # # Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== include_directories( ${AKANTU_INCLUDE_DIRS} ${AKANTU_EXTERNAL_LIB_INCLUDE_DIR} ) set(AKANTU_TESTS_FILES CACHE INTERNAL "") -akantu_pybind11_add_module(aka_test MODULE pybind11_akantu.cc) #=============================================================================== # List of tests #=============================================================================== add_akantu_test(test_common "Test the common part of Akantu") add_akantu_test(test_static_memory "Test static memory") add_akantu_test(test_fe_engine "Test finite element functionalties") add_akantu_test(test_mesh_utils "Test mesh utils") add_akantu_test(test_mesh "Test mesh") add_akantu_test(test_model "Test model objects") add_akantu_test(test_solver "Test solver function") add_akantu_test(test_io "Test the IO modules") add_akantu_test(test_contact "Test the contact part of Akantu") add_akantu_test(test_geometry "Test the geometry module of Akantu") add_akantu_test(test_synchronizer "Test synchronizers") add_akantu_test(test_python_interface "Test python interface") package_add_files_to_package( cmake/akantu_test_driver.sh cmake/AkantuTestsMacros.cmake ) package_is_activated(parallel _is_parallel) if (_is_parallel) option(AKANTU_TESTS_ALWAYS_USE_MPI "Defines if sequential tests should also use MPIEXEC" FALSE) mark_as_advanced(AKANTU_TESTS_ALWAYS_USE_MPI) endif() package_is_activated(gbenchmark _has_gbenchmark) if (_has_gbenchmark) add_subdirectory(benchmark) endif() diff --git a/test/pybind11_akantu.cc b/test/pybind11_akantu.cc deleted file mode 100644 index 7e2d16fb2..000000000 --- a/test/pybind11_akantu.cc +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file pybind11_akantu.cc - * - * @author Nicolas Richart - * - * @date creation: Fri Dec 22 2017 - * @date last modification: Thu Dec 28 2017 - * - * @brief tool to wrap akantu classes in python - * - * @section LICENSE - * - * Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) - * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) - * - * Akantu is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Akantu. If not, see . - * - */ - -/* -------------------------------------------------------------------------- */ -#include "pybind11_akantu.hh" -/* -------------------------------------------------------------------------- */ -#include -#include -/* -------------------------------------------------------------------------- */ - -namespace py = pybind11; - -namespace akantu { - -PYBIND11_MODULE(aka_test, m) { - m.doc() = "Module for the tests of akantu"; - - py::class_>(m, "ArrayProxy", py::buffer_protocol()) - .def_buffer([](ArrayProxy & a) { - return py::buffer_info( - a.storage(), /* Pointer to buffer */ - sizeof(Real), /* Size of one scalar */ - py::format_descriptor::format(), /* Python struct-style - format descriptor */ - 2, /* Number of dimensions */ - {a.size(), a.getNbComponent()}, /* Buffer dimensions */ - {sizeof(Real) * - a.getNbComponent(), /* Strides (in bytes) for each index */ - sizeof(Real)}); - }) - .def(py::init([](py::array & n) { - /* Request a buffer descriptor from Python */ - py::buffer_info info = n.request(); - - /* Some sanity checks ... */ - if (info.format != py::format_descriptor::format()) - throw std::runtime_error( - "Incompatible format: expected a double array!"); - - if (info.ndim != 2) - throw std::runtime_error("Incompatible buffer dimension!"); - - return std::make_unique>(static_cast(info.ptr), - info.shape[0], info.shape[1]); - })); - - py::class_>(m, "Matrix", py::buffer_protocol()) - .def_buffer([](MatrixProxy & a) { - return py::buffer_info( - a.storage(), /* Pointer to buffer */ - sizeof(Real), /* Size of one scalar */ - py::format_descriptor::format(), /* Python struct-style - format descriptor */ - 2, /* Number of dimensions */ - {a.size(0), a.size(1)}, /* Buffer dimensions */ - {sizeof(Real), a.size(0) * sizeof(Real)} - /* Strides (in bytes) for each index */ - ); - }) - .def(py::init([](py::array & n) { - /* Request a buffer descriptor from Python */ - py::buffer_info info = n.request(); - - /* Some sanity checks ... */ - if (info.format != py::format_descriptor::format()) - throw std::runtime_error( - "Incompatible format: expected a double array!"); - - if (info.ndim != 2) - throw std::runtime_error("Incompatible buffer dimension!"); - - return std::make_unique>( - static_cast(info.ptr), info.shape[0], info.shape[1]); - })); -} // Module aka test -} // namespace akantu diff --git a/test/pybind11_akantu.hh b/test/pybind11_akantu.hh deleted file mode 100644 index f5e801144..000000000 --- a/test/pybind11_akantu.hh +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file pybind11_akantu.hh - * - * @author Nicolas Richart - * - * @date creation: Fri Dec 22 2017 - * @date last modification: Thu Dec 28 2017 - * - * @brief tool to wrap akantu classes in python - * - * @section LICENSE - * - * Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) - * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) - * - * Akantu is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Akantu. If not, see . - * - */ - -#include "aka_array.hh" -#include "aka_types.hh" -/* -------------------------------------------------------------------------- */ -#include -#include -#include -/* -------------------------------------------------------------------------- */ - -#ifndef __AKANTU_PYBIND11_AKANTU_HH__ -#define __AKANTU_PYBIND11_AKANTU_HH__ - -namespace akantu { - -template class ArrayProxy : public Array { -public: - ArrayProxy(T * wrapped_memory, UInt size = 0, UInt nb_component = 1, - const ID & id = "") - : Array(0, nb_component, id) { - this->values = wrapped_memory; - this->size_ = size; - } - - ArrayProxy(const ArrayProxy & array) - : Array(0, array.nb_component, array.id) { - this->values = array.values; - this->size_ = array.size_; - } - - ArrayProxy(ArrayProxy && array) { - this->nb_component = std::move(array.nb_component); - this->values = std::move(array.values); - this->size_ = std::move(array.size_); - this->id = std::move(array.id); - } - - ArrayProxy(Array & array) - : Array(0, array.getNbComponent(), array.getID()) { - this->values = array.storage(); - this->size_ = array.size(); - } - - ~ArrayProxy() { - this->values = nullptr; - this->size_ = 0; - } - - void setNbComponent(UInt nb_component) { - UInt new_size = this->size_ / nb_component; - AKANTU_DEBUG_ASSERT( - nb_component * new_size == this->nb_component * this->size_, - nb_component - << " is not valid as a new number of component for this array"); - - this->nb_component = nb_component; - this->size_ = new_size; - } - - void resize(UInt new_size) { - AKANTU_DEBUG_ASSERT(this->size_ == new_size, - "cannot resize a temporary vector"); - } -}; - -template decltype(auto) make_proxy(Array & array) { - return ArrayProxy(array); -} - -template decltype(auto) make_proxy(const Matrix & array) { - return MatrixProxy(array); -} - -} // namespace akantu - -// namespace pybind11 { -// namespace detail { -// template <> struct type_caster> { -// public: -// PYBIND11_TYPE_CASTER(akantu::ArrayProxy, _("ArrayProxy")); -// bool load(handle, bool) { -// // /* Extract PyObject from handle */ -// // PyObject *source = src.ptr(); -// // /* Try converting into a Python integer value */ -// // PyObject *tmp = PyNumber_Long(source); -// // if (!tmp) -// // return false; -// // /* Now try to convert into a C++ int */ -// // value.long_value = PyLong_AsLong(tmp); -// // Py_DECREF(tmp); -// // /* Ensure return code was OK (to avoid out-of-range errors etc) */ -// // return !(value.long_value == -1 && !PyErr_Occurred()); -// return false; -// } - -// static handle cast(akantu::ArrayProxy & src, -// return_value_policy /* policy */, handle parent) { -// constexpr ssize_t elem_size = sizeof(akantu::Real); -// ssize_t nb_comp = src.getNbComponent(); -// ssize_t size = src.size(); -// std::cout << "(src.storage()) -// << ">\n"; - -// auto a = array({size, nb_comp}, {elem_size * nb_comp, elem_size}, -// src.storage(), handle()); -// return a.release(); -// } -// }; -// } // namespace detail -// } // namespace pybind11 - -#endif /* __AKANTU_PYBIND11_AKANTU_HH__ */ diff --git a/test/test_fe_engine/CMakeLists.txt b/test/test_fe_engine/CMakeLists.txt index 149d623ab..16e286eb6 100644 --- a/test/test_fe_engine/CMakeLists.txt +++ b/test/test_fe_engine/CMakeLists.txt @@ -1,125 +1,129 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Lucas Frerot # @author Nicolas Richart # # @date creation: Fri Sep 03 2010 # @date last modification: Fri Jan 26 2018 # # @brief configuration for FEM tests # # @section LICENSE # -# Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # -# Akantu is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. # -# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. # -# You should have received a copy of the GNU Lesser General Public License along with Akantu. If not, see . +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== function(register_fem_test operation type) set(_target test_${operation}${type}) register_test(${_target} SOURCES test_${operation}.cc FILES_TO_COPY ${type}.msh COMPILE_OPTIONS TYPE=${type} PACKAGE core ) endfunction() #=============================================================================== macro(register_mesh_types package) package_get_element_types(${package} _types) foreach(_type ${_types}) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_type}.msh) list(APPEND _meshes ${_type}.msh) - #register_fem_test(fe_engine_precomputation ${_type }) else() if(NOT ${_type} STREQUAL _point_1) message("The mesh ${_type}.msh is missing, the fe_engine test cannot be activated without it") endif() endif() endforeach() endmacro(register_mesh_types) set(_meshes) register_mesh_types(core) package_is_activated(structural_mechanics has_structural_mechanics) if(has_structural_mechanics) register_mesh_types(structural_mechanics) endif() -#add_mesh(test_fem_circle_1_mesh circle.geo 2 1 OUTPUT circle1.msh) -#add_mesh(test_fem_circle_2_mesh circle.geo 2 2 OUTPUT circle2.msh) - # Tests for class MeshData macro(register_typed_test test_name type value1 value2) set(target test_${test_name}_${type}) register_test(${target} SOURCES test_${test_name}.cc COMPILE_OPTIONS "TYPE=${type};VALUE1=${value1};VALUE2=${value2}" PACKAGE core ) endmacro() register_typed_test(mesh_data string \"5\" \"10\") register_typed_test(mesh_data UInt 5 10) add_mesh(test_boundary_msh cube.geo 3 1) add_mesh(test_boundary_msh_physical_names cube_physical_names.geo 3 1) register_test(test_mesh_boundary SOURCES test_mesh_boundary.cc DEPENDS test_boundary_msh test_boundary_msh_physical_names PACKAGE core) register_test(test_facet_element_mapping SOURCES test_facet_element_mapping.cc DEPENDS test_boundary_msh_physical_names PACKAGE core) register_gtest_sources( SOURCES test_fe_engine_precomputation.cc PACKAGE core pybind11 - DEPENDS aka_test + LINK_LIBRARIES pyakantu ) register_gtest_sources( SOURCES test_fe_engine_precomputation_structural.cc PACKAGE structural_mechanics ) register_gtest_sources( SOURCES test_fe_engine_gauss_integration.cc PACKAGE core ) register_gtest_sources( SOURCES test_gradient.cc PACKAGE core ) register_gtest_sources( SOURCES test_integrate.cc PACKAGE core ) register_gtest_sources( SOURCES test_inverse_map.cc PACKAGE core ) register_gtest_test(test_fe_engine FILES_TO_COPY ${_meshes}) diff --git a/test/test_fe_engine/py_engine/py_engine.py b/test/test_fe_engine/py_engine/py_engine.py index 0bd2c7f84..7767f9edc 100644 --- a/test/test_fe_engine/py_engine/py_engine.py +++ b/test/test_fe_engine/py_engine/py_engine.py @@ -1,355 +1,355 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ __author__ = "Nicolas Richart" __copyright__ = "Copyright (C) 2016-2018, EPFL (Ecole Polytechnique Fédérale" \ " de Lausanne) Laboratory (LSMS - Laboratoire de Simulation" \ " en Mécanique des Solides)" __credits__ = ["Nicolas Richart"] __license__ = "L-GPLv3" __maintainer__ = "Nicolas Richart" __email__ = "nicolas.richart@epfl.ch" # ------------------------------------------------------------------------------ __all__ = ['Shapes'] import numpy as np import numpy.polynomial.polynomial as poly -import aka_test +import akantu as aka class Shapes(object): NATURAL_COORDS = { (1, 'quadrangle'): np.array([[-1.], [1.], [0.]]), (2, 'quadrangle'): np.array([[-1., -1.], [ 1., -1.], [ 1., 1.], [-1., 1.], [ 0., -1.], [ 1., 0.], [ 0., 1.], [-1., 0.]]), (3, 'quadrangle'): np.array([[-1., -1., -1.], [ 1., -1., -1.], [ 1., 1., -1.], [-1., 1., -1.], [-1., -1., 1.], [ 1., -1., 1.], [ 1., 1., 1.], [-1., 1., 1.], [ 0., -1., -1.], [ 1., 0., -1.], [ 0., 1., -1.], [-1., 0., -1.], [-1., -1., 0.], [ 1., -1., 0.], [ 1., 1., 0.], [-1., 1., 0.], [ 0., -1., 1.], [ 1., 0., 1.], [ 0., 1., 1.], [-1., 0., 1.]]), (2, 'triangle'): np.array([[0., 0.], [1., 0.], [0., 1,], [.5, 0.], [.5, .5], [0., .5]]), (3, 'triangle'): np.array([[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.], [.5, 0., 0.], [.5, .5, 0.], [0., .5, 0.], [0., 0., .5], [.5, 0., .5], [0., .5, .5]]), (3, 'pentahedron'): np.array([[-1., 1., 0.], [-1., 0., 1.], [-1., 0., 0.], [ 1., 1., 0.], [ 1., 0., 1.], [ 1., 0., 0.], [-1., .5, .5], [-1., 0., .5], [-1., .5, 0.], [ 0., 1., 0.], [ 0., 0., 1.], [ 0., 0., 0.], [ 1., .5, .5], [ 1., 0., .5], [ 1., .5, 0.], [ 0., .5, .5], [ 0., 0., .5], [ 0., .5, 0.]]), } QUADRATURE_W = { (1, 'quadrangle', 1): np.array([2.]), (1, 'quadrangle', 2): np.array([1., 1.]), (2, 'triangle', 1): np.array([1./2.]), (2, 'triangle', 2): np.array([1., 1., 1.])/6., (3, 'triangle', 1): np.array([1./6.]), (3, 'triangle', 2): np.array([1., 1., 1., 1.])/24., (2, 'quadrangle', 1): np.array([1., 1., 1., 1.]), (2, 'quadrangle', 2): np.array([1., 1., 1., 1.]), (3, 'quadrangle', 1): np.array([1., 1., 1., 1., 1., 1., 1., 1.]), (3, 'quadrangle', 2): np.array([1., 1., 1., 1., 1., 1., 1., 1.]), (3, 'pentahedron', 1): np.array([1., 1., 1., 1., 1., 1.])/6., (3, 'pentahedron', 2): np.array([1., 1., 1., 1., 1., 1.])/6., } _tet_a = (5. - np.sqrt(5.))/20. _tet_b = (5. + 3.*np.sqrt(5.))/20. QUADRATURE_G = { (1, 'quadrangle', 1): np.array([[0.]]), (1, 'quadrangle', 2): np.array([[-1.], [1.]])/np.sqrt(3.), (2, 'triangle', 1): np.array([[1., 1.]])/3., (2, 'triangle', 2): np.array([[1./6., 1./6.], [2./3, 1./6], [1./6., 2./3.]]), (3, 'triangle', 1): np.array([[1., 1., 1.]])/4., (3, 'triangle', 2): np.array([[_tet_a, _tet_a, _tet_a], [_tet_b, _tet_a, _tet_a], [_tet_a, _tet_b, _tet_a], [_tet_a, _tet_a, _tet_b]]), (2, 'quadrangle', 1): np.array([[-1., -1.], [ 1., -1.], [-1., 1.], [ 1., 1.]])/np.sqrt(3.), (2, 'quadrangle', 2): np.array([[-1., -1.], [ 1., -1.], [-1., 1.], [ 1., 1.]])/np.sqrt(3.), (3, 'quadrangle', 1): np.array([[-1., -1., -1.], [ 1., -1., -1.], [-1., 1., -1.], [ 1., 1., -1.], [-1., -1., 1.], [ 1., -1., 1.], [-1., 1., 1.], [ 1., 1., 1.]])/np.sqrt(3.), (3, 'quadrangle', 2): np.array([[-1., -1., -1.], [ 1., -1., -1.], [-1., 1., -1.], [ 1., 1., -1.], [-1., -1., 1.], [ 1., -1., 1.], [-1., 1., 1.], [ 1., 1., 1.]])/np.sqrt(3.), # (3, 'pentahedron', 1): np.array([[-1./np.sqrt(3.), 0.5, 0.5], # [-1./np.sqrt(3.), 0. , 0.5], # [-1./np.sqrt(3.), 0.5, 0. ], # [ 1./np.sqrt(3.), 0.5, 0.5], # [ 1./np.sqrt(3.), 0. , 0.5], # [ 1./np.sqrt(3.), 0.5 ,0. ]]), (3, 'pentahedron', 1): np.array([[-1./np.sqrt(3.), 1./6., 1./6.], [-1./np.sqrt(3.), 2./3., 1./6.], [-1./np.sqrt(3.), 1./6., 2./3.], [ 1./np.sqrt(3.), 1./6., 1./6.], [ 1./np.sqrt(3.), 2./3., 1./6.], [ 1./np.sqrt(3.), 1./6., 2./3.]]), (3, 'pentahedron', 2): np.array([[-1./np.sqrt(3.), 1./6., 1./6.], [-1./np.sqrt(3.), 2./3., 1./6.], [-1./np.sqrt(3.), 1./6., 2./3.], [ 1./np.sqrt(3.), 1./6., 1./6.], [ 1./np.sqrt(3.), 2./3., 1./6.], [ 1./np.sqrt(3.), 1./6., 2./3.]]), } ELEMENT_TYPES = { '_segment_2': ('quadrangle', 1, 'lagrange', 1, 2), '_segment_3': ('quadrangle', 2, 'lagrange', 1, 3), '_triangle_3': ('triangle', 1, 'lagrange', 2, 3), '_triangle_6': ('triangle', 2, 'lagrange', 2, 6), '_quadrangle_4': ('quadrangle', 1, 'serendip', 2, 4), '_quadrangle_8': ('quadrangle', 2, 'serendip', 2, 8), '_tetrahedron_4': ('triangle', 1, 'lagrange', 3, 4), '_tetrahedron_10': ('triangle', 2, 'lagrange', 3, 10), '_pentahedron_6': ('pentahedron', 1, 'lagrange', 3, 6), '_pentahedron_15': ('pentahedron', 2, 'lagrange', 3, 15), '_hexahedron_8': ('quadrangle', 1, 'serendip', 3, 8), '_hexahedron_20': ('quadrangle', 2, 'serendip', 3, 20), } MONOMES = {(1, 'quadrangle'): np.array([[0], [1], [2], [3], [4], [5]]), (2, 'triangle'): np.array([[0, 0], # 1 [1, 0], [0, 1], # x y [2, 0], [1, 1], [0, 2]]), # x^2 x.y y^2 (2, 'quadrangle'): np.array([[0, 0], [1, 0], [1, 1], [0, 1], [2, 0], [2, 1], [1, 2], [0, 2]]), (3, 'triangle'): np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [2, 0, 0], [1, 1, 0], [0, 2, 0], [0, 1, 1], [0, 0, 2], [1, 0, 1]]), (3, 'quadrangle'): np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [1, 0, 1], [0, 1, 1], [1, 1, 1], [2, 0, 0], [0, 2, 0], [0, 0, 2], [2, 1, 0], [2, 0, 1], [2, 1, 1], [1, 2, 0], [0, 2, 1], [1, 2, 1], [1, 0, 2], [0, 1, 2], [1, 1, 2]]), } SHAPES = { (3, 'pentahedron', 1): np.array([ [[[ 0., 0.], [ 1., 0.]], [[ 0., 0.], [-1., 0.]]], [[[ 0., 1.], [ 0., 0.]], [[ 0., -1.], [ 0., 0.]]], [[[ 1., -1.], [-1., 0.]], [[-1., 1.], [ 1., 0.]]], [[[ 0., 0.], [ 1., 0.]], [[ 0., 0.], [ 1., 0.]]], [[[ 0., 1.], [ 0., 0.]], [[ 0., 1.], [ 0., 0.]]], [[[ 1., -1.], [-1., 0.]], [[ 1., -1.], [-1., 0.]]] ])/2., (3, 'pentahedron', 2): np.array([ # 0 [[[ 0. , 0. , 0. ], [-1. , 0. , 0. ], [ 1. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0.5, 0. , 0. ], [-1. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0.5, 0. , 0. ], [ 0. , 0. , 0. ]]], # 1 [[[ 0. , -1. , 1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0.5, -1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0.5, 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 2 [[[ 0. , -1. , 1. ], [-1. , 2. , 0. ], [ 1. , 0. , 0. ]], [[-0.5, 1.5, -1. ], [ 1.5, -2. , 0. ], [-1. , 0. , 0. ]], [[ 0.5, -0.5, 0. ], [-0.5, 0. , 0. ], [ 0. , 0. , 0. ]]], # 3 [[[ 0. , 0. , 0. ], [-1. , 0. , 0. ], [ 1. , 0. , 0. ]], [[ 0. , 0. , 0. ], [-0.5, 0. , 0. ], [ 1. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0.5, 0. , 0. ], [ 0. , 0. , 0. ]]], # 4 [[[ 0. , -1. , 1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , -0.5, 1. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0.5, 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 5 [[[ 0. , -1. , 1. ], [-1. , 2. , 0. ], [ 1. , 0. , 0. ]], [[ 0.5, -1.5, 1. ], [-1.5, 2. , 0. ], [ 1. , 0. , 0. ]], [[ 0.5, -0.5, 0. ], [-0.5, 0. , 0. ], [ 0. , 0. , 0. ]]], # 6 [[[ 0. , 0. , 0. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 7 [[[ 0. , 2. , -2. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , -2. , 2. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 8 [[[ 0. , 0. , 0. ], [ 2. , -2. , 0. ], [-2. , 0. , 0. ]], [[ 0. , 0. , 0. ], [-2. , 2. , 0. ], [ 2. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 9 [[[ 0. , 0. , 0. ], [ 1. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [-1. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 10 [[[ 0. , 1. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , -1. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 11 [[[ 1. , -1. , 0. ], [-1. , 0. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]], [[-1. , 1. , 0. ], [ 1. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 12 [[[ 0. , 0. , 0. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 13 [[[ 0. , 2. , -2. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 2. , -2. ], [ 0. , -2. , 0. ], [ 0. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], # 14 [[[ 0. , 0. , 0. ], [ 2. , -2. , 0. ], [-2. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 2. , -2. , 0. ], [-2. , 0. , 0. ]], [[ 0. , 0. , 0. ], [ 0. , 0. , 0. ], [ 0. , 0. , 0. ]]], ])} def __init__(self, element): self._shape, self._order, self._inter_poly, self._dim, self._nnodes = self.ELEMENT_TYPES[element] self._ksi = self.NATURAL_COORDS[(self._dim, self._shape)][:self._nnodes] self._g = self.QUADRATURE_G[(self._dim, self._shape, self._order)] self._w = self.QUADRATURE_W[(self._dim, self._shape, self._order)] def polyval(self, x, p): if 1 == self._dim: return poly.polyval(x[0], p) if 2 == self._dim: return poly.polyval2d(x[0], x[1], p) if 3 == self._dim: return poly.polyval3d(x[0], x[1], x[2], p) def shape_from_monomes(self): momo = self.MONOMES[(self._dim, self._shape)][:self._nnodes] _shape = list(momo[0]) for s in range(len(_shape)): _shape[s] = max(momo[:,s])+1 self._poly_shape = tuple(_shape) self._monome = [] for m in momo: p = np.zeros(self._poly_shape) p[tuple(m)] = 1 self._monome.append(p) # evaluate polynomial constant for shapes _x = self._ksi _xe = np.zeros((self._nnodes, self._nnodes)) for n in range(self._nnodes): _xe[:,n] = [self.polyval(_x[n], m) for m in self._monome] _a = np.linalg.inv(_xe) _n = np.zeros((self._nnodes,) + self._monome[0].shape) # set shapes polynomials for n in range(self._nnodes): for m in range(len(self._monome)): _n[n] += _a[n, m] * self._monome[m] return _n def compute_shapes(self): if (self._dim, self._shape) in self.MONOMES: return self.shape_from_monomes() else: _n = self.SHAPES[(self._dim, self._shape, self._order)] self._poly_shape = _n[0].shape return _n def precompute(self, **kwargs): X = np.array(kwargs["X"], copy=False) nb_element = X.shape[0] X = X.reshape(nb_element, self._nnodes, self._dim) _x = self._ksi _n = self.compute_shapes() # sanity check on shapes for n in range(self._nnodes): for m in range(self._nnodes): v = self.polyval(_x[n], _n[m]) ve = 1. if n == m else 0. test = np.isclose(v, ve) if not test: raise Exception("Most probably an error in the shapes evaluation") # compute shapes derivatives _b = np.zeros((self._dim, self._nnodes,) + self._poly_shape) for d in range(self._dim): for n in range(self._nnodes): _der = poly.polyder(_n[n], axis=d) _mshape = np.array(self._poly_shape) _mshape[d] = _mshape[d] - _der.shape[d] _mshape = tuple(_mshape) _comp = np.zeros(_mshape) if 1 == self._dim: _bt = np.hstack((_der, _comp)) else: if 0 == d: _bt = np.vstack((_der, _comp)) if 1 == d: _bt = np.hstack((_der, _comp)) if 2 == d: _bt = np.dstack((_der, _comp)) _b[d, n] = _bt _nb_quads = len(self._g) _nq = np.zeros((_nb_quads, self._nnodes)) _bq = np.zeros((_nb_quads, self._dim, self._nnodes)) # evaluate shapes and shapes derivatives on gauss points for q in range(_nb_quads): _g = self._g[q] for n in range(self._nnodes): _nq[q, n] = self.polyval(_g, _n[n]) for d in range(self._dim): _bq[q, d, n] = self.polyval(_g, _b[d, n]) _j = np.array(kwargs['j'], copy=False).reshape((nb_element, _nb_quads)) _B = np.array(kwargs['B'], copy=False).reshape((nb_element, _nb_quads, self._nnodes, self._dim)) _N = np.array(kwargs['N'], copy=False).reshape((nb_element, _nb_quads, self._nnodes)) - _Q = np.array(kwargs['Q'], copy=False) + _Q = kwargs['Q'] if np.linalg.norm(_Q - self._g.T) > 1e-15: - raise Exception('Not using the same quadrature points') + raise Exception('Not using the same quadrature points norm({0} - {1}) = {2}'.format(_Q, self._g.T, np.linalg.norm(_Q - self._g.T))) for e in range(nb_element): for q in range(_nb_quads): _J = np.matmul(_bq[q], X[e]) if(np.linalg.norm(_N[e, q] - _nq[q]) > 1e-10): print(f"{e},{q}") print(_N[e, q]) print(_nq[q]) _N[e, q] = _nq[q] _tmp = np.matmul(np.linalg.inv(_J), _bq[q]) _B[e, q] = _tmp.T _j[e, q] = np.linalg.det(_J) * self._w[q] diff --git a/test/test_fe_engine/test_fe_engine_precomputation.cc b/test/test_fe_engine/test_fe_engine_precomputation.cc index e393066fa..0ee453258 100644 --- a/test/test_fe_engine/test_fe_engine_precomputation.cc +++ b/test/test_fe_engine/test_fe_engine_precomputation.cc @@ -1,111 +1,116 @@ /** * @file test_fe_engine_precomputation.cc * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Mon Feb 19 2018 * * @brief test of the fem class * * @section LICENSE * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include "pybind11_akantu.hh" +#include "py_aka_array.hh" #include "test_fe_engine_fixture.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; namespace py = pybind11; using namespace py::literals; +template +decltype(auto) make_proxy(Array & array) { + return Proxy>(array); +} + template class TestFEMPyFixture : public TestFEMFixture { using parent = TestFEMFixture; public: void SetUp() override { parent::SetUp(); const auto & connectivities = this->mesh->getConnectivity(this->type); const auto & nodes = this->mesh->getNodes().begin(this->dim); coordinates = std::make_unique>( connectivities.size(), connectivities.getNbComponent() * this->dim); for (auto && tuple : zip(make_view(connectivities, connectivities.getNbComponent()), make_view(*coordinates, this->dim, connectivities.getNbComponent()))) { const auto & conn = std::get<0>(tuple); const auto & X = std::get<1>(tuple); for (auto s : arange(conn.size())) { Vector(X(s)) = Vector(nodes[conn(s)]); } } } void TearDown() override { parent::TearDown(); coordinates.reset(nullptr); } protected: std::unique_ptr> coordinates; }; TYPED_TEST_SUITE(TestFEMPyFixture, fe_engine_types); TYPED_TEST(TestFEMPyFixture, Precompute) { SCOPED_TRACE(std::to_string(this->type)); this->fem->initShapeFunctions(); const auto & N = this->fem->getShapeFunctions().getShapes(this->type); const auto & B = this->fem->getShapeFunctions().getShapesDerivatives(this->type); const auto & j = this->fem->getIntegrator().getJacobians(this->type); // Array ref_N(this->nb_quadrature_points_total, N.getNbComponent()); // Array ref_B(this->nb_quadrature_points_total, B.getNbComponent()); Array ref_j(this->nb_quadrature_points_total, j.getNbComponent()); auto ref_N(N); auto ref_B(B); py::module py_engine = py::module::import("py_engine"); auto py_shape = py_engine.attr("Shapes")(py::str(std::to_string(this->type))); auto kwargs = py::dict( - "N"_a = make_proxy(ref_N), "B"_a = make_proxy(ref_B), - "j"_a = make_proxy(ref_j), "X"_a = make_proxy(*this->coordinates), - "Q"_a = make_proxy(this->fem->getIntegrationPoints(this->type))); + "N"_a = ref_N, "B"_a = ref_B, + "j"_a = ref_j, "X"_a = *this->coordinates, + "Q"_a = this->fem->getIntegrationPoints(this->type)); auto ret = py_shape.attr("precompute")(**kwargs); auto check = [&](auto & ref_A, auto & A, const auto & id) { SCOPED_TRACE(std::to_string(this->type) + " " + id); for (auto && n : zip(make_view(ref_A, ref_A.getNbComponent()), make_view(A, A.getNbComponent()))) { auto diff = (std::get<0>(n) - std::get<1>(n)).template norm(); EXPECT_NEAR(0., diff, 1e-10); } }; check(ref_N, N, "N"); check(ref_B, B, "B"); check(ref_j, j, "j"); } diff --git a/test/test_model/test_common/test_non_local_toolbox/CMakeLists.txt b/test/test_model/test_common/test_non_local_toolbox/CMakeLists.txt index 0538de1ec..01f80999e 100644 --- a/test/test_model/test_common/test_non_local_toolbox/CMakeLists.txt +++ b/test/test_model/test_common/test_non_local_toolbox/CMakeLists.txt @@ -1,86 +1,86 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Aurelia Isabel Cuba Ramos # @author Nicolas Richart # # @date creation: Fri Sep 03 2010 # @date last modification: Fri Feb 02 2018 # # @brief configuration for heat transfer model tests # # @section LICENSE # # Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== package_is_activated(damage_non_local _act) if(_act) - add_library(test_material test_material.hh test_material.cc) - add_library(test_material_damage test_material_damage.hh test_material_damage.cc) + add_library(test_material OBJECT test_material.hh test_material.cc) + add_library(test_material_damage OBJECT test_material_damage.hh test_material_damage.cc) target_link_libraries(test_material akantu) target_link_libraries(test_material_damage akantu) endif() register_test(test_non_local_neighborhood_base SOURCES test_non_local_neighborhood_base.cc FILES_TO_COPY material.dat plot_neighborhoods.py plate.msh PACKAGE damage_non_local ) register_test(test_weight_computation SOURCES test_weight_computation.cc FILES_TO_COPY material_weight_computation.dat plate.msh PACKAGE damage_non_local ) register_test(test_non_local_averaging SOURCES test_non_local_averaging.cc FILES_TO_COPY material_avg.dat plate.msh PACKAGE damage_non_local LINK_LIBRARIES test_material ) register_test(test_remove_damage_weight_function SOURCES test_remove_damage_weight_function.cc FILES_TO_COPY material_remove_damage.dat plate.msh PACKAGE damage_non_local LINK_LIBRARIES test_material_damage ) register_test(test_build_neighborhood_parallel SOURCES test_build_neighborhood_parallel.cc FILES_TO_COPY material_parallel_test.dat parallel_test.msh PARALLEL PARALLEL_LEVEL 2 PACKAGE damage_non_local LINK_LIBRARIES test_material ) register_test(test_pair_computation SOURCES test_pair_computation.cc FILES_TO_COPY material_remove_damage.dat pair_test.msh PARALLEL PARALLEL_LEVEL 1 2 PACKAGE damage_non_local LINK_LIBRARIES test_material_damage ) diff --git a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt index 620d5a60b..98a086245 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt @@ -1,90 +1,91 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # # @date creation: Fri Oct 22 2010 # @date last modification: Mon Jan 29 2018 # # @brief configuration for materials tests # # @section LICENSE # # Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== #add_mesh(test_local_material_barre_trou_mesh barre_trou.geo 2 2) add_mesh(test_local_material_barre_trou_mesh mesh_section_gap.geo 2 2) register_test(test_local_material SOURCES test_local_material.cc local_material_damage.cc EXTRA_FILES local_material_damage.hh local_material_damage_inline_impl.cc DEPENDS test_local_material_barre_trou_mesh FILES_TO_COPY material.dat DIRECTORIES_TO_CREATE paraview PACKAGE core ) # ============================================================================== add_mesh(test_interpolate_stress_mesh interpolation.geo 3 2) register_test(test_interpolate_stress test_interpolate_stress.cc FILES_TO_COPY material_interpolate.dat DEPENDS test_interpolate_stress_mesh DIRECTORIES_TO_CREATE paraview PACKAGE lapack core ) #=============================================================================== add_mesh(test_material_orthotropic_square_mesh square.geo 2 1) register_test(test_material_orthotropic SOURCES test_material_orthotropic.cc DEPENDS test_material_orthotropic_square_mesh FILES_TO_COPY orthotropic.dat DIRECTORIES_TO_CREATE paraview PACKAGE core lapack ) #=============================================================================== register_test(test_material_mazars SOURCES test_material_mazars.cc FILES_TO_COPY material_mazars.dat DIRECTORIES_TO_CREATE paraview PACKAGE core lapack UNSTABLE ) # ============================================================================== add_akantu_test(test_material_viscoelastic "test the visco elastic materials") add_akantu_test(test_material_non_local "test the non-local materials") add_akantu_test(test_material_elasto_plastic_linear_isotropic_hardening "test the elasto plastic with linear isotropic hardening materials") add_akantu_test(test_material_viscoelastic_maxwell "test the viscoelastic maxwell material") # ============================================================================== add_mesh(test_multi_material_elastic_mesh test_multi_material_elastic.geo 2 1) register_test(test_multi_material_elastic SOURCES test_multi_material_elastic.cc FILES_TO_COPY test_multi_material_elastic.dat DEPENDS test_multi_material_elastic_mesh PACKAGE implicit) # ============================================================================== # Material unit tests # ============================================================================== register_gtest_sources(SOURCES test_elastic_materials.cc PACKAGE core) register_gtest_sources(SOURCES test_finite_def_materials.cc PACKAGE core) -register_gtest_sources(SOURCES test_damage_materials.cc PACKAGE core pybind11 DEPENDS aka_test +register_gtest_sources(SOURCES test_damage_materials.cc PACKAGE core pybind11 + LINK_LIBRARIES pyakantu FILES_TO_COPY py_mazars.py) register_gtest_sources(SOURCES test_plastic_materials.cc PACKAGE core) register_gtest_sources(SOURCES test_material_thermal.cc PACKAGE core) register_gtest_test(test_material) diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc index a6fdb0652..808b7f902 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_damage_materials.cc @@ -1,250 +1,246 @@ /** * @file test_damage_materials.cc * * @author Guillaume Anciaux * * @date creation: Fri Nov 17 2017 * @date last modification: Tue Feb 20 2018 * * @brief Tests for damage materials * * @section LICENSE * * Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ -#include "pybind11_akantu.hh" +#include "py_aka_array.hh" #include "test_material_fixtures.hh" #include "material_marigo.hh" #include "material_mazars.hh" #include "solid_mechanics_model.hh" #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; namespace py = pybind11; using namespace py::literals; using mat_types = ::testing::Types< // Traits, Traits, // Traits, Traits, Traits, Traits>; /*****************************************************************/ template <> void FriendMaterial>::setParams() { K0.setDefaultValue(1e-4); At = 1.0; Bt = 5e3; Ac = 0.8; Bc = 1391.3; beta = 1.; E = 25e9; nu = 0.2; updateInternalParameters(); } template <> void FriendMaterial>::setParams() { K0.setDefaultValue(1e-4); At = 1.0; Bt = 5e3; Ac = 0.8; Bc = 1391.3; beta = 1.; E = 25e9; nu = 0.2; plane_stress = true; updateInternalParameters(); } template <> void FriendMaterial>::setParams() { K0.setDefaultValue(1e-4); At = 1.0; Bt = 5e3; Ac = 0.8; Bc = 1391.3; beta = 1.; E = 25e9; nu = 0.2; updateInternalParameters(); } - template <> void FriendMaterial>::testComputeStress() { Array epsilons(1001, 1); Array sigmas(1001, 1); Array damages(1001, 1); for (auto && data : enumerate(epsilons)) { std::get<1>(data) = 2e-6 * std::get<0>(data); } Real _K0 = K0; py::module py_engine = py::module::import("py_mazars"); auto kwargs_mat_params = py::dict("K0"_a = _K0, "At"_a = At, "Bt"_a = Bt, "Ac"_a = Ac, "Bc"_a = Bc, "E"_a = E, "nu"_a = nu); - auto kwargs = py::dict("epsilons"_a = make_proxy(epsilons), - "sigmas"_a = make_proxy(sigmas), - "damages"_a = make_proxy(damages)); + auto kwargs = py::dict("epsilons"_a = epsilons, "sigmas"_a = sigmas, + "damages"_a = damages); auto py_mazars = py_engine.attr("Mazars")(**kwargs_mat_params); // auto Gf_py = py_mazars.attr("compute")(**kwargs); Real dam = 0.; Real dam_ref = 0.; Real ehat = 0.; for (auto && epsilon : epsilons) { Matrix strain(this->spatial_dimension, this->spatial_dimension, 0.); Matrix sigma(this->spatial_dimension, this->spatial_dimension, 0.); strain(0, 0) = epsilon; computeStressOnQuad(strain, sigma, dam, ehat); Real sigma_ref; auto py_data = py_mazars.attr("compute_step")(epsilon, sigma_ref, dam_ref, false); std::tie(sigma_ref, dam_ref) = py::cast>(py_data); - + EXPECT_NEAR(sigma(0, 0), sigma_ref, 1e-5); EXPECT_NEAR(dam, dam_ref, 1e-10); } } template <> void FriendMaterial>::testComputeStress() { Array epsilons(1001, 1); Array sigmas(1001, 1); Array damages(1001, 1); for (auto && data : enumerate(epsilons)) { std::get<1>(data) = 2e-6 * std::get<0>(data); } Real _K0 = K0; py::module py_engine = py::module::import("py_mazars"); auto kwargs_mat_params = py::dict("K0"_a = _K0, "At"_a = At, "Bt"_a = Bt, "Ac"_a = Ac, "Bc"_a = Bc, "E"_a = E, "nu"_a = nu); - auto kwargs = py::dict("epsilons"_a = make_proxy(epsilons), - "sigmas"_a = make_proxy(sigmas), - "damages"_a = make_proxy(damages)); + auto kwargs = py::dict("epsilons"_a = epsilons, "sigmas"_a = sigmas, + "damages"_a = damages); auto py_mazars = py_engine.attr("Mazars")(**kwargs_mat_params); // auto Gf_py = py_mazars.attr("compute")(**kwargs); Real dam = 0.; Real dam_ref = 0.; Real ehat = 0.; for (auto && epsilon : epsilons) { Matrix strain(this->spatial_dimension, this->spatial_dimension, 0.); Matrix sigma(this->spatial_dimension, this->spatial_dimension, 0.); strain(0, 0) = epsilon; - strain(1, 1) = - this->nu * epsilon; + strain(1, 1) = -this->nu * epsilon; computeStressOnQuad(strain, sigma, dam, ehat); Real sigma_ref; auto py_data = py_mazars.attr("compute_step")(epsilon, sigma_ref, dam_ref, false); std::tie(sigma_ref, dam_ref) = py::cast>(py_data); - + EXPECT_NEAR(sigma(0, 0), sigma_ref, 1e-5); EXPECT_NEAR(dam, dam_ref, 1e-10); } } template <> void FriendMaterial>::testComputeStress() { Array epsilons(1001, 1); Array sigmas(1001, 1); Array damages(1001, 1); for (auto && data : enumerate(epsilons)) { std::get<1>(data) = 2e-6 * std::get<0>(data); } Real _K0 = K0; py::module py_engine = py::module::import("py_mazars"); auto kwargs_mat_params = py::dict("K0"_a = _K0, "At"_a = At, "Bt"_a = Bt, "Ac"_a = Ac, "Bc"_a = Bc, "E"_a = E, "nu"_a = nu); - auto kwargs = py::dict("epsilons"_a = make_proxy(epsilons), - "sigmas"_a = make_proxy(sigmas), - "damages"_a = make_proxy(damages)); + auto kwargs = py::dict("epsilons"_a = epsilons, "sigmas"_a = sigmas, + "damages"_a = damages); auto py_mazars = py_engine.attr("Mazars")(**kwargs_mat_params); // auto Gf_py = py_mazars.attr("compute")(**kwargs); Real dam = 0.; Real dam_ref = 0.; Real ehat = 0.; for (auto && epsilon : epsilons) { Matrix strain(this->spatial_dimension, this->spatial_dimension, 0.); Matrix sigma(this->spatial_dimension, this->spatial_dimension, 0.); strain(0, 0) = epsilon; strain(1, 1) = strain(2, 2) = -this->nu * epsilon; computeStressOnQuad(strain, sigma, dam, ehat); Real sigma_ref; auto py_data = py_mazars.attr("compute_step")(epsilon, sigma_ref, dam_ref, false); std::tie(sigma_ref, dam_ref) = py::cast>(py_data); - + EXPECT_NEAR(sigma(0, 0), sigma_ref, 1e-5); EXPECT_NEAR(dam, dam_ref, 1e-10); } } namespace { template class TestDamageMaterialFixture : public ::TestMaterialFixture {}; TYPED_TEST_SUITE(TestDamageMaterialFixture, mat_types); TYPED_TEST(TestDamageMaterialFixture, ComputeStress) { this->material->testComputeStress(); } TYPED_TEST(TestDamageMaterialFixture, DISABLED_EnergyDensity) { this->material->testEnergyDensity(); } TYPED_TEST(TestDamageMaterialFixture, DISABLED_ComputeTangentModuli) { this->material->testComputeTangentModuli(); } TYPED_TEST(TestDamageMaterialFixture, DISABLED_ComputeCelerity) { this->material->testCelerity(); } } // namespace /*****************************************************************/ diff --git a/test/test_python_interface/CMakeLists.txt b/test/test_python_interface/CMakeLists.txt index e9440d88e..e42f285df 100644 --- a/test/test_python_interface/CMakeLists.txt +++ b/test/test_python_interface/CMakeLists.txt @@ -1,33 +1,41 @@ #=============================================================================== # @file CMakeLists.txt # # @author Fabian Barras # @author Lucas Frerot # # @date creation: Fri Sep 03 2010 # @date last modification: Mon Feb 05 2018 # # @brief Python Interface tests # # @section LICENSE # -# Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # -# Akantu is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. # -# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. # -# You should have received a copy of the GNU Lesser General Public License along with Akantu. If not, see . +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see . # #=============================================================================== akantu_pybind11_add_module(py11_akantu_test_common MODULE test_common.cc) target_link_libraries(py11_akantu_test_common PRIVATE pyakantu) -add_mesh(mesh_dcb_2d mesh_dcb_2d.geo 2 1) +add_mesh(mesh_dcb_2d mesh_dcb_2d.geo 2 2) register_test(test_python_interface SCRIPT test_pybind.py FILES_TO_COPY elastic.dat DEPENDS mesh_dcb_2d py11_akantu_test_common PACKAGE python_interface )