diff --git a/CMakeLists.txt b/CMakeLists.txt index 1696214..78183dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,145 +1,143 @@ #==================================================================================================# # # # (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM # # # #==================================================================================================# # initialization # -------------- # required to specify the c++ standard cmake_minimum_required(VERSION 3.0) # required for install include(CMakePackageConfigHelpers) include(GNUInstallDirs) # options option(PKGCONFIG "Build pkg-config" ON) option(BUILD_TESTS "${PROJECT_NAME} test suite" OFF) # project settings # ---------------- # name project(GooseFEM) # file that contains the version information set(parse_version include/GooseFEM/GooseFEM.h) # header files set(headers include/GooseFEM/GooseFEM.h include/GooseFEM/Mesh.hpp include/GooseFEM/Mesh.h include/GooseFEM/MeshTri3.hpp include/GooseFEM/MeshTri3.h include/GooseFEM/MeshQuad4.hpp include/GooseFEM/MeshQuad4.h include/GooseFEM/MeshHex8.hpp include/GooseFEM/MeshHex8.h include/GooseFEM/Element.hpp include/GooseFEM/Element.h include/GooseFEM/ElementQuad4.hpp include/GooseFEM/ElementQuad4.h include/GooseFEM/ElementQuad4Planar.hpp include/GooseFEM/ElementQuad4Planar.h include/GooseFEM/ElementHex8.hpp include/GooseFEM/ElementHex8.h include/GooseFEM/Vector.hpp include/GooseFEM/Vector.h include/GooseFEM/VectorPartitioned.hpp include/GooseFEM/VectorPartitioned.h include/GooseFEM/MatrixPartitioned.hpp include/GooseFEM/MatrixPartitioned.h include/GooseFEM/MatrixDiagonal.hpp include/GooseFEM/MatrixDiagonal.h include/GooseFEM/MatrixDiagonalPartitioned.hpp include/GooseFEM/MatrixDiagonalPartitioned.h include/GooseFEM/Iterate.hpp include/GooseFEM/Iterate.h - include/GooseFEM/Dynamics.hpp - include/GooseFEM/Dynamics.h ) # automatically parse the version number file(READ "${parse_version}" version) string(REGEX MATCH "define[ \t]+GOOSEFEM_WORLD_VERSION[ \t]+([0-9]+)" _ "${version}") set(world_version "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+GOOSEFEM_MAJOR_VERSION[ \t]+([0-9]+)" _ "${version}") set(major_version "${CMAKE_MATCH_1}") string(REGEX MATCH "define[ \t]+GOOSEFEM_MINOR_VERSION[ \t]+([0-9]+)" _ "${version}") set(minor_version "${CMAKE_MATCH_1}") set(GOOSEFEM_VERSION ${world_version}.${major_version}.${minor_version}) # print information to screen message(STATUS "Building ${PROJECT_NAME} v${GOOSEFEM_VERSION}") # paths # ----- set(GOOSEFEM_ROOT_DIR "${CMAKE_INSTALL_PREFIX}") set(GOOSEFEM_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_DIR}") set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}") set(CMAKEPACKAGE_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}") set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/pkgconfig") set(fcmake "GooseFEMConfig.cmake") set(fpkg "GooseFEM.pc") # configure CMake # --------------- configure_package_config_file( ${CMAKE_CURRENT_SOURCE_DIR}/GooseFEMConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/GooseFEMConfig.cmake PATH_VARS GOOSEFEM_INCLUDE_DIR GOOSEFEM_ROOT_DIR INSTALL_DESTINATION ${CMAKEPACKAGE_INSTALL_DIR} NO_CHECK_REQUIRED_COMPONENTS_MACRO ) # install/build # ------------- # build test cases if(BUILD_TESTS) add_subdirectory(test) endif() # disable pkg-config for native Windows builds if(WIN32 OR CMAKE_HOST_SYSTEM_NAME MATCHES Windows) option(PKGCONFIG "Build pkg-config ${fpkg} file" OFF) endif() # pkg-config if(PKGCONFIG) configure_file(${fpkg}.in ${fpkg} @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${fpkg} DESTINATION ${PKGCONFIG_INSTALL_DIR}) endif() # CMake install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${fcmake} DESTINATION ${CMAKEPACKAGE_INSTALL_DIR}) # header files install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${headers} DESTINATION ${INCLUDE_INSTALL_DIR}) # print information to screen # --------------------------- message(STATUS "") message(STATUS "+---------------------------------------------------------------------------------") message(STATUS "|") message(STATUS "| Use 'make install' to install in") message(STATUS "| ${CMAKE_INSTALL_PREFIX}") if(BUILD_TESTS) message(STATUS "|") message(STATUS "| Use 'make' and './test/test' to run the tests") endif() message(STATUS "|") message(STATUS "| To specify a custom directory call") message(STATUS "| cmake /path/to/${PROJECT_NAME} -DCMAKE_INSTALL_PREFIX=yourprefix") message(STATUS "|") message(STATUS "| For custom paths, add the following line to your '~/.bashrc'") message(STATUS "| export PKG_CONFIG_PATH=${CMAKE_INSTALL_PREFIX}/share/pkgconfig:$PKG_CONFIG_PATH") message(STATUS "|") message(STATUS "+---------------------------------------------------------------------------------") message(STATUS "") diff --git a/docs/Mesh.rst b/docs/Mesh.rst index 26aa329..3fa5502 100644 --- a/docs/Mesh.rst +++ b/docs/Mesh.rst @@ -1,323 +1,323 @@ ************** GooseFEM::Mesh ************** Generic methods =============== -[:download:`GooseFEM/Mesh.h <../src/GooseFEM/Mesh.h>`, :download:`GooseFEM/Mesh.hpp <../src/GooseFEM/Mesh.hpp>`] +[:download:`GooseFEM/Mesh.h <../include/GooseFEM/Mesh.h>`, :download:`GooseFEM/Mesh.hpp <../include/GooseFEM/Mesh.hpp>`] GooseFEM::Mesh::dofs -------------------- .. code-block:: cpp GooseFEM::MatS GooseFEM::Mesh::dofs(size_t nnode, size_t ndim) Get a sequential list of DOF-numbers for each vector-component of each node. For example for 3 nodes in 2 dimensions the output is .. math:: \begin{bmatrix} 0 & 1 \\ 2 & 3 \\ 4 & 5 \end{bmatrix} GooseFEM::Mesh::renumber ------------------------ .. code-block:: cpp GooseFEM::MatS GooseFEM::Mesh::renumber(const GooseFEM::MatS &dofs) Renumber (DOF) indices to lowest possible indices. For example: .. math:: \begin{bmatrix} 0 & 1 \\ 5 & 4 \end{bmatrix} is renumbered to .. math:: \begin{bmatrix} 0 & 1 \\ 3 & 2 \end{bmatrix} Or, in pseudo-code, the result of this function is that: .. code-block:: python dofs = renumber(dofs) sort(unique(dofs[:])) == range(max(dofs+1)) .. tip:: A generic interface using iterator is available if you do not which to use the default Eigen interface. GooseFEM::Mesh::reorder ----------------------- .. code-block:: cpp GooseFEM::MatS GooseFEM::Mesh::reorder(const GooseFEM::MatS &dofs, const ColS &idx, std::string location="end") Reorder (DOF) indices such to the lowest possible indices, such that some items are at the beginning or the end. For example: .. math:: \mathrm{dofs} = \begin{bmatrix} 0 & 1 \\ 2 & 3 \\ 4 & 5 \end{bmatrix} with .. math:: \mathrm{idx} = \begin{bmatrix} 0 & 1 \end{bmatrix} Implies that ``dofs`` is renumbered such that 0 becomes the one-before-last index (:math:`0 \rightarrow 4`), and the 1 becomes the last index (:math:`1 \rightarrow 5`). The remaining items are renumbered to the lowest index while keeping the same order. The result: .. math:: \begin{bmatrix} 4 & 5 \\ 0 & 1 \\ 2 & 3 \end{bmatrix} .. tip:: A generic interface using iterator is available if you do not which to use the default Eigen interface. GooseFEM::Mesh::elem2node ------------------------- .. code-block:: cpp GooseFEM::SpMatS GooseFEM::Mesh::elem2node(const GooseFEM::MatS &conn) Return a sparse matrix which contains the element numbers (columns) that are connected to each node (rows). .. warning:: One should not confuse the element ``0`` when this matrix is converted to a dense matrix. When this is done all the 'missing' items are filled in as zero, which does have a meaning here. Predefined meshes ================= GooseFEM::Mesh::Tri3 -------------------- -[:download:`GooseFEM/MeshTri3.h <../src/GooseFEM/MeshTri3.h>`, :download:`GooseFEM/MeshTri3.hpp <../src/GooseFEM/MeshTri3.hpp>`] +[:download:`GooseFEM/MeshTri3.h <../include/GooseFEM/MeshTri3.h>`, :download:`GooseFEM/MeshTri3.hpp <../include/GooseFEM/MeshTri3.hpp>`] GooseFEM::Mesh::Tri3::Regular ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ No description yet, please consult the code. GooseFEM::Mesh::Quad4 --------------------- -[:download:`GooseFEM/MeshQuad4.h <../src/GooseFEM/MeshQuad4.h>`, :download:`GooseFEM/MeshQuad4.hpp <../src/GooseFEM/MeshQuad4.hpp>`] +[:download:`GooseFEM/MeshQuad4.h <../include/GooseFEM/MeshQuad4.h>`, :download:`GooseFEM/MeshQuad4.hpp <../include/GooseFEM/MeshQuad4.hpp>`] Naming convention ^^^^^^^^^^^^^^^^^ .. image:: figures/MeshQuad4/naming_convention.svg :width: 350px :align: center GooseFEM::Mesh::Quad4::Regular ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: cpp GooseFEM::Mesh::Quad4::Regular(size_t nelx, size_t nely, double h=1.); Regular mesh of linear quadrilaterals in two-dimensions. The element edges are all of the same size :math:`h` (by default equal to one), optional scaling can be applied afterwards. For example the mesh shown below that consists of 21 x 11 elements. In that image the element numbers are indicated with a color, and likewise for the boundary nodes. .. image:: figures/MeshQuad4/Regular/example.svg :width: 500px :align: center Methods: .. code-block:: cpp // A matrix with on each row a nodal coordinate: // [ x , y ] MatD = GooseFEM::Mesh::Quad4::Regular.coor(); // A matrix with the connectivity, with on each row to the nodes of each element MatS = GooseFEM::Mesh::Quad4::Regular.conn(); // A list of boundary nodes ColS = GooseFEM::Mesh::Quad4::Regular.nodesBottom(); ColS = GooseFEM::Mesh::Quad4::Regular.nodesTop(); ColS = GooseFEM::Mesh::Quad4::Regular.nodesLeft(); ColS = GooseFEM::Mesh::Quad4::Regular.nodesRight(); // A matrix with periodic node pairs on each row: // [ independent nodes, dependent nodes ] MatS = GooseFEM::Mesh::Quad4::Regular.nodesPeriodic(); // The node at the origin size_t = GooseFEM::Mesh::Quad4::Regular.nodeOrigin(); // A matrix with DOF-numbers: two per node in sequential order MatS = GooseFEM::Mesh::Quad4::Regular.dofs(); // A matrix with DOF-numbers: two per node in sequential order // All the periodic repetitions are eliminated from the system MatS = GooseFEM::Mesh::Quad4::Regular.dofsPeriodic(); GooseFEM::Mesh::Quad4::FineLayer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Regular mesh with a fine layer of quadrilateral elements, and coarser elements above and below. .. image:: figures/MeshQuad4/FineLayer/example.svg :width: 500px :align: center .. note:: The coarsening depends strongly on the desired number of elements in horizontal elements. The becomes clear from the following example: .. code-block:: cpp mesh = GooseFEM::Mesh::Quad4::FineLayer(6*9 ,51); // left image : 546 elements mesh = GooseFEM::Mesh::Quad4::FineLayer(6*9+3,51); // middle image : 703 elements mesh = GooseFEM::Mesh::Quad4::FineLayer(6*9+1,51); // right image : 2915 elements .. image:: figures/MeshQuad4/FineLayer/behavior.svg :width: 1000px :align: center Methods: .. code-block:: cpp // A matrix with on each row a nodal coordinate: // [ x , y ] MatD = GooseFEM::Mesh::Quad4::Regular.coor(); // A matrix with the connectivity, with on each row to the nodes of each element MatS = GooseFEM::Mesh::Quad4::Regular.conn(); // A list of boundary nodes ColS = GooseFEM::Mesh::Quad4::Regular.nodesBottom(); ColS = GooseFEM::Mesh::Quad4::Regular.nodesTop(); ColS = GooseFEM::Mesh::Quad4::Regular.nodesLeft(); ColS = GooseFEM::Mesh::Quad4::Regular.nodesRight(); // A matrix with periodic node pairs on each row: // [ independent nodes, dependent nodes ] MatS = GooseFEM::Mesh::Quad4::Regular.nodesPeriodic(); // The node at the origin size_t = GooseFEM::Mesh::Quad4::Regular.nodeOrigin(); // A matrix with DOF-numbers: two per node in sequential order MatS = GooseFEM::Mesh::Quad4::Regular.dofs(); // A matrix with DOF-numbers: two per node in sequential order // All the periodic repetitions are eliminated from the system MatS = GooseFEM::Mesh::Quad4::Regular.dofsPeriodic(); // A list with the element numbers of the fine elements in the center of the mesh // (highlighted in the plot below) ColS = GooseFEM::Mesh::Quad4::FineLayer.elementsFine(); .. image:: figures/MeshQuad4/FineLayer/example_elementsFine.svg :width: 500px :align: center GooseFEM::Mesh::Hex8 -------------------- -[:download:`MeshHex8.h <../src/GooseFEM/MeshHex8.h>`, :download:`MeshHex8.hpp <../src/GooseFEM/MeshHex8.hpp>`] +[:download:`MeshHex8.h <../include/GooseFEM/MeshHex8.h>`, :download:`MeshHex8.hpp <../include/GooseFEM/MeshHex8.hpp>`] Naming convention ^^^^^^^^^^^^^^^^^ The following naming convention is used: * **Front**: all nodes whose coordinates :math:`0 \leq x \leq L_x`, :math:`0 \leq y \leq L_y`, :math:`z = 0`. * **Back**: all nodes whose coordinates :math:`0 \leq x \leq L_x`, :math:`0 \leq y \leq L_y`, :math:`z = L_z`. * **Bottom**: all nodes whose coordinates :math:`0 \leq x \leq L_x`, :math:`0 \leq z \leq L_z`, :math:`y = 0`. * **Top**: all nodes whose coordinates :math:`0 \leq x \leq L_x`, :math:`0 \leq z \leq L_z`, :math:`y = L_y`. * **Left**: all nodes whose coordinates :math:`0 \leq y \leq L_y`, :math:`0 \leq z \leq L_z`, :math:`x = 0`. * **Right**: all nodes whose coordinates :math:`0 \leq y \leq L_y`, :math:`0 \leq z \leq L_z`, :math:`x = L_x`. The edges and corners follow from the intersections, i.e. * **FrontBottomEdge**: all nodes whose coordinates :math:`0 \leq x \leq L_x`, :math:`y = 0`, :math:`z = 0`. * ... * **FrontBottomLeftCorner**: the node whose coordinate :math:`x = 0`, :math:`y = 0`, :math:`z = 0`. * ... .. image:: figures/MeshHex8/naming_convention.svg :width: 350px :align: center GooseFEM::Mesh::Hex8::Regular ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Regular mesh. GooseFEM::Mesh::Hex8::FineLayer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Mesh with a middle plane that is fine the middle, and becomes course away from this plane. Type specific methods ===================== GooseFEM::Mesh::Tri3 -------------------- GooseFEM::Mesh::Tri3::Regular ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -[:download:`GooseFEM/MeshTri3.h <../src/GooseFEM/MeshTri3.h>`, :download:`GooseFEM/MeshTri3.hpp <../src/GooseFEM/MeshTri3.hpp>`] +[:download:`GooseFEM/MeshTri3.h <../include/GooseFEM/MeshTri3.h>`, :download:`GooseFEM/MeshTri3.hpp <../include/GooseFEM/MeshTri3.hpp>`] GooseFEM::Mesh::Tri3::getOrientation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ No description yet, please consult the code. GooseFEM::Mesh::Tri3::setOrientation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ No description yet, please consult the code. GooseFEM::Mesh::Tri3::retriangulate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ No description yet, please consult the code. GooseFEM::Mesh::Tri3::TriUpdate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ No description yet, please consult the code. GooseFEM::Mesh::Tri3::Edge ^^^^^^^^^^^^^^^^^^^^^^^^^^ No description yet, please consult the code. diff --git a/docs/examples/Dynamics/laminateElastic/noDamping/CMakeLists.txt b/docs/examples/Dynamics/laminateElastic/noDamping/CMakeLists.txt index e9ed08c..74b3098 100644 --- a/docs/examples/Dynamics/laminateElastic/noDamping/CMakeLists.txt +++ b/docs/examples/Dynamics/laminateElastic/noDamping/CMakeLists.txt @@ -1,55 +1,54 @@ cmake_minimum_required(VERSION 3.1) # basic info # ---------- # define a project name project(example) # define empty list of libraries to link set(PROJECT_LIBS "") - # basic compiler options # ---------------------- # set optimization level set(CMAKE_BUILD_TYPE Release) # set C++ standard set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) # set warnings on set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -g") # enable optimisation set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DXTENSOR_USE_XSIMD=ON") # load packages # ------------- -# add custom paths +# add custom include paths if(NOT "$ENV{INCLUDE_PATH}" STREQUAL "") string(REPLACE ":" ";" INCLUDE_LIST "$ENV{INCLUDE_PATH}") include_directories(${INCLUDE_LIST}) endif() # load HDF5 find_package(HDF5 COMPONENTS CXX REQUIRED) include_directories(${HDF5_INCLUDE_DIRS}) set(PROJECT_LIBS ${PROJECT_LIBS} ${HDF5_LIBS} ${HDF5_LIBRARIES}) # load eigen find_package(PkgConfig) pkg_check_modules(EIGEN3 REQUIRED eigen3) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIRS}) # create executable # ----------------- add_executable(${PROJECT_NAME} main.cpp) target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS}) diff --git a/docs/examples/Dynamics/readme.rst b/docs/examples/Dynamics/readme.rst new file mode 100644 index 0000000..4f98b7c --- /dev/null +++ b/docs/examples/Dynamics/readme.rst @@ -0,0 +1,101 @@ + +******** +Dynamics +******** + +Time discretisation +=================== + +Verlet +------ + +.. code-block:: cpp + + while ( ... ) + { + // variables & history + + xt::xtensor u; + xt::xtensor V; + xt::xtensor A; + xt::xtensor V_n = g.dofs_v(); + xt::xtensor A_n = g.dofs_a(); + + // new displacement + + xt::noalias(u) = g.u() + dt * g.v() + 0.5 * std::pow(dt,2.) * g.a(); + + g.set_u(u); + + // new acceleration + + xt::noalias(A) = g.solve_A(); + + g.set_a(A); + + // new velocity + + xt::noalias(V) = V_n + .5 * dt * ( A_n + A ); + + g.set_v(V); + } + +Velocity Verlet +--------------- + +.. code-block:: cpp + + while ( ... ) + { + // variables & history + + xt::xtensor u; + xt::xtensor V; + xt::xtensor A; + xt::xtensor V_n = g.dofs_v(); + xt::xtensor A_n = g.dofs_a(); + + // new displacement + + xt::noalias(u) = g.u() + dt * g.v() + 0.5 * std::pow(dt,2.) * g.a(); + + g.set_u(u); + + // estimate new velocity + + xt::noalias(V) = V_n + dt * A_n; + + g.set_v(V); + + xt::noalias(A) = g.solve_A(); + + xt::noalias(V) = V_n + .5 * dt * ( A_n + A ); + + g.set_v(V); + + // new velocity + + xt::noalias(A) = g.solve_A(); + + xt::noalias(V) = V_n + .5 * dt * ( A_n + A ); + + g.set_v(V); + + // new acceleration + + xt::noalias(A) = g.solve_A(); + + g.set_a(A); + } + +Forward Euler +------------- + +.. code-block:: cpp + + while ( ... ) + { + xt::noalias(U) = g.dofs_u() + dt * g.solve_V(); + + g.set_u(U); + } diff --git a/docs/examples/Statics/LinearElasticity.cpp b/docs/examples/Statics/LinearElasticity.cpp index d6ead42..1e78bd0 100644 --- a/docs/examples/Statics/LinearElasticity.cpp +++ b/docs/examples/Statics/LinearElasticity.cpp @@ -1,71 +1,71 @@ #include -#include +#include int main() { // mesh // ---- GooseFEM::Mesh::Quad4::Regular mesh(5,5); xt::xtensor coor = mesh.coor(); xt::xtensor conn = mesh.conn(); xt::xtensor dofs = mesh.dofs(); xt::xtensor disp = xt::zeros(coor.shape()); xt::xtensor nodesLeft = mesh.nodesLeftEdge(); xt::xtensor nodesRight = mesh.nodesRightEdge(); xt::xtensor nodesTop = mesh.nodesTopEdge(); xt::xtensor nodesBottom = mesh.nodesBottomEdge(); // boundary displacements // ---------------------- xt::xtensor iip = xt::empty({2*nodesLeft.size()+2*nodesBottom.size()}); xt::xtensor u_p = xt::zeros(iip.shape()); size_t i = 0; for ( auto &n : nodesRight ) { iip(i) = dofs(n,0); u_p(i) = 0.1; ++i; } for ( auto &n : nodesTop ) { iip(i) = dofs(n,1); u_p(i) = -0.1; ++i; } for ( auto &n : nodesLeft ) { iip(i) = dofs(n,0); u_p(i) = 0.0; ++i; } for ( auto &n : nodesBottom ) { iip(i) = dofs(n,1); u_p(i) = 0.0; ++i; } // element definition // ------------------ GooseFEM::VectorPartitioned vector(conn, dofs, iip); GooseFEM::MatrixPartitioned K (conn, dofs, iip); GooseFEM::Element::Quad4::QuadraturePlanar elem(vector.asElement(coor)); - GMatLinearElastic::Cartesian3d::Material mat(mesh.nelem(), elem.nip(), 1., 1.); + GMatLinearElastic::Cartesian3d::Matrix mat(mesh.nelem(), elem.nip(), 1., 1.); // solve // ----- // strain xt::xtensor Eps = elem.symGradN_vector(vector.asElement(disp)); // stress xt::xtensor Sig = mat.Sig(Eps); // tangent xt::xtensor C = mat.Tangent(); // internal force xt::xtensor fint = vector.assembleNode(elem.int_gradN_dot_tensor2_dV(Sig)); // stiffness matrix K.assemble(elem.int_gradN_dot_tensor4_dot_gradNT_dV(C)); // solve xt::xtensor u_u = K.solve(vector.asDofs_u(fint), u_p); // assemble to nodal vector disp = vector.asNode(u_u, u_p); // print result std::cout << disp << std::endl; return 0; } diff --git a/docs/index.rst b/docs/index.rst index 6532fbb..57bd479 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,124 +1,135 @@ ********* GooseFEM ********* .. |badge1| image:: https://img.shields.io/badge/license-GPLv3-brightgreen.svg :target: https://github.com/tdegeus/GooseFEM/blob/master/LICENSE :alt: GPLv3 license .. |badge2| image:: https://img.shields.io/badge/warranty-no-red.svg :target: https://github.com/tdegeus/GooseFEM/blob/master/LICENSE :alt: GPLv3 license .. |badge3| image:: https://img.shields.io/badge/download-.zip-lightgray.svg :target: https://github.com/tdegeus/GooseFEM/zipball/master :alt: Download as .zip .. |badge4| image:: https://img.shields.io/badge/download-.tar.gz-lightgray.svg :target: https://github.com/tdegeus/GooseFEM/tarball/master :alt: Download as .tar.gz .. |badge5| image:: https://img.shields.io/badge/contact-tom@geus.me-blue.svg :target: mailto:tom@geus.me :alt: Contact tom@geus.me .. |badge6| image:: https://img.shields.io/badge/contact-www.geus.me-blue.svg :target: http://www.geus.me :alt: Website www.geus.me .. |badge7| image:: https://img.shields.io/badge/GitHub-tdegeus/GooseFEM-blue.svg :target: https://github.com/tdegeus/GooseFEM :alt: Github tdegeus/GooseFEM .. |badge8| image:: https://img.shields.io/badge/documentation-GooseFEM.geus.me-blue.svg :target: http://GooseFEM.geus.me :alt: Website GooseFEM.geus.me | |badge1| |badge2| |badge3| |badge4| | |badge5| |badge6| |badge7| | |badge8| .. note:: This library is free to use under the `GPLv3 license `_. Any additions are very much appreciated, in terms of suggested functionality, code, documentation, testimonials, word of mouth advertisement, .... Bugs or feature requests can be filed on `GitHub `_. As always, the code comes with no guarantee. None of the developers can be held responsible for possible mistakes. .. tip:: This document should be considered as a quick-start guide. A lot effort has been spent on the readability of the code itself (in particular the ``*.h`` files should be instructive). One is highly encouraged to answer more advanced questions that arise from this guide directly using the code. Download buttons to the relevant files are included throughout this reader. This header-only module provides C++ classes and several accompanying methods to work with n-d arrays and/or tensors. It's usage, programmatically and from a compilation perspective, is really simple. One just has to ``#include `` and tell your compiler where GooseFEM is located (and to use the C++14 or younger standard). Really, that's it! Data-types ========== -[:download:`GooseFEM/GooseFEM.h <../src/GooseFEM/GooseFEM.h>`] +[:download:`GooseFEM/GooseFEM.h <../include/GooseFEM/GooseFEM.h>`] Beyond the default C++ types, GooseFEM use Eigen columns/matrices and cppmat multi-dimensional arrays. In particular: +------------+---------------------------------------------+ | Type | Description | +============+=============================================+ | ``MatD`` | row-major ``Eigen::matrix`` | +------------+---------------------------------------------+ | ``ColD`` | (column-major) ``Eigen::Matrix`` (column) | +------------+---------------------------------------------+ | ``SpMatD`` | row-major ``Eigen::SparseMatrix`` | +------------+---------------------------------------------+ | ``ArrD`` | multi-dimensional ``cppmat::array`` | +------------+---------------------------------------------+ The last letter thereby indicates the type specialisation: +------------+----------------+ | Indicator | Description | +============+================+ | ``D`` | ``double`` | +------------+----------------+ | ``S`` | ``size_t`` | +------------+----------------+ | ``I`` | ``int`` | +------------+----------------+ Data-storage ============ +-----------+------------------------------------------------+-------------+----------------------------------+ | Alias | Description | Type | Shape | +===========+================================================+=============+==================================+ | "dofval" | degrees-of-freedom | ``ColD`` | [ndof] | +-----------+------------------------------------------------+-------------+----------------------------------+ | "nodevec" | nodal vectors | ``MatD`` | [nnode, ndim] | +-----------+------------------------------------------------+-------------+----------------------------------+ | "elemvec" | nodal vectors stored per element | ``ArrD`` | [nelem, nne, ndim] | +-----------+------------------------------------------------+-------------+----------------------------------+ | "elemmat" | matrices stored per element | ``ArrD`` | [nelem, nne*ndim, nne*ndim] | +-----------+------------------------------------------------+-------------+----------------------------------+ | "qtensor" | tensors stored (as list) per integration point | ``ArrD`` | [nelem, nip, #tensor-components] | +-----------+------------------------------------------------+-------------+----------------------------------+ | "qscalar" | scalars stored per integration point | ``ArrD`` | [nelem, nip] | +-----------+------------------------------------------------+-------------+----------------------------------+ Contents ======== +Code overview +------------- + .. toctree:: :maxdepth: 1 Mesh.rst Element.rst Vector.rst compile.rst develop.rst +Examples +-------- + +.. toctree:: + :maxdepth: 1 + + examples/Dynamics/readme.rst + .. tip:: A compact reader covering the basic theory is available `here `_ Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` diff --git a/include/GooseFEM/Dynamics.h b/include/GooseFEM/Dynamics.h deleted file mode 100644 index 69658c1..0000000 --- a/include/GooseFEM/Dynamics.h +++ /dev/null @@ -1,67 +0,0 @@ -/* ================================================================================================= - -(c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM - -================================================================================================= */ - -#ifndef GOOSEFEM_DYNAMICS_H -#define GOOSEFEM_DYNAMICS_H - -// ------------------------------------------------------------------------------------------------- - -#include "GooseFEM.h" - -// ======================================= GooseFEM::Dynamics ======================================= - -namespace GooseFEM { -namespace Dynamics { - -// ------------------------------------------ dummy class ------------------------------------------ - -class Geometry -{ -public: - - // destructor - virtual ~Geometry() {}; - - // solve for DOF-accelerations [ndof] - virtual xt::xtensor solve_A() { return xt::empty({0}); }; - virtual xt::xtensor solve_V() { return xt::empty({0}); }; - - // return nodal vectors [nnode, ndim] - virtual xt::xtensor u() const { return xt::empty({0,0}); }; - virtual xt::xtensor v() const { return xt::empty({0,0}); }; - virtual xt::xtensor a() const { return xt::empty({0,0}); }; - - // return DOF values [ndof] - virtual xt::xtensor dofs_u() const { return xt::empty({0}); }; - virtual xt::xtensor dofs_v() const { return xt::empty({0}); }; - virtual xt::xtensor dofs_a() const { return xt::empty({0}); }; - - // overwrite nodal vectors [nnode, ndim] - virtual void set_u(const xt::xtensor &nodevec) { UNUSED(nodevec); return; }; - - // overwrite nodal vectors, reconstructed from DOF values [ndof] - virtual void set_u(const xt::xtensor &dofval) { UNUSED(dofval); return; }; - virtual void set_v(const xt::xtensor &dofval) { UNUSED(dofval); return; }; - virtual void set_a(const xt::xtensor &dofval) { UNUSED(dofval); return; }; - -}; - -// ------------------------------------ evaluate one time step ------------------------------------- - -inline void Verlet (Geometry &geometry, double dt, size_t nstep=1); -inline void velocityVerlet(Geometry &geometry, double dt, size_t nstep=1); - -namespace Overdamped { -inline void forwardEuler (Geometry &geometry, double dt, size_t nstep=1); -} - -// ------------------------------------------------------------------------------------------------- - -}} // namespace ... - -// ================================================================================================= - -#endif diff --git a/include/GooseFEM/Dynamics.hpp b/include/GooseFEM/Dynamics.hpp deleted file mode 100644 index bfe60f6..0000000 --- a/include/GooseFEM/Dynamics.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* ================================================================================================= - -(c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM - -================================================================================================= */ - -#ifndef GOOSEFEM_DYNAMCS_CPP -#define GOOSEFEM_DYNAMCS_CPP - -// ------------------------------------------------------------------------------------------------- - -#include "Dynamics.h" - -// ======================================= GooseFEM::Dynamics ======================================= - -namespace GooseFEM { -namespace Dynamics { - -// ------------------------------------------------------------------------------------------------- - -inline void Verlet(Geometry &g, double dt, size_t nstep) -{ - for ( size_t istep = 0 ; istep < nstep ; ++istep ) - { - // variables & history - - xt::xtensor u; - xt::xtensor V; - xt::xtensor A; - xt::xtensor V_n = g.dofs_v(); - xt::xtensor A_n = g.dofs_a(); - - // new displacement - - xt::noalias(u) = g.u() + dt * g.v() + 0.5 * std::pow(dt,2.) * g.a(); - - g.set_u(u); - - // new acceleration - - xt::noalias(A) = g.solve_A(); - - g.set_a(A); - - // new velocity - - xt::noalias(V) = V_n + .5 * dt * ( A_n + A ); - - g.set_v(V); - } -} - -// ------------------------------------------------------------------------------------------------- - -inline void velocityVerlet(Geometry &g, double dt, size_t nstep) -{ - for ( size_t istep = 0 ; istep < nstep ; ++istep ) - { - // variables & history - - xt::xtensor u; - xt::xtensor V; - xt::xtensor A; - xt::xtensor V_n = g.dofs_v(); - xt::xtensor A_n = g.dofs_a(); - - // new displacement - - xt::noalias(u) = g.u() + dt * g.v() + 0.5 * std::pow(dt,2.) * g.a(); - - g.set_u(u); - - // estimate new velocity - - xt::noalias(V) = V_n + dt * A_n; - - g.set_v(V); - - xt::noalias(A) = g.solve_A(); - - xt::noalias(V) = V_n + .5 * dt * ( A_n + A ); - - g.set_v(V); - - // new velocity - - xt::noalias(A) = g.solve_A(); - - xt::noalias(V) = V_n + .5 * dt * ( A_n + A ); - - g.set_v(V); - - // new acceleration - - xt::noalias(A) = g.solve_A(); - - g.set_a(A); - } -} - -// ------------------------------------------------------------------------------------------------- - -namespace Overdamped -{ -inline void forwardEuler(Geometry &g, double dt, size_t nstep) -{ - xt::xtensor U; - - for ( size_t istep = 0 ; istep < nstep ; ++istep ) - { - xt::noalias(U) = g.dofs_u() + dt * g.solve_V(); - - g.set_u(U); - } -} -} - -// ------------------------------------------------------------------------------------------------- - -}} // namespace ... - -// ================================================================================================= - -#endif diff --git a/include/GooseFEM/GooseFEM.h b/include/GooseFEM/GooseFEM.h index 3772938..35b0181 100644 --- a/include/GooseFEM/GooseFEM.h +++ b/include/GooseFEM/GooseFEM.h @@ -1,112 +1,110 @@ /* ================================================================================================= (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM ================================================================================================= */ #ifndef GOOSEFEM_H #define GOOSEFEM_H // ================================================================================================= #define _USE_MATH_DEFINES // to use "M_PI" from "math.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace xt::placeholders; // ================================================================================================= #define GOOSEFEM_WORLD_VERSION 0 #define GOOSEFEM_MAJOR_VERSION 1 #define GOOSEFEM_MINOR_VERSION 0 #define GOOSEFEM_VERSION_AT_LEAST(x,y,z) \ (GOOSEFEM_WORLD_VERSION>x || (GOOSEFEM_WORLD_VERSION>=x && \ (GOOSEFEM_MAJOR_VERSION>y || (GOOSEFEM_MAJOR_VERSION>=y && \ GOOSEFEM_MINOR_VERSION>=z)))) #define GOOSEFEM_VERSION(x,y,z) \ (GOOSEFEM_WORLD_VERSION==x && \ GOOSEFEM_MAJOR_VERSION==y && \ GOOSEFEM_MINOR_VERSION==z) // ================================================================================================= // dummy operation that can be use to suppress the "unused parameter" warnings #define UNUSED(p) ( (void)(p) ) // ================================================================================================= // alias Eigen sparse matrices namespace GooseFEM { typedef Eigen::SparseMatrix SpMatD; typedef Eigen::SparseMatrix SpMatS; typedef Eigen::Triplet TripD; } // ================================================================================================= #include "Mesh.h" #include "Mesh.hpp" #include "MeshTri3.h" #include "MeshTri3.hpp" #include "MeshQuad4.h" #include "MeshQuad4.hpp" #include "MeshHex8.h" #include "MeshHex8.hpp" #include "Element.h" #include "Element.hpp" #include "ElementQuad4.h" #include "ElementQuad4.hpp" #include "ElementQuad4Planar.h" #include "ElementQuad4Planar.hpp" #include "ElementHex8.h" #include "ElementHex8.hpp" #include "Vector.h" #include "Vector.hpp" #include "VectorPartitioned.h" #include "VectorPartitioned.hpp" #include "MatrixPartitioned.h" #include "MatrixPartitioned.hpp" #include "MatrixDiagonal.h" #include "MatrixDiagonal.hpp" #include "MatrixDiagonalPartitioned.h" #include "MatrixDiagonalPartitioned.hpp" #include "Iterate.h" #include "Iterate.hpp" -#include "Dynamics.h" -#include "Dynamics.hpp" // ================================================================================================= #endif diff --git a/include/GooseFEM/MatrixDiagonal.h b/include/GooseFEM/MatrixDiagonal.h index f557569..df5aeb9 100644 --- a/include/GooseFEM/MatrixDiagonal.h +++ b/include/GooseFEM/MatrixDiagonal.h @@ -1,84 +1,100 @@ /* ================================================================================================= (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM ================================================================================================= */ #ifndef GOOSEFEM_MATRIXDIAGONAL_H #define GOOSEFEM_MATRIXDIAGONAL_H // ------------------------------------------------------------------------------------------------- #include "GooseFEM.h" // =========================================== GooseFEM ============================================ namespace GooseFEM { // ------------------------------------------------------------------------------------------------- class MatrixDiagonal { public: - // constructor + // constructors + MatrixDiagonal() = default; MatrixDiagonal(const xt::xtensor &conn, const xt::xtensor &dofs); // dimensions + size_t nelem() const; // number of elements size_t nne() const; // number of nodes per element size_t nnode() const; // number of nodes size_t ndim() const; // number of dimensions size_t ndof() const; // number of DOFs // DOF lists + xt::xtensor dofs() const; // DOFs - // product: b_i = A_ij * x_j - xt::xtensor dot(const xt::xtensor &x) const; + // set matrix components + + void set(const xt::xtensor &A); // assemble from matrices stored per element [nelem, nne*ndim, nne*ndim] // WARNING: ignores any off-diagonal terms + void assemble(const xt::xtensor &elemmat); - // set - void set(const xt::xtensor &A); + // product: b_i = A_ij * x_j + + void dot(const xt::xtensor &x, + xt::xtensor &b) const; // solve: x = A \ b - xt::xtensor solve(const xt::xtensor &b); + + void solve(const xt::xtensor &b, + xt::xtensor &x); // return matrix as diagonal matrix (column) + xt::xtensor asDiagonal() const; + // auto allocation of the functions above + + xt::xtensor dot(const xt::xtensor &x) const; + + xt::xtensor solve(const xt::xtensor &b); + private: - // the diagonal matrix (not-partitioned), and its inverse (re-used to solve different RHS) + // the diagonal matrix, and its inverse (re-used to solve different RHS) xt::xtensor m_data; xt::xtensor m_inv; // signal changes to data compare to the last inverse bool m_change=false; // bookkeeping xt::xtensor m_conn; // connectivity [nelem, nne ] xt::xtensor m_dofs; // DOF-numbers per node [nnode, ndim] // dimensions size_t m_nelem; // number of elements size_t m_nne; // number of nodes per element size_t m_nnode; // number of nodes size_t m_ndim; // number of dimensions size_t m_ndof; // number of DOFs // compute inverse (automatically evaluated by "solve") void factorize(); }; // ------------------------------------------------------------------------------------------------- } // namespace ... // ================================================================================================= #endif diff --git a/include/GooseFEM/MatrixDiagonal.hpp b/include/GooseFEM/MatrixDiagonal.hpp index b7c54da..6f5fe67 100644 --- a/include/GooseFEM/MatrixDiagonal.hpp +++ b/include/GooseFEM/MatrixDiagonal.hpp @@ -1,177 +1,167 @@ /* ================================================================================================= (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM ================================================================================================= */ #ifndef GOOSEFEM_MATRIXDIAGONAL_CPP #define GOOSEFEM_MATRIXDIAGONAL_CPP // ------------------------------------------------------------------------------------------------- #include "MatrixDiagonal.h" // ================================================================================================= namespace GooseFEM { // ------------------------------------------------------------------------------------------------- inline MatrixDiagonal::MatrixDiagonal(const xt::xtensor &conn, const xt::xtensor &dofs) : m_conn(conn), m_dofs(dofs) { // mesh dimensions m_nelem = m_conn.shape()[0]; m_nne = m_conn.shape()[1]; m_nnode = m_dofs.shape()[0]; m_ndim = m_dofs.shape()[1]; // dimensions of the system m_ndof = xt::amax(m_dofs)[0] + 1; // allocate matrix and its inverse m_data = xt::empty({m_ndof}); m_inv = xt::empty({m_ndof}); // check consistency assert( xt::amax(m_conn)[0] + 1 == m_nnode ); assert( m_ndof <= m_nnode * m_ndim ); } // ------------------------------------------------------------------------------------------------- -inline size_t MatrixDiagonal::nelem() const -{ - return m_nelem; -} - -// ------------------------------------------------------------------------------------------------- - -inline size_t MatrixDiagonal::nne() const -{ - return m_nne; -} - -// ------------------------------------------------------------------------------------------------- - -inline size_t MatrixDiagonal::nnode() const -{ - return m_nnode; -} +inline size_t MatrixDiagonal::nelem() const { return m_nelem; } -// ------------------------------------------------------------------------------------------------- - -inline size_t MatrixDiagonal::ndim() const -{ - return m_ndim; -} +inline size_t MatrixDiagonal::nne() const { return m_nne; } -// ------------------------------------------------------------------------------------------------- +inline size_t MatrixDiagonal::nnode() const { return m_nnode; } -inline size_t MatrixDiagonal::ndof() const -{ - return m_ndof; -} +inline size_t MatrixDiagonal::ndim() const { return m_ndim; } -// ------------------------------------------------------------------------------------------------- +inline size_t MatrixDiagonal::ndof() const { return m_ndof; } -inline xt::xtensor MatrixDiagonal::dofs() const -{ - return m_dofs; -} +inline xt::xtensor MatrixDiagonal::dofs() const { return m_dofs; } // ------------------------------------------------------------------------------------------------- -inline xt::xtensor MatrixDiagonal::dot(const xt::xtensor &x) const +inline void MatrixDiagonal::dot(const xt::xtensor &x, + xt::xtensor &b) const { - // check input assert( x.size() == m_ndof ); + assert( b.size() == m_ndof ); - // compute product - return m_data * x; + xt::noalias(b) = m_data * x; } // ------------------------------------------------------------------------------------------------- inline void MatrixDiagonal::assemble(const xt::xtensor &elemmat) { // check input assert( elemmat.shape()[0] == m_nelem ); assert( elemmat.shape()[1] == m_nne*m_ndim ); assert( elemmat.shape()[2] == m_nne*m_ndim ); assert( Element::isDiagonal(elemmat) ); // zero-initialize matrix m_data.fill(0.0); // assemble for ( size_t e = 0 ; e < m_nelem ; ++e ) for ( size_t m = 0 ; m < m_nne ; ++m ) for ( size_t i = 0 ; i < m_ndim ; ++i ) m_data(m_dofs(m_conn(e,m),i)) += elemmat(e,m*m_ndim+i,m*m_ndim+i); // signal change m_change = true; } // ------------------------------------------------------------------------------------------------- inline void MatrixDiagonal::set(const xt::xtensor &A) { // check input assert( A.shape()[0] == m_ndof ); // copy std::copy(A.begin(), A.end(), m_data.begin()); // signal change m_change = true; } // ------------------------------------------------------------------------------------------------- inline void MatrixDiagonal::factorize() { // skip for unchanged "m_data" if ( ! m_change ) return; // invert #pragma omp parallel for for ( size_t i = 0 ; i < m_ndof ; ++i ) m_inv(i) = 1. / m_data(i); // reset signal m_change = false; } // ------------------------------------------------------------------------------------------------- -inline xt::xtensor MatrixDiagonal::solve(const xt::xtensor &b) +inline void MatrixDiagonal::solve(const xt::xtensor &b, + xt::xtensor &x) { - // check input assert( b.size() == m_ndof ); + assert( x.size() == m_ndof ); - // factorise (if needed) this->factorize(); - // solve - xt::xtensor x = m_inv * b; - - // return output - return x; + xt::noalias(x) = m_inv * b; } // ------------------------------------------------------------------------------------------------- inline xt::xtensor MatrixDiagonal::asDiagonal() const { return m_data; } // ------------------------------------------------------------------------------------------------- +inline xt::xtensor MatrixDiagonal::dot(const xt::xtensor &x) const +{ + xt::xtensor b = xt::empty({m_ndof}); + + this->dot(x, b); + + return b; +} + +// ------------------------------------------------------------------------------------------------- + +inline xt::xtensor MatrixDiagonal::solve(const xt::xtensor &b) +{ + xt::xtensor x = xt::empty({m_ndof}); + + this->solve(b, x); + + return x; +} + +// ------------------------------------------------------------------------------------------------- + } // namespace ... // ================================================================================================= #endif diff --git a/include/GooseFEM/MatrixDiagonalPartitioned.h b/include/GooseFEM/MatrixDiagonalPartitioned.h index 2713f93..e688355 100644 --- a/include/GooseFEM/MatrixDiagonalPartitioned.h +++ b/include/GooseFEM/MatrixDiagonalPartitioned.h @@ -1,99 +1,120 @@ /* ================================================================================================= (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM ================================================================================================= */ #ifndef GOOSEFEM_MATRIXDIAGONALPARTITIONED_H #define GOOSEFEM_MATRIXDIAGONALPARTITIONED_H // ------------------------------------------------------------------------------------------------- #include "GooseFEM.h" // =========================================== GooseFEM ============================================ namespace GooseFEM { // ------------------------------------------------------------------------------------------------- class MatrixDiagonalPartitioned { public: - // default constructor - MatrixDiagonalPartitioned() = default; + // constructors - // constructor + MatrixDiagonalPartitioned() = default; MatrixDiagonalPartitioned(const xt::xtensor &conn, const xt::xtensor &dofs, const xt::xtensor &iip); // dimensions + size_t nelem() const; // number of elements size_t nne() const; // number of nodes per element size_t nnode() const; // number of nodes size_t ndim() const; // number of dimensions size_t ndof() const; // number of DOFs size_t nnu() const; // number of unknown DOFs size_t nnp() const; // number of prescribed DOFs // DOF lists + xt::xtensor dofs() const; // DOFs xt::xtensor iiu() const; // unknown DOFs xt::xtensor iip() const; // prescribed DOFs - // product: b_i = A_ij * x_j - // b = A * x - xt::xtensor dot (const xt::xtensor &x ) const; - // b_u = A_uu * x_u + A_up * x_p - xt::xtensor dot_u(const xt::xtensor &x_u, const xt::xtensor &x_p) const; - // b_p = A_pu * x_u + A_pp * x_p - xt::xtensor dot_p(const xt::xtensor &x_u, const xt::xtensor &x_p) const; - // assemble from matrices stored per element [nelem, nne*ndim, nne*ndim] // WARNING: ignores any off-diagonal terms + void assemble(const xt::xtensor &elemmat); - // solve: x_u = A_uu \ ( b_u - A_up * x_p ) - xt::xtensor solve(const xt::xtensor &b_u, const xt::xtensor &x_p); + // product: b_i = A_ij * x_j + + // b = A * x + void dot(const xt::xtensor &x, + xt::xtensor &b) const; + + // b_u = A_uu * x_u + A_up * x_p == A_uu * x_u + void dot_u(const xt::xtensor &x_u, const xt::xtensor &x_p, + xt::xtensor &b_u) const; + + // b_p = A_pu * x_u + A_pp * x_p == A_pp * x_p + void dot_p(const xt::xtensor &x_u, const xt::xtensor &x_p, + xt::xtensor &b_p) const; + + // solve: x_u = A_uu \ ( b_u - A_up * x_p ) == A_uu \ b_u + + void solve(const xt::xtensor &b_u, const xt::xtensor &x_p, + xt::xtensor &x_u); + + // return matrix as diagonal matrix (column) - // return matrix as diagonal matrix xt::xtensor asDiagonal() const; + // auto allocation of the functions above + + xt::xtensor dot(const xt::xtensor &x) const; + + xt::xtensor dot_u(const xt::xtensor &x_u, const xt::xtensor &x_p) const; + + xt::xtensor dot_p(const xt::xtensor &x_u, const xt::xtensor &x_p) const; + + xt::xtensor solve(const xt::xtensor &b_u, const xt::xtensor &x_p); + private: // the diagonal matrix, and its inverse (re-used to solve different RHS) xt::xtensor m_data_uu; xt::xtensor m_data_pp; xt::xtensor m_inv_uu; // signal changes to data compare to the last inverse bool m_change=false; // bookkeeping xt::xtensor m_conn; // connectivity [nelem, nne ] xt::xtensor m_dofs; // DOF-numbers per node [nnode, ndim] xt::xtensor m_part; // DOF-numbers per node, renumbered [nnode, ndim] xt::xtensor m_iiu; // DOF-numbers that are unknown [nnu] xt::xtensor m_iip; // DOF-numbers that are prescribed [nnp] // dimensions size_t m_nelem; // number of elements size_t m_nne; // number of nodes per element size_t m_nnode; // number of nodes size_t m_ndim; // number of dimensions size_t m_ndof; // number of DOFs size_t m_nnu; // number of unknown DOFs size_t m_nnp; // number of prescribed DOFs // compute inverse (automatically evaluated by "solve") void factorize(); }; // ------------------------------------------------------------------------------------------------- } // namespace ... // ================================================================================================= #endif diff --git a/include/GooseFEM/MatrixDiagonalPartitioned.hpp b/include/GooseFEM/MatrixDiagonalPartitioned.hpp index 18b179c..897891a 100644 --- a/include/GooseFEM/MatrixDiagonalPartitioned.hpp +++ b/include/GooseFEM/MatrixDiagonalPartitioned.hpp @@ -1,297 +1,265 @@ /* ================================================================================================= (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM ================================================================================================= */ #ifndef GOOSEFEM_MATRIXDIAGONALPARTITIONED_CPP #define GOOSEFEM_MATRIXDIAGONALPARTITIONED_CPP // ------------------------------------------------------------------------------------------------- #include "MatrixDiagonalPartitioned.h" // ================================================================================================= namespace GooseFEM { // ------------------------------------------------------------------------------------------------- inline MatrixDiagonalPartitioned::MatrixDiagonalPartitioned(const xt::xtensor &conn, const xt::xtensor &dofs, const xt::xtensor &iip) : m_conn(conn), m_dofs(dofs), m_iip(iip) { // mesh dimensions m_nelem = m_conn.shape()[0]; m_nne = m_conn.shape()[1]; m_nnode = m_dofs.shape()[0]; m_ndim = m_dofs.shape()[1]; // list with unknown DOFs m_iiu = xt::setdiff1d(dofs, iip); // dimensions of the system m_ndof = xt::amax(m_dofs)[0] + 1; m_nnp = m_iip.size(); m_nnu = m_iiu.size(); // DOFs per node, such that iiu = arange(nnu), iip = nnu + arange(nnp) m_part = Mesh::reorder(m_dofs, m_iip, "end"); // allocate matrix and its inverse m_data_uu = xt::empty({m_nnu}); m_data_pp = xt::empty({m_nnp}); m_inv_uu = xt::empty({m_nnu}); // check consistency assert( xt::amax(m_conn)[0] + 1 == m_nnode ); assert( xt::amax(m_iip)[0] <= xt::amax(m_dofs)[0] ); assert( m_ndof <= m_nnode * m_ndim ); } // ------------------------------------------------------------------------------------------------- -inline size_t MatrixDiagonalPartitioned::nelem() const -{ - return m_nelem; -} - -// ------------------------------------------------------------------------------------------------- - -inline size_t MatrixDiagonalPartitioned::nne() const -{ - return m_nne; -} - -// ------------------------------------------------------------------------------------------------- - -inline size_t MatrixDiagonalPartitioned::nnode() const -{ - return m_nnode; -} - -// ------------------------------------------------------------------------------------------------- +inline size_t MatrixDiagonalPartitioned::nelem() const { return m_nelem; } -inline size_t MatrixDiagonalPartitioned::ndim() const -{ - return m_ndim; -} +inline size_t MatrixDiagonalPartitioned::nne() const { return m_nne; } -// ------------------------------------------------------------------------------------------------- +inline size_t MatrixDiagonalPartitioned::nnode() const { return m_nnode; } -inline size_t MatrixDiagonalPartitioned::ndof() const -{ - return m_ndof; -} +inline size_t MatrixDiagonalPartitioned::ndim() const { return m_ndim; } -// ------------------------------------------------------------------------------------------------- +inline size_t MatrixDiagonalPartitioned::ndof() const { return m_ndof; } -inline size_t MatrixDiagonalPartitioned::nnu() const -{ - return m_nnu; -} +inline size_t MatrixDiagonalPartitioned::nnu() const { return m_nnu; } -// ------------------------------------------------------------------------------------------------- +inline size_t MatrixDiagonalPartitioned::nnp() const { return m_nnp; } -inline size_t MatrixDiagonalPartitioned::nnp() const -{ - return m_nnp; -} +inline xt::xtensor MatrixDiagonalPartitioned::dofs() const { return m_dofs; } -// ------------------------------------------------------------------------------------------------- +inline xt::xtensor MatrixDiagonalPartitioned::iiu() const { return m_iiu; } -inline xt::xtensor MatrixDiagonalPartitioned::dofs() const -{ - return m_dofs; -} +inline xt::xtensor MatrixDiagonalPartitioned::iip() const { return m_iip; } // ------------------------------------------------------------------------------------------------- -inline xt::xtensor MatrixDiagonalPartitioned::iiu() const +inline void MatrixDiagonalPartitioned::dot(const xt::xtensor &x, + xt::xtensor &b) const { - return m_iiu; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonalPartitioned::iip() const -{ - return m_iip; -} - -// ------------------------------------------------------------------------------------------------- - -inline xt::xtensor MatrixDiagonalPartitioned::dot(const xt::xtensor &x) const -{ - // check input assert( x.size() == m_ndof ); + assert( b.size() == m_ndof ); - // allocate output - xt::xtensor b = xt::empty({m_ndof}); - - // compute product - // - #pragma omp parallel for for ( size_t i = 0 ; i < m_nnu ; ++i ) b(m_iiu(i)) = m_data_uu(i) * x(m_iiu(i)); - // - + #pragma omp parallel for for ( size_t i = 0 ; i < m_nnp ; ++i ) b(m_iip(i)) = m_data_pp(i) * x(m_iip(i)); - - // return output - return b; } // ------------------------------------------------------------------------------------------------- -inline xt::xtensor MatrixDiagonalPartitioned::dot_u( - const xt::xtensor &x_u, const xt::xtensor &x_p) const +inline void MatrixDiagonalPartitioned::dot_u( + const xt::xtensor &x_u, const xt::xtensor &x_p, + xt::xtensor &b_u) const { - // suppress warning UNUSED(x_p); - // check input assert( x_u.size() == m_nnu ); assert( x_p.size() == m_nnp ); + assert( b_u.size() == m_nnu ); - // allocate output - xt::xtensor b_u = xt::empty({m_nnu}); - - // compute product #pragma omp parallel for for ( size_t i = 0 ; i < m_nnu ; ++i ) b_u(i) = m_data_uu(i) * x_u(i); - - return b_u; } // ------------------------------------------------------------------------------------------------- -inline xt::xtensor MatrixDiagonalPartitioned::dot_p( - const xt::xtensor &x_u, const xt::xtensor &x_p) const +inline void MatrixDiagonalPartitioned::dot_p( + const xt::xtensor &x_u, const xt::xtensor &x_p, + xt::xtensor &b_p) const { - // suppress warning UNUSED(x_u); - // check input assert( x_u.size() == m_nnu ); assert( x_p.size() == m_nnp ); + assert( b_p.size() == m_nnp ); - // allocate output - xt::xtensor b_p = xt::empty({m_nnp}); - - // compute product #pragma omp parallel for for ( size_t i = 0 ; i < m_nnp ; ++i ) b_p(i) = m_data_pp(i) * x_p(i); - - return b_p; } // ------------------------------------------------------------------------------------------------- inline void MatrixDiagonalPartitioned::assemble(const xt::xtensor &elemmat) { // check input assert( elemmat.shape()[0] == m_nelem ); assert( elemmat.shape()[1] == m_nne*m_ndim ); assert( elemmat.shape()[2] == m_nne*m_ndim ); assert( Element::isDiagonal(elemmat) ); // zero-initialize matrix m_data_uu.fill(0.0); m_data_pp.fill(0.0); // assemble for ( size_t e = 0 ; e < m_nelem ; ++e ) { for ( size_t m = 0 ; m < m_nne ; ++m ) { for ( size_t i = 0 ; i < m_ndim ; ++i ) { size_t di = m_part(m_conn(e,m),i); if ( di < m_nnu ) m_data_uu(di ) += elemmat(e,m*m_ndim+i,m*m_ndim+i); else m_data_pp(di-m_nnu) += elemmat(e,m*m_ndim+i,m*m_ndim+i); } } } // signal change m_change = true; } // ------------------------------------------------------------------------------------------------- inline void MatrixDiagonalPartitioned::factorize() { // skip for unchanged "m_data" if ( ! m_change ) return; // invert #pragma omp parallel for for ( size_t i = 0 ; i < m_nnu ; ++i ) m_inv_uu(i) = 1. / m_data_uu(i); // reset signal m_change = false; } // ------------------------------------------------------------------------------------------------- -inline xt::xtensor MatrixDiagonalPartitioned::solve( - const xt::xtensor &b_u, const xt::xtensor &x_p) +inline void MatrixDiagonalPartitioned::solve( + const xt::xtensor &b_u, const xt::xtensor &x_p, + xt::xtensor &x_u) { - // suppress warning UNUSED(x_p); - // check input assert( b_u.shape()[0] == m_nnu ); assert( x_p.shape()[0] == m_nnp ); + assert( x_u.shape()[0] == m_nnu ); - // factorise (if needed) this->factorize(); - // allocate output - xt::xtensor x_u = xt::empty({m_nnu}); - - // solve #pragma omp parallel for for ( size_t i = 0 ; i < m_nnu ; ++i ) x_u(i) = m_inv_uu(i) * b_u(i); - - // return output - return x_u; } // ------------------------------------------------------------------------------------------------- inline xt::xtensor MatrixDiagonalPartitioned::asDiagonal() const { - // allocate output xt::xtensor out = xt::zeros({m_ndof}); - // assemble output - // - #pragma omp parallel for for ( size_t i = 0 ; i < m_nnu ; ++i ) out(m_iiu(i)) = m_data_uu(i); - // - + #pragma omp parallel for for ( size_t i = 0 ; i < m_nnp ; ++i ) out(m_iip(i)) = m_data_pp(i); - // return output return out; } // ------------------------------------------------------------------------------------------------- +inline xt::xtensor MatrixDiagonalPartitioned::dot(const xt::xtensor &x) const +{ + xt::xtensor b = xt::empty({m_ndof}); + + this->dot(x, b); + + return b; +} + +// ------------------------------------------------------------------------------------------------- + +inline xt::xtensor MatrixDiagonalPartitioned::dot_u( + const xt::xtensor &x_u, const xt::xtensor &x_p) const +{ + xt::xtensor b_u = xt::empty({m_nnu}); + + this->dot_u(x_u, x_p, b_u); + + return b_u; +} + +// ------------------------------------------------------------------------------------------------- + +inline xt::xtensor MatrixDiagonalPartitioned::dot_p( + const xt::xtensor &x_u, const xt::xtensor &x_p) const +{ + xt::xtensor b_p = xt::empty({m_nnp}); + + this->dot_p(x_u, x_p, b_p); + + return b_p; +} + +// ------------------------------------------------------------------------------------------------- + +inline xt::xtensor MatrixDiagonalPartitioned::solve( + const xt::xtensor &b_u, const xt::xtensor &x_p) +{ + xt::xtensor x_u = xt::empty({m_nnu}); + + this->solve(b_u, x_p, x_u); + + return x_u; +} + +// ------------------------------------------------------------------------------------------------- + } // namespace ... // ================================================================================================= #endif diff --git a/include/GooseFEM/python.cpp b/include/GooseFEM/python.cpp index 8c282ed..702bcfd 100644 --- a/include/GooseFEM/python.cpp +++ b/include/GooseFEM/python.cpp @@ -1,757 +1,699 @@ /* ================================================================================================= (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM ================================================================================================= */ #include #include #include #include #include #include #include "GooseFEM.h" // ================================================================================================= namespace py = pybind11; namespace M = GooseFEM; -// ======================================= trampoline class ======================================== - -class PyGeometry : public GooseFEM::Dynamics::Geometry -{ -public: - using GooseFEM::Dynamics::Geometry::Geometry; - using Arr1 = xt::xtensor; - using Arr2 = xt::xtensor; - using Arr3 = xt::xtensor; - - xt::xtensor solve_A() override { PYBIND11_OVERLOAD_PURE( Arr1, GooseFEM::Dynamics::Geometry, solve_A ); } - xt::xtensor solve_V() override { PYBIND11_OVERLOAD_PURE( Arr1, GooseFEM::Dynamics::Geometry, solve_V ); } - xt::xtensor u() const override { PYBIND11_OVERLOAD_PURE( Arr2, GooseFEM::Dynamics::Geometry, u ); } - xt::xtensor v() const override { PYBIND11_OVERLOAD_PURE( Arr2, GooseFEM::Dynamics::Geometry, v ); } - xt::xtensor a() const override { PYBIND11_OVERLOAD_PURE( Arr2, GooseFEM::Dynamics::Geometry, a ); } - xt::xtensor dofs_u() const override { PYBIND11_OVERLOAD_PURE( Arr1, GooseFEM::Dynamics::Geometry, dofs_u ); } - xt::xtensor dofs_v() const override { PYBIND11_OVERLOAD_PURE( Arr1, GooseFEM::Dynamics::Geometry, dofs_v ); } - xt::xtensor dofs_a() const override { PYBIND11_OVERLOAD_PURE( Arr1, GooseFEM::Dynamics::Geometry, dofs_a ); } - - void set_u(const xt::xtensor &nodevec) override { PYBIND11_OVERLOAD_PURE( void, GooseFEM::Dynamics::Geometry, set_u , nodevec); } - void set_u(const xt::xtensor &dofval ) override { PYBIND11_OVERLOAD_PURE( void, GooseFEM::Dynamics::Geometry, set_u , dofval ); } - void set_v(const xt::xtensor &dofval ) override { PYBIND11_OVERLOAD_PURE( void, GooseFEM::Dynamics::Geometry, set_v , dofval ); } - void set_a(const xt::xtensor &dofval ) override { PYBIND11_OVERLOAD_PURE( void, GooseFEM::Dynamics::Geometry, set_a , dofval ); } -}; - // =========================================== GooseFEM ============================================ PYBIND11_MODULE(GooseFEM, m) { m.doc() = "Some simple finite element meshes and operations"; // ======================================== GooseFEM.Vector ======================================== py::class_(m, "VectorPartitioned") .def(py::init &, const xt::xtensor &, const xt::xtensor &>(), "Switch between dofval/nodevec/elemvec", py::arg("conn"), py::arg("dofs"), py::arg("iip")) .def("nelem", &M::VectorPartitioned::nelem, "Return number of element") .def("nne" , &M::VectorPartitioned::nne , "Return number of nodes per element") .def("nnode", &M::VectorPartitioned::nnode, "Return number of nodes") .def("ndim" , &M::VectorPartitioned::ndim , "Return number of dimensions") .def("ndof" , &M::VectorPartitioned::ndof , "Return number of degrees-of-freedom") .def("nnu" , &M::VectorPartitioned::nnu , "Return number of unknown degrees-of-freedom") .def("nnp" , &M::VectorPartitioned::nnp , "Return number of prescribed degrees-of-freedom") .def("dofs" , &M::VectorPartitioned::dofs , "Return degrees-of-freedom") .def("iiu" , &M::VectorPartitioned::iiu , "Return unknown degrees-of-freedom") .def("iip" , &M::VectorPartitioned::iip , "Return prescribed degrees-of-freedom") .def("asDofs" , py::overload_cast&,const xt::xtensor&>(&M::VectorPartitioned::asDofs , py::const_), "Set 'dofval" , py::arg("dofval_u"), py::arg("dofval_p")) .def("asDofs" , py::overload_cast& >(&M::VectorPartitioned::asDofs , py::const_), "Set 'dofval" , py::arg("nodevec")) .def("asDofs" , py::overload_cast& >(&M::VectorPartitioned::asDofs , py::const_), "Set 'dofval" , py::arg("elemvec")) .def("asDofs_u" , py::overload_cast& >(&M::VectorPartitioned::asDofs_u , py::const_), "Set 'dofval" , py::arg("nodevec")) .def("asDofs_u" , py::overload_cast& >(&M::VectorPartitioned::asDofs_u , py::const_), "Set 'dofval" , py::arg("elemvec")) .def("asDofs_p" , py::overload_cast& >(&M::VectorPartitioned::asDofs_p , py::const_), "Set 'dofval" , py::arg("nodevec")) .def("asDofs_p" , py::overload_cast& >(&M::VectorPartitioned::asDofs_p , py::const_), "Set 'dofval" , py::arg("elemvec")) .def("asNode" , py::overload_cast&,const xt::xtensor&>(&M::VectorPartitioned::asNode , py::const_), "Set 'nodevec", py::arg("dofval_u"), py::arg("dofval_p")) .def("asNode" , py::overload_cast& >(&M::VectorPartitioned::asNode , py::const_), "Set 'nodevec", py::arg("dofval")) .def("asNode" , py::overload_cast& >(&M::VectorPartitioned::asNode , py::const_), "Set 'nodevec", py::arg("elemvec")) .def("asElement", py::overload_cast&,const xt::xtensor&>(&M::VectorPartitioned::asElement, py::const_), "Set 'elemvec", py::arg("dofval_u"), py::arg("dofval_p")) .def("asElement", py::overload_cast& >(&M::VectorPartitioned::asElement, py::const_), "Set 'elemvec", py::arg("dofval")) .def("asElement", py::overload_cast& >(&M::VectorPartitioned::asElement, py::const_), "Set 'elemvec", py::arg("nodevec")) .def("assembleDofs" , py::overload_cast&>(&M::VectorPartitioned::assembleDofs , py::const_), "Assemble 'dofval'" , py::arg("nodevec")) .def("assembleDofs" , py::overload_cast&>(&M::VectorPartitioned::assembleDofs , py::const_), "Assemble 'dofval'" , py::arg("elemvec")) .def("assembleDofs_u", py::overload_cast&>(&M::VectorPartitioned::assembleDofs_u, py::const_), "Assemble 'dofval'" , py::arg("nodevec")) .def("assembleDofs_u", py::overload_cast&>(&M::VectorPartitioned::assembleDofs_u, py::const_), "Assemble 'dofval'" , py::arg("elemvec")) .def("assembleDofs_p", py::overload_cast&>(&M::VectorPartitioned::assembleDofs_p, py::const_), "Assemble 'dofval'" , py::arg("nodevec")) .def("assembleDofs_p", py::overload_cast&>(&M::VectorPartitioned::assembleDofs_p, py::const_), "Assemble 'dofval'" , py::arg("elemvec")) .def("assembleNode" , py::overload_cast&>(&M::VectorPartitioned::assembleNode , py::const_), "Assemble 'nodevec'", py::arg("elemvec")) .def("__repr__", [](const GooseFEM::VectorPartitioned &){ return ""; }); -// ==================================== GooseFEM.MatrixDiagonalPartitioned ==================================== +// ============================== GooseFEM.MatrixDiagonalPartitioned =============================== py::class_(m, "MatrixDiagonalPartitioned") .def(py::init &, const xt::xtensor &, const xt::xtensor &>(), "Diagonal matrix", py::arg("conn"), py::arg("dofs"), py::arg("iip")) .def("nelem", &M::MatrixDiagonalPartitioned::nelem, "Return number of element") .def("nne" , &M::MatrixDiagonalPartitioned::nne , "Return number of nodes per element") .def("nnode", &M::MatrixDiagonalPartitioned::nnode, "Return number of nodes") .def("ndim" , &M::MatrixDiagonalPartitioned::ndim , "Return number of dimensions") .def("ndof" , &M::MatrixDiagonalPartitioned::ndof , "Return number of degrees-of-freedom") .def("nnu" , &M::MatrixDiagonalPartitioned::nnu , "Return number of unknown degrees-of-freedom") .def("nnp" , &M::MatrixDiagonalPartitioned::nnp , "Return number of prescribed degrees-of-freedom") + .def("assemble", &M::MatrixDiagonalPartitioned::assemble, "Assemble matrix from 'elemmat", py::arg("elemmat")) + .def("dofs" , &M::MatrixDiagonalPartitioned::dofs , "Return degrees-of-freedom") .def("iiu" , &M::MatrixDiagonalPartitioned::iiu , "Return unknown degrees-of-freedom") .def("iip" , &M::MatrixDiagonalPartitioned::iip , "Return prescribed degrees-of-freedom") - .def("dot" , &M::MatrixDiagonalPartitioned::dot , "Dot product 'b_i = A_ij * x_j", py::arg("x")) - .def("dot_u", &M::MatrixDiagonalPartitioned::dot_u, "Dot product 'b_i = A_ij * x_j", py::arg("x_u"), py::arg("x_p")) - .def("dot_p", &M::MatrixDiagonalPartitioned::dot_p, "Dot product 'b_i = A_ij * x_j", py::arg("x_u"), py::arg("x_p")) - - .def("assemble", &M::MatrixDiagonalPartitioned::assemble, "Assemble from 'elemmat", py::arg("elemmat")) + .def("dot" , py::overload_cast& >(&M::MatrixDiagonalPartitioned::dot , py::const_), "Dot product 'b_i = A_ij * x_j" , py::arg("x")) + .def("dot_u", py::overload_cast&, const xt::xtensor&>(&M::MatrixDiagonalPartitioned::dot_u, py::const_), "Dot product 'b_i = A_ij * x_j (b_u = A_uu * x_u + A_up * x_p == A_uu * x_u)", py::arg("x_u"), py::arg("x_p")) + .def("dot_p", py::overload_cast&, const xt::xtensor&>(&M::MatrixDiagonalPartitioned::dot_p, py::const_), "Dot product 'b_i = A_ij * x_j (b_p = A_pu * x_u + A_pp * x_p == A_pp * x_p)", py::arg("x_u"), py::arg("x_p")) - .def("solve", &M::MatrixDiagonalPartitioned::solve, "Solve", py::arg("b_u"), py::arg("x_p")) + .def("solve", py::overload_cast&, const xt::xtensor&>(&M::MatrixDiagonalPartitioned::solve), "Solve 'x_u = A_uu \\ ( b_u - A_up * x_p ) == A_uu \\ b_u'", py::arg("b_u"), py::arg("x_p")) .def("asDiagonal", &M::MatrixDiagonalPartitioned::asDiagonal, "Return as diagonal matrix (column)") .def("__repr__", [](const GooseFEM::MatrixDiagonalPartitioned &){ return ""; }); -// ======================================= GooseFEM.Dynamics ======================================= - -py::module mDynamics = m.def_submodule("Dynamics", "Solve routines for dynamic FEM"); - -// ------------------------------------------------------------------------------------------------- - -mDynamics.def("Verlet" , &GooseFEM::Dynamics::Verlet , "Verlet time integration" , py::arg("geometry"), py::arg("dt"), py::arg("nstep")=1); -mDynamics.def("velocityVerlet", &GooseFEM::Dynamics::velocityVerlet, "Velocity-Verlet time integration", py::arg("geometry"), py::arg("dt"), py::arg("nstep")=1); - -// ------------------------------------------------------------------------------------------------- - -py::class_(mDynamics, "Geometry") - - .def(py::init<>()) - - .def("solve_A" , &GooseFEM::Dynamics::Geometry::solve_A, "Solve for accelerations (dofval)" ) - .def("solve_V" , &GooseFEM::Dynamics::Geometry::solve_V, "Solve for velocities (dofval)" ) - - .def("u" , &GooseFEM::Dynamics::Geometry::u , "Return displacements (nodevec)") - .def("v" , &GooseFEM::Dynamics::Geometry::v , "Return velocities (nodevec)") - .def("a" , &GooseFEM::Dynamics::Geometry::a , "Return accelerations (nodevec)") - - .def("dofs_u" , &GooseFEM::Dynamics::Geometry::dofs_u , "Return displacements (dofval)" ) - .def("dofs_v" , &GooseFEM::Dynamics::Geometry::dofs_v , "Return velocities (dofval)" ) - .def("dofs_a" , &GooseFEM::Dynamics::Geometry::dofs_a , "Return accelerations (dofval)" ) - - .def("set_u" , py::overload_cast &>(&GooseFEM::Dynamics::Geometry::set_u), "Overwrite displacements", py::arg("dofval" )) - .def("set_u" , py::overload_cast &>(&GooseFEM::Dynamics::Geometry::set_u), "Overwrite displacements", py::arg("nodevec")) - .def("set_v" , &GooseFEM::Dynamics::Geometry::set_v , "Overwrite velocities" , py::arg("nodevec")) - .def("set_a" , &GooseFEM::Dynamics::Geometry::set_a , "Overwrite accelerations", py::arg("nodevec")) - - .def("__repr__", [](const GooseFEM::Dynamics::Geometry &){ return ""; }); - // ======================================= GooseFEM.Element ======================================== py::module mElement = m.def_submodule("Element", "Generic element routines"); // ------------------------------------------------------------------------------------------------- mElement.def("asElementVector" , &GooseFEM::Element::asElementVector , "Covert to 'elemvec'", py::arg("conn"), py::arg("nodevec")); mElement.def("assembleElementVector", &GooseFEM::Element::assembleNodeVector, "Assemble 'nodevec'" , py::arg("conn"), py::arg("elemvec")); // ==================================== GooseFEM.Element.Quad4 ===================================== { py::module sm = mElement.def_submodule("Quad4", "Linear quadrilateral elements (2D)"); // ------------------------------------------------------------------------------------------------- py::class_(sm, "Quadrature") .def(py::init &>(), "Quadrature", py::arg("x")) .def(py::init &, const xt::xtensor &, const xt::xtensor &>(), "Quadrature", py::arg("x"), py::arg("xi"), py::arg("w")) .def("nelem", &GooseFEM::Element::Quad4::Quadrature::nelem, "Return number of elements" ) .def("nne" , &GooseFEM::Element::Quad4::Quadrature::nne , "Return number of nodes per element" ) .def("ndim" , &GooseFEM::Element::Quad4::Quadrature::ndim , "Return number of dimensions" ) .def("nip" , &GooseFEM::Element::Quad4::Quadrature::nip , "Return number of integration points") .def("dV" , py::overload_cast<>(&GooseFEM::Element::Quad4::Quadrature::dV , py::const_), "Integration point volume (qscalar)") .def("dVtensor", py::overload_cast<>(&GooseFEM::Element::Quad4::Quadrature::dVtensor, py::const_), "Integration point volume (qtensor)") .def("gradN_vector" , py::overload_cast &>(&GooseFEM::Element::Quad4::Quadrature::gradN_vector , py::const_), "Dyadic product, returns 'qtensor'", py::arg("elemvec")) .def("gradN_vector_T" , py::overload_cast &>(&GooseFEM::Element::Quad4::Quadrature::gradN_vector_T , py::const_), "Dyadic product, returns 'qtensor'", py::arg("elemvec")) .def("symGradN_vector", py::overload_cast &>(&GooseFEM::Element::Quad4::Quadrature::symGradN_vector, py::const_), "Dyadic product, returns 'qtensor'", py::arg("elemvec")) .def("int_N_scalar_NT_dV" , py::overload_cast &>(&GooseFEM::Element::Quad4::Quadrature::int_N_scalar_NT_dV , py::const_), "Integration, returns 'elemmat'", py::arg("qscalar")) .def("int_gradN_dot_tensor2_dV", py::overload_cast &>(&GooseFEM::Element::Quad4::Quadrature::int_gradN_dot_tensor2_dV, py::const_), "Integration, returns 'elemvec'", py::arg("qtensor")) .def("__repr__", [](const GooseFEM::Element::Quad4::Quadrature &){ return ""; }); // ------------------------------------------------------------------------------------------------- { py::module ssm = sm.def_submodule("Gauss", "Gauss quadrature"); ssm.def("nip", &GooseFEM::Element::Quad4::Gauss::nip, "Return number of integration point" ); ssm.def("xi" , &GooseFEM::Element::Quad4::Gauss::xi , "Return integration point coordinates"); ssm.def("w" , &GooseFEM::Element::Quad4::Gauss::w , "Return integration point weights" ); } // ------------------------------------------------------------------------------------------------- { py::module ssm = sm.def_submodule("Nodal", "Nodal quadrature"); ssm.def("nip", &GooseFEM::Element::Quad4::Nodal::nip, "Return number of integration point" ); ssm.def("xi" , &GooseFEM::Element::Quad4::Nodal::xi , "Return integration point coordinates"); ssm.def("w" , &GooseFEM::Element::Quad4::Nodal::w , "Return integration point weights" ); } // ------------------------------------------------------------------------------------------------- } // ===================================== GooseFEM.Element.Hex8 ===================================== { py::module sm = mElement.def_submodule("Hex8", "Linear hexahedron (brick) elements (3D)"); // ------------------------------------------------------------------------------------------------- py::class_(sm, "Quadrature") .def(py::init &>(), "Quadrature", py::arg("x")) .def(py::init &, const xt::xtensor &, const xt::xtensor &>(), "Quadrature", py::arg("x"), py::arg("xi"), py::arg("w")) .def("nelem", &GooseFEM::Element::Hex8::Quadrature::nelem, "Return number of elements" ) .def("nne" , &GooseFEM::Element::Hex8::Quadrature::nne , "Return number of nodes per element" ) .def("ndim" , &GooseFEM::Element::Hex8::Quadrature::ndim , "Return number of dimensions" ) .def("nip" , &GooseFEM::Element::Hex8::Quadrature::nip , "Return number of integration points") .def("dV" , py::overload_cast<>(&GooseFEM::Element::Hex8::Quadrature::dV , py::const_), "Integration point volume (qscalar)") .def("dVtensor", py::overload_cast<>(&GooseFEM::Element::Hex8::Quadrature::dVtensor, py::const_), "Integration point volume (qtensor)") .def("gradN_vector" , py::overload_cast &>(&GooseFEM::Element::Hex8::Quadrature::gradN_vector , py::const_), "Dyadic product, returns 'qtensor'", py::arg("elemvec")) .def("gradN_vector_T" , py::overload_cast &>(&GooseFEM::Element::Hex8::Quadrature::gradN_vector_T , py::const_), "Dyadic product, returns 'qtensor'", py::arg("elemvec")) .def("symGradN_vector", py::overload_cast &>(&GooseFEM::Element::Hex8::Quadrature::symGradN_vector, py::const_), "Dyadic product, returns 'qtensor'", py::arg("elemvec")) .def("int_N_scalar_NT_dV" , py::overload_cast &>(&GooseFEM::Element::Hex8::Quadrature::int_N_scalar_NT_dV , py::const_), "Integration, returns 'elemmat'", py::arg("qscalar")) .def("int_gradN_dot_tensor2_dV", py::overload_cast &>(&GooseFEM::Element::Hex8::Quadrature::int_gradN_dot_tensor2_dV, py::const_), "Integration, returns 'elemvec'", py::arg("qtensor")) .def("__repr__", [](const GooseFEM::Element::Hex8::Quadrature &){ return ""; }); // ------------------------------------------------------------------------------------------------- { py::module ssm = sm.def_submodule("Gauss", "Gauss quadrature"); ssm.def("nip", &GooseFEM::Element::Hex8::Gauss::nip, "Return number of integration point" ); ssm.def("xi" , &GooseFEM::Element::Hex8::Gauss::xi , "Return integration point coordinates"); ssm.def("w" , &GooseFEM::Element::Hex8::Gauss::w , "Return integration point weights" ); } // ------------------------------------------------------------------------------------------------- { py::module ssm = sm.def_submodule("Nodal", "Nodal quadrature"); ssm.def("nip", &GooseFEM::Element::Hex8::Nodal::nip, "Return number of integration point" ); ssm.def("xi" , &GooseFEM::Element::Hex8::Nodal::xi , "Return integration point coordinates"); ssm.def("w" , &GooseFEM::Element::Hex8::Nodal::w , "Return integration point weights" ); } // ------------------------------------------------------------------------------------------------- } // ========================================= GooseFEM.Mesh ========================================= py::module mMesh = m.def_submodule("Mesh", "Generic mesh routines"); // ------------------------------------------------------------------------------------------------- mMesh.def("dofs", &GooseFEM::Mesh::dofs, "List with DOF-numbers (in sequential order)", py::arg("nnode"), py::arg("ndim")); mMesh.def("renumber", &GooseFEM::Mesh::renumber, "Renumber DOF-list to use the lowest possible index", py::arg("dofs")); mMesh.def("renumber_index", &GooseFEM::Mesh::renumber_index, "Index-list to renumber", py::arg("dofs")); mMesh.def("reorder", &GooseFEM::Mesh::reorder, "Renumber DOF-list to begin or end with 'idx'", py::arg("dofs"), py::arg("idx"), py::arg("location")="end"); mMesh.def("reorder_index", &GooseFEM::Mesh::reorder_index, "Index-list to reorder", py::arg("dofs"), py::arg("idx"), py::arg("location")="end"); mMesh.def("coordination", &GooseFEM::Mesh::coordination, "Coordination number of each node", py::arg("conn")); mMesh.def("elem2node", &GooseFEM::Mesh::elem2node, "Elements connect to each node", py::arg("conn")); // ====================================== GooseFEM.Mesh.Hex8 ======================================= { py::module sm = mMesh.def_submodule("Hex8", "Linear hexahedron (brick) elements (3D)"); // ------------------------------------------------------------------------------------------------- py::class_(sm, "Regular") .def(py::init(), "mesh with nx*ny*nz 'pixels' and edge size h", py::arg("nx"), py::arg("ny"), py::arg("nz"), py::arg("h")=1.) .def("nelem" , &GooseFEM::Mesh::Hex8::Regular::nelem ) .def("nnode" , &GooseFEM::Mesh::Hex8::Regular::nnode ) .def("nne" , &GooseFEM::Mesh::Hex8::Regular::nne ) .def("ndim" , &GooseFEM::Mesh::Hex8::Regular::ndim ) .def("coor" , &GooseFEM::Mesh::Hex8::Regular::coor ) .def("conn" , &GooseFEM::Mesh::Hex8::Regular::conn ) .def("nodesFront" , &GooseFEM::Mesh::Hex8::Regular::nodesFront ) .def("nodesBack" , &GooseFEM::Mesh::Hex8::Regular::nodesBack ) .def("nodesLeft" , &GooseFEM::Mesh::Hex8::Regular::nodesLeft ) .def("nodesRight" , &GooseFEM::Mesh::Hex8::Regular::nodesRight ) .def("nodesBottom" , &GooseFEM::Mesh::Hex8::Regular::nodesBottom ) .def("nodesTop" , &GooseFEM::Mesh::Hex8::Regular::nodesTop ) .def("nodesFrontFace" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontFace ) .def("nodesBackFace" , &GooseFEM::Mesh::Hex8::Regular::nodesBackFace ) .def("nodesLeftFace" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftFace ) .def("nodesRightFace" , &GooseFEM::Mesh::Hex8::Regular::nodesRightFace ) .def("nodesBottomFace" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomFace ) .def("nodesTopFace" , &GooseFEM::Mesh::Hex8::Regular::nodesTopFace ) .def("nodesFrontBottomEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontBottomEdge ) .def("nodesFrontTopEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontTopEdge ) .def("nodesFrontLeftEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontLeftEdge ) .def("nodesFrontRightEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontRightEdge ) .def("nodesBackBottomEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackBottomEdge ) .def("nodesBackTopEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackTopEdge ) .def("nodesBackLeftEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackLeftEdge ) .def("nodesBackRightEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackRightEdge ) .def("nodesBottomLeftEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomLeftEdge ) .def("nodesBottomRightEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomRightEdge ) .def("nodesTopLeftEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopLeftEdge ) .def("nodesTopRightEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopRightEdge ) .def("nodesBottomFrontEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomFrontEdge ) .def("nodesBottomBackEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomBackEdge ) .def("nodesTopFrontEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopFrontEdge ) .def("nodesTopBackEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopBackEdge ) .def("nodesLeftBottomEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBottomEdge ) .def("nodesLeftFrontEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftFrontEdge ) .def("nodesLeftBackEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBackEdge ) .def("nodesLeftTopEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftTopEdge ) .def("nodesRightBottomEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightBottomEdge ) .def("nodesRightTopEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightTopEdge ) .def("nodesRightFrontEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightFrontEdge ) .def("nodesRightBackEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightBackEdge ) .def("nodesFrontBottomOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontBottomOpenEdge ) .def("nodesFrontTopOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontTopOpenEdge ) .def("nodesFrontLeftOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontLeftOpenEdge ) .def("nodesFrontRightOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontRightOpenEdge ) .def("nodesBackBottomOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackBottomOpenEdge ) .def("nodesBackTopOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackTopOpenEdge ) .def("nodesBackLeftOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackLeftOpenEdge ) .def("nodesBackRightOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBackRightOpenEdge ) .def("nodesBottomLeftOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomLeftOpenEdge ) .def("nodesBottomRightOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomRightOpenEdge ) .def("nodesTopLeftOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopLeftOpenEdge ) .def("nodesTopRightOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopRightOpenEdge ) .def("nodesBottomFrontOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomFrontOpenEdge ) .def("nodesBottomBackOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomBackOpenEdge ) .def("nodesTopFrontOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopFrontOpenEdge ) .def("nodesTopBackOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesTopBackOpenEdge ) .def("nodesLeftBottomOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBottomOpenEdge ) .def("nodesLeftFrontOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftFrontOpenEdge ) .def("nodesLeftBackOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBackOpenEdge ) .def("nodesLeftTopOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftTopOpenEdge ) .def("nodesRightBottomOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightBottomOpenEdge ) .def("nodesRightTopOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightTopOpenEdge ) .def("nodesRightFrontOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightFrontOpenEdge ) .def("nodesRightBackOpenEdge" , &GooseFEM::Mesh::Hex8::Regular::nodesRightBackOpenEdge ) .def("nodesFrontBottomLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontBottomLeftCorner ) .def("nodesFrontBottomRightCorner", &GooseFEM::Mesh::Hex8::Regular::nodesFrontBottomRightCorner) .def("nodesFrontTopLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontTopLeftCorner ) .def("nodesFrontTopRightCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontTopRightCorner ) .def("nodesBackBottomLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackBottomLeftCorner ) .def("nodesBackBottomRightCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackBottomRightCorner ) .def("nodesBackTopLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackTopLeftCorner ) .def("nodesBackTopRightCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackTopRightCorner ) .def("nodesFrontLeftBottomCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontLeftBottomCorner ) .def("nodesBottomFrontLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomFrontLeftCorner ) .def("nodesBottomLeftFrontCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomLeftFrontCorner ) .def("nodesLeftFrontBottomCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftFrontBottomCorner ) .def("nodesLeftBottomFrontCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBottomFrontCorner ) .def("nodesFrontRightBottomCorner", &GooseFEM::Mesh::Hex8::Regular::nodesFrontRightBottomCorner) .def("nodesBottomFrontRightCorner", &GooseFEM::Mesh::Hex8::Regular::nodesBottomFrontRightCorner) .def("nodesBottomRightFrontCorner", &GooseFEM::Mesh::Hex8::Regular::nodesBottomRightFrontCorner) .def("nodesRightFrontBottomCorner", &GooseFEM::Mesh::Hex8::Regular::nodesRightFrontBottomCorner) .def("nodesRightBottomFrontCorner", &GooseFEM::Mesh::Hex8::Regular::nodesRightBottomFrontCorner) .def("nodesFrontLeftTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontLeftTopCorner ) .def("nodesTopFrontLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopFrontLeftCorner ) .def("nodesTopLeftFrontCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopLeftFrontCorner ) .def("nodesLeftFrontTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftFrontTopCorner ) .def("nodesLeftTopFrontCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftTopFrontCorner ) .def("nodesFrontRightTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesFrontRightTopCorner ) .def("nodesTopFrontRightCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopFrontRightCorner ) .def("nodesTopRightFrontCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopRightFrontCorner ) .def("nodesRightFrontTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesRightFrontTopCorner ) .def("nodesRightTopFrontCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesRightTopFrontCorner ) .def("nodesBackLeftBottomCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackLeftBottomCorner ) .def("nodesBottomBackLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomBackLeftCorner ) .def("nodesBottomLeftBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomLeftBackCorner ) .def("nodesLeftBackBottomCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBackBottomCorner ) .def("nodesLeftBottomBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBottomBackCorner ) .def("nodesBackRightBottomCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackRightBottomCorner ) .def("nodesBottomBackRightCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomBackRightCorner ) .def("nodesBottomRightBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBottomRightBackCorner ) .def("nodesRightBackBottomCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesRightBackBottomCorner ) .def("nodesRightBottomBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesRightBottomBackCorner ) .def("nodesBackLeftTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackLeftTopCorner ) .def("nodesTopBackLeftCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopBackLeftCorner ) .def("nodesTopLeftBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopLeftBackCorner ) .def("nodesLeftBackTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftBackTopCorner ) .def("nodesLeftTopBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesLeftTopBackCorner ) .def("nodesBackRightTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesBackRightTopCorner ) .def("nodesTopBackRightCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopBackRightCorner ) .def("nodesTopRightBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesTopRightBackCorner ) .def("nodesRightBackTopCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesRightBackTopCorner ) .def("nodesRightTopBackCorner" , &GooseFEM::Mesh::Hex8::Regular::nodesRightTopBackCorner ) .def("nodesPeriodic" , &GooseFEM::Mesh::Hex8::Regular::nodesPeriodic ) .def("nodesOrigin" , &GooseFEM::Mesh::Hex8::Regular::nodesOrigin ) .def("dofs" , &GooseFEM::Mesh::Hex8::Regular::dofs ) .def("dofsPeriodic" , &GooseFEM::Mesh::Hex8::Regular::dofsPeriodic ) .def("__repr__", [](const GooseFEM::Mesh::Hex8::Regular &){ return ""; }); // ------------------------------------------------------------------------------------------------- py::class_(sm, "FineLayer") .def(py::init(), "mesh with nx*ny*nz 'pixels' and edge size h", py::arg("nx"), py::arg("ny"), py::arg("nz"), py::arg("h")=1., py::arg("nfine")=1) .def("nelem" , &GooseFEM::Mesh::Hex8::FineLayer::nelem ) .def("nnode" , &GooseFEM::Mesh::Hex8::FineLayer::nnode ) .def("nne" , &GooseFEM::Mesh::Hex8::FineLayer::nne ) .def("ndim" , &GooseFEM::Mesh::Hex8::FineLayer::ndim ) .def("shape" , &GooseFEM::Mesh::Hex8::FineLayer::shape ) .def("coor" , &GooseFEM::Mesh::Hex8::FineLayer::coor ) .def("conn" , &GooseFEM::Mesh::Hex8::FineLayer::conn ) .def("elementsMiddleLayer" , &GooseFEM::Mesh::Hex8::FineLayer::elementsMiddleLayer ) .def("nodesFront" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFront ) .def("nodesBack" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBack ) .def("nodesLeft" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeft ) .def("nodesRight" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRight ) .def("nodesBottom" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottom ) .def("nodesTop" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTop ) .def("nodesFrontFace" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontFace ) .def("nodesBackFace" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackFace ) .def("nodesLeftFace" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftFace ) .def("nodesRightFace" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightFace ) .def("nodesBottomFace" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomFace ) .def("nodesTopFace" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopFace ) .def("nodesFrontBottomEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontBottomEdge ) .def("nodesFrontTopEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontTopEdge ) .def("nodesFrontLeftEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontLeftEdge ) .def("nodesFrontRightEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontRightEdge ) .def("nodesBackBottomEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackBottomEdge ) .def("nodesBackTopEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackTopEdge ) .def("nodesBackLeftEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackLeftEdge ) .def("nodesBackRightEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackRightEdge ) .def("nodesBottomLeftEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomLeftEdge ) .def("nodesBottomRightEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomRightEdge ) .def("nodesTopLeftEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopLeftEdge ) .def("nodesTopRightEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopRightEdge ) .def("nodesBottomFrontEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomFrontEdge ) .def("nodesBottomBackEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomBackEdge ) .def("nodesTopFrontEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopFrontEdge ) .def("nodesTopBackEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopBackEdge ) .def("nodesLeftBottomEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBottomEdge ) .def("nodesLeftFrontEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftFrontEdge ) .def("nodesLeftBackEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBackEdge ) .def("nodesLeftTopEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftTopEdge ) .def("nodesRightBottomEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBottomEdge ) .def("nodesRightTopEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightTopEdge ) .def("nodesRightFrontEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightFrontEdge ) .def("nodesRightBackEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBackEdge ) .def("nodesFrontBottomOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontBottomOpenEdge ) .def("nodesFrontTopOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontTopOpenEdge ) .def("nodesFrontLeftOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontLeftOpenEdge ) .def("nodesFrontRightOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontRightOpenEdge ) .def("nodesBackBottomOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackBottomOpenEdge ) .def("nodesBackTopOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackTopOpenEdge ) .def("nodesBackLeftOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackLeftOpenEdge ) .def("nodesBackRightOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackRightOpenEdge ) .def("nodesBottomLeftOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomLeftOpenEdge ) .def("nodesBottomRightOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomRightOpenEdge ) .def("nodesTopLeftOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopLeftOpenEdge ) .def("nodesTopRightOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopRightOpenEdge ) .def("nodesBottomFrontOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomFrontOpenEdge ) .def("nodesBottomBackOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomBackOpenEdge ) .def("nodesTopFrontOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopFrontOpenEdge ) .def("nodesTopBackOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopBackOpenEdge ) .def("nodesLeftBottomOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBottomOpenEdge ) .def("nodesLeftFrontOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftFrontOpenEdge ) .def("nodesLeftBackOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBackOpenEdge ) .def("nodesLeftTopOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftTopOpenEdge ) .def("nodesRightBottomOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBottomOpenEdge ) .def("nodesRightTopOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightTopOpenEdge ) .def("nodesRightFrontOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightFrontOpenEdge ) .def("nodesRightBackOpenEdge" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBackOpenEdge ) .def("nodesFrontBottomLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontBottomLeftCorner ) .def("nodesFrontBottomRightCorner", &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontBottomRightCorner) .def("nodesFrontTopLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontTopLeftCorner ) .def("nodesFrontTopRightCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontTopRightCorner ) .def("nodesBackBottomLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackBottomLeftCorner ) .def("nodesBackBottomRightCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackBottomRightCorner ) .def("nodesBackTopLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackTopLeftCorner ) .def("nodesBackTopRightCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackTopRightCorner ) .def("nodesFrontLeftBottomCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontLeftBottomCorner ) .def("nodesBottomFrontLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomFrontLeftCorner ) .def("nodesBottomLeftFrontCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomLeftFrontCorner ) .def("nodesLeftFrontBottomCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftFrontBottomCorner ) .def("nodesLeftBottomFrontCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBottomFrontCorner ) .def("nodesFrontRightBottomCorner", &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontRightBottomCorner) .def("nodesBottomFrontRightCorner", &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomFrontRightCorner) .def("nodesBottomRightFrontCorner", &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomRightFrontCorner) .def("nodesRightFrontBottomCorner", &GooseFEM::Mesh::Hex8::FineLayer::nodesRightFrontBottomCorner) .def("nodesRightBottomFrontCorner", &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBottomFrontCorner) .def("nodesFrontLeftTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontLeftTopCorner ) .def("nodesTopFrontLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopFrontLeftCorner ) .def("nodesTopLeftFrontCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopLeftFrontCorner ) .def("nodesLeftFrontTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftFrontTopCorner ) .def("nodesLeftTopFrontCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftTopFrontCorner ) .def("nodesFrontRightTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesFrontRightTopCorner ) .def("nodesTopFrontRightCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopFrontRightCorner ) .def("nodesTopRightFrontCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopRightFrontCorner ) .def("nodesRightFrontTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightFrontTopCorner ) .def("nodesRightTopFrontCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightTopFrontCorner ) .def("nodesBackLeftBottomCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackLeftBottomCorner ) .def("nodesBottomBackLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomBackLeftCorner ) .def("nodesBottomLeftBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomLeftBackCorner ) .def("nodesLeftBackBottomCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBackBottomCorner ) .def("nodesLeftBottomBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBottomBackCorner ) .def("nodesBackRightBottomCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackRightBottomCorner ) .def("nodesBottomBackRightCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomBackRightCorner ) .def("nodesBottomRightBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBottomRightBackCorner ) .def("nodesRightBackBottomCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBackBottomCorner ) .def("nodesRightBottomBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBottomBackCorner ) .def("nodesBackLeftTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackLeftTopCorner ) .def("nodesTopBackLeftCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopBackLeftCorner ) .def("nodesTopLeftBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopLeftBackCorner ) .def("nodesLeftBackTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftBackTopCorner ) .def("nodesLeftTopBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesLeftTopBackCorner ) .def("nodesBackRightTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesBackRightTopCorner ) .def("nodesTopBackRightCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopBackRightCorner ) .def("nodesTopRightBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesTopRightBackCorner ) .def("nodesRightBackTopCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightBackTopCorner ) .def("nodesRightTopBackCorner" , &GooseFEM::Mesh::Hex8::FineLayer::nodesRightTopBackCorner ) .def("nodesPeriodic" , &GooseFEM::Mesh::Hex8::FineLayer::nodesPeriodic ) .def("nodesOrigin" , &GooseFEM::Mesh::Hex8::FineLayer::nodesOrigin ) .def("dofs" , &GooseFEM::Mesh::Hex8::FineLayer::dofs ) .def("dofsPeriodic" , &GooseFEM::Mesh::Hex8::FineLayer::dofsPeriodic ) .def("__repr__", [](const GooseFEM::Mesh::Hex8::FineLayer &){ return ""; }); // ------------------------------------------------------------------------------------------------- } // ====================================== GooseFEM.Mesh.Quad4 ====================================== { py::module sm = mMesh.def_submodule("Quad4", "Linear quadrilateral elements (2D)"); // ------------------------------------------------------------------------------------------------- py::class_(sm, "Regular") .def(py::init(), "Regular mesh: 'nx' pixels in horizontal direction, 'ny' in vertical direction, edge size 'h'", py::arg("nx"), py::arg("ny"), py::arg("h")=1.) .def("coor" , &GooseFEM::Mesh::Quad4::Regular::coor ) .def("conn" , &GooseFEM::Mesh::Quad4::Regular::conn ) .def("nelem" , &GooseFEM::Mesh::Quad4::Regular::nelem ) .def("nnode" , &GooseFEM::Mesh::Quad4::Regular::nnode ) .def("nne" , &GooseFEM::Mesh::Quad4::Regular::nne ) .def("ndim" , &GooseFEM::Mesh::Quad4::Regular::ndim ) .def("nodesBottomEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesBottomEdge ) .def("nodesTopEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesTopEdge ) .def("nodesLeftEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesLeftEdge ) .def("nodesRightEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesRightEdge ) .def("nodesBottomOpenEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesBottomOpenEdge ) .def("nodesTopOpenEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesTopOpenEdge ) .def("nodesLeftOpenEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesLeftOpenEdge ) .def("nodesRightOpenEdge" , &GooseFEM::Mesh::Quad4::Regular::nodesRightOpenEdge ) .def("nodesBottomLeftCorner" , &GooseFEM::Mesh::Quad4::Regular::nodesBottomLeftCorner ) .def("nodesBottomRightCorner", &GooseFEM::Mesh::Quad4::Regular::nodesBottomRightCorner) .def("nodesTopLeftCorner" , &GooseFEM::Mesh::Quad4::Regular::nodesTopLeftCorner ) .def("nodesTopRightCorner" , &GooseFEM::Mesh::Quad4::Regular::nodesTopRightCorner ) .def("nodesLeftBottomCorner" , &GooseFEM::Mesh::Quad4::Regular::nodesLeftBottomCorner ) .def("nodesLeftTopCorner" , &GooseFEM::Mesh::Quad4::Regular::nodesLeftTopCorner ) .def("nodesRightBottomCorner", &GooseFEM::Mesh::Quad4::Regular::nodesRightBottomCorner) .def("nodesRightTopCorner" , &GooseFEM::Mesh::Quad4::Regular::nodesRightTopCorner ) .def("nodesPeriodic" , &GooseFEM::Mesh::Quad4::Regular::nodesPeriodic ) .def("nodesOrigin" , &GooseFEM::Mesh::Quad4::Regular::nodesOrigin ) .def("dofs" , &GooseFEM::Mesh::Quad4::Regular::dofs ) .def("dofsPeriodic" , &GooseFEM::Mesh::Quad4::Regular::dofsPeriodic ) .def("__repr__", [](const GooseFEM::Mesh::Quad4::Regular &){ return ""; }); // ------------------------------------------------------------------------------------------------- py::class_(sm, "FineLayer") .def( py::init(), "FineLayer mesh: 'nx' pixels in horizontal direction (length 'Lx'), idem in vertical direction", py::arg("nx"), py::arg("ny"), py::arg("h")=1., py::arg("nfine")=1 ) .def("shape" , &GooseFEM::Mesh::Quad4::FineLayer::shape ) .def("coor" , &GooseFEM::Mesh::Quad4::FineLayer::coor ) .def("conn" , &GooseFEM::Mesh::Quad4::FineLayer::conn ) .def("nelem" , &GooseFEM::Mesh::Quad4::FineLayer::nelem ) .def("nnode" , &GooseFEM::Mesh::Quad4::FineLayer::nnode ) .def("nne" , &GooseFEM::Mesh::Quad4::FineLayer::nne ) .def("ndim" , &GooseFEM::Mesh::Quad4::FineLayer::ndim ) .def("elementsMiddleLayer" , &GooseFEM::Mesh::Quad4::FineLayer::elementsMiddleLayer ) .def("nodesBottomEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesBottomEdge ) .def("nodesTopEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesTopEdge ) .def("nodesLeftEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesLeftEdge ) .def("nodesRightEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesRightEdge ) .def("nodesBottomOpenEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesBottomOpenEdge ) .def("nodesTopOpenEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesTopOpenEdge ) .def("nodesLeftOpenEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesLeftOpenEdge ) .def("nodesRightOpenEdge" , &GooseFEM::Mesh::Quad4::FineLayer::nodesRightOpenEdge ) .def("nodesBottomLeftCorner" , &GooseFEM::Mesh::Quad4::FineLayer::nodesBottomLeftCorner ) .def("nodesBottomRightCorner", &GooseFEM::Mesh::Quad4::FineLayer::nodesBottomRightCorner) .def("nodesTopLeftCorner" , &GooseFEM::Mesh::Quad4::FineLayer::nodesTopLeftCorner ) .def("nodesTopRightCorner" , &GooseFEM::Mesh::Quad4::FineLayer::nodesTopRightCorner ) .def("nodesLeftBottomCorner" , &GooseFEM::Mesh::Quad4::FineLayer::nodesLeftBottomCorner ) .def("nodesLeftTopCorner" , &GooseFEM::Mesh::Quad4::FineLayer::nodesLeftTopCorner ) .def("nodesRightBottomCorner", &GooseFEM::Mesh::Quad4::FineLayer::nodesRightBottomCorner) .def("nodesRightTopCorner" , &GooseFEM::Mesh::Quad4::FineLayer::nodesRightTopCorner ) .def("nodesPeriodic" , &GooseFEM::Mesh::Quad4::FineLayer::nodesPeriodic ) .def("nodesOrigin" , &GooseFEM::Mesh::Quad4::FineLayer::nodesOrigin ) .def("dofs" , &GooseFEM::Mesh::Quad4::FineLayer::dofs ) .def("dofsPeriodic" , &GooseFEM::Mesh::Quad4::FineLayer::dofsPeriodic ) .def("__repr__", [](const GooseFEM::Mesh::Quad4::FineLayer &){ return ""; } ); // ------------------------------------------------------------------------------------------------- } // ====================================== GooseFEM.Mesh.Tri3 ======================================= { py::module sm = mMesh.def_submodule("Tri3" , "Linear triangular elements (2D)"); // ------------------------------------------------------------------------------------------------- py::class_(sm, "Regular") .def( py::init(), "Regular mesh: 'nx' pixels in horizontal direction, 'ny' in vertical direction, edge size 'h'", py::arg("nx"), py::arg("ny"), py::arg("h")=1. ) .def("coor" , &GooseFEM::Mesh::Tri3::Regular::coor ) .def("conn" , &GooseFEM::Mesh::Tri3::Regular::conn ) .def("nelem" , &GooseFEM::Mesh::Tri3::Regular::nelem ) .def("nnode" , &GooseFEM::Mesh::Tri3::Regular::nnode ) .def("nne" , &GooseFEM::Mesh::Tri3::Regular::nne ) .def("ndim" , &GooseFEM::Mesh::Tri3::Regular::ndim ) .def("nodesBottomEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesBottomEdge ) .def("nodesTopEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesTopEdge ) .def("nodesLeftEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesLeftEdge ) .def("nodesRightEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesRightEdge ) .def("nodesBottomOpenEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesBottomOpenEdge ) .def("nodesTopOpenEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesTopOpenEdge ) .def("nodesLeftOpenEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesLeftOpenEdge ) .def("nodesRightOpenEdge" , &GooseFEM::Mesh::Tri3::Regular::nodesRightOpenEdge ) .def("nodesBottomLeftCorner" , &GooseFEM::Mesh::Tri3::Regular::nodesBottomLeftCorner ) .def("nodesBottomRightCorner", &GooseFEM::Mesh::Tri3::Regular::nodesBottomRightCorner) .def("nodesTopLeftCorner" , &GooseFEM::Mesh::Tri3::Regular::nodesTopLeftCorner ) .def("nodesTopRightCorner" , &GooseFEM::Mesh::Tri3::Regular::nodesTopRightCorner ) .def("nodesLeftBottomCorner" , &GooseFEM::Mesh::Tri3::Regular::nodesLeftBottomCorner ) .def("nodesLeftTopCorner" , &GooseFEM::Mesh::Tri3::Regular::nodesLeftTopCorner ) .def("nodesRightBottomCorner", &GooseFEM::Mesh::Tri3::Regular::nodesRightBottomCorner) .def("nodesRightTopCorner" , &GooseFEM::Mesh::Tri3::Regular::nodesRightTopCorner ) .def("nodesPeriodic" , &GooseFEM::Mesh::Tri3::Regular::nodesPeriodic ) .def("nodesOrigin" , &GooseFEM::Mesh::Tri3::Regular::nodesOrigin ) .def("dofs" , &GooseFEM::Mesh::Tri3::Regular::dofs ) .def("dofsPeriodic" , &GooseFEM::Mesh::Tri3::Regular::dofsPeriodic ) .def("__repr__", [](const GooseFEM::Mesh::Tri3::Regular &){ return ""; }); // ------------------------------------------------------------------------------------------------- sm.def("getOrientation", &GooseFEM::Mesh::Tri3::getOrientation, "Get the orientation of each element", py::arg("coor"), py::arg("conn")); sm.def("retriangulate", &GooseFEM::Mesh::Tri3::retriangulate, "Re-triangulate existing mesh", py::arg("coor"), py::arg("conn"), py::arg("orientation")=-1); // ------------------------------------------------------------------------------------------------- } // ================================================================================================= }