<?xml version="1.0" encoding="UTF-8"?>
<refentry version="5.0-subset Scilab" xml:id="step_by_step_example"
          xml:lang="en" xmlns="http://docbook.org/ns/docbook"
          xmlns:xlink="http://www.w3.org/1999/xlink"
          xmlns:xi="http://www.w3.org/2001/XInclude"
          xmlns:svg="http://www.w3.org/2000/svg"
          xmlns:mml="http://www.w3.org/1998/Math/MathML"
          xmlns:html="http://www.w3.org/1999/xhtml"
          xmlns:db="http://docbook.org/ns/docbook">
  <refnamediv>
    <refname>A step by step basic example</refname>

    <refpurpose>This example shows the basic usage of getfem.</refpurpose>
  </refnamediv>

  <refsection>
    <title>Description</title>

    <para>This example shows the basic usage of getfem, on the über-canonical
    problem above all others: solving the Laplacian, Δu+f=0 on a square, with
    the Dirichlet condition u=g(x) on the domain boundary.</para>

    <para>The first step is to create a mesh. Since getfem++ does not come
    with its own mesher, one has to rely on an external mesher (see
    gf_mesh('import')), or use very simple meshes. For this example, we just
    consider a regular mesh whose nodes are
    {xi=0...10,j=0..10=(i/10,j/10)}.</para>

    <programlisting role="example"><![CDATA[ 
// creation of a simple cartesian mesh
--> m = gf_mesh('cartesian',[0:.1:1],[0:.1:1])
m =
     id: 0
    cid: 0
 ]]></programlisting>

    <para>If you try to look at the value of m, you'll notice that it appears
    to be a structure containing two integers. The first one is its
    identifier, the second one is its class-id, i.e. an identifier of its
    type. This small structure is just an "handle" or "descriptor" to the real
    object, which is stored in the getfem++ memory and cannot be represented
    via Matlab data structures. Anyway, you can still inspect the getfem++
    objects via the command gf_workspace('stats').</para>

    <para>Now we can try to have a look at the mesh, with its vertices
    numbering and the convexes numbering:</para>

    <programlisting role="example"><![CDATA[
// we enable vertices and convexes labels
--> gf_plot_mesh(m, 'vertices', 'on', 'convexes', 'on');
 ]]></programlisting>

    <para>As you can see, the mesh is regular, and the numbering of its nodes
    and convexes is also regular (this is guaranteed for cartesian meshes, but
    do not hope a similar numbering for the degrees of freedom).</para>

    <para>The next step is to create a mesh_fem object. This one links a mesh
    with a set of FEM.</para>

    <programlisting role="example"><![CDATA[
--> mf = gf_mesh_fem(m,1);    // create a mesh_fem of for a field of dimension 1 (i.e. a scalar field)
--> gf_mesh_fem_set(mf,'fem',gf_fem('FEM_QK(2,2)'));
 ]]></programlisting>

    <para>The first instruction builds a new mesh_fem object, the second
    argument specifies that this object will be used to interpolate scalar
    fields (since the unknown is a scalar field). The second instruction
    assigns the Q2 FEM to every convex (each basis function is a polynomial of
    degree 4, remember that Pk =&gt; polynomials of degree k, while Qk =&gt;
    polynomials of degree 2k). As Q2 is a polynomial FEM, you can view the
    expression of its basis functions on the reference convex:</para>

    <programlisting role="example"><![CDATA[
--> gf_fem_get(gf_fem('FEM_QK(2,2)'), 'poly_str')
ans =
    '1 - 3*x - 3*y + 2*x^2 + 9*x*y + 2*y^2 - 6*x^2*y - 6*x*y^2 + 4*x^2*y^2'
    '4*x - 4*x^2 - 12*x*y + 12*x^2*y + 8*x*y^2 - 8*x^2*y^2'
    '-x + 2*x^2 + 3*x*y - 6*x^2*y - 2*x*y^2 + 4*x^2*y^2'
    '4*y - 12*x*y - 4*y^2 + 8*x^2*y + 12*x*y^2 - 8*x^2*y^2'
    '16*x*y - 16*x^2*y - 16*x*y^2 + 16*x^2*y^2'
    '-4*x*y + 8*x^2*y + 4*x*y^2 - 8*x^2*y^2'
    '-y + 3*x*y + 2*y^2 - 2*x^2*y - 6*x*y^2 + 4*x^2*y^2'
    '-4*x*y + 4*x^2*y + 8*x*y^2 - 8*x^2*y^2'
    'x*y - 2*x^2*y - 2*x*y^2 + 4*x^2*y^2'
 ]]></programlisting>

    <para>Now, in order to perform numerical integrations on mf, we need to
    build a mesh_im object:</para>

    <programlisting role="example"><![CDATA[
// assign the same integration method on all convexes 
--> mim=gf_mesh_im(m, gf_integ('IM_EXACT_PARALLELEPIPED(2)'));
  ]]></programlisting>

    <para>The integration method will be used to compute the various integrals
    on each element: here we choose to perform exact computations (no
    quadrature formula), which is possible since the geometric transformation
    of these convexes from the reference convex is linear (this is true for
    all simplices, and this is also true for the parallelepipeds of our
    regular mesh, but it is not true for general quadrangles), and the chosen
    FEM is polynomial. Hence it is possible to analytically integrate every
    basis function/product of basis functions/gradients/etc. There are many
    alternative FEM methods and integration methods (see the description of
    finite element and integration methods).</para>

    <para>Note however that in the general case, approximate integration
    methods are a better choice than exact integration methods.</para>

    <para>Now we have to find the "boundary" of the domain, in order to set a
    condition. A mesh object has the ability to store some sets of convexes
    and convex faces. These sets (called "regions") are accessed via an
    integer #id:</para>

    <programlisting role="example"><![CDATA[
--> border = gf_mesh_get(m,'outer faces');
--> gf_mesh_set(m, 'region', 42, border); // create the region #42
--> gf_plot_mesh(m, 'regions', [42]); // the boundary edges appears in red
  ]]></programlisting>

    <para>Here we find the faces of the convexes which are on the boundary of
    the mesh (i.e. the faces which are not shared by two convexes). remark: we
    could have used gf_mesh_get(m, 'OuTEr_faCes') , as the interface is
    case-insensitive, and whitespaces can be replaced by underscores. The
    array border has two rows, on the first row is a convex number, on the
    second row is a face number (which is local to the convex, there is no
    global numbering of faces). Then this set of faces is assigned to the
    region number 42.</para>

    <para>At this point, we just have to stack some model bricks and run the
    solver to get the solution! The "model bricks" are created with the
    gf_mdbrick constructor. A model brick is basically an object which
    modifies a global linear system (tangent matrix for non-linear problems)
    and its associated right hand side. Typical modifications are insertion of
    the stiffness matrix for the problem considered (linear elasticity,
    laplacian, etc), handling of a set of contraints, Dirichlet condition,
    addition of a source term to the right hand side etc. The global tangent
    matrix and its right hand side are stored in a "model state" structure,
    created with the gf_mdstate constructor.</para>

    <para>Let us build a problem with an easy solution: 
    <latex style="text"><![CDATA[u=x\left(x-1\right)y\left(y-1\right)+x^{5}]]></latex>, then we have 
    <latex style="text"><![CDATA[\Delta u=2\left(x^{2}+y^{2}\right)-2\left(x+y\right)+20y^{3}]]></latex>
    (the FEM won't be able to catch the exact solution since we use a Q2 method).</para>

    <para>We start with a "generic elliptic" brick, which handles
    <latex style="text"><![CDATA[-\text{div}\left(A\nabla u\right)=\cdots]]></latex>
    problems, where A can be a scalar field, a matrix field, or an order 4 tensor field. By default, A=1.</para>

    <programlisting role="example"><![CDATA[ 
--> b0=gf_mdbrick('generic elliptic',mim,mf)
  ]]></programlisting>

    <para>Each brick embeds a number of parameter fields. In the case of the
    generic elliptic brick, there is only one parameter field, the A(x)
    coefficient in <latex style="text"><![CDATA[-\text{div}\left(A\nabla u\right)=\cdots]]></latex>.
    It is possible to view the list of parameters of the brick with</para>

    <programlisting role="example"><![CDATA[ 
--> gf_mdbrick_get(b0, 'param list')
ans =

    'A'
--> gf_mdbrick_get(b0, 'param', 'A')

ans =

     1
 ]]></programlisting>

    <para>Next we add a Dirichlet condition on the domain boundary:</para>

    <programlisting role="example"><![CDATA[
--> b1=gf_mdbrick('dirichlet',b0,42,mf,'penalized')
  ]]></programlisting>

    <para>Here the number 42 is the region number to which the dirichlet
    condition is applied. The 'penalized' says that the Dirichlet condition
    should be imposed via a penalization technique. Other ways are possible
    (augmented system, direct elimination). A mesh fem argument is also
    required, as the Dirichlet condition u=r is imposed in a weak form </para>

    <para><latex align="center"><![CDATA[\int u\left(x\right)\nu\left(x\right)=\int r\left(x\right)\nu\left(x\right)\,\forall\nu]]></latex></para>

    <para>where v is taken in the space of multipliers given by here by
    mf.</para>

    <para>By default, the Dirichlet brick imposes u=0 on the specified
    boundary. We change this to <latex style="text"><![CDATA[u=\left(x-0.5\right)^{2}+\left(y-0.5\right)^{2}+x/5-y/3]]></latex>:</para>

    <programlisting role="example"><![CDATA[ 
--> R=gf_mesh_fem_get(mf, 'eval', list('(x-.5).^2 + (y-.5).^2 + x/5 - y/3'));
--> gf_mdbrick_set(b1, 'param', 'R', mf, R); 
  ]]></programlisting>

    <para>Remark: the polynomial expression was interpolated on mf. It is
    possible only if mf is of Lagrange type. In this first example we use the
    same mesh fem for the unknown and for the data such as R, but in the
    general case, mf won't be Lagrangian and another (Lagrangian) mesh fem
    will be used for the description of Dirichlet conditions, source terms
    etc.</para>

    <para>A "model state" variable is created, and the solver is
    launched:</para>

    <programlisting role="example"><![CDATA[
--> mds=gf_mdstate('real')
--> gf_mdbrick_get(b1, 'solve', mds)
 ]]></programlisting>

    <para>The model state now contains the solution (as well as other things,
    such as the linear system which was solved). It is extracted, a display
    into a matlab figure.</para>

    <programlisting role="example"><![CDATA[
--> U=gf_mdstate_get(mds, 'state');
--> gf_plot(mf, U, 'mesh','on');
 ]]></programlisting>
  </refsection>

  <refsection>
    <title>See Also</title>

    <simplelist type="inline">
      <member><link linkend="gf_workspace">gf_workspace</link></member>

      <member><link linkend="gf_mesh">gf_mesh</link></member>

      <member><link linkend="gf_fem">gf_fem</link></member>

      <member><link linkend="gf_plot">gf_plot</link></member>
    </simplelist>
  </refsection>

  <refsection>
    <title>Authors</title>

    <para>Y. Collette</para>
  </refsection>
</refentry>
