getfem-commits
[Top][All Lists]
Advanced

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

[Getfem-commits] (no subject)


From: Konstantinos Poulios
Subject: [Getfem-commits] (no subject)
Date: Thu, 28 Jun 2018 09:42:59 -0400 (EDT)

branch: master
commit ff6fe3768eab5b0ae7393177aa779079c81ac5e5
Author: Konstantinos Poulios <address@hidden>
Date:   Thu Jun 28 15:42:44 2018 +0200

    Add phase field with elasticity example
---
 interface/tests/python/Makefile.am         |   1 +
 interface/tests/python/demo_phase_field.py | 194 +++++++++++++++++++++++++++++
 2 files changed, 195 insertions(+)

diff --git a/interface/tests/python/Makefile.am 
b/interface/tests/python/Makefile.am
index e9af543..bd3c0ba 100644
--- a/interface/tests/python/Makefile.am
+++ b/interface/tests/python/Makefile.am
@@ -35,6 +35,7 @@ EXTRA_DIST=                                           \
        demo_laplacian_DG.py                            \
        demo_laplacian_aposteriori.py                   \
        demo_mortar.py                                  \
+       demo_phase_field.py                             \
        demo_plasticity.py                              \
        demo_plate.py                                   \
        demo_static_contact.py                          \
