Problem with variation formula

Hi everyone, i have a problem with variational formula . The error is : UFLValueError: Invalid type conversion: (Argument(FunctionSpace(Mesh(VectorElement(FiniteElement(‘Lagrange’, interval, 1), dim=1), 10), FiniteElement(‘Lagrange’, interval, 1)), 1, None),) can not be converted to any UFL type.

the full code is

‘’'from future import print_function
import matplotlib.pyplot as plt
from fenics import *
import matplotlib.pyplot as plt
from dolfin import *
import numpy as np
#from ufl import *
from mshr import *

nx = 10
epsilon = 0.1
lamda = 1
f = 1

mesh = UnitIntervalMesh(nx)

Q = FunctionSpace(mesh,“P”,1)

plt.figure(figsize=(10, 5))
plot(mesh, title=“Maillage pour n = 10”)

u = TrialFunctions(Q)

v = TestFunctions(Q)

a = inner(grad(u), grad(v))dx + lamdainner(grad(u), v)*dx’’’

Hi sambou-manu,

I think the source of your problem is

u = TrialFunctions(Q)
v = TestFunctions(Q)

I think they should be

u = TrialFunction(Q)
v = TestFunction(Q)

instead. Then, there is another error:

Invalid type conversion: FunctionSpace(Mesh(VectorElement(FiniteElement(‘Lagrange’, interval, 1), dim=1), 60), VectorElement(FiniteElement(‘Lagrange’, interval, 1), dim=1)) can not be converted to any UFL type.

Unfortunately, I am not competent enough to understand how function spaces works, so I tried to copy https://stackoverflow.com/questions/49305949/fenics-evaluate-gradient-of-function-at-point/51551956, but it doesn’t work.

from fenics import *
import matplotlib.pyplot as plt

# Parameters of the problem
nx       = 10
epsilon  = 0.1
lamda    = 1
f        = 1

# Create mesh and define function space
mesh = UnitIntervalMesh(nx)
Q = FunctionSpace(mesh, 'P', 1)

# Define variational problem
u = TrialFunction(Q)
v = TestFunction(Q)

# Compansate the dimension problem in second term - not working
v_vec = VectorFunctionSpace(mesh, "CG", 1)

plt.figure(figsize=(10, 5))
plot(mesh, title='Maillage pour n = 10')

a = inner(grad(u), grad(v))*dx + lamda*inner(grad(u), v_vec)*dx

I would like to learn how it can be solved.

