How to plot density on deformed mesh

Hi,
I’m having troubles to plot the density field on the deformed mesh. The code comes from the exemple in fenics documentation: Topology optimization using the SIMP method — Numerical tours of continuum mechanics using FEniCS master documentation

Blockquote
from dolfin import *
import matplotlib.pyplot as plt
import numpy as np
import time

Algorithmic parameters

niternp = 20 # number of non-penalized iterations
niter = 80 # total number of iterations
pmax = 4 # maximum SIMP exponent
exponent_update_frequency = 4 # minimum number of steps between exponent update
tol_mass = 1e-4 # tolerance on mass when finding Lagrange multiplier
thetamin = 0.001 # minimum density modeling void

Problem parameters

thetamoy = 0.4 # target average material density
E = Constant(30)
nu = Constant(0.2)
lamda = Enu/(1+nu)/(1-2nu)
mu = E/(2*(1+nu))
f_grav = Constant((0, -1e-3)) # vertical downwards force
f_surface=Constant((0,-1e-2))

Mesh

mesh = RectangleMesh(Point(-2, 0), Point(2, 1), 25, 6, “crossed”) #200,48

Boundaries

def cote(x, on_boundary):
return near (x[0],2) or near(x[0], -2) and on_boundary

def load(x, on_boundary):
return near(x[1], 1)

facets = MeshFunction(“size_t”, mesh, 1)
AutoSubDomain(load).mark(facets, 1)
ds = Measure(“ds”, subdomain_data=facets)
#plt.figure(1)
#plot(mesh,linewidth=0.1)
#plt.pause(10)

Function space for density field

V0 = FunctionSpace(mesh, “DG”, 0)

Function space for displacement

V2 = VectorFunctionSpace(mesh, “CG”, 2)

Fixed boundary condtions

bc = DirichletBC(V2, Constant((0, 0)), cote)

p = Constant(1) # SIMP penalty exponent
exponent_counter = 0 # exponent update counter
lagrange = Constant(1) # Lagrange multiplier for volume constraint

thetaold = Function(V0, name=“Density”)
thetaold.interpolate(Constant(thetamoy))
coeff = thetaold**p
theta = Function(V0)

volume = assemble(Constant(1.)dx(domain=mesh))
avg_density_0 = assemble(thetaold
dx)/volume # initial average density
avg_density = 0.

def eps(v):
return sym(grad(v))
def sigma(v):
return coeff*(lamdadiv(v)Identity(2)+2mueps(v))
def energy_density(u, v):
return inner(sigma(u), eps(v))

Inhomogeneous elastic variational problem

u_ = TestFunction(V2)
du = TrialFunction(V2)
a = inner(sigma(u_), eps(du))*dx
#L = dot(f_surface, u_)*ds(1)
L=inner(f_grav,u_)*dx +dot(f_surface, u_)*ds(1)

def local_project(v, V):
dv = TrialFunction(V)
v_ = TestFunction(V)
a_proj = inner(dv, v_)dx
b_proj = inner(v, v_)dx
solver = LocalSolver(a_proj, b_proj)
solver.factorize()
u = Function(V)
solver.solve_local_rhs(u)
return u
def update_theta():
theta.assign(local_project((p
coeff
energy_density(u, u)/lagrange)**(1/(p+1)), V0))
thetav = theta.vector().get_local()
theta.vector().set_local(np.maximum(np.minimum(1, thetav), thetamin))
theta.vector().apply(“insert”)
avg_density = assemble(theta*dx)/volume
return avg_density

def update_lagrange_multiplier(avg_density):
avg_density1 = avg_density
# Initial bracketing of Lagrange multiplier
if (avg_density1 < avg_density_0):
lagmin = float(lagrange)
while (avg_density < avg_density_0):
lagrange.assign(Constant(lagrange/2))
avg_density = update_theta()
lagmax = float(lagrange)
elif (avg_density1 > avg_density_0):
lagmax = float(lagrange)
while (avg_density > avg_density_0):
lagrange.assign(Constant(lagrange*2))
avg_density = update_theta()
lagmin = float(lagrange)
else:
lagmin = float(lagrange)
lagmax = float(lagrange)

#Dichotomy on Lagrange multiplier
inddico=0
while ((abs(1.-avg_density/avg_density_0)) > tol_mass):
    lagrange.assign(Constant((lagmax+lagmin)/2))
    avg_density = update_theta()
    inddico += 1;
    if (avg_density < avg_density_0):
        lagmin = float(lagrange)
    else:
        lagmax = float(lagrange)
print("   Dichotomy iterations:", inddico)

def update_exponent(exponent_counter):
exponent_counter += 1
if (i < niternp):
p.assign(Constant(1))
elif (i >= niternp):
if i == niternp:
print(“\n Starting penalized iterations\n”)
if ((abs(compliance-old_compliance) < 0.01compliance_history[0]) and
(exponent_counter > exponent_update_frequency) ):
# average gray level
gray_level = assemble((theta-thetamin)
(1.-theta)dx)4/volume
p.assign(Constant(min(float(p)
(1+0.3
*(1.+gray_level/2)), pmax)))
exponent_counter = 0
print(" Updated SIMP exponent p = ", float(p))
return exponent_counter

u = Function(V2, name=“Displacement”)

old_compliance = 1e30
ffile = XDMFFile(“topology_optimization.xdmf”)
ffile.parameters[“flush_output”]=True
ffile.parameters[“functions_share_mesh”]=True
compliance_history =

tini=time.time()

for i in range(niter):
start=time.time()
solve(a == L, u, bc, solver_parameters={“linear_solver”: “cg”, “preconditioner”: “hypre_amg”})
ffile.write(thetaold, i)
ffile.write(u, i)

compliance = assemble(action(L, u))
compliance_history.append(compliance)
print("Iteration {}: compliance =".format(i), compliance)

avg_density = update_theta()

update_lagrange_multiplier(avg_density)

exponent_counter = update_exponent(exponent_counter)

# Update theta field and compliance
thetaold.assign(theta)
old_compliance = compliance
finish=time.time()
print("temps écoulé",finish-start)
plt.figure(2)
plot(theta, cmap="bone_r")
plt.title("Density")
plt.show(block=False)
plt.pause(0.1)

tfin=time.time()

plt.figure(4)
plot(u,mode=“displacement”,cmap=“bone_r”)
plt.title(“déplacements”)

the plot at the end represent the amount of deformation on each element in the deformed mesh but not the density field (which is theta). I tried u*theta but it isn’t working. How can I get the kind of plot shown in the fenics documentation?
Thanks for your help!

I would suggest saving the displacement to file (pvd or xdmf) and visualize it with Paraview. In paraview, you have options such as Warp by vector.

You could also use Vedo, see for instance: https://github.com/marcomusy/vedo/blob/master/examples/other/dolfin/elastodynamics.py

Thanks ! Is there a way to plot the evolution directly with the plot function? It would be easier for me as I would like to save each step of the optimization in a .png format

Then you should use vedo, and as illustrated in the example i linked you to, there is a screenshot command.

The dolfin plotting function cannot work in this case? The plot at the end represent the right shape of the deformed mesh, except that I woud like the color of each triangles in the mesh to be mapped thanks to the Function theta wich indicates the density

The built-in dolfin plotting interface was reduced quite a lot when VTK-dependency was removed.

There are ways of hacking such as solution in dolfin, but I would not recommend it as there are other specialized plotting modules such as vedo available, that does this out of the box.

Thank you very much!