Hello Yves,
Than you very much for the reply. I thought and tried that rg1 and rg2
should be boundary numbers as you explained (and in the documents). Just
in case, I am attaching my code with a comment to highlight the line
issues an error. It is line number 200. Let me know if there is anything
unclear about this revised code.
Best regards,
Hojae
On 12/23/2016 2:43 PM, Yves Renard wrote:
Dear Hojae,
The best is that you send the lines of your code that are not working.
rg1 and rg2 are boundary numbers so that they should be some integers.
Yves.
----- Original Message -----
From: "Hojae Yi" <[email protected]>
To: "getfem-users" <[email protected]>
Sent: Thursday, December 22, 2016 8:25:34 PM
Subject: [Getfem-users] nodal contact problem
Hello,
First of all, thank you so much for a great FEA package!
I am currently using GetFEM 5.1 using Python. I have been toying with
provided 'demo_wheel_contact.py' and trying to apply
add_nodal_contact_between_nonmatching_meshes_brick using two contact
surfaces. However, when I run, it complains that rg1 (and rg2) should be
a string. Python Interface reference explains that rg1 and rg2 as
integers while User Document explains them as vectors.
Can someone kindly point me where I can find further information on how
these rg1 and rg2 should be defined? Let me know if any further details
are needed.
Thank you very much!
Hojae
_______________________________________________
Getfem-users mailing list
[email protected]
https://mail.gna.org/listinfo/getfem-users
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Python GetFEM++ interface
#
# Copyright (C) 2015-2015 Yves Renard.
#
# 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 3 of the License, or
# (at your option) any later version along with the GCC Runtime Library
# Exception either version 3.1 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 and GCC Runtime Library Exception 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.
#
############################################################################
#
# Contact of a deformable 'wheel' onto a plane deformable obstacle.
#
############################################################################
import getfem as gf
import numpy as np
gf.util('trace level', 3) # No trace for mesh generation nor for assembly
export_mesh = False;
Dirichlet_version = False; #True # Use a dirichlet condition instead of a
global load
#
# Physical parameters
#
#E = 2.1E5 # Young's Modulus (N/m^2)
approximately 30 psi
E = 2.1E10 # Young's Modulus (N/m^2)
approximately 30 psi + rubber (0.01 ~ 0.1 GPa)
nu = 0.3 # Poisson ratio
clambda = E*nu/((1+nu)*(1-2*nu)) # First Lame coefficient
(N/m^2)
cmu = E/(2*(1+nu)) # Second Lame coefficient
(N/m^2)
clambdastar = 2*clambda*cmu/(clambda+2*cmu) # Lame coefficient for
Plane stress
applied_force = 9.8E4 # Force at the hole
boundary (N) approximately 0.1 ton
E_f = 17.E9 # Concrete
nu_f = 0.15 # Poisson's ratio for the
foundation
clambda_f = E_f*nu_f/((1+nu_f)*(1-2*nu_f)) # First Lame coefficient
(N/m^2)
cmu_f = E_f/(2*(1+nu_f)) # Second Lame coefficient
(N/m^2)
clambdastar_f = 2*clambda_f*cmu_f/(clambda_f+2*cmu_f) # Lame coefficient for
Plane stress
friction_coeff = 0.4 ## coefficient of friction
#
# Numerical parameters
#
r = 5.0 # Augmentation Parameter
h = 0.05 # Approximate mesh size
elements_degree = 2 # Degree of the finite element methods
gamma0 = 1./E; # Augmentation parameter for the augmented Lagrangian
version = 1 # 1 : frictionless contact and the basic contact brick
# 2 : contact with 'static' Coulomb friction and basic contact
brick
#
# Mesh generation. Meshes can also been imported from several formats.
#
## set up base geometries
mo1 = gf.MesherObject('ball', [0., 1.5], 1.5) ## wheel's outer surface; 'ball',
vec center, scalar radius
mo2 = gf.MesherObject('ball', [0., 1.5], 0.8) ## wheel's inner surface;
mo3 = gf.MesherObject('set minus', mo1, mo2) ## whell with hole at the center
dimension = 2 ## Dimension of the problem
print ('Meshes are being generated...')
## wheel
mesh1 = gf.Mesh('generate', mo3, h, 2)
## bottom foundation
mesh2_length = 3
mesh2_height = 1
mesh2 =
gf.Mesh('import','structured','GT="GT_PK(2,1)";SIZES=[%d,%d];NOISED=0;NSUBDIV=[%d,%d];'
% (mesh2_length,mesh2_height,int(mesh2_length/h)+1, int(mesh2_height/h)+1));
## move mesh2's origion to [-1.5, -1.0] to align with the wheel center with the
foundation
mesh2.translate([-1.5,-1.0])
if (export_mesh):
mesh1.export_to_vtk('mesh1.vtk')
mesh2.export_to_vtk('mesh2.vtk')
print ('\nYou can view the meshes for instance with')
print ('mayavi2 -d mesh1.vtk -f ExtractEdges -m Surface -d mesh2.vtk -f
ExtractEdges -m Surface \n')
#
# Boundary selection
#
fb1 = mesh1.outer_faces_in_box([-0.81, 0.69], [0.81, 2.31]) # Boundary of the
inner hole
fb2 = mesh1.outer_faces_with_direction([0., -1.], np.pi/4) # Contact boundary
of the wheel ## increased contact boundary
fb3 = mesh2.outer_faces_with_direction([0., -1.], 0.01) # Bottom boundary of
the foundation; faces of bottom horizontal line
fb4 = mesh2.outer_faces_with_direction([0., 1.], np.pi/4) # Contact boundary of
the foundation
## define boundary region numbers
HOLE_BOUND=1; CONTACT_BOUND_WHEEL=2; BOTTOM_BOUND=3; CONTACT_BOUND_FND = 4
mesh1.set_region(HOLE_BOUND, fb1)
mesh1.set_region(CONTACT_BOUND_WHEEL, fb2)
mesh1.region_subtract(CONTACT_BOUND_WHEEL, HOLE_BOUND)
mesh2.set_region(BOTTOM_BOUND, fb3)
mesh2.set_region(CONTACT_BOUND_FND, fb4)
#
# Definition of finite elements methods and integration method
#
mfu1 = gf.MeshFem(mesh1, 2) ## on Mesh1 (wheel), qdim=2 for a vector field of
size 2
mfu1.set_classical_fem(elements_degree) ## fem with order of 'elements_degree'=2
mfu2 = gf.MeshFem(mesh2, 2)
mfu2.set_classical_fem(elements_degree)
mflambda = gf.MeshFem(mesh1, 2) ##
mflambda.set_classical_fem(elements_degree-1) ## fem of order 1 =
elements_degree - 1
mflambda_C = gf.MeshFem(mesh1, 1) ## on Mesh 1 (wheel), qdim=2 for a scalar
field
mflambda_C.set_classical_fem(elements_degree-1)
mfvm1 = gf.MeshFem(mesh1, 1) ## on mesh1 (wheel), qdim = 1 for a scalar field
mfvm1.set_classical_discontinuous_fem(elements_degree)
mfvm2 = gf.MeshFem(mesh2, 1) ## on mesh2 (foundation), qdim = 2 for a scalar
field
mfvm2.set_classical_discontinuous_fem(elements_degree)
## mim1, mim2 are two integration methods on the wheel and the foundation
mim1 = gf.MeshIm(mesh1, 4)
mim1c = gf.MeshIm(mesh1, gf.Integ('IM_STRUCTURED_COMPOSITE(IM_TRIANGLE(4),2)'))
mim2 = gf.MeshIm(mesh2, 4)
## various mesh descriptors
cdof_wheel = mfu1.dof_on_region(CONTACT_BOUND_WHEEL)
cdof_fnd = mfu2.dof_on_region(CONTACT_BOUND_FND)
nbc_wheel = cdof_wheel.shape[0] / dimension
nbc_fnd = cdof_fnd.shape[0] / dimension
nbdofu1 = mfu1.nbdof()
nbdofu2 = mfu2.nbdof()
#
# Model definition
#
md=gf.Model('real');
md.add_fem_variable('u1', mfu1) # Displacement of the structure 1; wheel
md.add_fem_variable('u2', mfu2) # Displacement of the structure 2;
foundation
md.add_initialized_data('cmu', [cmu]) ## First Lame Coefficient for wheel
md.add_initialized_data('clambda', [clambda]) ## Second Lame Coefficient for
wheel
md.add_initialized_data('clambdastar', [clambdastar]) ## Second Lame
Coefficient for wheel with plane strain
md.add_initialized_data('cmu_f', [cmu_f]) ## First Lame Coefficient for
foundation
md.add_initialized_data('clambda_f', [clambda_f]) ## Second Lame Coefficient
for foundation
md.add_initialized_data('clambdastar_f', [clambdastar_f]) ## Second Lame
Coefficient for foundation for plane strain
md.add_isotropic_linearized_elasticity_brick(mim1, 'u1', 'clambda', 'cmu') ##
Linear Elasticity using Lame constants on MeshIm (mim1) and a fem variable
('u1')
md.add_isotropic_linearized_elasticity_brick(mim2, 'u2', 'clambda_f', 'cmu_f')
## Linear Elasticity using Lame constants on MeshIm (mim1) and a fem variable
('u1') for plane strain case
bottom_bv = mfu2.eval('[0,0]') ### Bottom boundary prescribed value (fixed)
md.add_initialized_fem_data('bbv', mfu2, bottom_bv)
#md.add_Dirichlet_condition_with_multipliers(mim2, 'u2', elements_degree-1,
BOTTOM_BOUND) ## Dirichlet boundary condition with multipliers on the fem
variable 'u2' on 'BOTTOM_BOUND' boundary. mult_description = elements_degree-1
= 1
## Above Dirichlet condition implies zero displacement at the bottom of the
foundation
md.add_Dirichlet_condition_with_multipliers(mim2, 'u2', elements_degree-1,
BOTTOM_BOUND, 'bbv') ## or use prescribed value with the given Lagrange
multiplier
### Conatac Conditions:
if version == 91:
# Contact condition (augmented Lagrangian)
md.add_initialized_data('gamma0', [gamma0]) ## Augmentation parameter for
the augmented Lagrangian defined as gamma0 = 1./E
md.add_interpolate_transformation_from_expression('Proj1', mesh1, mesh2,
'[X(1);0]') ## Project mesh1's coordinates to mesh2's coordinate
md.add_filtered_fem_variable('lambda1', mflambda_C, CONTACT_BOUND_WHEEL) #
mflambda_C is a contact multiplier MeshFem
## An integral contact condition using augmented Lagrangian formulations
using the high-level generic assembly bricks
md.add_nonlinear_generic_assembly_brick(mim1c, 'lambda1*(Test_u1.[0;1])'
'-
lambda1*(Interpolate(Test_u2,Proj1).[0;1])', CONTACT_BOUND_WHEEL)
md.add_nonlinear_generic_assembly_brick(mim1c,
'-(gamma0*element_size)*(lambda1 +
neg_part(lambda1+(1/(gamma0*element_size))*((u1-Interpolate(u2,Proj1)+X-Interpolate(X,Proj1)).[0;1])))*Test_lambda1',
CONTACT_BOUND_WHEEL);
elif version == 1 or version == 2: # defining the matrices BN (B in normal
direction) and BT (T in traction direction) by hand ## Boundary normal/traction
## for the wheel
contact_wheel_dof = cdof_wheel[dimension-1:nbc_wheel*dimension:dimension]
## DOF in y directions
contact_wheel_nodes = mfu1.basic_dof_nodes(contact_wheel_dof) ## get
location of basic degrees of freedom.
BN_wheel = gf.Spmat('empty', nbc_wheel, nbdofu1)
ngap_wheel = np.zeros(nbc_wheel)
for i in range(nbc_wheel):
BN_wheel[i, contact_wheel_dof[i]] = -1. ## set contact dof's as a
negative one; contact??
ngap_wheel[i] = contact_wheel_nodes[dimension-1, i] ## gap defined at the
master contact ??
## for the foundation
contact_fnd_dof = cdof_fnd[dimension-1:nbc_fnd*dimension:dimension] ## DOF
in y directions
contact_fnd_nodes = mfu2.basic_dof_nodes(contact_fnd_dof) ## get location
of basic degrees of freedom.
BN_fnd = gf.Spmat('empty', nbc_fnd, nbdofu2)
#ngap_fnd = np.zeros(nbc_fnd)
for i in range(nbc_fnd):
BN_fnd[i, contact_fnd_dof[i]] = -1. ## set contact dof's as a negative
one; contact??
## ngap_fnd[i] = contact_fnd_nodes[dimension-1, i]
## model variables and data to account for the contact
md.add_variable('lambda_n', nbc_wheel) ## Number of contact boundary dof
for normal contact`
md.add_initialized_data('r', [r]) ## Augmentation parameter
md.add_initialized_data('f_coeff', 0.0)
md.add_initialized_data('ngap_wheel', ngap_wheel) ## number of Gap nodes
(dof)
md.add_initialized_data('alpha', np.ones(nbc_wheel)) ## an optional
homogenization parameter for the augmentation parameter
if version == 1: ## THIS SHOULD BE REPLACED WITH
add_*_contact_between_nonmatching_meshes_brick() ## 2016-12-20
###
### BELOW LINE COMPLAINS THAT ARGUMENT 01 MUST BE A STRING
###
md.add_nodal_contact_between_nonmatching_meshes_brick(mim1, mim2, 'u1',
'u2', 'lambda_n', 'lambda_t', 'r', mesh1.pid_in_regions(CONTACT_BOUND_WHEEL),
mesh2.pid_in_regions(CONTACT_BOUND_FND), True, False, 1)
#md.add_multiplier('lambda_n', mfu1, 'u1', mim1, CONTACT_BOUND_WHEEL)
#md.add_integral_contact_between_nonmatching_meshes_brick(mim1, 'u1',
'u2', 'lambda_n', 'r', CONTACT_BOUND_WHEEL, CONTACT_BOUND_FND) ## Frictionless
contact ## NOT WORKING PROPERLY
#md.add_integral_contact_between_nonmatching_meshes_brick(mim1, 'u1',
'u2', 'lambda_n', 'r', 'f_coeff', CONTACT_BOUND_WHEEL, CONTACT_BOUND_FND) ##
Frictional contact
elif version == 2:
BT = gf.Spmat('empty', nbc_wheel*(dimension-1), nbdofu1)
for i in range(nbc_wheel):
for j in range(dimension-1):
BT[j+i*(dimension-1), contact_wheel_dof[i]-dimension+j+1] = 1.0
md.add_variable('lambda_t', nbc_wheel * (dimension-1)) ## number of
contact boundary for traction contact
md.add_initialized_data('friction_coeff', [friction_coeff])
md.add_basic_contact_brick('u1', 'lambda_n', 'lambda_t', 'r', BN, BT,
'friction_coeff', 'ngap', 'alpha', 1);
# Prescribed force in the hole
if (Dirichlet_version): ## prescribed vertical displacement
md.add_initialized_data('DData', [0., -0.1]) ## vertical displacement of 0.1
m deformation in the negative y direction
md.add_Dirichlet_condition_with_multipliers(mim1, 'u1', elements_degree-1,
HOLE_BOUND, 'DData'); ## vertical displacement BC on wheel's inner rim
else: ## prescribed force on the rim considering the rigidity of rim
## mflambda is meshfem to approximate a multiplier to take into account the
rigidity of the rim
md.add_filtered_fem_variable('lambda_D', mflambda, HOLE_BOUND) ## add a
variable to the model linked to a MeshFem, mflambda: The variable is filtered
in the sense that only the dof on the region are considered
md.add_initialized_data('F', [applied_force/(0.8*2*np.pi)]) ## applied_force
= 9.8E4 = 1 ton over the diameter of the rim
## add a variable to the model of constant sizes. 'sizes'=1 is either an
integer (for a scalar or vector variable) or a vector of dimensions for a
tensor variable.
## name = 'alpha_D' is th evariable name
md.add_variable('alpha_D', 1) ## Unknown vertical displacement of wheel rim
md.add_linear_generic_assembly_brick(mim1, '-lambda_D.Test_u1 +
(alpha_D*[0;1] - u1).Test_lambda_D + (lambda_D.[0;1] + F)*Test_alpha_D +
1E-9*alpha_D*Test_alpha_D', HOLE_BOUND)
# The small penalization 1E-6*alpha_D*Test_alpha_D seems necessary to have
# a convergence in all cases. Why ?
#
# Model solve
#
print ('Solve problem with ', md.nbdof(), ' dofs')
md.solve('max_res', 1E-5, 'max_iter', 100, 'very_noisy' , 'lsearch',
'simplest', 'alpha min', 0.8)
#HY#md.solve('max_res', 1E-9, 'max_iter', 40, 'noisy') # , 'lsearch',
'simplest', 'alpha min', 0.8)
if not(Dirichlet_version):
print ('alpha_D = ', md.variable('alpha_D')[0])
#print (md.variable_list())
#print 'Contact multiplier ', md.variable('lambda1')
#
# Solution export
#
U1 = md.variable('u1')
U2 = md.variable('u2')
VM1 = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u1', 'clambdastar',
'cmu', mfvm1)
VM2 = md.compute_isotropic_linearized_Von_Mises_or_Tresca('u2', 'clambdastar',
'cmu', mfvm2)
if (Dirichlet_version):
mfvm1.export_to_vtk('displacement_with_von_mises1_DisplacementBC.vtk', mfvm1,
VM1, 'Von Mises Stresses', mfu1, U1, 'Displacements')
mfvm2.export_to_vtk('displacement_with_von_mises2_DisplacementBC.vtk', mfvm2,
VM2, 'Von Mises Stresses', mfu2, U2, 'Displacements')
else:
mfvm1.export_to_vtk('displacement_with_von_mises1_ForceBC.vtk', mfvm1, VM1,
'Von Mises Stresses', mfu1, U1, 'Displacements')
mfvm2.export_to_vtk('displacement_with_von_mises2_ForceBC.vtk', mfvm2, VM2,
'Von Mises Stresses', mfu2, U2, 'Displacements')
print ('You can view solutions with for instance:\nmayavi2 -d
displacement_with_von_mises1.vtk -f WarpVector -m Surface -d
displacement_with_von_mises2.vtk -f WarpVector -m Surface')
_______________________________________________
Getfem-users mailing list
[email protected]
https://mail.gna.org/listinfo/getfem-users