123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- // This code simulates the static deflection of an electrically actuated 2D micromembrane.
- // The problem is nonlinear because of the electrostatic-elastic coupling.
- //
- // The electrostatic problem and the electrostatic forces are computed on a mesh
- // deformed by the mechanical displacement. The mesh in the vacuum gap below the membrane
- // is deformed smoothly by solving an additional Laplace problem.
- //
- // The interpolation order for the electric potential field and mechanical displacement
- // is adapted to every geometrical region.
- #include "sparselizardbase.h"
- using namespace mathop;
- void sparselizard(void)
- {
- // The domain regions as defined in 'cmut2d.geo':
- int insulator = 1, pillars = 2, vacuumgap = 3, membrane = 4, ground = 5, clamp = 5, electrode = 6;
-
- // The mesh can be curved!
- mesh mymesh("cmut2d.msh");
-
- // Define the region for the mechanical problem:
- int solid = regionunion({insulator, pillars, membrane});
- // Define the region for the electric problem:
- int electricdomain = regionunion({insulator, pillars, membrane, vacuumgap});
-
- // Nodal shape functions 'h1' for the electric potential field v
- // and membrane deflection u (u has components x and y).
- // umesh smoothly deforms the mesh in the vacuum gap for a given membrane deflection.
- field u("h1xy"), umesh("h1xy"), v("h1");
- // Use interpolation order:
- //
- // - 3 for u on the membrane
- // - 2 for u on the pillars
- // - 1 elsewhere
- //
- // - 1 for the electric potential v
- //
- // Default order is 1.
-
- u.setorder(pillars, 2);
- u.setorder(membrane, 3);
-
- // Clamp and ground (i.e. 0 valued-Dirichlet conditions for u and v):
- u.setconstraint(clamp);
- v.setconstraint(ground);
- // Force the electric potential on the electrode to a close-to-pull-in voltage:
- v.setconstraint(electrode, 200);
-
- // E is Young's modulus. nu is Poisson's ratio.
- // epsilon is the electric permittivity.
- //
- // The membrane is polysilicon, the insulator is silicon dioxyde.
-
- parameter E, nu, epsilon;
-
- E|insulator = 70e9;
- E|pillars = 150e9;
- E|membrane = 150e9;
-
- nu|insulator = 0.17;
- nu|pillars = 0.3;
- nu|membrane = 0.3;
-
- epsilon|vacuumgap = 8.854e-12;
- epsilon|insulator = 3.9*8.854e-12;
- epsilon|pillars = 11.7*8.854e-12;
- epsilon|membrane = 11.7*8.854e-12;
-
- // An electrostatic formulation is used for the electric problem.
- // An elasticity formulation is used for the mechanical problem.
- formulation electrostatics, elasticity;
-
- // Weak electrostatic formulation, computed on the mesh deformed by field umesh:
- electrostatics += integral(electricdomain, umesh, epsilon*grad(dof(v))*grad(tf(v)));
-
- // The linear elasticity formulation is classical and thus predefined:
- elasticity += integral(solid, predefinedelasticity(dof(u), tf(u), E, nu, "planestrain"));
-
- // Electrostatic forces, computed on the elements of the whole electric domain
- // but with mechanical deflection test functions tf(u) only on solid.
- //
- // The electrostatic forces often appear in MEMS simulations and are thus predefined.
- // The inputs are the gradient of the test function of u defined on the mechanical domain,
- // the gradient of the previously computed electric potential field and the electric permittivity.
- //
- // The electrostatic forces are computed on the mesh deformed by field umesh.
- elasticity += integral(electricdomain, umesh, predefinedelectrostaticforce(tf(u,solid), grad(v), epsilon));
-
-
- // Solve the Laplace equation in the vacuum gap to smoothly deform the mesh.
- // umesh is forced to field u on region solid:
- umesh.setconstraint(solid, u);
- formulation laplacian;
- laplacian += integral(vacuumgap, grad(dof(compx(umesh)))*grad(tf(compx(umesh))) + grad(dof(compy(umesh)))*grad(tf(compy(umesh))) );
-
-
- // NONLINEAR ITERATION TO GET THE STATIC DEFLECTION:
-
- // Start with an all-zero solution vector for the elasticity formulation:
- vec solu(elasticity);
-
- double relresnorm = 1; int iter = 0;
- while (relresnorm > 1e-5)
- {
- electrostatics.generate();
- vec solv = solve(electrostatics.A(), electrostatics.b());
- // Transfer the data from the solution vector to the v field:
- v.setdata(electricdomain, solv);
- // Write the electric field with an order 1 interpolation (default).
- // The electric field is computed and saved on the geometry deformed by umesh.
- (-grad(v)).write(electricdomain, umesh, "E.pos");
-
- // Use the now known electric potential v to compute the membrane deflection:
- elasticity.generate();
-
- vec b = elasticity.b();
- mat A = elasticity.A();
- // Compute the norm of the relative residual:
- relresnorm = (b-A*solu).norm()/b.norm();
- solu = solve(A,b);
- u.setdata(solid, solu);
- // Write the deflection u with an order 3 interpolation:
- u.write(solid, "u.pos", 3);
-
- // Smooth the mesh on the vacuum gap:
- laplacian.generate();
- vec solumesh = solve(laplacian.A(), laplacian.b());
- // Save the smoothed mesh on the vacuum region:
- umesh.setdata(vacuumgap, solumesh);
- // Also save the u field on region solid to umesh.
- // This is done by selecting field u with |u on the solu vector.
- umesh.setdata(solid, solu|u);
- umesh.write(electricdomain, "umesh.pos", 3);
-
- // Print the iteration number and relative residual norm:
- std::cout << "Relative residual norm @iteration " << iter << " is " << relresnorm << std::endl;
- iter++;
- }
-
- // Code validation line. Can be removed.
- std::cout << (compy(grad(v)).integrate(vacuumgap, u, 4) < 0.0022901 && compy(grad(v)).integrate(vacuumgap, u, 4) > 0.0022900);
- }
- int main(void)
- {
- SlepcInitialize(0,{},0,0);
- sparselizard();
- SlepcFinalize();
- return 0;
- }
|