Hi guys,
I am tried to perform an eigenanalysis of a plate where tensile or spring loads applied at the bottom four corners of the plate.
Can anyone tell me how to apply these loads. I read similar topics for guidance, but I cannot find one that applies to my case. Here is the code so far.
# importing libraries for pre-processing
import dolfin as df
from ufl import nabla_div, nabla_grad
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path
import json
from mshr import Polygon, generate_mesh
from scipy.optimize import root
from math import cos, cosh
import sys
import argparse
from functools import partial
import pandas as pd
import meshio as mio
from stl import mesh as mstl
np.set_printoptions(precision=5)
## Plate Parameters
# Universal Constants
GRAVITY = 9.81
WATER_DENSITY = 1000
PLATE_LENGTH = 1
WATER_DEPTH = 1
# Plate Data
PLATE_DEPTH = 0.2 * WATER_DEPTH
PLATE_WIDTH = 16 * PLATE_LENGTH
PLATE_THICKNESS = 1e-3 * PLATE_LENGTH
PLATE_DENSITY = 1 * WATER_DENSITY
YOUNGS_MODULUS = 1e6 * (WATER_DENSITY * GRAVITY * WATER_DEPTH**4)
POISSONS_RATIO = 0.3
LAMES_MU = 0.5 * YOUNGS_MODULUS / (1+POISSONS_RATIO)
LAMES_LAMBDA = YOUNGS_MODULUS * POISSONS_RATIO / ((1+POISSONS_RATIO)*(1-2*POISSONS_RATIO))
# Tension load at the bottom four corners of the plate
TENSION_LOADS = np.array([0.05, 0.15, 1e4]) * (WATER_DENSITY * GRAVITY * WATER_DEPTH**4)
# Mode Data
MODE_COUNT = 6
# Meshing Data
PANEL_RES = np.array([20, 60, 3],dtype=int)
PANEL_HIGH_RES = np.array([20, 160, 6],dtype=int)
# Simulation directories
MAIN_DIR = Path(".")
OUTPUT_DIR = MAIN_DIR / "output"
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
PLOTS_DIR = MAIN_DIR / "plots"
PLOTS_DIR.mkdir(parents=True, exist_ok=True)
## Meshing
PLATE_THICKNESS/PANEL_RES[2]
CORNER1 = df.Point(0, 0, -PLATE_THICKNESS-PLATE_DEPTH)
# corner2 is diagonally opposite to the corner1
CORNER2 = df.Point(PLATE_LENGTH,
PLATE_WIDTH,
-PLATE_DEPTH)
# res is the resolution of the mesh
low_res_mesh = df.BoxMesh(CORNER1, CORNER2, PANEL_RES[0], PANEL_RES[1], PANEL_RES[2])
# Saving the mesh
df.File("low_res_mesh.pvd") << low_res_mesh
df.File("low_res_mesh.xml") << low_res_mesh
mesh = df.BoxMesh(CORNER1, CORNER2,
PANEL_HIGH_RES[0], PANEL_HIGH_RES[1], PANEL_HIGH_RES[2])
# Saving the mesh
df.File("hig_res_mesh.pvd") << mesh
df.File("high_res_mesh.xml") << mesh
DIM = mesh.geometric_dimension()
MESH_SIZES = np.array([PLATE_LENGTH/PANEL_HIGH_RES[0],
PLATE_WIDTH/PANEL_HIGH_RES[1],
PLATE_THICKNESS/PANEL_HIGH_RES[2]])
print(f"{MESH_SIZES=}")
mesh
# Saving the mesh
df.File("mesh.pvd") << mesh
df.File("mesh.xml") << mesh
## Strain and Stress Functions
# Strain Function
def strain(disp):
return df.sym(df.grad(disp))
# Stress Function
def stress(disp):
dim = disp.geometric_dimension()
return 2.0*LAMES_MU*strain(disp) + \
LAMES_LAMBDA*df.tr(strain(disp))*df.Identity(dim)
## Applying Constraint Boundary Conditions at the corners of the plate bottom
Note: Following code also has option to add boundary condition at the corners
V = df.VectorFunctionSpace(mesh, 'Lagrange', degree=1)
u_ = df.TrialFunction(V)
du = df.TestFunction(V)
# https://fenicsproject.org/qa/9049/how-to-create-a-dirichletbc-on-a-single-vertex-or-dof/
def corner_spring_bc(x, on_boundary):
"""Function to apply spring boundary condition at the corners of the plate bottom"""
bottom = df.near(x[2],-PLATE_THICKNESS,MESH_SIZES[2]) and on_boundary
if bottom:
left = df.near(x[0], 0, MESH_SIZES[0])
right = df.near(x[0], PLATE_LENGTH, MESH_SIZES[0])
front = df.near(x[1], PLATE_WIDTH, MESH_SIZES[1])
back = df.near(x[1], 0, MESH_SIZES[1])
corner1 = left and front
corner2 = left and back
corner3 = right and front
corner4 = right and back
return corner1 or corner2 or corner3 or corner4
return bottom
def right_corners(x, on_boundary):
"""Function to apply spring boundary condition at the corners of the plate bottom"""
bottom = df.near(x[2],-PLATE_THICKNESS,MESH_SIZES[2]) and on_boundary
if bottom:
right = df.near(x[0], PLATE_LENGTH, MESH_SIZES[0])
front = df.near(x[1], PLATE_WIDTH, MESH_SIZES[1])
back = df.near(x[1], 0, MESH_SIZES[1])
corner3 = right and front
corner4 = right and back
return corner3 or corner4
return bottom
def left_corners(x, on_boundary):
"""Function to apply spring boundary condition at the corners of the plate bottom"""
bottom = df.near(x[2],-PLATE_THICKNESS,MESH_SIZES[2]) and on_boundary
if bottom:
left = df.near(x[0], 0, MESH_SIZES[0])
front = df.near(x[1], PLATE_WIDTH, MESH_SIZES[1])
back = df.near(x[1], 0, MESH_SIZES[1])
corner1 = left and front
corner2 = left and back
return corner1 or corner2
return bottom
# bc = df.DirichletBC(V.sub(0), 0, corner_spring_bc, method='pointwise')
bc = None
# Applying Tensile Loads
corner1_load = df.PointSource(V.sub(0), df.Point(0, 0 ,0),TENSION_LOADS[0])
corner2_load = df.PointSource(V.sub(0), df.Point(PLATE_LENGTH,0 ,0),TENSION_LOADS[0])
corner3_load = df.PointSource(V.sub(0), df.Point(0, PLATE_WIDTH,0),TENSION_LOADS[0])
corner4_load = df.PointSource(V.sub(0), df.Point(PLATE_LENGTH,PLATE_WIDTH,0),TENSION_LOADS[0])
pointsourceb = assemble(Constant(0.0)*v*dx)
corner1_load.apply(pointsourceb)
corner2_load.apply(pointsourceb)
corner3_load.apply(pointsourceb)
corner4_load.apply(pointsourceb)
## Creating the system stiffness K and mass matrix M
k_form = df.inner(stress(du),strain(u_))*df.dx
l_form = df.Constant(1.)*u_[0]*df.dx + pointsourceb
K = df.PETScMatrix()
b = df.PETScVector()
df.assemble_system(k_form, l_form, bc, A_tensor=K, b_tensor=b)
m_form = PLATE_DENSITY*df.dot(du,u_)*df.dx
M = df.PETScMatrix()
assembly = df.assemble(m_form, tensor=M)
# Solving for Modeshapes
eigensolver = df.SLEPcEigenSolver(K, M)
eigensolver.parameters['problem_type'] = 'gen_hermitian'
eigensolver.parameters['spectral_transform'] = 'shift-and-invert'
eigensolver.parameters['spectral_shift'] = 0.0
eigensolver.solve(MODE_COUNT)
falpha = lambda x: cos(x)*cosh(x)+1
alpha = lambda n: root(falpha, (2*n+1)*pi/2.)['x'][0]
normal_M = []
normal_K = []
lamba = []
Modes = []
Modes_vectors = []
file_results = df.XDMFFile(f"{MAIN_DIR}/modes.xdmf")
file_results.parameters["flush_output"] = True
file_results.parameters["functions_share_mesh"] = True
def int_zfill(index, total_len):
from math import floor, log10
return str(index).zfill(1+floor(log10(total_len)))
print("Computing {} first eigenvalues...".format(MODE_COUNT))
print("id | freq(Hz) | Ang Freq(rad/s) | Lambda")
for i in range(MODE_COUNT):
# Extract eigenpair
r, c, rx, cx = eigensolver.get_eigenpair(i)
rx[:] /= max(rx[:])
# 3D eigenfrequency
freq_3D = df.sqrt(r)/2/np.pi
lamba.append(r)
print(f"{i+1:2d} | {np.abs(freq_3D.real):.3e} | {np.abs(2*np.pi*freq_3D.real):.3e} | {np.abs(r.real):.3e}", )
# Initialize function and assign eigenvector
eigenmode = df.Function(V,name=f"Eigenvector {int_zfill(i+1, MODE_COUNT)}")
eigenmode.vector()[:] = rx
Modes.append(rx[:].reshape((DIM,int(rx[:].shape[0]/DIM)),order='F').T)
Modes_vectors.append(eigenmode)
normal_M.append(np.dot(rx[:],M*rx[:]))
normal_K.append(np.dot(rx[:],K*rx[:]))
# Function can be plotted as usual:
rx_func = df.Function(V)
rx_func.vector()[:] = rx
file_results.write(eigenmode, 0.)
file_results.close()
But in getting the following error.
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
/tmp/ipykernel_992/51715959.py in <module>
165 # Applying Tensile Loads
166
--> 167 corner1_load = df.PointSource(V.sub(0), df.Point(0, 0 ,0),TENSION_LOADS[0])
168 corner2_load = df.PointSource(V.sub(0), df.Point(PLATE_LENGTH,0 ,0),TENSION_LOADS[0])
169 corner3_load = df.PointSource(V.sub(0), df.Point(0, PLATE_WIDTH,0),TENSION_LOADS[0])
RuntimeError:
*** -------------------------------------------------------------------------
*** DOLFIN encountered an error. If you are not able to resolve this issue
*** using the information listed below, you can ask for help at
***
*** fenics-support@googlegroups.com
***
*** Remember to include the error message listed below and, if possible,
*** include a *minimal* running example to reproduce the error.
***
*** -------------------------------------------------------------------------
*** Error: Unable to apply point source to vector.
*** Reason: The point is outside of the domain.
*** Where: This error was encountered inside PointSource.cpp.
*** Process: 0
***
*** DOLFIN version: 2019.1.0
*** Git changeset: 7f46aeb0b296da5bbb1fb0845822a72ab9b09c55
*** -------------------------------------------------------------------------
This topic is the continuation of the following topic
Any help would be really appreciated.