/*
 * circular_waveguide_filter.java
 */

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on May 15 2026, 11:31 by COMSOL 6.4.0.421. */
public class circular_waveguide_filter {

  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 Axisymmetric.
//    In the Select Physics tree, select Radio Frequency > Electromagnetic Waves, Frequency Domain (emw).
//    Click Add.
//    Click Study.
//    In the Select Study tree, select General Studies > Frequency Domain.
//    Click Done.

    model.component().create("comp1", true);

    model.component("comp1").geom().create("geom1", 2);
    model.component("comp1").geom("geom1").axisymmetric(true);

    model.component("comp1").mesh().create("mesh1");

    model.component("comp1").physics().create("emw", "ElectromagneticWaves", "geom1");

    model.study().create("std1");
    model.study("std1").create("freq", "Frequency");
    model.study("std1").feature("freq").set("solnum", "auto");
    model.study("std1").feature("freq").set("notsolnum", "auto");
    model.study("std1").feature("freq").set("outputmap", new String[]{});
    model.study("std1").feature("freq").set("ngenAUX", "1");
    model.study("std1").feature("freq").set("goalngenAUX", "1");
    model.study("std1").feature("freq").set("ngenAUX", "1");
    model.study("std1").feature("freq").set("goalngenAUX", "1");

//    Define the study frequency ahead of performing any frequency-dependent operation such as building mesh. The physics-controlled mesh uses the highest frequency value in the specified range.
//    In the Model Builder window, under Study 1, click Step 1: Frequency Domain.
//    In the Settings window for Frequency Domain, locate the Study Settings section.
//    In the Frequencies text field, type range(4.8[GHz],10[MHz],5.2[GHz]).

    model.study("std1").feature("freq").set("plist", "range(4.8[GHz],10[MHz],5.2[GHz])");

//    The choices of 4.8 GHz and 5.2 GHz ensured that the parametric sweep will start above the cutoff frequency and contain the resonant frequency.
//    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 circular_waveguide_filter_parameters.txt.
//    To import content from file, use:
//    model.param().loadFile("FILENAME");
    model.param().set("r1", "0.02[m]", "Waveguide radius");
    model.param().set("ir1", "0.006[m]", "Iris 1");
    model.param().set("ir2", "0.0088[m]", "Iris 2");
    model.param().set("ir3", "0.0096[m]", "Iris 3");
    model.param().set("cl1", "0.054[m]", "Cavity length 1");
    model.param().set("cl2", "0.06[m]", "Cavity length 2");
    model.param().set("cl3", "0.061[m]", "Cavity length 3");
    model.param().set("irth", "0.002[m]", "Iris thickness");

//    First load the geometric parameters. Now, we will first calculate the cutoff and resonant frequency of the waveguide to choose appropriate values for the parametric sweep.
//    In the table, enter the following settings:

    model.param().set("fnml", "c_const/pi/2*sqrt((1.841/r1)^2+(pi/0.06)^2)");
    model.param().descr("fnml", "Cavity resonance frequency");
    model.param().set("fc", "1.841*c_const/2/pi/r1");
    model.param().descr("fc", "Cutoff frequency");

//    Here, <c>c_const</c> is a predefined COMSOL constant for the speed of light in vacuum.
//    In the Geometry toolbar, click Rectangle.

    model.component("comp1").geom("geom1").create("r1", "Rectangle");

//    In the Settings window for Rectangle, locate the Size and Shape section.
//    In the Width text field, type r1.

    model.component("comp1").geom("geom1").feature("r1").set("size", new String[]{"r1", "1"});

//    In the Height text field, type 0.4.

    model.component("comp1").geom("geom1").feature("r1").set("size", new String[]{"r1", "0.4"});

//    Locate the Position section.
//    In the z text field, type -0.2.

    model.component("comp1").geom("geom1").feature("r1").set("pos", new double[]{0, -0.2});

//    In the Geometry toolbar, click Rectangle.

    model.component("comp1").geom("geom1").run("r1");
    model.component("comp1").geom("geom1").create("r2", "Rectangle");

//    In the Settings window for Rectangle, locate the Size and Shape section.
//    In the Width text field, type ir1.

    model.component("comp1").geom("geom1").feature("r2").set("size", new String[]{"ir1", "1"});

//    In the Height text field, type irth.

    model.component("comp1").geom("geom1").feature("r2").set("size", new String[]{"ir1", "irth"});

//    Locate the Position section.
//    In the r text field, type r1-ir1.

    model.component("comp1").geom("geom1").feature("r2").set("pos", new String[]{"r1-ir1", "0"});

//    In the z text field, type -cl3/2-cl2-cl1-irth/2.

