Is a displacement solution affected by a translation?

Here is the problem (I tried my best to explain. Please let me know if it needs further clarification):

Consider an annulus of inner radius 3 and outer radius 5. Here is the original configuration:

Next, apply a traction of 5 units along the inner circle outwards. There are no essential bcs on the outer boundary. The outer boundary is subjected to a 0 Neumann bc. What I am expecting here is a uniform displacement along the boundary of the inner circle. But here is what I am getting:

Clearly, the displacement along the inner circle is not uniform.

Now if we superimpose the original and the deformed meshes, we can clearly see that there is a translation happening because of the absence of essential bcs.

Because the translation is along the X-axis and the displacement at the “most blue region” is along the negative X-axis (traction is applied opposite to the normal to the inner circle. For the inner circle, the normal point towards the center), some of the displacement is negated by the translation and hence the difference in the displacement gradient along the inner circle.

Now, keeping the moved mesh fixed, can we reverse the effect of the translation on the displacement vector along the inner circle? In short, what I want to see in Paraview is a deformed moved mesh with uniform displacement along the inner circle.

Hi, just fix the rigid body motions by fixing the displacement at some points or removing them within the weak form as in Poisson equation with pure Neumann boundary conditions — DOLFIN documentation

Hi @bleyerj , thanks for the suggestion. I had already thought of that. But I wanted to avoid doing that since peer reviews of my paper can pose the question “why did you fix the displacement when the dynamics of your model doesn’t recommend you doing that?”

Hi @bleyerj , I decided to implement the following strategy for re-centering the deformed annulus:

I have the center of the original undeformed annulus at (0.0, 0.0) and I have calculated the translation for each of the nodes for the deformed, moved frame and named it translation. Now in order to move the mesh back using the translation, I implemented

V = VectorFunctionSpace(mesh, "Lagrange", 1)
trans = project(translation, V)
u1 = Function(V)
u1 = u - trans  # u is the solution to the variational form
file = File("example.pvd");
file << u1;

But this raises the error:

