Hello Thibaut,
It's been a while since your original post, but I have figured out how to make the PDE toolbox accept the Young's modulus as a function of coordinates.
It was a nasty ride, so if there's anyone interested, buckle up.
As noted by Thibaut, the 'structural' model object accepts the material properties only as constants. Who knows what difficulty it was to make them definable as functions (in the thermal objects you can set a variable conductivity easily). So the key is to use the general PDE object as described in, for example, here. The general PDEmodel object is more flexible than dedicated structural or thermal objects - you can define your PDE(s) the way you want and specify all the coefficients the way you want. The drawback, one of them at least, is that you have to interpret all the results yourself. Recalculate displacements into stresses, etc.
Let's look at an example. I want to stretch a square plate with a cylindrical inclusion of higher stiffness. You can see it as a composite unite cell (a fibre in matrix).
model = createpde(3);
g = importGeometry(model,'square_flat.stl');
extrude(g,10);
pdegplot(model,'EdgeLabel','on','VertexLabels','on','FaceLabels','on');
Generate the mesh
Hmax = 3.5;
msh = generateMesh(model,'GeometricOrder','quadratic','Hmax', Hmax);
figure; pdemesh(model);
title('Mesh with Quadratic Triangular Elements');
dofss = length(msh.Nodes)
Boundary conditions
applyBoundaryCondition(model,'dirichlet','Face',3,'u',[0,0,0]);
applyBoundaryCondition(model,'dirichlet','Face',5,'u',[110,0,0]);
Here is a trick to define constant isotropic material for the general PDE object. I found it in the depths of the documentation. It uses an undocumented function elasticityC3D, inside which is this:
function cmat = elasticityC3D(E,nu)
G = E/(2*(1+nu));
c1 = E*(1-nu)/((1+nu)*(1-2*nu));
c12 = c1*nu/(1-nu);
C11 = [c1 0 G 0 0 G];
C12 = [0 G 0 c12 0 0 0 0 0];
C13 = [0 0 G 0 0 0 c12 0 0];
C22 = [G 0 c1 0 0 G];
C23 = [0 0 0 0 0 G 0 c12 0];
C33 = [G 0 G 0 0 c1];
cmat = [C11 C12 C22 C13 C23 C33]';
end
If we opt for the constant modulus, we define the PDE coefficients as follows:
E = 200e9;
nu = 0.3;
specifyCoefficients(model,'m',0,...
'd',0,...
'c',elasticityC3D(E,nu),...
'a',0,...
'f',[0;0;0]);
Solve the system:
rslt = solvepde(model);
u = rslt.NodalSolution;
pdeplot3D(model,'ColorMapData',u(:,1)); title('ux')
pdeplot3D(model,'ColorMapData',u(:,2)); title('uy')
pdeplot3D(model,'ColorMapData',u(:,3)); title('uz')
And we see the displecement fields as expected
Now, instead of using the elasticityC3D, let's define our own function, where the non-zero coefficient matrix entries are going to depend on coordinates. I am using a sort of logistic function to draw a circular field with certain slope. But it does not necessarily have to be like this.
function cmatrix = ccoeffunction(location,state)
E_m = 100E2;
E_f = 10E9;
nu = 0.3;
kk = 3000;
r = 35;
x0 = 50; y0 = 50;
E = E_m + (E_f -E_m)./( 1 + exp( kk*( sqrt((location.x-x0).^2+(location.y-y0).^2) - 1*r)) );
cmatrix = zeros(45,numel(location.x));
G = E./(2*(1+nu));
c1 = E.*(1-nu)./((1+nu)*(1-2*nu));
c12 = c1.*nu/(1-nu);
cmatrix (1,:) = c1;
cmatrix (3,:) = G;
cmatrix (6,:) = G;
cmatrix (8,:) = G;
cmatrix (10,:) = c12;
cmatrix (16,:) = G;
cmatrix (18,:) = c1;
cmatrix (21,:) = G;
cmatrix (24,:) = G;
cmatrix (28,:) = c12;
cmatrix (36,:) = G;
cmatrix (38,:) = c12;
cmatrix (40,:) = G;
cmatrix (42,:) = G;
cmatrix (45,:) = c1;
end
See the section 3N(3N+1)/2-Element Column Vector c, 3-D Systems.
Let's now re-evaluate the coefficients and solve the problem.
specifyCoefficients(model,'m',0,...
'd',0,...
'c',@ccoeffunction,...
'a',0,...
'f',[0;0;0]);
rslt = solvepde(model);
u = rslt.NodalSolution;
pdeplot3D(model,'ColorMapData',u(:,1)); title('ux')
pdeplot3D(model,'ColorMapData',u(:,2)); title('uy')
pdeplot3D(model,'ColorMapData',u(:,3)); title('uz')
And now we see the fictitious fibre in the displacement fields.
During the solve, there was a warning of poor conditioning. So it's probably better to define different geometric domains for such problem. But this suffices for the example.
I hope it helps someone,
Roman