18

There are many examples of eigenmodes computations for surfaces with Mathematica, such as:

I wanted to compute the slightly more complicated case of eigenmodes of a volume, or, more precisely, a shell (i.e., a volume with one dimension much small than the two others).

The mesh is created with:

ir = ImplicitRegion[0.8 <= x^2 + y^2 <= 1 && 0 <= z <= 3, {x, y, z}];
dr = DiscretizeRegion[ir, {{-1, 1}, {-1, 1}, {0, 2}}];

enter image description here

The 3D wave equation for a linear elastic material is

$$(\lambda+\mu)\boldsymbol\nabla(\boldsymbol\nabla \cdot \mathbf{u})+\mu \Delta \mathbf{u} = \rho \ddot{\mathbf{u}}$$

where lambda and mu are the Lamé parameters. I implemented this PDE (without the RHS) as:

uVec = Through[{u, v, w}[x, y, z]];
vars = {x, y, z};
pde = Table[(lambda + mu)*
    D[Sum[D[uVec[[j]], vars[[j]]], {j, 3}], vars[[i]]] + 
              mu*Sum[D[uVec[[i]], {vars[[j]], 2}], {j, 3}], {i, 3}]

so the goal is to compute the eigenfunctions of this system of PDEs. Let us say the bottom of the cylinder is clamped, that is $u(x,y,0)=0$ or:

