getfem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Getfem-commits] (no subject)


From: Tetsuo Koyama
Subject: [Getfem-commits] (no subject)
Date: Sun, 3 Nov 2019 03:01:21 -0500 (EST)

branch: devel-tetsuo-hht_method
commit 84d2b7b37b1d529433b7226bd6fe709ad995c5f5
Author: Tetsuo Koyama <address@hidden>
Date:   Sun Nov 3 14:21:13 2019 +0900

    :package: ADD HHT scheme
---
 .../source/userdoc/model_time_integration.rst      |  13 +-
 interface/src/gf_model_set.cc                      |  17 ++-
 interface/tests/python/demo_wave_equation.py       |  21 ++-
 src/getfem/getfem_models.h                         |   3 +
 src/getfem_models.cc                               | 151 ++++++++++++++++++++-
 5 files changed, 195 insertions(+), 10 deletions(-)

diff --git a/doc/sphinx/source/userdoc/model_time_integration.rst 
b/doc/sphinx/source/userdoc/model_time_integration.rst
index 5180564..d0213ca 100644
--- a/doc/sphinx/source/userdoc/model_time_integration.rst
+++ b/doc/sphinx/source/userdoc/model_time_integration.rst
@@ -265,7 +265,7 @@ For a problem which reads
 
 .. math::
 
-  \left(\left(1+\alpha\right)K+\left(1+\alpha\right)\dfrac{\gamma}{\beta\Delta 
t}C+\dfrac{1}{\beta\Delta 
t^{2}}M\right)U^{n}=F^{n}+M\left(\left(\dfrac{1}{2\beta}-1\right)A^{n-1}+\dfrac{1}{\beta\Delta
 t}V^{n-1}+\dfrac{1}{\beta\Delta 
t^{2}}U^{n-1}\right)+\left(1+\alpha\right)C\left[\left(\dfrac{\gamma}{2\beta}-1\right)\Delta
 
tA^{n-1}+\left(\dfrac{\gamma}{\beta}-1\right)V^{n-1}+\dfrac{\gamma}{\beta\Delta 
t}U^{n-1}\right]+\alpha KU^{n-1}+\alpha CV^{n-1}
+  \left(\left(1+\alpha\right)K+\left(1+\alpha\right)\dfrac{\gamma}{\beta\Delta 
t}C+\dfrac{1}{\beta\Delta 
t^{2}}M\right)U^{t}=F^{t+\alpha*dt}+M\left(\left(\dfrac{1}{2\beta}-1\right)A^{t-dt}+\dfrac{1}{\beta\Delta
 t}V^{t-dt}+\dfrac{1}{\beta\Delta 
t^{2}}U^{t-dt}\right)+\left(1+\alpha\right)C\left[\left(\dfrac{\gamma}{2\beta}-1\right)\Delta
 
tA^{t-dt}+\left(\dfrac{\gamma}{\beta}-1\right)V^{t-dt}+\dfrac{\gamma}{\beta\Delta
 t}U^{t-dt}\right]+\alpha KU^{t-dt}+\alpha CV^{t-dt}
 
 where :math:`dt` means a time step, :math:`M` the matrix in term of "Dot2_u", 
:math:`C` the matrix in term of "Dot_u" and :math:`K` the matrix in term of "u".
 
@@ -286,7 +286,7 @@ The following data are also added::
 
 which correspond to the values of "u", "Dot_u"  and "Dot2_u" at the previous 
time step.
 
-Before the first solve, the data  "Previous_u" and "Previous_Dot_u" 
(corresponding to :math:`U^0` in the example) have to be initialized. The data 
"Previous_Dot2_u" is to be given or precomputed (see 
:ref:`precomp_time_der_section` and except for :math:`\alpha = 0, \beta = 1/2, 
\gamma = 1`).
+Before the first solve, the data  "Previous_u" and "Previous_Dot_u" 
(corresponding to :math:`U^0` in the example) have to be initialized. The data 
"Previous_Dot2_u" is to be given or precomputed (see 
:ref:`precomp_time_der_section` and except for :math:`\beta = 1/2, \gamma = 1`).
 
 
 The addition of this scheme to a variable is to be done thanks to::