    model.component("comp1").geom("geom1").feature("r2").set("pos", new String[]{"r1-ir1", "-cl3/2-cl2-cl1-irth/2"});

//    In the Geometry toolbar, click Rectangle.

    model.component("comp1").geom("geom1").run("r2");
    model.component("comp1").geom("geom1").create("r3", "Rectangle");

//    In the Settings window for Rectangle, locate the Size and Shape section.
//    In the Width text field, type ir2.

    model.component("comp1").geom("geom1").feature("r3").set("size", new String[]{"ir2", "1"});

//    In the Height text field, type irth.

    model.component("comp1").geom("geom1").feature("r3").set("size", new String[]{"ir2", "irth"});

//    Locate the Position section.
//    In the r text field, type r1-ir2.

    model.component("comp1").geom("geom1").feature("r3").set("pos", new String[]{"r1-ir2", "0"});

//    In the z text field, type -cl3/2-cl2-irth/2.

    model.component("comp1").geom("geom1").feature("r3").set("pos", new String[]{"r1-ir2", "-cl3/2-cl2-irth/2"});

//    In the Geometry toolbar, click Rectangle.

    model.component("comp1").geom("geom1").run("r3");
    model.component("comp1").geom("geom1").create("r4", "Rectangle");

//    In the Settings window for Rectangle, locate the Size and Shape section.
//    In the Width text field, type ir3.

    model.component("comp1").geom("geom1").feature("r4").set("size", new String[]{"ir3", "1"});

//    In the Height text field, type irth.

    model.component("comp1").geom("geom1").feature("r4").set("size", new String[]{"ir3", "irth"});

//    Locate the Position section.
//    In the r text field, type r1-ir3.

    model.component("comp1").geom("geom1").feature("r4").set("pos", new String[]{"r1-ir3", "0"});

//    In the z text field, type -cl3/2-irth/2.

    model.component("comp1").geom("geom1").feature("r4").set("pos", new String[]{"r1-ir3", "-cl3/2-irth/2"});

//    In the Geometry toolbar, click Transforms and choose Mirror.

    model.component("comp1").geom("geom1").run("r4");
    model.component("comp1").geom("geom1").create("mir1", "Mirror");

//    Select the objects r2, r3, r4.

    model.component("comp1").geom("geom1").feature("mir1").selection("input").set("r2", "r3", "r4");

//    In the Settings window for Mirror, locate the Input section.
//    Select the Keep input objects checkbox.

    model.component("comp1").geom("geom1").feature("mir1").set("keep", true);

//    Locate the Normal Vector to Line of Reflection section.
//    In the r text field, type 0.

    model.component("comp1").geom("geom1").feature("mir1").set("axis", new double[]{0, 0});

//    In the z text field, type 1.

    model.component("comp1").geom("geom1").feature("mir1").set("axis", new double[]{0, 1});

//    In the Geometry toolbar, click Booleans and Partitions and choose Difference.

    model.component("comp1").geom("geom1").run("mir1");
    model.component("comp1").geom("geom1").create("dif1", "Difference");

//    Select the object r1.

    model.component("comp1").geom("geom1").feature("dif1").selection("input").set("r1");

//    In the Settings window for Difference, locate the Difference section.
//    Select the Activate Selection toggle button for Objects to subtract.
//    Select the objects mir1(1), mir1(2), mir1(3), r2, r3, r4.

    model.component("comp1").geom("geom1").feature("dif1").selection("input2").set("mir1", "r2", "r3", "r4");

//    Click Build All Objects.

    model.component("comp1").geom("geom1").runPre("fin");

//    The finished geometry should look like this.

    model.component("comp1").geom("geom1").run();

//    In the Model Builder window, under Component 1 (comp1), click Electromagnetic Waves, Frequency Domain (emw).
//    In the Settings window for Electromagnetic Waves, Frequency Domain, locate the Out-of-Plane Wave Number section.
//    In the \[m\] text field, type 1.

    model.component("comp1").physics("emw").prop("outofplanewavenumber").set("mFloquet", 1);

//    This defines the azimuthal dependency of the fields that the model is solving for.
//    In the Physics toolbar, click Boundaries and choose Port.

    model.component("comp1").physics("emw").create("port1", "Port", 1);

//    Select Boundary 2.

    model.component("comp1").physics("emw").feature("port1").selection().set(2);

//    In the Settings window for Port, locate the Port Properties section.
//    From the Type of port list, select Circular.

    model.component("comp1").physics("emw").feature("port1").set("PortType", "Circular");

//    For the first port, wave excitation is <l>on</l> by default.
//    In the Physics toolbar, click Boundaries and choose Port.

