Hi,
I am currently performing a harmonic analysis of the damped 3D elastic model in FenicsX. I have implemented the following code below. I am stuck in splitting the solution vector into its real and imaginary parts. I want to plot the frequency response v/s amplitude values of the z-component of the displacement field. In order to do so, I want to access the real and imaginary values of the displacement fields z-component.
Amplitude = sqrt(Uz_real^^2 +Uz_imag^^2).
In this case, how can I access the real and imaginary values in dolfinx? rather than exporting the result to xdmf file to view in ParaView. Is there a way to split the solution into real and imaginary parts?
import dolfinx
from dolfinx.fem import (Constant,dirichletbc, Function, FunctionSpace, VectorFunctionSpace,LinearProblem,assemble_scalar, locate_dofs_geometrical, locate_dofs_topological)
from dolfinx.fem import (assemble_matrix, assemble,assemble_vector, form, apply_lifting, locate_dofs_geometrical, set_bc)
import ufl
from ufl import (Form, SpatialCoordinate, TestFunction, TrialFunction,dx, ds, grad, FacetNormal,inner, max_value,nabla_grad, nabla_div, Identity)
from mpi4py import MPI
import dolfinx.io
import numpy as np
from petsc4py import PETSc
from petsc4py.PETSc import ScalarType
from dolfinx.io import XDMFFile
with dolfinx.io.XDMFFile(MPI.COMM_WORLD, "mesh.xdmf", "r") as xdmf:
mesh = xdmf.read_mesh(name="Grid")
mesh.topology.create_connectivity(mesh.topology.dim, mesh.topology.dim)
m_subdomains = xdmf.read_meshtags(mesh, name="Grid")
mesh.topology.create_connectivity(mesh.topology.dim-1, mesh.topology.dim)
with dolfinx.io.XDMFFile(MPI.COMM_WORLD, "mf.xdmf", "r") as xdmf:
m_boundaries = xdmf.read_meshtags(mesh, name="Grid")
# function space
V = VectorFunctionSpace(mesh, ("CG", 2))
num_dofs_global = V.dofmap.index_map.size_global * V.dofmap.index_map_bs
print(f"Number of dofs global: {num_dofs_global}")
dx = ufl.Measure("dx", domain=mesh, subdomain_data=m_subdomains)
ds = ufl.Measure("ds", domain=mesh, subdomain_data=m_boundaries)
# Material parameters and elastic constitutive relations
E, nu = (2E11), (0.31)
rho = (7900)
# Lame coefficient for constitutive relation
mu = E/2./(1+nu)
lmbda = E*nu/(1+nu)/(1-2*nu)
# Strain function
def epsilon(u):
return 0.5*(nabla_grad(u) + nabla_grad(u).T)
# Stress function
def sigma(u):
return lmbda * nabla_div(u) * Identity(u.geometric_dimension()) + 2*mu*epsilon(u)
# Rayliegh Coefficients
alpha = (0) # mass coefficient
beta = (1e-3) # stiffness coefficient
# trial and test functions
u = TrialFunction(V)
w = TestFunction(V)
# dirichlet bc
left_facets = m_boundaries.indices[m_boundaries.values==1]
left_dofs = locate_dofs_topological(V, mesh.topology.dim-1, left_facets)
u_D = Function(V)
u_D = np.array([0,0,1e-3], dtype=ScalarType)
bc = [dirichletbc(u_D, left_dofs, V)]
T = Constant(mesh, ScalarType((0, 0, 0)))
start = 100; d_freq = 10; freq=130
with XDMFFile(MPI.COMM_WORLD,"Frequency_Response.xdmf", "w") as outfile:
outfile.write_mesh(mesh)
while start <= freq:
print(start)
omega=2*np.pi*start
print(omega)
# Matrices
M_form = rho*inner(u, w)*dx
K_form = inner(sigma(u), epsilon(w))*dx
C_form = alpha * M_form + beta * K_form
a = - omega**2*M_form + 1j * omega * C_form + K_form
L = inner(T, w) * ds
# Set up the PDE
solnU = Function(V)
problem = LinearProblem(a, L, bc, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
solnU = problem.solve()
outfile.write_function(solnU, freq)
start = start + d_freq
else:
print("Harmonic Analysis Completed")