@@ -294,6 +294,15 @@ The addition of this scheme to a variable is to be done 
thanks to::
   add_Hilber_Hughes_Taylor_scheme(model &md, const std::string &varname,
                                   scalar_type alpha, scalar_type beta, 
scalar_type gamma);
 
+.. warning::
+  You have to set exact time of external force :math:`F^{t+\alpha*dt}` when 
you use this scheme.
+
+such as::
+
+  // Volumic source term.
+  getfem::add_source_term_generic_assembly_brick(model, mim, 
"sin(t+alpha*dt)*Test_u");
+
+
 Transient terms
 ***************
 
diff --git a/interface/src/gf_model_set.cc b/interface/src/gf_model_set.cc
index 8f1ad05..711a65b 100644
--- a/interface/src/gf_model_set.cc
+++ b/interface/src/gf_model_set.cc
@@ -2860,7 +2860,7 @@ void gf_model_set(getfemint::mexargs_in& m_in,
        );
 
     /*@SET ('add Newmark scheme', @str varname, @scalar beta, @scalar gamma)
-      Attach a theta method for the time discretization of the variable
+      Attach a Newmark method for the time discretization of the variable
       `varname`. Valid only if there is at most second order time derivative
       of the variable. @*/
     sub_command
@@ -2871,7 +2871,7 @@ void gf_model_set(getfemint::mexargs_in& m_in,
        getfem::add_Newmark_scheme(*md, varname, beta, gamma);
        );
 
-    /*@SET ('add_Houbolt_scheme', @str varname)
+    /*@SET ('add Houbolt scheme', @str varname)
       Attach a Houbolt method for the time discretization of the variable
       `varname`. Valid only if there is at most second order time derivative
       of the variable  @*/
@@ -2881,6 +2881,19 @@ void gf_model_set(getfemint::mexargs_in& m_in,
        getfem::add_Houbolt_scheme(*md, varname);
        );
 
+    /*@SET ('add Hilber Hughes Taylor scheme', @str varname, @scalar alpha, 
@scalar beta, @scalar gamma)
+      Attach a Hilber Hughes Taylor method for the time discretization of the 
variable
+      `varname`. Valid only if there is at most second order time derivative
+      of the variable. @*/
+    sub_command
+      ("add Hilber Hughes Taylor scheme", 4, 4, 0, 0,
+       std::string varname = in.pop().to_string();
+       double alpha = in.pop().to_scalar();
+       double beta = in.pop().to_scalar();
+       double gamma = in.pop().to_scalar();
+       getfem::add_Hilber_Hughes_Taylor_scheme(*md, varname, alpha, beta, 
gamma);
+       );
+
      /*@SET ('disable bricks', @ivec bricks_indices)
        Disable a brick (the brick will no longer participate to the
        building of the tangent linear system).@*/
