Subdomains with different material properties

Project kappa into a suitable function space, and visualize it with the plot command or with paraview

Thank you very much, one last question. So, when I want to use kappa in the variational formulation, should I use the kappa projection or with the kappa I already calculated in my previous code?

You should use the UserExpression, as it is evaluated at quadrature points rather than at degrees of freedom.

Hi
I am trying to solve a problem with different materials.
The code i am using is:

from fenics import *

# Create mesh and define function space
mesh = UnitSquareMesh(8, 8)
V = FunctionSpace(mesh, 'P', 1)

# Define boundary condition
u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=2)

def boundary(x, on_boundary):
    return on_boundary

bc = DirichletBC(V, u_D, boundary)

#使用网格函数定义子域
tol = 1E-14
class Omega_0(SubDomain):
    def inside(self, x, on_boundary):
        return x[1] <= 0.5 + tol

class Omega_1(SubDomain):
    def inside(self, x, on_boundary):
        return x[1] >= 0.5 - tol

materials = MeshFunction('size_t', mesh, mesh.topology().dim(), 0)

subdomain_0 = Omega_0()
subdomain_1 = Omega_1()
#这会将属于 Ω0 的每个单元上的网格函数材质值设置为 0,将属于 Ω1 的所有单元上的网格函数材质值设置为 1
subdomain_0.mark(materials, 0)
subdomain_1.mark(materials, 1)

plot(materials)
#File(’materials.xml.gz’) << materials

k_0 = 1
k_1 = 0.01

#使用网格函数定义可变系数K
class K(UserExpression):
    def __init__(self, materials, k_0, k_1, **kwargs):
        super().__init__(**kwargs)
        self.materials = materials
        self.k_0 = k_0
        self.k_1 = k_1

def eval_cell(self, values, x, cell):
        if self.materials[cell.index] == 0:
            values[0] = self.k_0
        else:
            values[0] = self.k_1

def values_shape(self):
    return (1,)

Kappa = K(materials, k_0, k_1, degree=0)

# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Constant(-6.0)
a = Kappa*dot(grad(u), grad(v))*dx
L = f*v*dx

# Compute solution
u = Function(V)
solve(a == L, u, bc)

# Plot solution and mesh
plot(u)
plot(mesh)

However, I always get this Error:
WARNING: user expression has not supplied value_shape method or an element. Assuming scalar element.
Solving linear variational problem.

RuntimeError                              Traceback (most recent call last)
Cell In[24], line 68
     66 # Compute solution
     67 u = Function(V)
---> 68 solve(a == L, u, bc)
     70 # Plot solution and mesh
     71 plot(u)

File ~/anaconda3/envs/fenicsproject/lib/python3.12/site-packages/dolfin/fem/solving.py:220, in solve(*args, **kwargs)
    217 # Call variational problem solver if we get an equation (but not a
    218 # tolerance)
    219 elif isinstance(args[0], ufl.classes.Equation):
--> 220     _solve_varproblem(*args, **kwargs)
    222 # Default case, just call the wrapped C++ solve function
    223 else:
    224     if kwargs:

File ~/anaconda3/envs/fenicsproject/lib/python3.12/site-packages/dolfin/fem/solving.py:247, in _solve_varproblem(*args, **kwargs)
    245     solver = LinearVariationalSolver(problem)
    246     solver.parameters.update(solver_parameters)
--> 247     solver.solve()
    249 # Solve nonlinear variational problem
    250 else:
    251 
    252     # Create Jacobian if missing
    253     if J is None:

Here is a corrected version of your code that runs, please study it carefully:

from fenics import *

# Create mesh and define function space
mesh = UnitSquareMesh(8, 8)
V = FunctionSpace(mesh, 'P', 1)

# Define boundary condition
u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=2)

def boundary(x, on_boundary):
    return on_boundary

bc = DirichletBC(V, u_D, boundary)

#使用网格函数定义子域
tol = 1E-14
class Omega_0(SubDomain):
    def inside(self, x, on_boundary):
        return x[1] <= 0.5 + tol

class Omega_1(SubDomain):
    def inside(self, x, on_boundary):
        return x[1] >= 0.5 - tol

materials = MeshFunction('size_t', mesh, mesh.topology().dim(), 0)

subdomain_0 = Omega_0()
subdomain_1 = Omega_1()
#这会将属于 Ω0 的每个单元上的网格函数材质值设置为 0,将属于 Ω1 的所有单元上的网格函数材质值设置为 1
subdomain_0.mark(materials, 0)
subdomain_1.mark(materials, 1)

plot(materials)
#File(’materials.xml.gz’) << materials

k_0 = 1
k_1 = 0.01

#使用网格函数定义可变系数K
class K(UserExpression):
    def __init__(self, materials, k_0, k_1, **kwargs):
        super().__init__(**kwargs)
        self.materials = materials
        self.k_0 = k_0
        self.k_1 = k_1

    def eval_cell(self, values, x, cell):
        if self.materials[cell.index] == 0:
            values[0] = self.k_0
        else:
            values[0] = self.k_1

    def value_shape(self):
        return ()

Kappa = K(materials, k_0, k_1, degree=0)

# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Constant(-6.0)
a = Kappa*dot(grad(u), grad(v))*dx
L = f*v*dx

# Compute solution
u = Function(V)
solve(a == L, u, bc)

# Plot solution and mesh
plot(u)
plot(mesh)

It works now thank you very much.