// This simple code shows how to setup a 3D mechanical problem with a periodic condition. // A central 1.3 um thick, 50 um diameter polysilicon micromembrane stands above a 300 nm deep cavity. // The central micromembrane is surrounded by 6 identical ones, one every 60 degrees. // Assuming a periodic vibration with 60 degrees periodicity allows to reduce the problem to only a 1/6 of the geometry. // // In the .nas mesh used the meshes on both faces of the periodic condition do not match. #include "sparselizardbase.h" using namespace mathop; void processmesh(void); void sparselizard(void) { // Name the regions for the inner and outer electrode, the clamp and the regions 'gamma' on which to apply the periodic condition: int electrodein = 1, electrodeout = 2, clamp = 3, gamma1 = 4, gamma2 = 5, cavity = 4007, solid = 4008, all = 4009; // Define all regions needed in the source .nas mesh and save it in .msh format. processmesh(); mesh mymesh("cmutperiodic.msh"); // The periodic condition is only applied to the solid region: gamma1 = regionintersection({gamma1, solid}); gamma2 = regionintersection({gamma2, solid}); wallclock clk; // Harmonic simulation at f0 = 1 MHz: setfundamentalfrequency(1e6); // Nodal shape functions 'h1' with 3 components for u, the membrane deflection. // Use harmonic 2 to have u = U*sin(2pi*f0*t). field u("h1xyz", {2}); // Use interpolation order 2 everywhere: u.setorder(all, 2); // Clamp on surface 'clamp' (i.e. 0 valued-Dirichlet conditions): u.setconstraint(clamp); // E is Young's modulus. nu is Poisson's ratio. double E = 160e9, nu = 0.22, rho = 2320; formulation elasticity; // The linear elasticity formulation is classical and thus predefined: elasticity += integral(solid, predefinedelasticity(dof(u), tf(u), E, nu)); // Add a pressure load at frequency f0 on both inner and outer electrodes: double p = 1e5; elasticity += integral(electrodein, -p*compz(tf(u.harmonic(2)))); elasticity += integral(electrodeout, -p*compz(tf(u.harmonic(2)))); // Add the inertia term: elasticity += integral(solid, -rho*dtdt(dof(u))*tf(u)); // Add the periodic condition between gamma1 and gamma2. // Region gamma2 is obtained from gamma1 by a 60 degrees rotation around z (rotation center is the origin). elasticity += periodicitycondition(gamma1, gamma2, u, {0,0,0}, {0,0,60}); // Generate, solve and store the solution to field u: solve(elasticity); // Write the deflection to ParaView .vtk format. Write with an order 2 interpolation. u.write(solid, "u.vtk", 2); // Confirm that the periodic condition is correct by comparing the inner and outer cavity deflection: double ucenterin = 1e9 * norm(u.harmonic(2)).interpolate(solid,{0,0,1.5e-6})[0]; double ucenterout = 1e9 * norm(u.harmonic(2)).interpolate(solid,{60e-6,0,1.5e-6})[0]; std::cout << "Deflection at center of inner/outer cavity is " << ucenterin << " / " << ucenterout << " nm" << std::endl; clk.print(); // Code validation line. Can be removed. std::cout << (ucenterin < 26.5977 && ucenterin > 26.5975); } void processmesh(void) { // Define the central electrode, outer electrode and clamp regions as well as the regions to apply the periodic condition. int elecc = 1, eleco = 2, clamp = 3, gamma1 = 4, gamma2 = 5; setphysicalregionshift(1000); mesh mymesh1; mymesh1.load("cmutperiodic.nas", 0); int vac = regionunion({4001,4005}); int solid = regionunion({4002,4003,4004,4006}); int all = regionunion({vac,solid}); // Rotate the mesh to easily select the bottom side for the periodic condition: mymesh1.rotate(0,0,30); mymesh1.write("cmutperiodic.msh", 0); setphysicalregionshift(0); mesh mymesh2; mymesh2.boxselection(elecc, 4001, 2, {-10,10,-10,10,0.3e-6-1e-10,0.3e-6+1e-10}); mymesh2.boxselection(eleco, 4006, 2, {-10,10,-10,10,0.3e-6-1e-10,0.3e-6+1e-10}); mymesh2.boxselection(clamp, all, 2, {-10,10,-10,10,-1e-10,1e-10}); mymesh2.boxselection(gamma1, all, 2, {-10,10,-1e-10,1e-10,-10,10}); mymesh2.load("cmutperiodic.msh", 0); // Rotate to the other direction to align the other region for the periodic condition: mymesh2.rotate(0,0,-60); mymesh2.write("cmutperiodic.msh", 0); mesh mymesh3; mymesh3.boxselection(gamma2, all, 2, {-10,10,-1e-10,1e-10,-10,10}); mymesh3.load("cmutperiodic.msh", 0); // Bring the mesh back to its original angle: mymesh3.rotate(0,0,30); // Write the processed mesh: mymesh3.write("cmutperiodic.msh", 0); } int main(void) { SlepcInitialize(0,{},0,0); sparselizard(); SlepcFinalize(); return 0; }