/*
 * thermoelastic_damping_3d.java
 */

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on May 15 2026, 14:02 by COMSOL 6.4.0.421. */
public class thermoelastic_damping_3d {

  public static Model run() {
    Model model = ModelUtil.create("Model");

//    From the File menu, choose New.
//    In the New window, click Model Wizard.
//    In the Model Wizard window, click 3D.
//    In the Select Physics tree, select Structural Mechanics > Thermal–Structure Interaction > Thermoelasticity.
//    Click Add.
//    Click Study.
//    In the Select Study tree, select Preset Studies for Selected Physics Interfaces > Heat Transfer in Solids > Thermal Perturbation, Eigenfrequency.
//    Click Done.

    model.component().create("comp1", true);

    model.component("comp1").geom().create("geom1", 3);
    model.component("comp1").geom("geom1").geomRep("comsol");

    model.component("comp1").mesh().create("mesh1");
    model.component("comp1").mesh("mesh1").contribute("geom/detail", true);

    model.component("comp1").physics().create("solid", "SolidMechanics", "geom1");
    model.component("comp1").physics("solid").prop("StructuralTransientBehavior")
         .set("StructuralTransientBehavior", "IncludeInertia");
    model.component("comp1").physics().create("ht", "HeatTransfer", "geom1");

    model.component("comp1").multiphysics().create("te1", "ThermalExpansion", 3);
    model.component("comp1").multiphysics("te1").set("Heat_physics", "ht");
    model.component("comp1").multiphysics("te1").set("Solid_physics", "solid");
    model.component("comp1").multiphysics("te1").selection().all();

    model.study().create("std1");
    model.study("std1").create("stat", "Stationary");
    model.study("std1").feature("stat").set("solnum", "auto");
    model.study("std1").feature("stat").set("notsolnum", "auto");
    model.study("std1").feature("stat").set("outputmap", new String[]{});
    model.study("std1").feature("stat").set("ngenAUX", "1");
    model.study("std1").feature("stat").set("goalngenAUX", "1");
    model.study("std1").feature("stat").set("ngenAUX", "1");
    model.study("std1").feature("stat").set("goalngenAUX", "1");
    model.study("std1").create("eig", "Eigenfrequency");
    model.study("std1").feature("eig").set("chkeigregion", true);
    model.study("std1").feature("eig").set("storefact", false);
    model.study("std1").feature("eig").set("linpsolnum", "auto");
    model.study("std1").feature("eig").set("solnum", "auto");
    model.study("std1").feature("eig").set("notsolnum", "auto");
    model.study("std1").feature("eig").set("outputmap", new String[]{});
    model.study("std1").feature("eig").set("ngenAUX", "1");
    model.study("std1").feature("eig").set("goalngenAUX", "1");
    model.study("std1").feature("eig").set("ngenAUX", "1");
    model.study("std1").feature("eig").set("goalngenAUX", "1");

//    The Model Wizard led to the <l>Geometry</l> node in the Model Builder tree structure. Start building the simple beam structure by specifying a convenient length unit.
//    In the Model Builder window, under Component 1 (comp1), click Geometry 1.
//    In the Settings window for Geometry, locate the Units section.
//    From the Length unit list, select µm.

    model.component("comp1").geom("geom1").lengthUnit("\u00b5m");

//    In the Geometry toolbar, click Block.

    model.component("comp1").geom("geom1").create("blk1", "Block");

//    In the Settings window for Block, locate the Size and Shape section.
//    In the Width text field, type 400.

    model.component("comp1").geom("geom1").feature("blk1").set("size", new double[]{400, 1, 1});

//    In the Depth text field, type 12.

    model.component("comp1").geom("geom1").feature("blk1").set("size", new double[]{400, 12, 1});

//    In the Height text field, type 12.

    model.component("comp1").geom("geom1").feature("blk1").set("size", new double[]{400, 12, 12});

//    Click Build All Objects.

    model.component("comp1").geom("geom1").runPre("fin");

//    Import material parameters from a file.
//    In the Model Builder window, under Global Definitions, click Parameters 1.
//    In the Settings window for Parameters, locate the Parameters section.
//    Click Load from File.
//    Browse to the model's Application Library folder and double-click the file thermoelastic_damping_3d_parameters.txt.
//    To import content from file, use:
//    model.param().loadFile("FILENAME");
    model.param().set("E0", "157[GPa]", "Young's modulus");
    model.param().set("rho0", "2330[kg/m^3]", "Density");
    model.param().set("nu0", "0.3", "Poisson's ratio");
    model.param().set("alpha0", "2.6e-6[1/K]", "Coefficient of thermal expansion");
    model.param().set("Cp0", "700[J/(kg*K)]", "Heat capacity");
    model.param().set("kappa0", "90[W/(m*K)]", "Thermal conductivity");

//    Create a blank material and fill in the material properties using the parameters that we just imported.

    model.component("comp1").geom("geom1").run();

//    In the Model Builder window, right-click Component 1 (comp1) > Materials and choose Blank Material.

    model.component("comp1").material().create("mat1", "Common");

//    In the Settings window for Material, locate the Material Contents section.
//    In the table, enter the following settings:

    model.component("comp1").material("mat1").propertyGroup()
         .create("Enu", "Enu", "Young's_modulus_and_Poisson's_ratio");
    model.component("comp1").material("mat1").propertyGroup("Enu").set("E", new String[]{"E0"});
    model.component("comp1").material("mat1").propertyGroup("Enu").set("nu", new String[]{"nu0"});
    model.component("comp1").material("mat1").propertyGroup("def").set("density", new String[]{"rho0"});
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("thermalconductivity", new String[]{"kappa0"});
    model.component("comp1").material("mat1").propertyGroup("def").set("heatcapacity", new String[]{"Cp0"});
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("thermalexpansioncoefficient", new String[]{"alpha0"});

//    Set up boundary conditions. For the solid mechanics part, the beam is fixed at the two ends and has a symmetry B.C. on one of its sides.
//    In the Physics toolbar, click Boundaries and choose Fixed Constraint.

    model.component("comp1").physics("solid").create("fix1", "Fixed", 2);

//    Select Boundaries 1, 6.

    model.component("comp1").physics("solid").feature("fix1").selection().set(1, 6);

//    In the Physics toolbar, click Boundaries and choose Symmetry.

    model.component("comp1").physics("solid").create("sym1", "SymmetrySolid", 2);

//    Select Boundary 2.

    model.component("comp1").physics("solid").feature("sym1").selection().set(2);

//    For the heat transfer part, the temperature at the two ends of the beam are fixed at the default stationary temperature. For the <l>Eigenfrequency</l> study step, the same <l>Temperature</l> boundary condition sets the temperature deviation to zero.
//    In the Physics toolbar, click Boundaries and choose Temperature.

    model.component("comp1").physics("ht").create("temp1", "TemperatureBoundary", 2);

//    Select Boundaries 1, 6.

    model.component("comp1").physics("ht").feature("temp1").selection().set(1, 6);

//    Create a structured mesh for the beam.
//    In the Mesh toolbar, click More Generators and choose Mapped.

    model.component("comp1").mesh("mesh1").create("map1", "Map");

//    Select Boundary 1.

    model.component("comp1").mesh("mesh1").feature("map1").selection().set(1);

//    Right-click Mapped 1 and choose Distribution.

    model.component("comp1").mesh("mesh1").feature("map1").create("dis1", "Distribution");

//    Select Edges 1, 2.

    model.component("comp1").mesh("mesh1").feature("map1").feature("dis1").selection().set(1, 2);

//    In the Mesh toolbar, click Swept.

    model.component("comp1").mesh("mesh1").create("swe1", "Sweep");

//    Right-click Swept 1 and choose Distribution.

    model.component("comp1").mesh("mesh1").feature("swe1").create("dis1", "Distribution");

//    In the Settings window for Distribution, locate the Distribution section.
//    In the Number of elements text field, type 70.

    model.component("comp1").mesh("mesh1").feature("swe1").feature("dis1").set("numelem", 70);

//    Click Build All.

    model.component("comp1").mesh("mesh1").run();

//    Give the eigenfrequency study a good initial guess. Use the <l>Larger real part</l> option to avoid spurious modes near zero frequency.
//    In the Model Builder window, under Study 1, click Step 2: Eigenfrequency.
//    In the Settings window for Eigenfrequency, locate the Study Settings section.
//    Select the Desired number of eigenfrequencies checkbox.

    model.study("std1").feature("eig").set("neigsactive", true);

//    In the associated text field, type 1.

    model.study("std1").feature("eig").set("neigs", 1);

//    Select the Search for eigenfrequencies around shift checkbox.

    model.study("std1").feature("eig").set("shiftactive", true);

//    In the associated text field, type 0.63e6.

    model.study("std1").feature("eig").set("shift", "0.63e6");

//    From the Search method around shift list, select Larger real part.

    model.study("std1").feature("eig").set("eigwhich", "lr");

//    Since the stationary study step is only used to compute the linearization point for the eigenvalue study (corresponding to zero displacement and a uniform temperature) the dependent variables need to be scaled manually.
//    In the Study toolbar, click Show Default Solver.

    model.study("std1").showAutoSequences("all");

//    In the Model Builder window, expand the Solution 1 (sol1) node, then click Dependent Variables 1.
//    In the Settings window for Dependent Variables, locate the Scaling section.
//    From the Method list, select Manual.

    model.sol("sol1").feature("v1").set("scalemethod", "manual");

//    In the Study toolbar, click Compute.

    model.study("std1").createAutoSequences("all");

    model.sol("sol1").runAll();

    model.result().create("pg1", "PlotGroup3D");
    model.result("pg1").set("data", "dset1");
    model.result("pg1").setIndex("looplevel", 1, 0);
    model.result("pg1").label("Mode Shape (solid)");
    model.result("pg1").set("showlegends", false);
    model.result("pg1").create("surf1", "Surface");
    model.result("pg1").feature("surf1").set("expr", new String[]{"solid.disp"});
    model.result("pg1").feature("surf1").set("threshold", "manual");
    model.result("pg1").feature("surf1").set("thresholdvalue", 0.2);
    model.result("pg1").feature("surf1").set("colortable", "Rainbow");
    model.result("pg1").feature("surf1").set("colortabletrans", "none");
    model.result("pg1").feature("surf1").set("colorscalemode", "linear");
    model.result("pg1").feature("surf1").set("colortable", "AuroraBorealis");
    model.result("pg1").feature("surf1").create("def", "Deform");
    model.result("pg1").feature("surf1").feature("def").set("expr", new String[]{"u", "v", "w"});
    model.result("pg1").feature("surf1").feature("def").set("descr", "Displacement field");
    model.result().evaluationGroup().create("std1EvgFrq", "EvaluationGroup");
    model.result().evaluationGroup("std1EvgFrq").set("data", "dset1");
    model.result().evaluationGroup("std1EvgFrq").label("Eigenfrequencies (Study 1)");
    model.result().evaluationGroup("std1EvgFrq").create("gev1", "EvalGlobal");
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("expr", "2*pi*freq", 0);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("unit", "rad/s", 0);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("descr", "Angular frequency", 0);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("expr", "imag(freq)/abs(freq)", 1);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("unit", "1", 1);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("descr", "Damping ratio", 1);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("expr", "abs(freq)/imag(freq)/2", 2);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("unit", "1", 2);
    model.result().evaluationGroup("std1EvgFrq").feature("gev1").setIndex("descr", "Quality factor", 2);
    model.result().evaluationGroup("std1EvgFrq").run();
    model.result().create("pg2", "PlotGroup3D");
    model.result("pg2").label("Temperature (ht)");
    model.result("pg2").set("smooth", "internal");
    model.result("pg2").feature().create("vol1", "Volume");
    model.result("pg2").feature("vol1").set("solutionparams", "parent");
    model.result("pg2").feature("vol1").set("expr", "T");
    model.result("pg2").feature("vol1").set("colortable", "HeatCameraLight");
    model.result("pg2").feature("vol1").set("smooth", "internal");
    model.result("pg2").feature("vol1").set("data", "parent");
    model.result("pg1").run();

//    Add mode shape deformation to the default temperature plot.

    model.result("pg2").run();

//    In the Model Builder window, click Temperature (ht).
//    In the Settings window for 3D Plot Group, locate the Color Legend section.
//    Clear the Show legends checkbox.

    model.result("pg2").set("showlegends", false);
    model.result("pg2").run();

//    In the Model Builder window, expand the Temperature (ht) node.
//    Right-click Volume 1 and choose Deformation.

    model.result("pg2").feature("vol1").create("def1", "Deform");
    model.result("pg2").run();

//    In the Temperature (ht) toolbar, click Plot.

    model.result("pg2").run();

//    Compute the Q factor.
//    In the Results toolbar, click Global Evaluation.

    model.result().numerical().create("gev1", "EvalGlobal");

//    In the Settings window for Global Evaluation, click Replace Expression in the upper-right corner of the Expressions section.
//    From the menu, choose Component 1 (comp1) > Solid Mechanics > Global > solid.Q_eig - Quality factor for eigenvalue - 1.

    model.result().numerical("gev1").set("expr", new String[]{"solid.Q_eig"});
    model.result().numerical("gev1").set("descr", new String[]{"Quality factor for eigenvalue"});
    model.result().numerical("gev1").set("unit", new String[]{"1"});

//    Click Evaluate.

    model.result().table().create("tbl1", "Table");
    model.result().table("tbl1").comments("Global Evaluation 1");
    model.result().numerical("gev1").set("table", "tbl1");
    model.result().numerical("gev1").setResult();

    model.title("Thermoelastic Damping in a MEMS Resonator");

    model
         .description("Thermoelastic damping is an important factor when designing MEMS resonators. The cyclic deformation of the resonator creates local temperature variations and thermal expansion of the material, which appears as damping. This 3D model shows how to model thermoelastic damping in a MEMS resonator using fully coupled thermal and structural equations.");

    return model;
  }

  public static void main(String[] args) {
    run();
  }

}
