/*
 * isospectral_drums.java
 */

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on May 15 2026, 13:27 by COMSOL 6.4.0.421. */
public class isospectral_drums {

  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 2D.
//    In the Select Physics tree, select Mathematics > PDE Interfaces > Coefficient Form PDE (c).
//    Click Add.
//    Click Study.
//    In the Select Study tree, select General Studies > Eigenvalue.
//    Click Done.

    model.component().create("comp1", true);

    model.component("comp1").geom().create("geom1", 2);

    model.component("comp1").mesh().create("mesh1");

    model.component("comp1").physics().create("c", "CoefficientFormPDE", "geom1");
    model.component("comp1").physics("c").prop("EquationForm").set("form", "Automatic");

    model.study().create("std1");
    model.study("std1").create("eigv", "Eigenvalue");

//    In the Geometry toolbar, click Polygon.

    model.component("comp1").geom("geom1").create("pol1", "Polygon");
    model.component("comp1").geom("geom1").feature("pol1").set("source", "table");

//    In the Settings window for Polygon, locate the Coordinates section.
//    In the table, enter the following settings:

    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -3, 0, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -3, 0, 1);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -3, 1, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -1, 1, 1);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", 1, 2, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", 3, 2, 1);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", 1, 3, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", 1, 3, 1);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", 3, 4, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", 1, 4, 1);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", 1, 5, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -1, 5, 1);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -1, 6, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -1, 6, 1);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -1, 7, 0);
    model.component("comp1").geom("geom1").feature("pol1").setIndex("table", -3, 7, 1);

//    Click Build All Objects.

    model.component("comp1").geom("geom1").runPre("fin");

//    Click the Zoom Extents button in the Graphics toolbar.

    model.component("comp1").geom("geom1").run();

//    Use the default values of the coefficients of PDE to model this problem.
//    In the Physics toolbar, click Boundaries and choose Dirichlet Boundary Condition.

    model.component("comp1").physics("c").create("dir1", "DirichletBoundary", 1);

//    In the Settings window for Dirichlet Boundary Condition, locate the Boundary Selection section.
//    From the Selection list, select All boundaries.

    model.component("comp1").physics("c").feature("dir1").selection().all();

//    Applying Dirichlet boundary conditions corresponds to clamping the drum's membrane at the edges.
//    In the Model Builder window, under Component 1 (comp1), click Mesh 1.
//    In the Settings window for Mesh, locate the Physics-Controlled Mesh section.
//    From the Element size list, select Extra fine.

    model.component("comp1").mesh("mesh1").autoMeshSize(2);

//    By using a finer mesh, you reduce the apparent discrepancies between the matching eigenvalues caused by numerical errors.
//    Click Build All.

    model.component("comp1").mesh("mesh1").run();

//    In the Study toolbar, click Compute.

    model.study("std1").createAutoSequences("all");

    model.sol("sol1").runAll();

    model.result().create("pg1", "PlotGroup2D");
    model.result("pg1").set("data", "dset1");
    model.result("pg1").setIndex("looplevel", 1, 0);
    model.result("pg1").create("surf1", "Surface");
    model.result("pg1").label("Coefficient Form PDE");
    model.result("pg1").feature("surf1").set("expr", "u");
    model.result("pg1").run();

//    The default settings for an Eigenvalue study step gives the six lowest eigenvalues.
//    Click the Zoom Extents button in the Graphics toolbar.
//    Now add a second model for the alternative membrane shape.
//    In the Model Builder window, right-click the root node and choose Add Component > 2D.

    model.component().create("comp2", true);

    model.component("comp2").geom().create("geom2", 2);

    model.component("comp2").mesh().create("mesh2");

//    In the Home toolbar, click Add Physics to open the Add Physics window.
//    In the tree, select Mathematics > PDE Interfaces > Coefficient Form PDE (c).
//    Find the Physics interfaces in study subsection.
//    In the table, enter the following settings:
//    Click Add to Component 2 in the window toolbar.

    model.component("comp2").physics().create("c2", "CoefficientFormPDE", "geom2");

    model.study("std1").feature("eigv").setSolveFor("/physics/c2", false);

    model.component("comp2").physics("c2").prop("EquationForm").set("form", "Automatic");

    model.component("comp2").geom("geom2").run();

//    In the Home toolbar, click Add Physics to close the Add Physics window.
//    In the Home toolbar, click Add Study to open the Add Study window.
//    Find the Physics interfaces in study subsection.
//    In the table, enter the following settings:
//    Find the Studies subsection.
//    In the Select Study tree, select General Studies > Eigenvalue.
//    Click Add Study in the window toolbar.

    model.study().create("std2");
    model.study("std2").create("eigv", "Eigenvalue");
    model.study("std2").feature("eigv").setSolveFor("/physics/c", false);