trans = project(translation, V)
  File "/usr/lib/petsc/lib/python3/dist-packages/dolfin/fem/projection.py", line 129, in project
    L = ufl.inner(w, v) * dx
  File "/usr/lib/python3/dist-packages/ufl/operators.py", line 155, in inner
    b = as_ufl(b)
  File "/usr/lib/python3/dist-packages/ufl/constantvalue.py", line 437, in as_ufl
    raise UFLValueError("Invalid type conversion: %s can not be converted"
ufl.log.UFLValueError: Invalid type conversion: [[ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]
 ...
 [ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]] can not be converted to any UFL type.

Can’t quite figure out what’s wrong here. Any help would be greatly appreciated.

You should probably do:

u1.vector()[:] = u.vector() - trans.vector()
1 Like

Thanks @hernan . I will try it out and let you know. Sorry for the late response.

I tried what you suggested.

trans = project(translation, V)
u1 = Function(V)
u1.vector()[:] = u.vector() - trans.vector() # u is the solution to the variational form
# Save solution in VTK format
file = File("meshmovetrans.pvd");
file << u1;

Here is the error code from FEniCS:

trans = project(translation, V)
  File "/usr/lib/petsc/lib/python3/dist-packages/dolfin/fem/projection.py", line 129, in project
    L = ufl.inner(w, v) * dx
  File "/usr/lib/python3/dist-packages/ufl/operators.py", line 155, in inner
    b = as_ufl(b)
  File "/usr/lib/python3/dist-packages/ufl/constantvalue.py", line 437, in as_ufl
    raise UFLValueError("Invalid type conversion: %s can not be converted"
ufl.log.UFLValueError: Invalid type conversion: [[ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]
 ...
 [ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]
 [ 1.25784105 -0.37946378]] can not be converted to any UFL type.

The error is not in what I suggested but in the projection of the translation. According to your error message, translation is an array and cannot be projected. The project function is expecting a Function object or a ufl object rather than an array as first argument.

1 Like

@hernan So when I am projecting translation (which has dimension n,2; n = number of nodes in the mesh) to V (which is a vector function space), translation becomes a vector function and not a scalar one. So do i need to project it to a function space rather than a vector function space. Will that work?

Sorry for so many questions. I am a little lost here.

The error is pretty simple and has nothing to do with your function space. The error says that the project function does not like one of its arguments, i.e., the translation object, which should be either a Function or a ufl type.

You can use print(type(translation)) in your script to see which kind of object it is and help(project) to elucidate the correct arguments. Being said that, you should post a MWE including the translation estimation to dig a bit deeper.

2 Likes

Hi @hernan , here is the MWE. The problem is the solution “u” is a n1 column vector, where n is the number of nodes of the mesh. But the vector “translation” is n2. This records the X and the Y components of the translation for each of the nodes. Please suggest what should be done here. Need help with this.

MWE:

from __future__ import print_function
from fenics import *
import matplotlib.pyplot as plt
from ufl import cofac
from dolfin import *
import meshio
from dolfin import Mesh, XDMFFile, File, MeshValueCollection, cpp

# Optimization options for the form compiler
parameters["form_compiler"]["cpp_optimize"] = True
ffc_options = {"optimize": True, \
               "eliminate_zeros": True, \
               "precompute_basis_const": True, \
               "precompute_ip_const": True}

import numpy as np
import meshio
from mshr import Circle, generate_mesh
from dolfin import Mesh, File, MeshFunction, Point, BoundaryMesh, SubDomain, plot, File
import matplotlib.pyplot as plt
from dolfin import *

C1 = Circle(Point(0, 0),1)
C2 = Circle(Point(0, 0),2)
C = C2 - C1

mesh = generate_mesh(C, 100)

class inner(SubDomain):
  def inside(self, x, on_boundary):
      return near(x[0]**2 + x[1]**2, 1, eps=1e-3) and on_boundary
class outer(SubDomain):
  def inside(self, x, on_boundary):
      return near(x[0]**2 + x[1]**2, 4, eps=1e-3) and on_boundary
class annulus(SubDomain):
    def inside(self, x, on_boundary):
        return x[0]**2 + x[1]**2 > 1 and x[0]**2 + x[1]**2 < 4


boundary_markers = MeshFunction("size_t", mesh, mesh.topology().dim()-1, 0)
surface_markers = MeshFunction("size_t", mesh, mesh.topology().dim(), 0)
inner().mark(boundary_markers, 1)
outer().mark(boundary_markers, 2)
annulus().mark(surface_markers, 3)

#V = VectorFunctionSpace(mesh, "Lagrange", 1)
#mesh11 = project(mesh1,V)

plot(mesh)
plt.show()

ds = Measure('ds', domain=mesh, subdomain_data=boundary_markers)
dx = Measure('dx', domain=mesh, subdomain_data=surface_markers)
print(assemble(Constant(1)*ds(1)),assemble(Constant(1)*ds(2)))
print(assemble(Constant(1)*dx(3)))


V = VectorFunctionSpace(mesh, "Lagrange", 1)
n=FacetNormal(mesh)

du = TrialFunction(V)
v  = TestFunction(V)             
u  = Function(V)                 
T = Constant(5.0)

bcs=[]

# Kinematics
d = mesh.geometry().dim()
I = Identity(d)             
F = I + grad(u)             
C = F.T*F                   
M = cofac(F)
Finvt = (inv(F)).T
Ic = tr(C)
J  = det(F)

E, nu = 10.0, 0.499   
mu, lmbda = 27.9, Constant(E*nu/((1 + nu)*(1 - 2*nu)))
psi = (mu/2)*(Ic - 3) + ((nu)*(mu)/(1-2*nu))*(J-1)**2 - mu*(ln(J))


Coords = Expression(('x[0]','x[1]'),degree=0)
coords = project(Coords, V)
phi = coords+u

Pi = psi*dx - (0.5)*dot(M*T*(-n), phi)*ds(1)
ddPI = derivative(Pi, u, v)
solve(ddPI == 0, u, bcs,
     form_compiler_parameters=ffc_options)
     
mesh1 = Mesh(mesh) 
X = mesh1.coordinates()
X += np.vstack(map(u, X))

mesh_moved = Mesh(mesh1)
outer_nodes = BoundaryMesh(mesh_moved, "exterior", True)
translated_center = np.mean(outer_nodes.coordinates(), axis=0)

n = np.shape(mesh_moved.coordinates())[0]
translation = np.zeros([n, 2])
translation[:, 0] = translated_center[0]; translation[:, 1] = translated_center[1]
mesh_moved.coordinates()[:] = mesh_moved.coordinates() - translation

trans = project(translation, V)
u1 = Function(V)
u1.vector()[:] = u.vector() - trans.vector()

file = File("MWE.pvd");
file << u1;

Hi @hernan , any suugestions on how to resolve this issue?

Unfortunately your MWE example didn’t work for me using the version 2019.2.0.dev0 of dolfin. Particularly, it fails during the definition of C1.

@avishmj please clean up your code. You have tons of import statements that are not needed (several duplications and unused imports).
By simplifying the example it increases the likelyhood of anyone being able to help you.

Please Also make sure that your code runs before posting it