diff --git a/doc/dev-doc/manual/getting_started.rst b/doc/dev-doc/manual/getting_started.rst index ea7a75556..6f37daa3e 100644 --- a/doc/dev-doc/manual/getting_started.rst +++ b/doc/dev-doc/manual/getting_started.rst @@ -1,308 +1,437 @@ Getting Started =============== Compiling ``Akantu`` -------------------- ``Akantu`` is a `CMake `_ project, so to configure it, you can either follow the usual way:: > cd akantu > mkdir build > cd build > ccmake .. [ Set the options that you need ] > make > make install All the ``Akantu`` options are documented in Appendix app:package-dependencies. Writing a ``main`` function --------------------------- ``Akantu`` first needs to be initialized. The memory management included in the core library handles the correct allocation and de-allocation of vectors, structures and/or objects. Moreover, in parallel computations, the initialization procedure performs the communication setup. This is achieved by the function :cpp:func:`initialize ` that is used as follows:: #include "aka_common.hh" #include "..." using namespace akantu; int main(int argc, char *argv[]) { initialize("input_file.dat", argc, argv); // your code ... } The :cpp:func:`initialize ` function takes the text inpute file and the program parameters which can be parsed by ``Akantu`` in due form (see sect:parser). Obviously it is necessary to include all files needed in main. In this manual all provided code implies the usage of ``akantu`` as namespace. -.. _loading mesh: +Compiling your simulation +------------------------- + +The easiest way to compile your simulation is to create a ``cmake`` project by +putting all your code in some directory of your choosing. Then, make sure that +you have ``cmake`` installed and create a ``CMakeLists.txt`` file. An example of +a minimal ``CMakeLists.txt`` file would look like this: + +.. code-block:: cmake + + project(my_simu) + cmake_minimum_required(VERSION 3.0.0) + + find_package(Akantu REQUIRED) + + add_akantu_simulation(my_simu my_simu.cc) + +Then create a directory called ``build`` and inside it execute ``cmake +-DAkantu_DIR= -DCMAKE_BUILD_TYPE=RelWithDebInfo ..``. If you +installed ``Akantu`` in a standard directory such as ``/usr/local`` (using +``make install``), you can omit the ``-DAkantu_DIR=`` option. + +Other why ``path_to_akantu`` is either the folder where you built ``Akantu`` if +you did not do a ``make install``, or if you installed ``Akantu`` in +``CMAKE_INSTALL_PREFIX`` it is ``/share/cmake/Akantu``. + +Once ``cmake`` managed to configure and generate a ``makefile`` you can just do +``make`` + + +.. _loading_mesh: Creating and Loading a Mesh --------------------------- In its current state, ``Akantu`` supports three types of meshes: Gmsh, Abaqus and Diana. Once a :cpp:class:`akantu::Mesh` object is created with a given spatial dimension, it can be filled by reading a mesh input file. The method :cpp:func:`read ` of the class :cpp:class:`Mesh ` infers the mesh type from the file extension. If a non-standard file extension is used, the mesh type has to be specified. :: UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); // Reading Gmsh files mesh.read("my_gmsh_mesh.msh"); mesh.read("my_gmsh_mesh", _miot_gmsh); The Gmsh reader adds the geometrical and physical tags as mesh data. The physical values are stored as a :cpp:type:`UInt ` data called ``tag_0``, if a string name is provided it is stored as a ``std::string`` data named ``physical_names``. The geometrical tag is stored as a :cpp:type:`UInt ` data named ``tag_1``. Using Arrays ------------ Data in ``Akantu`` can be stored in data containers implemented by the :cpp:class:`akantu::Array` class. In its most basic usage, the :cpp:class:`Array ` class implemented in \akantu is similar to the ``std::vector`` class of the Standard Template Library (STL) for C++. A simple :cpp:class:`Array ` containing a sequence of ``nb_element`` values (of a given type) can be generated with:: Array example_array(nb_element); where ``type`` usually is :cpp:type:`Real `, :cpp:type:`Int `, :cpp:type:`UInt ` or ``bool``. Each value is associated to an index, so that data can be accessed by typing:: auto & val = example_array(index); ``Arrays`` can also contain tuples of values for each index. In that case, the number of components per tuple must be specified at the :cpp:class:`Array ` creation. For example, if we want to create an :cpp:class:`Array ` to store the coordinates (sequences of three values) of ten nodes, the appropriate code is the following:: UInt nb_nodes = 10; UInt spatial_dimension = 3; Array position(nb_nodes, spatial_dimension); In this case the :math:`x` position of the eighth node number will be given by ``position(7, 0)`` (in C++, numbering starts at 0 and not 1). If the number of components for the sequences is not specified, the default value of 1 is used. Here is a list of some basic operations that can be performed on :cpp:class:`Array `: - :cpp:func:`resize(size) ` change the size of the :cpp:class:`Array `. - :cpp:func:`clear ` reset the size of the :cpp:class:`Array ` to zero. (*warning* this changed in > v4.0) - :cpp:func:`set(t) ` set all entries of the :cpp:class:`Array ` to ``t``. - :cpp:func:`copy(const Array & other) ` copy another :cpp:class:`Array ` into the current one. The two :cpp:class:`Arrays ` should have the same number of components. - :cpp:func:`push_back(tuple) ` append a tuple with the correct number of components at the end of the :cpp:class:`Array `. - :cpp:func:`erase(i) ` erase the value at the i-th position. - :cpp:func:`find(value) ` search ``value`` in the current :cpp:class:`Array `. Return position index of the first occurence or -1 if not found. - :cpp:func:`storage() ` Return the address of the allocated memory of the :cpp:class:`Array `. Array iterators -------------------- +--------------- It is very common in ``Akantu`` to loop over arrays to perform a specific treatment. This ranges from geometric calculation on nodal quantities to tensor algebra (in constitutive laws for example). The :cpp:class:`Array ` object has the possibility to request iterators in order to make the writing of loops easier and enhance readability. For instance, a loop over the nodal coordinates can be performed like:: // accessing the nodal coordinates Array // with spatial_dimension components const auto & nodes = mesh.getNodes(); for (const auto & coords : make_view(nodes, spatial_dimension)) { // do what you need .... } In that example, each ``coords`` is a :cpp:class:`Vector\ ` containing geometrical array of size ``spatial_dimension`` and the iteration is conveniently performed by the :cpp:class:`Array ` iterator. The :cpp:class:`Array ` object is intensively used to store second order tensor values. In that case, it should be specified that the returned object type is a matrix when constructing the iterator. This is done when calling the :cpp:func:`make_view `. For instance, assuming that we have a :cpp:class:`Array ` storing stresses, we can loop over the stored tensors by:: for (const auto & stress : make_view(stresses, spatial_dimension, spatial_dimension)) { // stress is of type `const Matrix&` } In that last example, the :cpp:class:`Matrix\ ` objects are ``spatial_dimension`` :math:`\times` ``spatial_dimension`` matrices. The light objects :cpp:class:`Matrix\ ` and :cpp:class:`Vector\ ` can be used and combined to do most common linear algebra. If the number of component is 1, it is possible to use :cpp:func:`make_view ` to this effect. In general, a mesh consists of several kinds of elements. Consequently, the amount of data to be stored can differ for each element type. The straightforward example is the connectivity array, namely the sequences of nodes belonging to each element (linear triangular elements have fewer nodes than, say, rectangular quadratic elements etc.). A particular data structure called :cpp:class:`ElementTypeMapArray\ ` is provided to easily manage this kind of data. It consists of a group of ``Arrays``, each associated to an element type. The following code can retrieve the :cpp:class:`ElementTypeMapArray\ ` which stores the connectivity arrays for a mesh:: const ElementTypeMapArray & connectivities = mesh.getConnectivities(); Then, the specific array associated to a given element type can be obtained by:: const Array & connectivity_triangle = connectivities(_triangle_3); where the first order 3-node triangular element was used in the presented piece of code. Vector & Matrix ``````````````` The :cpp:class:`Array\ ` iterators as presented in the previous section can be shaped as :cpp:class:`Vector\ ` or :cpp:class:`Matrix\ `. This objects represent 1st and 2nd order tensors. As such they come with some functionalities that we will present a bit more into detail in this here. ``Vector`` ''''''''''''' - Accessors: - - ``v(i)`` gives the ``i`` -th component of the vector ``v`` - - ``v[i]`` gives the ``i`` -th component of the vector ``v`` - - ``v.size()`` gives the number of component + - :cpp:func:`v(i) ` gives the ``i`` -th + component of the vector ``v`` + - :cpp:func:`v[i] ` gives the ``i`` -th + component of the vector ``v`` + - :cpp:func:`v.size() ` gives the number of component - Level 1: (results are scalars) - - ``v.norm()`` returns the geometrical norm (:math:`L_2`) - - ``v.norm()`` returns the :math:`L_N` norm defined as :math:`\left(\sum_i - |v(i)|^N\right)^{1/N}`. N can take any positive integer value. - There are also some particular values for the most commonly used - norms, ``L_1`` for the Manhattan norm, ``L_2`` for the geometrical - norm and ``L_inf`` for the norm infinity. - - ``v.dot(x)`` return the dot product of ``v`` and ``x`` - - ``v.distance(x)`` return the geometrical norm of :math:`v - x` + - :cpp:func:`v.norm() ` returns the geometrical norm + (:math:`L_2`) + - :cpp:func:`v.norm\() >` returns the :math:`L_N` + norm defined as :math:`\left(\sum_i |v(i)|^N\right)^{1/N}`. N can take any + positive integer value. There are also some particular values for the most + commonly used norms, ``L_1`` for the Manhattan norm, ``L_2`` for the + geometrical norm and ``L_inf`` for the norm infinity. + - :cpp:func:`v.dot(x) ` return the dot product of + ``v`` and ``x`` + - :cpp:func:`v.distance(x) ` return the + geometrical norm of :math:`v - x` - Level 2: (results are vectors) - - ``v += s``, ``v -= s``, ``v *= s``, ``v /= s`` those are - element-wise operators that sum, substract, multiply or divide all the - component of ``v`` by the scalar ``s`` - - ``v += x``, ``v -= x`` sums or substracts the vector ``x`` to/from ``v`` - - ``v.mul(A, x, alpha)`` stores the result of :math:`\alpha \boldsymbol{A} \vec{x}` in ``v``, :math:`\alpha` is equal to 1 by default - - ``v.solve(A, b)`` stores the result of the resolution of the system - :math:`\boldsymbol{A} \vec{x} = \vec{b}` in ``v`` - - ``v.crossProduct(v1, v2)`` computes the cross product of ``v1`` and ``v2`` - and stores the result in ``v`` + - :cpp:func:`v += s `, + :cpp:func:`v -= s `, + :cpp:func:`v *= s `, + :cpp:func:`v /= s ` those are element-wise + operators that sum, substract, multiply or divide all the component of ``v`` + by the scalar ``s`` + - :cpp:func:`v += x `, :cpp:func:`v -= x + ` sums or substracts the vector ``x`` to/from + ``v`` + - :cpp:func:`v.mul(A, x, alpha) ` stores the result of + :math:`\alpha \boldsymbol{A} \vec{x}` in ``v``, :math:`\alpha` is equal to 1 + by default + - :cpp:func:`v.solve(A, b) ` stores the result of + the resolution of the system :math:`\boldsymbol{A} \vec{x} = \vec{b}` in ``v`` + - :cpp:func:`v.crossProduct(v1, v2) ` + computes the cross product of ``v1`` and ``v2`` and stores the result in + ``v`` ``Matrix`` ''''''''''''' - Accessors: - - ``A(i, j)`` gives the component :math:`A_{ij}` of the matrix ``A`` - - ``A(i)`` gives the :math:`i^{th}` column of the matrix as a ``Vector`` - - ``A[k]`` gives the :math:`k^{th}` component of the matrix, matrices are - stored in a column major way, which means that to access :math:`A_{ij}`, - :math:`k = i + j M` - - ``A.rows()`` gives the number of rows of ``A`` (:math:`M`) - - ``A.cols()`` gives the number of columns of ``A`` (:math:`N`) - - ``A.size()`` gives the number of component in the matrix (:math:`M \times - N`) + - :cpp:func:`A(i, j) ` gives the component + :math:`A_{ij}` of the matrix ``A`` + - :cpp:func:`A(i) ` gives the :math:`i^{th}` + column of the matrix as a ``Vector`` + - :cpp:func:`A[k] ` gives the :math:`k^{th}` + component of the matrix, matrices are stored in a column major way, which + means that to access :math:`A_{ij}`, :math:`k = i + j M` + - :cpp:func:`A.rows() ` gives the number of rows of + ``A`` (:math:`M`) + - :cpp:func:`A.cols() ` gives the number of columns + of ``A`` (:math:`N`) + - :cpp:func:`A.size() ` gives the number of component + in the matrix (:math:`M \times N`) - Level 1: (results are scalars) - - ``A.norm()`` is equivalent to ``A.norm()`` - - ``A.norm()`` returns the :math:`L_N` norm defined as - :math:`\left(\sum_i\sum_j |A(i,j)|^N\right)^{1/N}`. N can take - any positive integer value. There are also some particular values - for the most commonly used norms, ``L_1`` for the Manhattan - norm, ``L_2`` for the geometrical norm and ``L_inf`` for - the norm infinity. - - ``A.trace()`` return the trace of ``A`` - - ``A.det()`` return the determinant of ``A`` - - ``A.doubleDot(B)`` return the double dot product of ``A`` and - ``B``, :math:`\mat{A}:\mat{B}` + - :cpp:func:`A.norm() ` is equivalent to + ``A.norm()`` + - :cpp:func:`A.norm\() >` returns the :math:`L_N` + norm defined as :math:`\left(\sum_i\sum_j |A(i,j)|^N\right)^{1/N}`. N can take + any positive integer value. There are also some particular values for the most + commonly used norms, ``L_1`` for the Manhattan norm, ``L_2`` for the + geometrical norm and ``L_inf`` for the norm infinity. + - :cpp:func:`A.trace() ` return the trace of ``A`` + - :cpp:func:`A.det() ` return the determinant of ``A`` + - :cpp:func:`A.doubleDot(B) ` return the double + dot product of ``A`` and ``B``, :math:`\mat{A}:\mat{B}` - Level 3: (results are matrices) - - ``A.eye(s)``, ``Matrix::eye(s)`` fills/creates a matrix with - the :math:`s\mat{I}` with :math:`\mat{I}` the identity matrix - - ``A.inverse(B)`` stores :math:`\mat{B}^{-1}` in ``A`` - - ``A.transpose()`` returns :math:`\mat{A}^{t}` - - ``A.outerProduct(v1, v2)`` stores :math:`\vec{v_1} \vec{v_2}^{t}` in - ``A`` - - ``C.mul(A, B, alpha)``: stores the result of the product of - ``A`` and code{B} time the scalar ``alpha`` in ``C``. ``t_A`` - and ``t_B`` are boolean defining if ``A`` and ``B`` should be + - :cpp:func:`A.eye(s) `, ``Matrix::eye(s)`` + fills/creates a matrix with the :math:`s\mat{I}` with :math:`\mat{I}` the + identity matrix + - :cpp:func:`A.inverse(B) ` stores + :math:`\mat{B}^{-1}` in ``A`` + - :cpp:func:`A.transpose() ` returns + :math:`\mat{A}^{t}` + - :cpp:func:`A.outerProduct(v1, v2) ` stores + :math:`\vec{v_1} \vec{v_2}^{t}` in ``A`` + - :cpp:func:`C.mul\(A, B, alpha) `: stores + the result of the product of ``A`` and code{B} time the scalar ``alpha`` in + ``C``. ``t_A`` and ``t_B`` are boolean defining if ``A`` and ``B`` should be transposed or not. +----------+----------+--------------+ |``t_A`` |``t_B`` |result | | | | | +----------+----------+--------------+ |false |false |:math:`\mat{C}| | | |= \alpha | | | |\mat{A} | | | |\mat{B}` | | | | | +----------+----------+--------------+ |false |true |:math:`\mat{C}| | | |= \alpha | | | |\mat{A} | | | |\mat{B}^t` | | | | | +----------+----------+--------------+ |true |false |:math:`\mat{C}| | | |= \alpha | | | |\mat{A}^t | | | |\mat{B}` | | | | | +----------+----------+--------------+ |true |true |:math:`\mat{C}| | | |= \alpha | | | |\mat{A}^t | | | |\mat{B}^t` | +----------+----------+--------------+ - - ``A.eigs(d, V)`` this method computes the eigenvalues and eigenvectors of - ``A`` and store the results in ``d`` and ``V`` such that :math:`d(i) = - \lambda_i` and :math:`V(i) = \vec{v_i}` with :math:`\mat{A}\vec{v_i} = - \lambda_i\vec{v_i}` and :math:`\lambda_1 > ... > \lambda_i > ... > - \lambda_N` + - :cpp:func:`A.eigs(d, V) ` this method computes the + eigenvalues and eigenvectors of ``A`` and store the results in ``d`` and + ``V`` such that :math:`d(i) = \lambda_i` and :math:`V(i) = \vec{v_i}` with + :math:`\mat{A}\vec{v_i} = \lambda_i\vec{v_i}` and :math:`\lambda_1 > ... > + \lambda_i > ... > \lambda_N` + + +.. _sect-common-groups: + +Mesh +---- + + + +Manipulating group of nodes and/or elements +``````````````````````````````````````````` + +``Akantu`` provides the possibility to manipulate subgroups of elements and +nodes. Any :cpp:class:`ElementGroup ` and/or +:cpp:class:`NodeGroup ` must be managed by a +:cpp:class:`GroupManager `. Such a manager has the role to +associate group objects to names. This is a useful feature, in particular for +the application of the boundary conditions, as will be demonstrated in section +:ref:`sect-smm-boundary`. To most general group manager is the :cpp:class:`Mesh +` class which inherits from :cpp:class:`GroupManager +`. + +For instance, the following code shows how to request an element group +to a mesh: + +.. code-block:: c++ + + // request creation of a group of nodes + NodeGroup & my_node_group = mesh.createNodeGroup("my_node_group"); + // request creation of a group of elements + ElementGroup & my_element_group = mesh.createElementGroup("my_element_group"); + + /* fill and use the groups */ + + +The ``NodeGroup`` object +'''''''''''''''''''''''' + +A group of nodes is stored in :cpp:class:`NodeGroup ` +objects. They are quite simple objects which store the indexes of the selected +nodes in a :cpp:class:`Array\ `. Nodes are selected by +adding them when calling :cpp:func:`add `. For instance +you can select nodes having a positive :math:`X` coordinate with the following +code: + +.. code-block:: c++ + + const auto & nodes = mesh.getNodes(); + auto & group = mesh.createNodeGroup("XpositiveNode"); + + for (auto && data : enumerate(make_view(nodes, spatial_dimension))){ + auto node = std::get<0>(data); + const auto & position = std::get<1>(data); + if (position(0) > 0) group.add(node); + } + + +The ``ElementGroup`` object +''''''''''''''''''''''''''' + +A group of elements is stored in :cpp:class:`ElementGroup +` objects. Since a group can contain elements of various +types the :cpp:class:`ElementGroup ` object stores indexes +in a :cpp:class:`ElementTypeMapArray\ ` +object. Then elements can be added to the group by calling :cpp:func:`add +`. + +For instance, selecting the elements for which the barycenter of the +nodes has a positive :math:`X` coordinate can be made with: + +.. code-block:: c++ + + auto & group = mesh.createElementGroup("XpositiveElement"); + Vector barycenter(spatial_dimension); + + for_each_element(mesh, [&](auto && element) { + mesh.getBarycenter(element, barycenter); + if (barycenter(_x) > 0.) { group.add(element); } + }); diff --git a/doc/dev-doc/reference.rst b/doc/dev-doc/reference.rst index 20f199e39..461844223 100644 --- a/doc/dev-doc/reference.rst +++ b/doc/dev-doc/reference.rst @@ -1,114 +1,118 @@ .. _reference: Reference --------- Common `````` .. doxygenfunction:: akantu::initialize(const std::string &input_file, int &argc, char **&argv) .. doxygenfunction:: akantu::initialize(int &argc, char **&argv) .. doxygentypedef:: akantu::UInt .. doxygentypedef:: akantu::Int .. doxygentypedef:: akantu::Real .. doxygenenum:: akantu::ElementType .. doxygenenum:: akantu::ModelType .. doxygenenum:: akantu::AnalysisMethod .. doxygenenum:: akantu::SolveConvergenceCriteria .. doxygenclass:: akantu::ArrayBase .. doxygenclass:: akantu::ArrayDataLayer .. doxygenclass:: akantu::Array .. doxygenclass:: akantu::ElementTypeMapArray .. doxygenclass:: akantu::Vector .. doxygenclass:: akantu::Matrix Mesh ```` .. doxygenclass:: akantu::Mesh .. doxygenclass:: akantu::FEEngine +.. doxygenclass:: akantu::Element +.. doxygenclass:: akantu::GroupManager +.. doxygenclass:: akantu::ElementGroup +.. doxygenclass:: akantu::NodeGroup Models `````` Common ...... .. doxygenclass:: akantu::BC::Dirichlet::FixedValue .. doxygenclass:: akantu::BC::Dirichlet::FlagOnly .. doxygenclass:: akantu::BC::Dirichlet::IncrementValue .. doxygenclass:: akantu::BC::Neumann::FromStress .. doxygenclass:: akantu::BC::Neumann::FromTraction .. doxygenclass:: akantu::BoundaryCondition .. doxygenclass:: akantu::BoundaryConditionFunctor .. doxygenclass:: akantu::EventHandlerManager .. doxygenclass:: akantu::Model .. doxygenclass:: akantu::NonLocalManagerCallback Solvers ....... .. doxygenclass:: akantu::ModelSolver .. doxygenclass:: akantu::DOFManager .. doxygenclass:: akantu::NonLinearSolver .. doxygenclass:: akantu::NonLinearSolverNewtonRaphson Solid Mechanics Model ..................... .. doxygenclass:: akantu::SolidMechanicsModel .. doxygenclass:: akantu::SolidMechanicsModelOptions .. doxygenclass:: akantu::MaterialSelector .. doxygenclass:: akantu::MeshDataMaterialSelector .. doxygenclass:: akantu::Material .. doxygenclass:: akantu::InternalField Solid Mechanics Model Cohesive .............................. .. doxygenclass:: akantu::SolidMechanicsModelCohesive .. doxygenclass:: akantu::FragmentManager Heat Transfer Model ................... .. doxygenclass:: akantu::HeatTransferModel Phase Field Model ................... .. doxygenclass:: akantu::PhaseFieldModel .. doxygenclass:: akantu::PhaseField Structural Mechanics Model .......................... .. doxygenclass:: akantu::StructuralMaterial .. doxygenclass:: akantu::StructuralMechanicsModel Coupler Solid PhaseField ................... .. doxygenclass:: akantu::CouplerSolidPhaseField Synchronizers ````````````` .. doxygenclass:: akantu::DataAccessor Input/Output ```````````` .. doxygenclass:: akantu::Dumpable .. doxygenclass:: akantu::DumperIOHelper .. doxygenclass:: akantu::DumperParaview .. doxygenclass:: akantu::DumperText .. doxygenclass:: akantu::Field .. doxygenclass:: akantu::Parser .. doxygenclass:: akantu::ParserParameter .. doxygenclass:: akantu::ParserSection .. doxygenenum:: akantu::SectionType