main.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // This code gives the static deflection and mechanical vibration eigenfrequencies and eigenmodes
  2. // around that static deflection for a 3D bilayer disk (800um diameter, 10um thick) whose top layer is prestressed,
  3. // whose bottom layer is clamped at its external boundary and on top of which the atmospheric pressure is pushing.
  4. //
  5. // Small-strain GEOMETRIC NONLINEARITY is used to simulate this prestressed membrane.
  6. //
  7. // With minimal extra effort the buckling of the membrane can be simulated with the Newmark time
  8. // resolution available in sparselizard.
  9. #include "sparselizardbase.h"
  10. using namespace mathop;
  11. void sparselizard(void)
  12. {
  13. // The domain regions as defined in 'disk.geo':
  14. int botlayer = 1, toplayer = 2, sur = 3, top = 4;
  15. // The mesh can be curved!
  16. mesh mymesh("disk.msh");
  17. // Define the whole domain for convenience:
  18. int vol = regionunion({botlayer, toplayer});
  19. // Nodal shape functions 'h1' with 3 components.
  20. // Field u is the membrane deflection.
  21. field u("h1xyz");
  22. // Use interpolation order 2 on the whole domain:
  23. u.setorder(vol, 2);
  24. // Clamp on surface 'sur' (i.e. 0 valued-Dirichlet conditions):
  25. u.setconstraint(sur);
  26. // E is Young's modulus [Pa]. nu is Poisson's ratio []. rho is the density [kg/m^3].
  27. // The material is a polymer.
  28. parameter E, nu, rho;
  29. E|botlayer = 10e9; nu|botlayer = 0.4; rho|botlayer = 1500;
  30. E|toplayer = 15e9; nu|toplayer = 0.4; rho|toplayer = 2000;
  31. formulation elasticity;
  32. // The linear elasticity formulation with geometric nonlinearity for small strains is predefined:
  33. elasticity += integral(botlayer, predefinedelasticity(dof(u), tf(u), u, E, nu, 0.0));
  34. // The top layer is prestressed with 10 MPa in the x and y direction (sigma xx and yy):
  35. expression prestress(6,1,{10e6,10e6,0,0,0,0});
  36. elasticity += integral(toplayer, predefinedelasticity(dof(u), tf(u), u, E, nu, prestress));
  37. // Add the atmospheric pressure force at the top face (perpendicular to it).
  38. // With u provided as second argument all calculations are performed on the deformed
  39. // mesh for this term (thus the normal is updated with the deflection).
  40. double pressure = 1e5;
  41. elasticity += integral(top, u, -pressure*normal(top)*tf(u));
  42. ///// STEP 1: GET THE STATIC DEFLECTION WITH A NONLINEAR LOOP:
  43. // Start with an all-zero deflection:
  44. vec solu(elasticity);
  45. double relres = 1;
  46. while (relres > 1e-5)
  47. {
  48. // Generate and get the algebraic matrix A and vector b of the static Ax = b problem:
  49. elasticity.generate();
  50. mat A = elasticity.A();
  51. vec b = elasticity.b();
  52. // Compute the relative residual at the previous iteration:
  53. relres = (b-A*solu).norm() / b.norm();
  54. // Solve for x in Ax = b:
  55. solu = solve(A, b);
  56. // Make solution available in field u:
  57. u.setdata(vol, solu);
  58. // Write the deflection on the top surface of the membrane with an order 2 interpolation:
  59. u.write(top, "ustatic.pos", 2);
  60. std::cout << "Relative residual is: " << relres << std::endl;
  61. }
  62. std::cout << std::endl << "Peak static deflection: " << norm(u).max(vol,4)[0]*1e6 << " um" << std::endl;
  63. ///// STEP 2: COMPUTE THE EIGENFREQUENCIES AND EIGENMODES AROUND THE STATIC DEFLECTION:
  64. // Add the inertia terms to the formulation (required for eigenvalue computation):
  65. elasticity += integral(vol, -rho*dtdt(dof(u))*tf(u));
  66. elasticity.generate();
  67. // Get the stiffness and mass matrix:
  68. mat K = elasticity.K();
  69. mat M = elasticity.M();
  70. // Remove the rows and columns corresponding to the 0 constraints:
  71. K.removeconstraints();
  72. M.removeconstraints();
  73. // Create the object to solve the generalised eigenvalue problem K*x = lambda*M*x :
  74. eigenvalue eig(K, M);
  75. // Compute the 5 eigenvalues closest to the target magnitude 0.0 (i.e. the 5 first ones):
  76. eig.compute(5, 0.0);
  77. // Print the eigenfrequencies:
  78. eig.printeigenfrequencies();
  79. // The eigenvectors are real thus we only need the real part:
  80. std::vector<vec> myeigenvectors = eig.geteigenvectorrealpart();
  81. // Loop on all eigenvectors found:
  82. for (int i = 0; i < myeigenvectors.size(); i++)
  83. {
  84. // Transfer the data from the ith eigenvector to field u:
  85. u.setdata(top, myeigenvectors[i]);
  86. // Write the deflection on the top surface of the membrane with an order 2 interpolation:
  87. u.write(top, "ueigenmode"+std::to_string(i)+".pos", 2);
  88. }
  89. // Code validation line. Can be removed.
  90. std::cout << (eig.geteigenvaluerealpart()[0] < 1.1453e+12 && eig.geteigenvaluerealpart()[0] > 1.1451e+12);
  91. }
  92. int main(void)
  93. {
  94. SlepcInitialize(0,{},0,0);
  95. sparselizard();
  96. SlepcFinalize();
  97. return 0;
  98. }