diff --git a/interface/tests/python/demo_wave_equation.py 
b/interface/tests/python/demo_wave_equation.py
index a56505e..eaf2c28 100644
--- a/interface/tests/python/demo_wave_equation.py
+++ b/interface/tests/python/demo_wave_equation.py
@@ -27,9 +27,9 @@
   also a good example of use of GetFEM++.
 
 """
+import os
 import numpy as np
 import getfem as gf
-import os
 
 NX = 10
 m = gf.Mesh('cartesian', np.arange(0., 1.+1./NX,1./NX),
@@ -70,6 +70,7 @@ T = 5.0;
 # Set dt smaller to fix Newmark and Houbolt method.
 # dt = 0.001;
 dt = 0.025;
+alpha = 0.00;
 beta = 0.25;
 gamma = 0.5;
 
@@ -78,6 +79,7 @@ md.add_Houbolt_scheme('u1')
 md.add_Hilber_Hughes_Taylor_scheme('u2', alpha, beta, gamma)
 md.add_mass_brick(mim, 'Dot2_u')
 md.add_mass_brick(mim, 'Dot2_u1')
+md.add_mass_brick(mim, 'Dot2_u2')
 md.set_time_step(dt)
 
 ## Initial data.
@@ -86,6 +88,8 @@ md.set_variable('Previous_Dot_u',  V0)
 md.set_variable('Previous_u1', U0)
 md.set_variable('Previous2_u1', U0)
 md.set_variable('Previous3_u1', U0)
+md.set_variable('Previous_u2', U0)
+md.set_variable('Previous_Dot_u', V0)
 
 ## Initialisation of the acceleration 'Previous_Dot2_u'
 md.perform_init_time_derivative(dt/2.)
@@ -93,7 +97,6 @@ md.solve()
 
 A0 = md.variable('Previous_Dot2_u')
 
-
 os.system('mkdir results');
 mf.export_to_vtk('results/displacement_0.vtk', U0)
 mf.export_to_vtk('results/velocity_0.vtk', V0)
@@ -106,6 +109,13 @@ mf.export_to_vtk('results1/displacement_0.vtk', U0)
 mf.export_to_vtk('results1/velocity_0.vtk', V0)
 mf.export_to_vtk('results1/acceleration_0.vtk', A0)
 
+A0 = md.variable('Previous_Dot2_u2')
+
+os.system('mkdir results2');
+mf.export_to_vtk('results2/displacement_0.vtk', U0)
+mf.export_to_vtk('results2/velocity_0.vtk', V0)
+mf.export_to_vtk('results2/acceleration_0.vtk', A0)
+
 ## Iterations
 n = 1;
 for t in np.arange(0.,T,dt):
@@ -127,6 +137,13 @@ for t in np.arange(0.,T,dt):
   mf.export_to_vtk('results1/velocity_%d.vtk' % n, V)
   mf.export_to_vtk('results1/acceleration_%d.vtk' % n, A)
 
+  U = md.variable('u2')
+  V = md.variable('Dot_u2')
+  A = md.variable('Dot2_u2')
+  mf.export_to_vtk('results2/displacement_%d.vtk' % n, U)
+  mf.export_to_vtk('results2/velocity_%d.vtk' % n, V)
+  mf.export_to_vtk('results2/acceleration_%d.vtk' % n, A)
+
   n += 1
   md.shift_variables_for_time_integration()
   
diff --git a/src/getfem/getfem_models.h b/src/getfem/getfem_models.h
index 0d72462..370fe84 100644
--- a/src/getfem/getfem_models.h
+++ b/src/getfem/getfem_models.h
@@ -1182,6 +1182,9 @@ namespace getfem {
 
   void add_Houbolt_scheme(model &md, const std::string &varname);
 
+  void add_Hilber_Hughes_Taylor_scheme(model &md, const std::string &varname,
+                                       scalar_type alpha, scalar_type beta,
+                                       scalar_type gamma);
 
 
   //=========================================================================
diff --git a/src/getfem_models.cc b/src/getfem_models.cc
index 8f6a42a..f17b904 100644
--- a/src/getfem_models.cc
+++ b/src/getfem_models.cc
@@ -1395,8 +1395,8 @@ namespace getfem {
       scalar_type beta, gamma;
 
     public:
-      // V = (U-U0)/(theta*dt) - dt*(1-theta)*V0
-      // A = (U-U0)/(theta^2*dt^2) - V0/(theta^2*dt) - dt*(1-theta)*A0
+      // V = (1-gamma/beta)*V0+(1-gamma/(2*beta))*dt*A0+gamma/(beta*dt)*(U-U0)
+      // A = (1-1/(2.0*beta))*A0-1/(beta*dt)*V0+1/(beta*dt*dt)*(U-U0)
       virtual void init_affine_dependent_variables(model &md) const {
         scalar_type dt = md.get_time_step();
         scalar_type a0 = scalar_type(1)/(beta*dt*dt), a1 =  dt*a0;
@@ -1429,7 +1429,6 @@ namespace getfem {
                    md.set_real_constant_part(A));
           gmm::add(gmm::scaled(md.real_variable(A0), -a2),
                    md.set_real_constant_part(A));
-
         }
       }
 
@@ -1513,7 +1512,6 @@ namespace getfem {
         }
       }
 
-
     };
 
   void add_Newmark_scheme(model &md, const std::string &varname,
@@ -1636,7 +1634,152 @@ namespace getfem {
     md.add_time_integration_scheme(varname, ptsc);
   }
 
+  // ----------------------------------------------------------------------
+  //
+  // Hilber Hughes Taylor (HHT) method
+  //
+  // ----------------------------------------------------------------------
+
+    class APIDECL Hilber_Hughes_Taylor_scheme
+      : public virtual_time_scheme {
+
+      std::string U, U0, V, V0, A, A0;
+      scalar_type alpha, beta, gamma;
 
+    public:
+      // V = (1-gamma/beta)*V0+(1-gamma/(2*beta))*dt*A0+gamma/(beta*dt)*(U-U0)
+      // A = (1-1/(2.0*beta))*A0-1/(beta*dt)*V0+1/(beta*dt*dt)*(U-U0)
+      virtual void init_affine_dependent_variables(model &md) const {
+        scalar_type dt = md.get_time_step();
+        scalar_type a0 = scalar_type(1)/(beta*dt*dt), a1 =  dt*a0;
+        scalar_type a2 = (scalar_type(1) - scalar_type(2)*beta)
+          / (scalar_type(2)*beta);
+        scalar_type b0 = (scalar_type(1)+alpha)*gamma/(beta*dt);
+        scalar_type b1 = (scalar_type(1)+alpha)*(beta-gamma)/beta - alpha;
+        scalar_type b2 = 
(scalar_type(1)+alpha)*dt*(1-gamma/(scalar_type(2)*beta));
+        scalar_type c0 = (scalar_type(1)+alpha);
+        scalar_type c1 = alpha;
+
+        md.set_factor_of_variable(U, c0);
+        md.set_factor_of_variable(V, b0);
+        md.set_factor_of_variable(A, a0);
+        if (md.is_complex()) {
+          gmm::copy(gmm::scaled(md.complex_variable(U0), complex_type(c1)),
+                   md.set_complex_constant_part(U));
+          gmm::add(gmm::scaled(md.complex_variable(U0), -complex_type(b0)),
+                   gmm::scaled(md.complex_variable(V0), complex_type(b1)),
+                   md.set_complex_constant_part(V));
+          gmm::add(gmm::scaled(md.complex_variable(A0), complex_type(b2)),
+                   md.set_complex_constant_part(V));
+          gmm::add(gmm::scaled(md.complex_variable(U0), -complex_type(a0)),
+                   gmm::scaled(md.complex_variable(V0), -complex_type(a1)),
+                   md.set_complex_constant_part(A));
+          gmm::add(gmm::scaled(md.complex_variable(A0), -complex_type(a2)),
+                   md.set_complex_constant_part(A));
+        } else {
+          gmm::add(gmm::scaled(md.real_variable(U0), -b0),
+                   gmm::scaled(md.real_variable(V0), b1),
+                   md.set_real_constant_part(V));
+          gmm::add(gmm::scaled(md.real_variable(A0), b2),
+                   md.set_real_constant_part(V));
+          gmm::add(gmm::scaled(md.real_variable(U0), -a0),
+                   gmm::scaled(md.real_variable(V0), -a1),
+                   md.set_real_constant_part(A));
+          gmm::add(gmm::scaled(md.real_variable(A0), -a2),
+                   md.set_real_constant_part(A));
+        }
+      }
+
+      // V = (U-U0)/dt (backward Euler for precomputation)
+      // A = (U-U0)/(dt^2) - V0/dt
+      virtual void init_affine_dependent_variables_precomputation(model &md)
+        const {
+        scalar_type dt = md.get_time_step();
+        md.set_factor_of_variable(V, scalar_type(1)/dt);
+        md.set_factor_of_variable(A, scalar_type(1)/(dt*dt));
+        if (md.is_complex()) {
+          gmm::copy(gmm::scaled(md.complex_variable(U0),
+                                -complex_type(1)/dt),
+                    md.set_complex_constant_part(V));
+          gmm::add(gmm::scaled(md.complex_variable(U0),
+                               -complex_type(1)/(dt*dt)),
+                   gmm::scaled(md.complex_variable(V0),
+                               -complex_type(1)/dt),
+                   md.set_complex_constant_part(A));
+        } else {
+          gmm::copy(gmm::scaled(md.real_variable(U0),
+                                -scalar_type(1)/dt),
+                    md.set_real_constant_part(V));
+          gmm::add(gmm::scaled(md.real_variable(U0),
+                               -scalar_type(1)/(dt*dt)),
+                   gmm::scaled(md.real_variable(V0),
+                               -scalar_type(1)/dt),
+                   md.set_real_constant_part(A));
+        }
+      }
+
+      virtual void time_derivative_to_be_initialized
+      (std::string &name_v, std::string &name_previous_v) const {
+        if (beta != scalar_type(0.5) || gamma != scalar_type(1))
+          { name_v = A; name_previous_v = A0; }
+      }
+
+      virtual void shift_variables(model &md) const {
+        if (md.is_complex()) {
+          gmm::copy(md.complex_variable(U), md.set_complex_variable(U0));
+          gmm::copy(md.complex_variable(V), md.set_complex_variable(V0));
+          gmm::copy(md.complex_variable(A), md.set_complex_variable(A0));
+        } else {
+          gmm::copy(md.real_variable(U), md.set_real_variable(U0));
+          gmm::copy(md.real_variable(V), md.set_real_variable(V0));
+          gmm::copy(md.real_variable(A), md.set_real_variable(A0));
+        }
+      }
+
+      Hilber_Hughes_Taylor_scheme(model &md, std::string varname,
+                                  scalar_type al, scalar_type be,
+                                  scalar_type ga) {
+        U = varname;
+        U0 = "Previous_" + U;
+        V = "Dot_" + U;
+        V0 = "Previous_Dot_" + U;
+        A = "Dot2_" + U;
+        A0 = "Previous_Dot2_" + U;
+        alpha = al; beta = be; gamma = ga;
+        GMM_ASSERT1(alpha >= -scalar_type(1) && alpha <= scalar_type(0)
+                    && beta > scalar_type(0) && beta <= scalar_type(1)
+                    && gamma >= scalar_type(0.5) && gamma <= scalar_type(1),
+                    "Invalid parameter values for the Hilber Hughes Taylor 
scheme");
+
+        if (!(md.variable_exists(V)))
+          md.add_affine_dependent_variable(V, U);
+        if (!(md.variable_exists(A)))
+          md.add_affine_dependent_variable(A, U);
+
+        const mesh_fem *mf = md.pmesh_fem_of_variable(U);
+        size_type s = md.is_complex() ? gmm::vect_size(md.complex_variable(U))
+          : gmm::vect_size(md.real_variable(U));
+
+        if (mf) {
+          if (!(md.variable_exists(U0))) md.add_fem_data(U0, *mf);
+          if (!(md.variable_exists(V0))) md.add_fem_data(V0, *mf);
+          if (!(md.variable_exists(A0))) md.add_fem_data(A0, *mf);
+        } else {
+          if (!(md.variable_exists(U0))) md.add_fixed_size_data(U0, s);
+          if (!(md.variable_exists(V0))) md.add_fixed_size_data(V0, s);
+          if (!(md.variable_exists(A0))) md.add_fixed_size_data(A0, s);
+        }
+      }
+
+    };
+
+  void add_Hilber_Hughes_Taylor_scheme(model &md, const std::string &varname,
+                                       scalar_type alpha, scalar_type beta,
+                                       scalar_type gamma) {
+    ptime_scheme ptsc = std::make_shared<Hilber_Hughes_Taylor_scheme>
+      (md, varname, alpha, beta, gamma);
+    md.add_time_integration_scheme(varname, ptsc);
+  }
 
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]