    model.component("comp1").physics("emw").create("port2", "Port", 1);

//    Select Boundary 3.

    model.component("comp1").physics("emw").feature("port2").selection().set(3);

//    In the Settings window for Port, locate the Port Properties section.
//    From the Type of port list, select Circular.

    model.component("comp1").physics("emw").feature("port2").set("PortType", "Circular");

//    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("def").set("relpermittivity", new String[]{"1"});
    model.component("comp1").material("mat1").propertyGroup("def").set("relpermeability", new String[]{"1"});
    model.component("comp1").material("mat1").propertyGroup("def").set("electricconductivity", new String[]{"0"});

//    In the Model Builder window, right-click Component 1 (comp1) > Mesh 1 and choose Build All.

    model.component("comp1").mesh("mesh1").run();

//    In the Study toolbar, click Compute.

    model.study("std1").createAutoSequences("all");

    model.component("comp1").probe("emw_port1_probe").genResult("none");

    model.sol("sol1").runAll();

    model.result().create("pg2", "PlotGroup2D");
    model.result("pg2").set("data", "dset1");
    model.result("pg2").setIndex("looplevel", 41, 0);
    model.result("pg2").create("surf1", "Surface");
    model.result("pg2").feature("surf1").set("expr", "emw.normE");
    model.result("pg2").feature("surf1").set("descr", "Electric field norm");
    model.result("pg2").set("showlegendsmaxmin", true);
    model.result("pg2").feature("surf1").set("colortable", "RainbowLight");
    model.result("pg2").label("Electric Field (emw)");
    model.result().dataset().create("rev1", "Revolve2D");
    model.result().dataset("rev1").set("data", "dset1");
    model.result().dataset("rev1").set("revangle", -90);
    model.result().dataset("rev1").set("startangle", 225);
    model.result().create("pg3", "PlotGroup1D");
    model.result("pg3").set("data", "dset1");
    model.result("pg3").create("glob1", "Global");
    model.result("pg3").feature("glob1").set("unit", new String[]{"", ""});
    model.result("pg3").feature("glob1").set("expr", new String[]{"emw.S11dB", "emw.S21dB"});
    model.result("pg3").feature("glob1").set("descr", new String[]{"S11", "S21"});
    model.result("pg3").label("S-Parameter (emw)");
    model.result("pg3").feature("glob1").set("titletype", "none");
    model.result("pg3").feature("glob1").set("xdata", "expr");
    model.result("pg3").set("ylabelactive", true);
    model.result("pg3").set("ylabel", "S-parameter (dB)");
    model.result("pg3").feature("glob1").set("xdataexpr", "freq");
    model.result("pg3").feature("glob1").set("xdataunit", "GHz");
    model.result("pg3").feature("glob1").set("markerpos", "datapoints");
    model.result("pg3").feature("glob1").set("xdatasolnumtype", "all");
    model.result().create("pg4", "SmithGroup");
    model.result("pg4").set("data", "dset1");
    model.result("pg4").create("rgr1", "ReflectionGraph");
    model.result("pg4").feature("rgr1").set("unit", new String[]{""});
    model.result("pg4").feature("rgr1").set("expr", new String[]{"emw.S11"});
    model.result("pg4").feature("rgr1").set("descr", new String[]{"S11"});
    model.result("pg4").label("Smith Plot (emw)");
    model.result("pg4").feature("rgr1").set("titletype", "manual");
    model.result("pg4").feature("rgr1").set("title", "Reflection Graph: S-parameter, Color: Frequency (GHz)");
    model.result("pg4").feature("rgr1").set("linemarker", "point");
    model.result("pg4").feature("rgr1").set("markerpos", "datapoints");
    model.result("pg4").feature("rgr1").create("col1", "Color");
    model.result("pg4").feature("rgr1").feature("col1").set("expr", "emw.freq/1e9");
    model.result("pg4").feature("rgr1").feature("col1").set("colortable", "Spectrum");
    model.result("pg2").run();

//    In the Settings window for 2D Plot Group, locate the Data section.
//    From the Parameter value (freq (GHz)) list, select 4.98.

    model.result("pg2").setIndex("looplevel", 19, 0);

//    In the Electric Field (emw) toolbar, click Plot.

    model.result("pg2").run();
    model.result("pg3").run();

    model.title("Circular Waveguide Filter");

    model
         .description("A circular waveguide filter is designed using a 2D axisymmetric model. Six annular rings added to the waveguide form circular cavities connected in series, and each cavity cutoff frequency is close to the center frequency of the filter. The simulated S-parameters show a bandpass frequency response.");

    return model;
  }

  public static void main(String[] args) {
    run();
  }

}