Hi,
What problem are you solving? It would be helpful to provide a succinct background with what you are trying to achieve and a minimal example code that reproduces your issue. You can encapsulate your code within triple fences ```python to format it such that it can be run by others.

from dolfin import *
import matplotlib.pyplot as plt

# Parameters of the problem
nx       = 10
epsilon  = 0.1
lmbda    = 1
f        = 1

# Create mesh and define function space
mesh = UnitIntervalMesh(nx)
Q = FunctionSpace(mesh, 'P', 1)

# Define variational problem
u = TrialFunction(Q)
v = TestFunction(Q)

plt.figure(figsize=(10, 5))
plot(mesh, title='Maillage pour n = 10')
a = inner(grad(u), grad(v))*dx + lmbda*inner(u.dx(0), v)*dx

I would also recommend against using the keyword lambda in python.

the équation is given by : \

-\epsilon u^{''}+ \lambda u^{'} = f \

the boundaries conditions are:\

u(1) = u(0) = 0 \
u is define in (0,1)
we have to find a numérical with finite élément P1 and P2
for P1 i have made this code :
‘’’ from future import print_function
import matplotlib.pyplot as plt
from fenics import *
import matplotlib.pyplot as plt
from dolfin import *
import numpy as np

from mshr import *

Parameters of the problem

nx = 10
epsilon = 0.1
lamda = 1.0
f = 1.0

Create mesh and define function space

mesh = UnitIntervalMesh(nx)

Q = FunctionSpace(mesh,“P”,1)

Define variational problem

plt.figure(figsize=(10, 5))
plot(mesh, title=“Maillage pour n = 10”)

Define the boundaries

u = TrialFunction(Q)

v = TestFunction(Q)

bord1 = ‘near(x[0], 0)’
bord2 = ‘near(x[0], 0)’

define boundary conditions

bcu_bord1 = DirichletBC(Q, Constant((0)), bord1)
bcu_bord2 = DirichletBC(Q, Constant((0)), bord2)
a = epsilon*inner(grad(u), grad(v))dx + lamdainner(u.dx(0), v)*dx
L = dot(f,v)*dx

solve the problem

bcu = [bcu_bord1, bcu_bord2]
w = Function(Q)
solve(a == L, w, bcu)

I want to plot the numérical solution of u but it doesnt work

I think you mistyped (both syntax as well as the actual boundary) the boundary conditions here. It should be:

bord1 = CompiledSubDomain("near(x[0], 0)")
bord2 = CompiledSubDomain("near(x[0], 1)")

A complete code, would thus be

from dolfin import *
import matplotlib.pyplot as plt

# Parameters of the problem
nx       = 10
epsilon  = 0.1
lmbda    = 1
f        = 1

# Create mesh and define function space
mesh = UnitIntervalMesh(nx)
Q = FunctionSpace(mesh, 'P', 1)

# Define variational problem
u = TrialFunction(Q)
v = TestFunction(Q)
w = Function(Q)
bord1 = CompiledSubDomain("near(x[0], 0)")
bord2 = CompiledSubDomain("near(x[0], 1)")

bcs = [
    DirichletBC(Q, Constant(0), bord1),
    DirichletBC(Q,Constant(0), bord2)
]

# plt.figure(figsize=(10, 5))
# plot(mesh, title='Maillage pour n = 10')
a = epsilon*inner(grad(u), grad(v))*dx + lmbda*inner(u.dx(0), v)*dx
f = Constant(1.)
solve(a==inner(f,v)*dx, w, bcs)
plot(w)

thank you very much . i have a last question
the exact solution is define by;
‘’‘u_e = Expression(’(x[0]-((exp(x[0]/0.1)-1)/exp(1/0.1)-1))’, degree=1)

i have made this code ;
‘’‘for n in range(10,10,10):
u_e = Expression(’(x[0]-((exp(x[0]/0.1)-1)/exp(1/0.1)-1))’, degree=1)
u_e = interpolate(u_e, Q)
error = np.abs(u_e.vector().get_local() - w.vector().get_local()).max()
print(‘n = %.2f: error = %.3g’ % (n, error))
print(‘max u:’, w.vector().get_local().max())

the error is always 1
i don’t understand why

Firstly, again, please enclose your code within triple fences (```) so that others can run it.

I think you mean range(10, 101, 10) or something of that sort to check the value of errors with varying mesh size (h). Alternatively you may also use the inbuilt function errornorm to calculate the error with respect to a reference solution (your composite expansion).

Since there is a boundary layer for this (singularly) perturbed equation at x=1, I expect that lagrange finite elements will converge poorly, you may see this by simply plotting your solution

from dolfin import *
import matplotlib.pyplot as plt

# Parameters of the problem
nx       = 10
epsilon  = 0.01
lmbda    = 1
f        = 1

fig, ax = plt.subplots(1,1,figsize=(8,8))
xvalues = np.linspace(0,1,301)
for nx in range(10, 1001, 201):
    # Create mesh and define function space
    mesh = UnitIntervalMesh(nx)
    Q = FunctionSpace(mesh, 'P', 1)

    # Define variational problem
    u = TrialFunction(Q)
    ue = Function(FunctionSpace(UnitIntervalMesh(nx), "P", 4))
    ue.interpolate(Expression("(x[0]-((exp(x[0]/0.1)-1)/exp(1/0.1)-1))", degree=4))

    v = TestFunction(Q)
    w = Function(Q)
    bord1 = CompiledSubDomain("near(x[0], 0)")
    bord2 = CompiledSubDomain("near(x[0], 1)")

    bcs = [
        DirichletBC(Q, Constant(0), bord1),
        DirichletBC(Q,Constant(0), bord2)
    ]

    a = epsilon*inner(grad(u), grad(v))*dx + lmbda*inner(u.dx(0), v)*dx
    f = Constant(1.)
    solve(a==inner(f,v)*dx, w, bcs)
    ax.plot(xvalues, np.array([w(x) for x in xvalues], float), label="nx={}".format(nx))
    print("error with {} elements = {}".format(nx, errornorm(w, ue, mesh=mesh)/norm(ue, "l2")))
ax.legend(loc=0, ncol=3, fontsize=18)

and also some apriori error estimates and consequent strategies for improved approximation here