Tested Finite Element codes¶
Table of Contents
CalculiX¶
CalculiX supports rigid body moves out of the box. Below there is an explanation of the input file.
** Mesh ++++++++++++++++++++++++++++++++++++++++++++++++
*INCLUDE, INPUT=Mesh/TET-0-5.inp # Path to mesh for ccx solver
** Material ++++++++++++++++++++++++++++++++++++++++++++++++
*Material, Name=Material-1 # Definition of material
*Density # Definition of density
7.829E-09
*Elastic # Definition of Young modulus and Poisson's ratio
207000, 0.33
** Sections ++++++++++++++++++++++++++++++++++++++++++++++++
** # Assigning material and solid elements to the elements sets in mesh
*Solid section, Elset=Fork-El_Section, Material=Material-1
** Steps +++++++++++++++++++++++++++++++++++++++++++++++++++
** # Definition of frequency step with 12 eigenmodes
*Step
*Frequency
12
** Field outputs +++++++++++++++++++++++++++++++++++++++++++
** # Commands responsible for saving results
*Node file
RF, U
*El file
S, E
** End step ++++++++++++++++++++++++++++++++++++++++++++++++
*End step
The simulation input file used in this study can be found on our GitHub!
Code_Aster¶
Unfortunately Code_Aster isn’t ideal solver to obtain frequencies which are almost zero therefore the option BANDE was used to calculate frequencies in certain bandwidth. Below there is an explanation of the input file of Code_Aster.
DEBUT()
mesh = LIRE_MAILLAGE(FORMAT='MED', # Read the mesh
UNITE=20,
VERI_MAIL=_F())
model = AFFE_MODELE(AFFE=_F(MODELISATION=('3D', ), # Assigning the element to the model
PHENOMENE='MECANIQUE',
TOUT='OUI'),
MAILLAGE=mesh)
mater = DEFI_MATERIAU(ELAS=_F(E=207000.0, # Defining the material
NU=0.33,
RHO=7.829e-09))
fieldmat = AFFE_MATERIAU(AFFE=_F(MATER=(mater, ), # Assigning the material to the mesh
TOUT='OUI'),
MAILLAGE=mesh,
MODELE=model)
ASSEMBLAGE(CHAM_MATER=fieldmat, # Setting the right matrixes for simulation
MATR_ASSE=(_F(MATRICE=CO('MASS'),
OPTION='MASS_MECA'),
_F(MATRICE=CO('RIGI'),
OPTION='RIGI_MECA')),
MODELE=model,
NUME_DDL=CO('ndl'))
modes = CALC_MODES(CALC_FREQ=_F(FREQ=(100.0, 3000.0)), # Setting the solver BANDE option between 100 and 3000 Hz.
MATR_MASS=MASS,
MATR_RIGI=RIGI,
OPTION='BANDE',
SOLVEUR_MODAL=_F(METHODE='TRI_DIAG',
),
TYPE_RESU='DYNAMIQUE')
IMPR_RESU(FORMAT='MED', # Saving the result in 3D format
RESU=_F(INFO_MAILLAGE='OUI',
RESULTAT=modes),
UNITE=80)
IMPR_RESU(FORMAT='RESULTAT', # Saving the result in .dat file
RESU=_F(RESULTAT=modes),
UNITE=8)
FIN()
The simulation input file used in this study can be found on our GitHub!
Elmer¶
Elmer supports rigid body modes out of the box. Below there is an explanation of solver input file.
Header
CHECK KEYWORDS Warn
Mesh DB "." "Mesh/QUAD-HEX-0-5" # Path to the mesh
Include Path ""
Results Directory "Results" # Path to results directory
End
Simulation # Settings and constants for simulation
Max Output Level = 5
Coordinate System = Cartesian
Coordinate Mapping(3) = 1 2 3
Simulation Type = Steady state
Steady State Max Iterations = 1
Output Intervals = 1
Timestepping Method = BDF
BDF Order = 1
Solver Input File = case.sif
Post File = case.ep
End
Constants
Gravity(4) = 0 -1 0 9.82
Stefan Boltzmann = 5.67e-08
Permittivity of Vacuum = 8.8542e-12
Boltzmann Constant = 1.3807e-23
Unit Charge = 1.602e-19
End
Body 1 # Assigning the material and equations to the mesh
Target Bodies(1) = 1
Name = "Body 1"
Equation = 1
Material = 1
End
Solver 1 # Solver settings
Equation = Linear elasticity
Procedure = "StressSolve" "StressSolver"
Eigen System Select = Smallest magnitude
Eigen System Values = 10
Variable = -dofs 3 Displacement
Eigen Analysis = True
Exec Solver = Always
Stabilize = True
Bubbles = False
Lumped Mass Matrix = False
Optimize Bandwidth = True
Linear System Convergence Tolerance = 1.0e-3
Steady State Convergence Tolerance = 1.0e-5
Nonlinear System Convergence Tolerance = 1.0e-7
Nonlinear System Max Iterations = 1
Nonlinear System Newton After Iterations = 3
Nonlinear System Newton After Tolerance = 1.0e-3
Nonlinear System Relaxation Factor = 1
Linear System Solver = Direct
Linear System Direct Method = MUMPS
End
Solver 2 # Extracting the result to the .dat file
Exec Solver = After Saving
Equation ="Equation 1"
Procedure = "SaveData" "SaveScalars"
Filename = "QUAD-HEX-0-5.dat"
Variable 1 = Displacement
Save Eigenfrequencies = Logical True
End
Equation 1 # Setting the active solvers
Name = "Equation 1"
Active Solvers(2) = 1 2
End
Material 1 # Defining the material
Name = "Steel"
Mesh Poisson ratio = 0.33
Youngs modulus = 207000
Poisson ratio = 0.33
Porosity Model = Always saturated
Density = 7.829e-9
End
The simulation input file used in this study can be found on our GitHub!
MoFEM¶
Users who would like to check how the MoFEM model was created are advised to look into the MoFEM tutorials section VEC-1: Eigen elastic
GetFEM¶
"""
"""
###############################################################################
import time
import getfem as gf
import numpy as np
import scipy
from scipy import io
from scipy.sparse import linalg
###############################################################################
# Let us now define the different physical and numerical parameters of the problem.
#
rho = 7.829e-09 # Young Modulus (kg/mm^3)
E = 207000 # Young Modulus (N/mm^2)
nu = 0.33 # Poisson ratio
clambda = E * nu / ((1 + nu) * (1 - 2 * nu)) # First Lame coefficient (N/mm^2)
cmu = E / (2 * (1 + nu)) # Second Lame coefficient (N/mm^2)
###############################################################################
# Set the numerical parameter of each case.
#
elements_degrees = []
msh_file_names = []
# Linear-Tet 2.0mm
elements_degrees.append(1)
msh_file_names.append("./LIN-TET/TET-2-0.msh")
# Linear-Tet 1.0mm
elements_degrees.append(1)
msh_file_names.append("./LIN-TET/TET-1-0.msh")
# Linear-Tet 0.5mm
elements_degrees.append(1)
msh_file_names.append("./LIN-TET/TET-0-5.msh")
# Quad-Tet 2.0mm
elements_degrees.append(2)
msh_file_names.append("./LIN-TET/TET-2-0.msh")
# Quad-Tet 1.0mm
elements_degrees.append(2)
msh_file_names.append("./LIN-TET/TET-1-0.msh")
# Quad-Tet 0.5mm
elements_degrees.append(2)
msh_file_names.append("./LIN-TET/TET-0-5.msh")
# Linear-Hex 2.0mm
elements_degrees.append(1)
msh_file_names.append("./LIN-HEX/HEX-2-0.msh")
# Linear-Hex 1.0mm
elements_degrees.append(1)
msh_file_names.append("./LIN-HEX/HEX-1-0.msh")
# Linear-Hex 0.5mm
elements_degrees.append(1)
msh_file_names.append("./LIN-HEX/HEX-0-5.msh")
# Quad-Hex 2.0mm
elements_degrees.append(2)
msh_file_names.append("./LIN-HEX/HEX-2-0.msh")
# Quad-Hex 1.0mm
elements_degrees.append(2)
msh_file_names.append("./LIN-HEX/HEX-1-0.msh")
# Quad-Hex 0.5mm
elements_degrees.append(2)
msh_file_names.append("./LIN-HEX/HEX-0-5.msh")
t = time.process_time()
###############################################################################
# Importing the mesh from gmsh format.
#
meshs = []
for i, msh_file_name in enumerate(msh_file_names):
mesh = gf.Mesh("import", "gmsh", msh_file_name)
meshs.append(mesh)
print("Time for import mesh", time.process_time() - t)
t = time.process_time()
###############################################################################
# Definition of finite elements methods and integration method
#
mfus = []
mfds = []
mims = []
for elements_degree, mesh in zip(elements_degrees, meshs):
mfu = gf.MeshFem(mesh, 3)
mfu.set_classical_fem(elements_degree)
mfus.append(mfu)
mfd = gf.MeshFem(mesh, 1)
mfd.set_classical_fem(elements_degree)
mfds.append(mfd)
mim = gf.MeshIm(mesh, elements_degree * 2)
mims.append(mim)
###############################################################################
# We get the mass and stiffness matrices using asm function.
#
mass_matrixs = []
linear_elasticitys = []
for i, (mfu, mfd, mim) in enumerate(zip(mfus, mfds, mims)):
mass_matrix = gf.asm_mass_matrix(mim, mfu, mfu)
mass_matrix.scale(rho)
mass_matrixs.append(mass_matrix)
lambda_d = np.repeat(clambda, mfd.nbdof())
mu_d = np.repeat(cmu, mfd.nbdof())
linear_elasticity = gf.asm_linear_elasticity(mim, mfu, mfd, lambda_d, mu_d)
linear_elasticitys.append(linear_elasticity)
mass_matrix.save("hb", "M" + "{:02}".format(i) + ".hb")
linear_elasticity.save("hb", "K" + "{:02}".format(i) + ".hb")
print("Time for assemble matrix", time.process_time() - t)
t = time.process_time()
###############################################################################
# Solve the eigenproblem.
#
# Compute the residual error for SciPy.
#
# :math:`Err=\frac{||(K-\lambda.M).\phi||_2}{||K.\phi||_2}`
#
# Convert Lambda values to Frequency values:
# :math:`freq = \frac{\sqrt(\lambda)}{2.\pi}`
#
for i, (mass_matrix, linear_elasticity, mfu) in enumerate(
zip(mass_matrixs, linear_elasticitys, mfus)
):
M = io.hb_read("M" + "{:02}".format(i) + ".hb")
K = io.hb_read("K" + "{:02}".format(i) + ".hb")
vals, vecs = linalg.eigsh(A=K, k=6, M=M, sigma=400.0, which="LA")
omegas = np.sqrt(np.abs(vals))
freqs = omegas / (2.0 * np.pi)
nev = 6
scipy_acc = np.zeros(nev)
print(f"case{i}")
for j in range(nev):
lam = vals[j] # j-th eigenvalue
phi = vecs.T[j] # j-th eigenshape
kphi = K * phi.T # K.Phi
mphi = M * phi.T # M.Phi
kphi_nrm = np.linalg.norm(kphi, 2) # Normalization scalar value
mphi *= lam # (K-\lambda.M).Phi
kphi -= mphi
scipy_acc[j] = np.linalg.norm(kphi, 2) / kphi_nrm # compute the residual
print(f"[{j}] : Freq = {freqs[j]:8.2f} Hz\t Residual = {scipy_acc[j]:.5}")
np.savetxt("freqs" + "{:0=3}".format(i) + ".txt", freqs)
mfu.export_to_vtk(
"vecs" + "{:0=3}".format(i) + ".vtk",
mfu,
vecs[:, 0],
"Mode_1",
mfu,
vecs[:, 1],
"Mode_2",
mfu,
vecs[:, 2],
"Mode_3",
mfu,
vecs[:, 3],
"Mode_4",
mfu,
vecs[:, 4],
"Mode_5",
mfu,
vecs[:, 5],
"Mode_6",
)
print("Time for solve eigen value problem", time.process_time() - t)
t = time.process_time()