Update:
Since version 13.0, all of this has become much, much simpler:
Set up the geometry:
Needs["NDSolve`FEM`"]
L = 1;
h = 0.125;
(*Shear stress on beam*)
ss = 5;
reg = Rectangle[{0, -h}, {L, h}];
mesh = ToElementMesh[reg];
Now, we can use the solid mechanics functionality. We set up variables and parameters:
vars = {{u[x, y], v[x, y]}, {x, y}};
pars = <|"YoungModulus" -> 10^3, "PoissonRatio" -> 33/100,
"ModelForm" -> "PlaneStress", "Thickness" -> 1|>;
Setup an solve the equations:
displacement =
NDSolveValue[{SolidMechanicsPDEComponent[vars, pars] ==
SolidBoundaryLoadValue[x == L, vars,
pars, <|"Pressure" -> {0, ss}|>],
SolidFixedCondition[x == 0, vars, pars]},
vars[[1]], {x, y} \[Element] mesh];
Visualize the displacement:
VectorDisplacementPlot[displacement, {x, y} \[Element] reg]
Compute strain, stress and von Mises stress:
strain = SolidMechanicsStrain[vars, pars, displacement];
stress = SolidMechanicsStress[vars, pars, strain];
vonMisesStress = PDEModels`VonMisesStress[vars, pars, stress];
Visualize the von Mises stress on the deformed geometry:
VectorDisplacementPlot[{displacement,
vonMisesStress}, {x, y} \[Element] reg,
ColorFunction -> "TemperatureMap"]
Voilà.
Old post
There are several part to you question and I'll try to tackle them one by one (not sure I'll be able to do this in one go)
How to calculate stresses
Here is the model problem.
L = 1;
h = 0.125;
(*Shear stress on beam*)
ss = 5;
reg = Rectangle[{0, -h}, {L, h}];
mesh = ToElementMesh[reg];
materialParameters = {Y -> 10^3, \[Nu] -> 33/100};
We use a plane stress formulation as you derived it and under consideration that we do not want the operator to evaluate:
Needs["NDSolve`FEM`"];
ps = {Inactive[
Div][({{-(Y/(1 - \[Nu]^2)),
0}, {0, -((Y (1 - \[Nu]))/(2 (1 - \[Nu]^2)))}}.Inactive[
Grad][u[x, y], {x, y}]), {x, y}] +
Inactive[
Div][({{0, -((Y \[Nu])/(1 - \[Nu]^2))}, {-((Y (1 - \[Nu]))/(2 \
(1 - \[Nu]^2))), 0}}.Inactive[Grad][v[x, y], {x, y}]), {x, y}],
Inactive[
Div][({{0, -((Y (1 - \[Nu]))/(2 (1 - \[Nu]^2)))}, {-((Y \
\[Nu])/(1 - \[Nu]^2)), 0}}.Inactive[Grad][u[x, y], {x, y}]), {x, y}] +
Inactive[
Div][({{-((Y (1 - \[Nu]))/(2 (1 - \[Nu]^2))),
0}, {0, -(Y/(1 - \[Nu]^2))}}.Inactive[Grad][
v[x, y], {x, y}]), {x, y}]};
We then solve
{uif, vif} =
NDSolveValue[{ps == {0, NeumannValue[ss, x == L]},
DirichletCondition[u[x, y] == 0, x == 0],
DirichletCondition[v[x, y] == 0, x == 0]} /.
materialParameters, {u, v}, {x, y} \[Element] mesh];
Note that I only included the plane stress formulation. We will recover the derivatives for the stress computation just now.
dmesh = ElementMeshDeformation[mesh, {uif, vif}, "ScalingFactor" -> 1];
Show[{mesh["Wireframe"],
dmesh["Wireframe"[
"ElementMeshDirective" -> Directive[EdgeForm[Red], FaceForm[]]]]}]
Here is a function to allow to recover the derivatives:
ClearAll[VonMisesStress]
VonMisesStress[{uif_InterpolatingFunction,
vif_InterpolatingFunction}, fac_] := Block[
{dd, df, mesh, coords, dv, ux, uy, vx, vy, ex, ey, gxy, sxx, syy,
sxy},
dd = Outer[(D[#1[x, y], #2]) &, {uif, vif}, {x, y}];
df = Table[Function[{x, y}, Evaluate[dd[[i, j]]]], {i, 2}, {j, 2}];
(* the coordinates from the ElementMesh *)
mesh = uif["Coordinates"][[1]];
coords = mesh["Coordinates"];
dv = Table[df[[i, j]] @@@ coords, {i, 2}, {j, 2}];
ux = dv[[1, 1]];
uy = dv[[1, 2]];
vx = dv[[2, 1]];
vy = dv[[2, 2]];
ex = ux;
ey = vy;
gxy = (uy + vx);
sxx = fac[[1, 1]]*ex + fac[[1, 2]]*ey;
syy = fac[[2, 1]]*ex + fac[[2, 2]]*ey;
sxy = fac[[3, 3]]*gxy;
(*ElementMeshInterpolation[{mesh},
Sqrt[(sxy^2) + (syy^2)+(sxx^2)]]*)
{sxx, syy, sxy}
]
If you uncomment the ElementMeshInterpolation
then this will compute the vonMises stress, but now it returns the stresses.
fac = Y/(1 - \[Nu]^2)*{{1, \[Nu], 0}, {\[Nu], 1, 0}, {0,
0, (1 - \[Nu])/2}};
facm = fac /. materialParameters;
fac // Simplify
{{Y/(1 - \[Nu]^2), (Y \[Nu])/(1 - \[Nu]^2), 0}, {(Y \[Nu])/(
1 - \[Nu]^2), Y/(1 - \[Nu]^2), 0}, {0, 0, Y/(2 + 2 \[Nu])}}
The factor is for plane stress; it needs to be adjusted for plain strain accordingly.
(*vonMisesStress =VonMisesStress[{uif,vif},facm]*)
{sxx, syy, sxy} =
VonMisesStress[{uif, vif}, facm];
ifsxx = ElementMeshInterpolation[{mesh}, sxx];
ifsyy = ElementMeshInterpolation[{mesh}, syy];
ifsxy = ElementMeshInterpolation[{mesh}, sxy];
Let's compare this with your approach:
(* Plot3D[ifsxx[x, y] - \[Sigma]xif[x, y], {x, y} \[Element] mesh,
BoxRatios -> {4, 1, 1}, PlotRange -> All] *)
Plot3D[ifsxy[x, y] - \[Sigma]xyif[x, y], {x, y} \[Element] mesh,
BoxRatios -> {4, 1, 1}, PlotRange -> All]
The differences at the boundary are expected, I think. Additionally, this has the advantage of not creating additional equations that need to be solved for.
Visualize the vonMises stress in the deformed beam:
ElementMeshContourPlot[Sqrt[(sxx^2) + (syy^2) + (sxy^2)],
ElementMeshDeformation[uif["ElementMesh"], {uif, vif} ],
AspectRatio -> Automatic]
So, this is how I'd compute the stresses.
Now, let's consider some of your other questions.
How to specify forces/stresses on the region and boundary.
A force on the entire body (e.g. gravity)
{uif, vif} =
NDSolveValue[{ps == {0, -9.8},
DirichletCondition[u[x, y] == 0, x == 0],
DirichletCondition[v[x, y] == 0, x == 0]} /.
materialParameters, {u, v}, {x, y} \[Element] mesh];
dmesh = ElementMeshDeformation[mesh, {uif, vif}, "ScalingFactor" -> 1];
Show[{mesh["Wireframe"],
dmesh["Wireframe"[
"ElementMeshDirective" -> Directive[EdgeForm[Red], FaceForm[]]]]}]
A force on the boundary:
{uif, vif} =
NDSolveValue[{ps == {0, NeumannValue[ss, x == L]},
DirichletCondition[u[x, y] == 0, x == 0],
DirichletCondition[v[x, y] == 0, x == 0]} /.
materialParameters, {u, v}, {x, y} \[Element] mesh];
dmesh = ElementMeshDeformation[mesh, {uif, vif}, "ScalingFactor" -> 1];
Show[{mesh["Wireframe"],
dmesh["Wireframe"[
"ElementMeshDirective" -> Directive[EdgeForm[Red], FaceForm[]]]]}]
Combined body and boundary force: (Gravity and a load on the right)
{uif, vif} =
NDSolveValue[{ps == {0, -9.8 + NeumannValue[ss, x == L]},
DirichletCondition[u[x, y] == 0, x == 0],
DirichletCondition[v[x, y] == 0, x == 0]} /.
materialParameters, {u, v}, {x, y} \[Element] mesh];
dmesh = ElementMeshDeformation[mesh, {uif, vif}, "ScalingFactor" -> 1];
Show[{mesh["Wireframe"],
dmesh["Wireframe"[
"ElementMeshDirective" -> Directive[EdgeForm[Red], FaceForm[]]]]}]
Sometimes one would like to model geometries that are under an initial stress (e.g. a pre-stressed beam that will be un-stressed once a load is applied). To pre-stress one can use:
preStress = {Inactive[
Div][({{0, -((Y \[Nu])/(1 - \[Nu]^2))}, {-((Y (1 - \[Nu]))/(2 \
(1 - \[Nu]^2))), 0}}.Inactive[Grad][v[x, y], {x, y}]), {x, y}] +
Inactive[Div][
Inactive[
Plus][({{-(Y/(1 - \[Nu]^2)),
0}, {0, -((Y (1 - \[Nu]))/(2 (1 - \[Nu]^2)))}}.Inactive[
Grad][u[x, y], {x, y}]), {{0}, {0}}], {x, y}],
Inactive[
Div][({{0, -((Y (1 - \[Nu]))/(2 (1 - \[Nu]^2)))}, {-((Y \
\[Nu])/(1 - \[Nu]^2)), 0}}.Inactive[Grad][u[x, y], {x, y}]), {x, y}] +
Inactive[Div][
Inactive[
Plus][({{-((Y (1 - \[Nu]))/(2 (1 - \[Nu]^2))),
0}, {0, -(Y/(1 - \[Nu]^2))}}.Inactive[Grad][
v[x, y], {x, y}]), {{ss}, {0}}], {x, y}]};
Note that now we have added a `+ {{ss},{0}} to the second equation (for completeness I added a {{0},{0}} to the first one as well)
Inspecting what is parsed one gets:
{state} =
NDSolve`ProcessEquations[{preStress == {0, 0},
DirichletCondition[u[x, y] == 0, x == 0],
DirichletCondition[v[x, y] == 0, x == 0]} /.
materialParameters, {u, v}, {x, y} \[Element] mesh];
state["FiniteElementData"][
"PDECoefficientData"]["LoadDerivativeCoefficients"]
{{{{0}, {0}}}, {{{5}, {0}}}}
And solving the equation:
{uif, vif} =
NDSolveValue[{preStress == {0, 0},
DirichletCondition[u[x, y] == 0, x == 0],
DirichletCondition[v[x, y] == 0, x == 0]} /.
materialParameters, {u, v}, {x, y} \[Element] mesh];
dmesh = ElementMeshDeformation[mesh, {uif, vif}, "ScalingFactor" -> 1];
Show[{mesh["Wireframe"],
dmesh["Wireframe"[
"ElementMeshDirective" -> Directive[EdgeForm[Red], FaceForm[]]]]}]
Which is the same as your example. Note that no boundary conditions on the right hand side were specified. This beam is pre-stressed.
I do not know how (if at all) one can achieve this with adding the stress equations as you did. I am not saying it's not possible but I don't know how.
A parser:
You could use something like this:
ClearAll[PlaneStress];
PlaneStress[{Y_, nu_}, {u_, v_}, X : {x_, y_}] :=
Module[{pStress},
pStress = -Y/(1 -
nu^2)*{{{{1, 0}, {0, (1 - nu)/2}}, {{0, nu}, {(1 - nu)/2,
0}}}, {{{0, (1 - nu)/2}, {nu, 0}}, {{(1 - nu)/2, 0}, {0, 1}}}};
{Inactive[Div][pStress[[1, 1]].Inactive[Grad][u, X], X] +
Inactive[Div][pStress[[1, 2]].Inactive[Grad][v, X], X],
Inactive[Div][pStress[[2, 1]].Inactive[Grad][u, X], X] +
Inactive[Div][pStress[[2, 2]].Inactive[Grad][v, X], X]}
]
PlaneStress[{Y, nu}, {u[x, y], v[x, y]}, {x, y}]
{Inactive[Div][{{0, -((nu*Y)/(1 - nu^2))}, {-((1 - nu)*Y)/(2*(1 - nu^2)), 0}} .
Inactive[Grad][v[x, y], {x, y}], {x, y}] +
Inactive[Div][{{-(Y/(1 - nu^2)), 0}, {0, -((1 - nu)*Y)/(2*(1 - nu^2))}} .
Inactive[Grad][u[x, y], {x, y}], {x, y}],
Inactive[Div][{{0, -((1 - nu)*Y)/(2*(1 - nu^2))}, {-((nu*Y)/(1 - nu^2)), 0}} .
Inactive[Grad][u[x, y], {x, y}], {x, y}] +
Inactive[Div][{{-((1 - nu)*Y)/(2*(1 - nu^2)), 0}, {0, -(Y/(1 - nu^2))}} .
Inactive[Grad][v[x, y], {x, y}], {x, y}]}
Hope this helps.