//    In the Home toolbar, click Add Study to close the Add Study window.
//    In the Geometry toolbar, click Polygon.

    model.component("comp2").geom("geom2").create("pol1", "Polygon");
    model.component("comp2").geom("geom2").feature("pol1").set("source", "table");

//    In the Settings window for Polygon, locate the Coordinates section.
//    In the table, enter the following settings:

    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -3, 0, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 1, 0, 1);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 1, 1, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 1, 1, 1);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 1, 2, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 3, 2, 1);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 3, 3, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 1, 3, 1);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", 1, 4, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -1, 4, 1);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -1, 5, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -1, 5, 1);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -1, 6, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -3, 6, 1);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -3, 7, 0);
    model.component("comp2").geom("geom2").feature("pol1").setIndex("table", -1, 7, 1);

//    Click Build All Objects.

    model.component("comp2").geom("geom2").runPre("fin");

//    Click the Zoom Extents button in the Graphics toolbar.

    model.component("comp2").geom("geom2").run();

//    Use the same domain settings and boundary conditions as for the first model.
//    In the Physics toolbar, click Boundaries and choose Dirichlet Boundary Condition.

    model.component("comp2").physics("c2").create("dir1", "DirichletBoundary", 1);

//    In the Settings window for Dirichlet Boundary Condition, locate the Boundary Selection section.
//    From the Selection list, select All boundaries.

    model.component("comp2").physics("c2").feature("dir1").selection().all();

//    In the Model Builder window, under Component 2 (comp2), click Mesh 2.
//    In the Settings window for Mesh, locate the Physics-Controlled Mesh section.
//    From the Element size list, select Extra fine.

    model.component("comp2").mesh("mesh2").autoMeshSize(2);

//    Click Build All.

    model.component("comp2").mesh("mesh2").run();

//    In the Study toolbar, click Compute.

    model.study("std2").createAutoSequences("all");

    model.sol("sol2").runAll();

    model.result().create("pg2", "PlotGroup2D");
    model.result("pg2").set("data", "dset3");
    model.result("pg2").setIndex("looplevel", 1, 0);
    model.result("pg2").create("surf1", "Surface");
    model.result("pg2").label("Coefficient Form PDE 2");
    model.result("pg2").feature("surf1").set("expr", "u2");
    model.result("pg2").run();

//    Click the Zoom Extents button in the Graphics toolbar.
//    Use the <c>with</c> operator to access different eigenmodes in order to show that they are orthogonal:
//    In the Model Builder window, right-click Results > Derived Values and choose Integration > Surface Integration.

    model.result().numerical().create("int1", "IntSurface");
    model.result().numerical("int1").set("intvolume", true);

//    Select Domain 1.

    model.result().numerical("int1").selection().set(1);

//    In the Settings window for Surface Integration, locate the Expressions section.
//    In the table, enter the following settings:

    model.result().numerical("int1").setIndex("expr", "with(1,u)*with(2,u)", 0);

//    Click Evaluate.

    model.result().table().create("tbl1", "Table");
    model.result().table("tbl1").comments("Surface Integration 1");
    model.result().numerical("int1").set("table", "tbl1");
    model.result().numerical("int1").setResult();

//    The value of integral, which is very small (of the order of \[10^{-16}\]), appears in the <l>Table</l> window. Ideally, the result should be zero when the eigenmodes are orthogonal, but using a numerical method you can expect a small nonzero number.
//    Finally, do the same for the second model.
//    In the Results toolbar, click More Derived Values and choose Integration > Surface Integration.

    model.result().numerical().create("int2", "IntSurface");
    model.result().numerical("int2").set("intvolume", true);

//    In the Settings window for Surface Integration, locate the Data section.
//    From the Dataset list, select Study 2/Solution 2 (3) (sol2).

    model.result().numerical("int2").set("data", "dset3");

//    Select Domain 1.

    model.result().numerical("int2").selection().set(1);

//    Locate the Expressions section.
//    In the table, enter the following settings:

    model.result().numerical("int2").setIndex("expr", "with(1,u2)*with(2,u2)", 0);

//    Click Evaluate.

    model.result().table().create("tbl2", "Table");
    model.result().table("tbl2").comments("Surface Integration 2");
    model.result().numerical("int2").set("table", "tbl2");
    model.result().numerical("int2").setResult();
    model.result("pg2").run();

    model.title("Isospectral Drums");

    model
         .description("By computing the same set of eigenvalues for two different planar membrane shapes, this example demonstrates that you cannot hear the shape of a drum.");

    return model;
  }

  public static void main(String[] args) {
    run();
  }

}
