Visualizing meshes with different Y-X scales in FEniCS/Python

I am used to creating meshes through GMSH (.msh), transform them into XDMF format by meshio-convert and read them in python as follows:

mesh = Mesh()
filename = "../meshes/fixed_bed-mesh.xdmf"
with XDMFFile(MPI.comm_world, filename) as infile:
    infile.read(mesh)

This mesh corresponds to a rectangle with dimensions 5.0 x 0.01. I have solved several PDEs systems with FEniCS over this kind of meshes but, given that this rectangle is too thin, I have been visualizing the results with ParaView since I am allowed to scale any direction (X, Y or Z).

For instance: Without Y-axis scaling (top mesh), with Y-axis scaling x 10 (bottom mesh).

However, I want to see the results directly in Python. Accordingly, I found the way to plot triangular grids with MatPlotLib as in the next short example:

from dolfin import *
from mshr import *
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np

# Mesh generation – but I usually create them with GMSH as mentioned above.
domain = Rectangle(Point(0.0, 0.0), Point(5.0, 0.01))
mesh = generate_mesh(domain, 20)
V = FunctionSpace(mesh, 'CG', 2)

f_exp = Expression('sin(2*pi*(x[0]*x[0]+x[1]*x[1]))', degree=2)
f = interpolate(f_exp, V)

n = mesh.num_vertices()
d = mesh.geometry().dim()

# Create the triangulation
mesh_coordinates = mesh.coordinates().reshape((n, d))
triangles = np.asarray([cell.entities(0) for cell in cells(mesh)])
triangulation = tri.Triangulation(mesh_coordinates[:, 0], 
                                  mesh_coordinates[:, 1], triangles)

# Get the z values for each vertex
z = np.asarray([f(point) for point in mesh_coordinates])

# Plot FEniCS solution with tripcolor function
cmap = plt.cm.jet
plt.figure()
plt.tripcolor(triangulation, z, cmap=cmap, shading='gouraud')
plt.colorbar()

The problem is that I don´t know how to scale Y-axis or any direction so that I can evidence what I normally see in ParaView. Is there any way to do that either with Matplotlib or FEniCS plots functions ?. Or will I be forced to keep using ParaView to visualize the results of my simulations when working with such thin meshes?

If somebody needs any additional information, I will be heedful.
Thank you very much for your attention and helpful suggestion.

best regards!

Try using

plt.axis('equal')

I had already tried it before, but the thing is that it modifies the figure size, It doesn’t extend (scale) the mesh such as ParaView does.

E.g.

Hi Santiago, a possible solution is this:

from dolfin import *
from mshr import *

domain = Rectangle(Point(0.0, 0.0), Point(5.0, 0.01))
mesh = generate_mesh(domain, 20)
V = FunctionSpace(mesh, "CG", 2)

f_exp = Expression("sin(2*pi*(x[0]*x[0]+x[1]*x[1]))", degree=2)
f = interpolate(f_exp, V)

####################################################
from vtkplotter.dolfin import MeshActor, show

actor = MeshActor(f)  # build a vtkActor from expression
actor.wireframe(False).lw(0.1).scale([1,100,1]).addScalarBar(horizontal=True)

show(actor, axes=8, bg="white", size=(500,900))  # show mesh with axes type 8

1 Like

…another possibility using the plot shortcut:

from vtkplotter.dolfin import plot

plt = plot(f, cmap='plasma',
           xtitle = 'y-coord is scaled by factor 100',
           interactive=False)
plt.actors[0].scale([1,100,1]) # retrieve actor object
plt.show(interactive=True)

1 Like

Hello Marcomusy, I am very thankful for your help and fast reply. I haven’t used your VTKplotter module before. It looks prominent!

Great!, Is there any way to hide the finite element grid from behind?
When working with highly refined meshes, colormaps could get overcasted.

to hide the line you can just set lw=0.
you can also elevate the scalar in z by setting e.g. warpZfactor=.1

Perfect!, It is just necessary to set it in two different lines, as follows:

actor.wireframe(False).lw(0.0)
actor.wireframe(False).scale([1,100,1]).addScalarBar(horizontal=True)

not really necessary, you can concatenate the operations in any order

actor.wireframe(False).lw(0.0).scale([1,100,1]).addScalarBar(horizontal=True)

Strangely, it produces this error when I try it.

actor.wireframe(False).lw(0).scale([1,5,1]).addScalarBar(horizontal=True)

AttributeError: ‘NoneType’ object has no attribute ‘scale’

you’re right ! you found a bug :grin:

2 Likes