diff --git a/interface/tests/python/demo_phase_field.py 
b/interface/tests/python/demo_phase_field.py
new file mode 100644
index 0000000..a223fd4
--- /dev/null
+++ b/interface/tests/python/demo_phase_field.py
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Python GetFEM++ interface
+#
+# Copyright (C) 2018-2018 Konstantinos Poulios.
+#
+# This file is a part of GetFEM++
+#
+# GetFEM++  is  free software;  you  can  redistribute  it  and/or modify it
+# under  the  terms  of the  GNU  Lesser General Public License as published
+# by  the  Free Software Foundation;  either version 2.1 of the License,  or
+# (at your option) any later version.
+# This program  is  distributed  in  the  hope  that it will be useful,  but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+# License for more details.
+# You  should  have received a copy of the GNU Lesser General Public License
+# along  with  this program;  if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+############################################################################
+
+import getfem as gf
+import numpy as np
+import os, sys
+
+np.set_printoptions(threshold=np.nan)
+gf.util_trace_level(1)
+
+# Input data
+NX = 60         # number of elements in horizontal direction
+NY = 60         # number of elements in verical direction
+
+LX = 1.         # [mm] Length
+LY = 1.         # [mm] Height
+
+E = 210e3       # [N/mm^2]
+nu = 0.3
+
+Gc0 = 2.7       # [N/mm]
+
+ll = 0.01       # [mm] length scale
+
+strain_rate = 2e-4
+init_time_step = 1.
+
+steps = 100
+
+#------------------------------------
+geotrans = "GT_QK(2,2)"  # geometric transformation
+disp_fem_order = 2       # displacements finite element order
+phi_fem_order = 2        # phase field finite element order
+
+integration_degree = 5   # 9 gauss points per quad
+
+#------------------------------------
+
+resultspath = "./demo_phase_field_results"
+if not os.path.exists(resultspath):
+   os.makedirs(resultspath)
+
+# auxiliary constants
+B_BOUNDARY = 4
+T_BOUNDARY = 6
+TB_BOUNDARY = 7
+
+NX_seed1 = np.linspace(-1, 0, NX/3+1)
+NX_seed2 = np.linspace(0, 1, (NX-NX/3)+1)[1:]
+NY_seed = np.linspace(-1, 1, NY+1)
+X_seed1 = 
LX/2*(0.2*NX_seed1+0.8*np.sign(NX_seed1)*np.power(np.abs(NX_seed1),1.5))
+X_seed2 = 
LX/2*(0.6*NX_seed2+0.4*np.sign(NX_seed2)*np.power(np.abs(NX_seed2),1.5))
+X_seed = np.concatenate((X_seed1,X_seed2))
+Y_seed = LY/2*(0.2*NY_seed+0.8*np.sign(NY_seed)*np.power(np.abs(NY_seed),1.5))
+mesh = gf.Mesh("cartesian", X_seed, Y_seed)
+N = mesh.dim()
+
+bottom_faces = 
mesh.outer_faces_in_box([-LX/2-1e-5,-LY/2-1e-5],[LX/2+1e-5,-LY/2+1e-5])
+top_faces = 
mesh.outer_faces_in_box([-LX/2-1e-5,LY/2-1e-5],[LX/2+1e-5,LY/2+1e-5])
+
+mesh.set_region(B_BOUNDARY, bottom_faces)
+mesh.set_region(T_BOUNDARY, top_faces)
+
+mesh.region_merge(TB_BOUNDARY, T_BOUNDARY)
+mesh.region_merge(TB_BOUNDARY, B_BOUNDARY)
+
+mesh.export_to_vtk("%s/mesh.vtk" % resultspath)
+
+# FEM
+mfu = gf.MeshFem(mesh, N)
+mfu.set_classical_fem(disp_fem_order)
+
+mfdir = mfu
+
+mfphi = gf.MeshFem(mesh, 1)
+mfphi.set_classical_fem(phi_fem_order)
+
+mfout = gf.MeshFem(mesh)
+mfout.set_classical_discontinuous_fem(2)
+
+# Integration method
+mim = gf.MeshIm(mesh, integration_degree)
+mimd1 = gf.MeshImData(mim, -1)
+
+# Model
+md = gf.Model("real")
+
+md.add_fem_variable("u", mfu)          # displacements
+md.add_fem_variable("phi", mfphi)      # phase field
+md.set_variable("phi", np.ones(mfphi.nbdof()))
+
+md.add_fem_data("u_stored", mfu)
+
+md.add_im_data("psi0_max", mimd1)
+
+md.add_initialized_data("kappa", E/(3.*(1.-2.*nu)))
+md.add_initialized_data("mu", E/(2*(1+nu)))
+
+md.add_initialized_data("Gc0", Gc0)
+md.add_initialized_data("l", ll)
+
+md.set_variable("psi0_max", 
md.interpolation("100000*min(1,max(0,1-(abs(X(2))+pos_part(X(1)))/(l/10)))", 
mimd1, -1))
+
+md.add_macro("damage", "max(1e-7,sqr(1-phi))")
+md.add_macro("psi0", 
"(0.5*kappa*sqr(Trace(Grad_u))+mu*Norm_sqr(Deviator(Sym(Grad_u))))")
+md.add_macro("Gc", "Gc0")
+
+md.add_nonlinear_term(mim, 
"damage*(kappa*Trace(Grad_u)*Id(2)+2*mu*Deviator(Sym(Grad_u))):Grad_Test_u")
+md.add_nonlinear_term(mim, 
"(-2*(1-phi)*max(psi0_max,psi0)*Test_phi+Gc*(phi/l*Test_phi+l*Grad_phi.Grad_Test_phi))")
+
+md.add_initialized_data("MM", 0)
+md.add_nonlinear_generic_assembly_brick(mim, "MM*(u-u_stored).Test_u")
+
+# Load
+md.add_fem_data("dirichlet_data", mfu);
+md.add_Dirichlet_condition_with_multipliers(mim, "u", mfdir, TB_BOUNDARY, 
"dirichlet_data")
+
+print("Displacement dofs: %i" % mfu.nbdof())
+print("Total model dofs: %i" % md.nbdof())
+
+time_step = init_time_step
+eps = 0.
+pseudodynamic = False
+MM = 0.
+for step in range(steps):
+  eps_old = eps
+  while True:
+    if step > 0:
+      eps = eps_old + strain_rate*time_step
+
+    X = md.from_variables()
+    print("Step %i with eps=%e" % (step, eps))
+    md.set_variable("dirichlet_data", 
md.interpolation("{eps}*[0;X(2)]".format(eps=eps), mfu, -1))
+    if pseudodynamic:
+      print("With damping %e" % MM)
+    md.set_variable("MM",[MM])
+
+    iters = 20
+    nit = \
+    md.solve("noisy", "lsolver", "mumps", "max_iter", iters, "max_res", 1e-7, 
#)[0]
+             "lsearch", "simplest", "alpha max ratio", 1.5, "alpha min", 0.4, 
"alpha mult", 0.6,
+              "alpha threshold res", 5e3)[0]
+    if nit >= iters:
+      if step == 0:
+        break
+      md.to_variables(X)
+      eps = eps_old
+      if time_step > init_time_step/50.:
+        time_step *= 0.5
+      else:
+        if pseudodynamic:
+          MM *= 100.
+        else:
+          pseudodynamic = True
+          MM = 10000.
+    else:
+      md.set_variable("u_stored", md.variable("u"))
+      if pseudodynamic:
+        if MM < 1e-4:
+          MM = 0.
+          pseudodynamic = False
+        else:
+          MM /= 10.
+      else:
+        TMP = md.interpolation("max(psi0_max,psi0)", mimd1, -1)
+        md.set_variable("psi0_max", TMP)
+        break
+
+  mfout.export_to_vtk("%s/demo_phase_field_%i.vtk" % (resultspath, step),
+                      mfu, md.variable("u"), "Displacements",
+                      mfphi, md.variable("phi"), "phi")
+
+
+
+



reply via email to

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