dirichlet = DirichletCondition[# == 0, z == 0] & /@ uVec;

The following retunrs the five first eigenfunctions:

{vals, funs} = NDEigensystem[Join[pde,dirichlet], uVec, {x, y, z} \[Element] ir,5]

Now, I would like to vizualize to modal shapes (funs). Each element of funs is a list of three InterpolatingFunctions. I tried ContourPlot3D or VectorPlot3D but no matter the PlotRange, I get InterpolatingFunction :: dmval Input value lies outside the range of data, which I don't undertand: the funs seem well defined on the domain of interest ($[-1,1]^2\times [0,3]$).

So my question is, did I do something wrong, and how to plot the eigenmodes of the shell?

Edit Using user21's answer, I am now able to plot some mode shapes. However, that's really strange. user21's system of PDEs pde2 is the same as mine (except the sign):

 pde2 = stressOperator[Y, nu] /. material
 Activate@pde === -Expand@pde2
 (* True *)

but the results are completely different...

anderstood
  • 14,301
  • 2
  • 29
  • 80

1 Answers1

17

I did not get it to work with your Navier-Cauchy operator, not sure if it is correct. Here is an approach with a standard stress operator:

Needs["NDSolve`FEM`"]

stressOperator[Y_, 
  nu_] := {Inactive[
     Div][{{0, 0, -((Y*nu)/((1 - 2*nu)*(1 + nu)))}, {0, 0, 
       0}, {-Y/(2*(1 + nu)), 0, 0}}.Inactive[Grad][
      w[x, y, z], {x, y, z}], {x, y, z}] + 
   Inactive[
     Div][{{0, -((Y*nu)/((1 - 2*nu)*(1 + nu))), 0}, {-Y/(2*(1 + nu)), 
       0, 0}, {0, 0, 0}}.Inactive[Grad][v[x, y, z], {x, y, z}], {x, y,
      z}] + Inactive[
     Div][{{-((Y*(1 - nu))/((1 - 2*nu)*(1 + nu))), 0, 
       0}, {0, -Y/(2*(1 + nu)), 0}, {0, 0, -Y/(2*(1 + nu))}}.Inactive[
       Grad][u[x, y, z], {x, y, z}], {x, y, z}], 
  Inactive[Div][{{0, 0, 0}, {0, 
       0, -((Y*nu)/((1 - 2*nu)*(1 + nu)))}, {0, -Y/(2*(1 + nu)), 
       0}}.Inactive[Grad][w[x, y, z], {x, y, z}], {x, y, z}] + 
   Inactive[
     Div][{{0, -Y/(2*(1 + nu)), 0}, {-((Y*nu)/((1 - 2*nu)*(1 + nu))), 
       0, 0}, {0, 0, 0}}.Inactive[Grad][u[x, y, z], {x, y, z}], {x, y,
      z}] + Inactive[
     Div][{{-Y/(2*(1 + nu)), 0, 
       0}, {0, -((Y*(1 - nu))/((1 - 2*nu)*(1 + nu))), 0}, {0, 
       0, -Y/(2*(1 + nu))}}.Inactive[Grad][v[x, y, z], {x, y, z}], {x,
      y, z}], 
  Inactive[Div][{{0, 0, 0}, {0, 
       0, -Y/(2*(1 + nu))}, {0, -((Y*nu)/((1 - 2*nu)*(1 + nu))), 
       0}}.Inactive[Grad][v[x, y, z], {x, y, z}], {x, y, z}] + 
   Inactive[
     Div][{{0, 0, -Y/(2*(1 + nu))}, {0, 0, 
       0}, {-((Y*nu)/((1 - 2*nu)*(1 + nu))), 0, 0}}.Inactive[Grad][
      u[x, y, z], {x, y, z}], {x, y, z}] + 
   Inactive[
     Div][{{-Y/(2*(1 + nu)), 0, 0}, {0, -Y/(2*(1 + nu)), 0}, {0, 
       0, -((Y*(1 - nu))/((1 - 2*nu)*(1 + nu)))}}.Inactive[Grad][
      w[x, y, z], {x, y, z}], {x, y, z}]}

material = {nu -> 1/3, Y -> 200*10^9};
rls = {lambda -> nu*Y/((1 + nu)*(1 - 2 nu)), mu -> Y/(2 (1 + nu))} /. 
   material;
uVec = Through[{u, v, w}[x, y, z]];
vars = {x, y, z};
pde = stressOperator[Y, nu] /. material;
(*pde=Table[(lambda+mu)*D[Sum[D[uVec[[j]],vars[[j]]],{j,3}],vars[[i]]]\
+mu*Sum[D[uVec[[i]],{vars[[j]],2}],{j,3}],{i,3}]/.rls;*)

Use a somewhat finer mesh than the default. I use a first order mesh because a second order mesh would take more time to compute.

ir = ImplicitRegion[0.8 <= x^2 + y^2 <= 1 && 0 <= z <= 3, {x, y, z}];
mesh = ToElementMesh[ir, {{-1, 1}, {-1, 1}, {0, 2}}, "MeshOrder" -> 1,
   MaxCellMeasure -> 0.0005]

nrEigen = 12;
{vals, vecs} = 
  NDEigensystem[
   Join[pde, DirichletCondition[# == 0, z == 0] & /@ uVec], {u, v, 
    w}, {x, y, z} \[Element] mesh, nrEigen];

GraphicsGrid[Partition[Show[
     MeshRegion[
      ElementMeshDeformation[mesh, vecs[[#]], "ScalingFactor" -> 1/5]],
     ElementMeshEdgeframe3D[mesh]] & /@ Range[nrEigen], 3]]

enter image description here

If you get it to work with a Navier-Cauchy operator, let me know.

There are a few other questions related to this, for example here and here.

enter image description here

Update:

Let's reconsider the Cauchy-Navier operator. Here is a different form of it:

pde2 = -((lambda + mu) Grad[
       Div[{u[x, y, z], v[x, y, z], w[x, y, z]}, {x, y, z}], {x, y, 
        z}] + mu Laplacian[{u[x, y, z], v[x, y, z], w[x, y, z]}, {x, 
        y, z}]) /. rls

In a first step one might compare this to the stress operator above:

Thread[Activate[pde] == pde2] // Simplify
{True, True, True}

This, however, is not the whole story. Let's look at what actually gets parsed for the inactive stress operator:

{state} = 
  NDSolve`ProcessEquations[
   Join[Thread[pde1 == {0, 0, 0}], 
    DirichletCondition[# == 0, z == 0] & /@ uVec], {u, v, 
    w}, {x, y, z} \[Element] mesh];
pdec = state["FiniteElementData"]["PDECoefficientData"];
pdec["DiffusionCoefficients"] // MatrixForm

enter image description here

Now, compare that to the activated or Navier-Cauchy operator:

{state} = 
  NDSolve`ProcessEquations[
   Join[Thread[pde2 == {0, 0, 0}], 
    DirichletCondition[# == 0, z == 0] & /@ uVec], {u, v, 
    w}, {x, y, z} \[Element] mesh];
pdec = state["FiniteElementData"]["PDECoefficientData"];
pdec["DiffusionCoefficients"] // MatrixForm

enter image description here

Now, closely look at the off diagonal elements and compare them. The inactive stress operator is able to retain the the skew off-diagonal elements of the operator while this form of the Cauchy-Navier operator is not. I currently do not see a way to make the Cauchy-Navier operator behave the same way as the inactive stress operator. So my advice is to use the inactive stress operator for 3D stress problems.

Update:

This behavior is expected and, in fact, was one of the main motivations for introducing Inactive. You can find this documented and explained with a 2D example in the section Formal Partial Differential Equations.

user21
  • 39,710
  • 8
  • 110
  • 167
  • 1
    Hope you don't mind the edit, couldn't resist :) – Kuba Jan 31 '18 at 09:15
  • @Kuba Yea! Great! Love it - reminds me of that dancing baby. We need sound on this page! Thx. – user21 Jan 31 '18 at 09:36
  • This is what I get using my pde and GraphicsGrid[ Partition[ Show[MeshRegion[ ElementMeshDeformation[mesh, vecs[[#]], "ScalingFactor" -> 1/5]]] & /@ Range[nrEigen], 3]]: https://imgur.com/a/YIeDO. Looks different but looks "a bit" like modes too... I'll double check later. (and thanks!) – anderstood Jan 31 '18 at 10:41
  • @anderstood, what platform and M version are you using, what happens with a finer mesh? – user21 Jan 31 '18 at 10:48
  • I'm using MMA 11.0 with Ubuntu 16.04. The result does not converge easily, even with MaxCellMeasure -> 0.0001. I'm not sure what is wrong with my pde. I'll try on a plate to verify. – anderstood Jan 31 '18 at 15:46
  • @anderstood, hm, I no longer have 11.0 installed. It works fine in 11.1 and 11.2 on Linux. It could very well be that there was an issue that is fixed now. – user21 Jan 31 '18 at 15:54
  • You mean, it works fine with my pde? Check my edit: your system and mine are the same (except the sign), so there should be no difference?! – anderstood Jan 31 '18 at 15:59
  • @anderstood, no not with your Navier-Cauchy PDE. If you want to check that I'd suggest to make a simple 3D beam, fixed on the left and put some force on the right and look at the deformation. Once with the PDE from this post and once with your PDE. – user21 Jan 31 '18 at 16:02
  • @anderstood, please see the update. – user21 Feb 01 '18 at 07:43
  • @Hugh, I think you might be interested in the findings about the Navier-Cauchy operator too. – user21 Feb 01 '18 at 09:58
  • Great! Thank you for the edit! Don't you think that's a bug? – anderstood Feb 01 '18 at 16:00
  • @anderstood, no, that's not a bug. See update for more info. – user21 Feb 02 '18 at 07:56
  • @user21 Thanks for pointing this out. Clearly there is no simple way of putting textbook equations into the FE method. Pity. – Hugh Feb 07 '18 at 18:02