Different material properties in subdomains

Hi,

If I use only one material property in the domain, it’s like the following

# Elasticity parameters
E = PETSc.ScalarType(1.0e0)
nu = PETSc.ScalarType(0.4999999)
mu = fem.Constant(domain, E/(2*(1 + nu)))

Now I want to set different Young’s modulus E to two subdomains Omega_0 and Omega_1. It’s the following way to set E:

# Young Modulus E1 and E2 for two different materials
E_0 = 1e4
E_1 = 50e4
def Omega_0(x):
    return x[0]<= 1

def Omega_1(x):
    return x[0] >= 1

E = fem.Function(V)

cells_0 = mesh.locate_entities(domain, domain.topology.dim, Omega_0)
cells_1 = mesh.locate_entities(domain, domain.topology.dim, Omega_1)

E.x.array[cells_0] = np.full_like(cells_0, E_0, dtype=PETSc.ScalarType)
E.x.array[cells_1] = np.full_like(cells_0, E_1, dtype=PETSc.ScalarType)

Could I ask how to set mu, which as a function of E in the two subdomains?
Could I write in the following way?

mu = E/(2*(1 + nu))

Thanks for your help

If I write

mu = E/(2*(1 + nu))

Then it’s a tuple, which is not supported for writing the residual form. How could I transfer it to available type?

Hi, I see that you’re following along with this tutorial? Is your function space V a DG0 space? The main difference that I see between your code (where several lines seem to be missing) and that example code is that you’re trying to use your Young’s modulus E to compute mu with several other PETSc Scalar instances. I would try defining a DG0 function mu and directly set its values on Omega_0 and Omega_1 with your known values for E_0, E_1 and nu:

mu = fem.Function(V)

cells_0 = mesh.locate_entities(domain, domain.topology.dim, Omega_0)
cells_1 = mesh.locate_entities(domain, domain.topology.dim, Omega_1)

mu.x.array[cells_0] = np.full_like(cells_0, E_0/(2*(1 + nu)), dtype=PETSc.ScalarType)
mu.x.array[cells_1] = np.full_like(cells_0, E_1/(2*(1 + nu)), dtype=PETSc.ScalarType)

Yes, I followed with the tutorial mentioned above, the space V here is a CG2 space, I am thinking if want to get the residual, and the residual R should be split into 2 parts: the first part R_0 in subdomain Omega_0 and the other part R_1 in Omega_1, then R = R_0 + R_1. Does that make sense?

P2 = ufl.VectorElement("CG", domain.ufl_cell(), 2)
P1 = ufl.FiniteElement("CG", domain.ufl_cell(), 1)

state_space = fem.FunctionSpace(domain, P2*P1)
V, _ = state_space.sub(0).collapse()
V0, _ = V.sub(0).collapse() #

Yes, I followed with the tutorial mentioned above, the space V here is a CG2 space

Why are you using a CG2 space for your material properties if you just want to set them as different constants in 2 parts of your domain?

I am thinking if want to get the residual, and the residual R should be split into 2 parts: the first part R_0 in subdomain Omega_0 and the other part R_1 in Omega_1, then R = R_0 + R_1. Does that make sense?

I’m not sure what you’re wanting to do here. Without seeing your full code in a single code block (preferably as a minimal working example) it’s hard for anyone to figure out the context of what you’re trying to do.

Hi,

Thanks a lot for your suggestion, I set DG0 space for E, and now problem is solved.

Could I ask why it should be DG0?

If you’re not familiar with Continuous Galerkin (CG) and Discontinuous Galerkin (DG) spaces you should really read up on how they are defined. Very briefly, DG0 is a space of discontinuous piecewise-constant functions. Since you’re trying to just apply constant material properties to different parts of your domain, DG0 contains exactly what you’re trying to do.

1 Like