/*
 * distributed_bragg_reflector.java
 */

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on May 15 2026, 09:56 by COMSOL 6.4.0.421. */
public class distributed_bragg_reflector {

  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 Optics > Ray Optics > Geometrical Optics (gop).
//    Click Add.
//    Click Study.
//    In the Select Study tree, select Preset Studies for Selected Physics Interfaces > Ray Tracing.
//    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("gop", "GeometricalOptics", "geom1");

    model.study().create("std1");
    model.study("std1").create("rtrac", "RayTracing");

//    Add some parameters for the refractive indices of the materials and the central wavelength.
//    In the Model Builder window, under Global Definitions, click Parameters 1.
//    In the Settings window for Parameters, locate the Parameters section.
//    In the table, enter the following settings:

    model.param().set("ns", "1.5");
    model.param().descr("ns", "Refractive index of substrate");
    model.param().set("nh", "2.32");
    model.param().descr("nh", "Refractive index of ZnS");
    model.param().set("nl", "1.38");
    model.param().descr("nl", "Refractive index of MgF2");
    model.param().set("lam0", "550[nm]");
    model.param().descr("lam0", "Vacuum wavelength");
    model.param().set("Nc", "2");
    model.param().descr("Nc", "Number of unit cells");

//    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 mm.

    model.component("comp1").geom("geom1").lengthUnit("mm");

//    In the Geometry toolbar, click Cylinder.

    model.component("comp1").geom("geom1").create("cyl1", "Cylinder");

//    In the Settings window for Cylinder, locate the Size and Shape section.
//    In the Radius text field, type 10.

    model.component("comp1").geom("geom1").feature("cyl1").set("r", 10);

//    In the Height text field, type 5.

    model.component("comp1").geom("geom1").feature("cyl1").set("h", 5);

//    Click Build All Objects.

    model.component("comp1").geom("geom1").runPre("fin");

//    In the Geometrical Optics interface, enable ray intensity calculation and allow distributions of ray wavelengths to be released. Also set the number of secondary rays to zero as this saves memory when it is not necessary to compute the trajectories of the reflected rays.

    model.component("comp1").geom("geom1").run();

//    In the Model Builder window, under Component 1 (comp1), click Geometrical Optics (gop).
//    In the Settings window for Geometrical Optics, locate the Intensity Computation section.
//    From the Intensity computation list, select Compute intensity.

    model.component("comp1").physics("gop").prop("IntensityComputation")
         .setIndex("IntensityComputation", "ComputeIntensity", 0);

//    Locate the Ray Release and Propagation section.
//    From the Wavelength distribution of released rays list, select Polychromatic, specify vacuum wavelength.

    model.component("comp1").physics("gop").prop("WavelengthDistribution")
         .setIndex("WavelengthDistribution", "PolychromaticWavelength", 0);

//    In the Maximum number of secondary rays text field, type 0.

    model.component("comp1").physics("gop").prop("MaximumSecondary").setIndex("MaximumSecondary", 0, 0);

//    Specify the refractive index of the substrate.
//    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("RefractiveIndex", "RefractiveIndex", "Refractive_index");
    model.component("comp1").material("mat1").propertyGroup("RefractiveIndex").set("n", new String[]{"ns"});

//    Edit the <l>Material Discontinuity</l> settings to allow periodic thin dielectric films to be added to the surface.
//    In the Model Builder window, under Component 1 (comp1) > Geometrical Optics (gop), click Material Discontinuity 1.
//    In the Settings window for Material Discontinuity, locate the Coatings section.
//    From the Thin dielectric films on boundary list, select Add layers to surface, repeating.

    model.component("comp1").physics("gop").feature("matd1")
         .set("ThinDielectricFilmsOnBoundary", "AddLayersToSurfaceRepeating");

//    In the \[N\] text field, type Nc.

    model.component("comp1").physics("gop").feature("matd1").set("Nft", "Nc");

//    Locate the Rays to Release section.
//    From the Release reflected rays list, select Never.

    model.component("comp1").physics("gop").feature("matd1").set("ReleaseReflectedRays", "Never");

//    Add two <l>Thin Dielectric Film</l> features to the <l>Material Discontinuity</l> feature. To visualize the arrangement of the thin dielectric layers, show the boundary normal in the <l>Graphics</l> window.
//    Click the Wireframe Rendering button in the Graphics toolbar.

    model.component("comp1").view("view1").set("renderwireframe", true);

//    Locate the Advanced Settings section.
//    Select the Show boundary normal checkbox.

    model.component("comp1").physics("gop").feature("matd1").set("ShowBoundaryNormal", true);

//    The red arrow points in the direction of the stack of layers; the last <l>Thin Dielectric Film</l> feature in the Model Builder will be at the top of the stack.
//    Add the layers and specify their refractive indices and thicknesses so that the optical thickness of each layer is equal to 1/4 of the vacuum wavelength.
//    In the Physics toolbar, click Attributes and choose Thin Dielectric Film.

    model.component("comp1").physics("gop").feature("matd1").create("film1", "ThinDielectricFilm", 2);

//    In the Settings window for Thin Dielectric Film, locate the Film Properties section.
//    In the \[n\] text field, type nh.

    model.component("comp1").physics("gop").feature("matd1").feature("film1").set("nf", "nh");

//    In the \[t\] text field, type lam0/(4*nh).

    model.component("comp1").physics("gop").feature("matd1").feature("film1").set("tf", "lam0/(4*nh)");

//    In the Model Builder window, click Material Discontinuity 1.
//    In the Physics toolbar, click Attributes and choose Thin Dielectric Film.

    model.component("comp1").physics("gop").feature("matd1").create("film2", "ThinDielectricFilm", 2);

//    In the Settings window for Thin Dielectric Film, locate the Film Properties section.
//    In the \[n\] text field, type nl.

    model.component("comp1").physics("gop").feature("matd1").feature("film2").set("nf", "nl");

//    In the \[t\] text field, type lam0/(4*nl).

    model.component("comp1").physics("gop").feature("matd1").feature("film2").set("tf", "lam0/(4*nl)");

//    The multilayer film will begin and end with the same layer. To allow any number of repeating unit cells to be applied, duplicate the first layer so that three <l>Thin Dielectric Film</l> nodes are present, two of which form the repeating unit cell.
//    In the Model Builder window, right-click Component 1 (comp1) > Geometrical Optics (gop) > Material Discontinuity 1 > Thin Dielectric Film 1 and choose Duplicate.

    model.component("comp1").physics("gop").feature("matd1").feature().duplicate("film3", "film1");

//    Exclude the first layer from the unit cell of the multilayer film.
//    In the Settings window for Thin Dielectric Film, click to expand the Repeating Multilayer Films section.
//    Clear the Repeat layer in multilayer films checkbox.

    model.component("comp1").physics("gop").feature("matd1").feature("film1")
         .set("RepeatLayerInMultilayerFilms", false);

//    Add a <l>Release from Grid</l> feature and specify a range of wavelengths to be released.
//    In the Physics toolbar, click Global and choose Release from Grid.

    model.component("comp1").physics("gop").create("relg1", "ReleaseGrid", -1);

//    Release rays with a large number of wavelengths within a given range.
//    In the Settings window for Release from Grid, locate the Initial Coordinates section.
//    In the \[q_{z,0}\] text field, type 10.

    model.component("comp1").physics("gop").feature("relg1").setIndex("x0", 10, 2);

//    Locate the Ray Direction Vector section.
//    Specify the \[\mathbf{L}_0\] vector as

    model.component("comp1").physics("gop").feature("relg1").set("L0", new int[]{0, 0, -1});

//    Locate the Vacuum Wavelength section.
//    From the Distribution function list, select List of values.

    model.component("comp1").physics("gop").feature("relg1").set("LDistributionFunction", "ListOfValues");

//    Click Range.
//    In the Range dialog, choose Number of values from the Entry method list.
//    In the Start text field, type 400[nm].
//    In the Stop text field, type 800[nm].
//    In the Number of values text field, type 1000.
//    Click Replace.

    model.component("comp1").physics("gop").feature("relg1")
         .setIndex("lambda0vals", "range(400[nm],(800[nm]-(400[nm]))/999,800[nm])", 0);

//    In the Study toolbar, click Parametric Sweep.

    model.study("std1").create("param", "Parametric");

//    Run a <l>Parametric Sweep</l> over the number of unit cells in the dielectric mirror in order to observe the changes in the reflectance.
//    In the Settings window for Parametric Sweep, locate the Study Settings section.
//    Click Add.

    model.study("std1").feature("param").setIndex("pname", "ns", 0);
    model.study("std1").feature("param").setIndex("plistarr", "", 0);
    model.study("std1").feature("param").setIndex("punit", "", 0);
    model.study("std1").feature("param").setIndex("pname", "ns", 0);
    model.study("std1").feature("param").setIndex("plistarr", "", 0);
    model.study("std1").feature("param").setIndex("punit", "", 0);

//    In the table, enter the following settings:

    model.study("std1").feature("param").setIndex("pname", "Nc", 0);
    model.study("std1").feature("param").setIndex("plistarr", "2 5 10 20", 0);

//    In the Model Builder window, click Step 1: Ray Tracing.
//    In the Settings window for Ray Tracing, locate the Study Settings section.
//    In the Output times text field, type 0 0.025.

    model.study("std1").feature("rtrac").set("tlist", "0 0.025");

//    In the Study toolbar, click Compute.

    model.study("std1").createAutoSequences("all");

    model.sol().create("sol2");
    model.sol("sol2").study("std1");
    model.sol("sol2").label("Parametric Solutions 1");

    model.batch("p1").feature("so1").set("psol", "sol2");
    model.batch("p1").run("compute");

    model.result().dataset().create("ray1", "Ray");
    model.result().dataset("ray1").set("solution", "sol2");
    model.result().dataset("ray1").set("posdof", new String[]{"comp1.qx", "comp1.qy", "comp1.qz"});
    model.result().dataset("ray1").set("geom", "geom1");
    model.result().dataset("ray1").set("rgeom", "pgeom_gop");
    model.result().dataset("ray1").set("rgeomspec", "fromphysics");
    model.result().dataset("ray1").set("physicsinterface", "gop");
    model.result().create("pg1", "PlotGroup3D");
    model.result("pg1").set("data", "ray1");
    model.result("pg1").setIndex("looplevel", 4, 1);
    model.result("pg1").label("Ray Trajectories (gop)");
    model.result("pg1").create("rtrj1", "RayTrajectories");
    model.result("pg1").feature("rtrj1").set("linetype", "line");
    model.result("pg1").feature("rtrj1").create("col1", "Color");
    model.result("pg1").feature("rtrj1").feature("col1").set("expr", "gop.I");
    model.result("pg1").feature("rtrj1").create("filt1", "RayTrajectoriesFilter");
    model.result("pg1").run();

//    To show the reflectance response of the mirror as a function of wavelength, use a <l>Ray</l> plot.
//    In the Results toolbar, click 1D Plot Group.

    model.result().create("pg2", "PlotGroup1D");
    model.result("pg2").run();

//    In the Settings window for 1D Plot Group, type Reflectance in the Label text field.

    model.result("pg2").label("Reflectance");

//    Locate the Data section.
//    From the Dataset list, select Ray 1.

    model.result("pg2").set("data", "ray1");

//    From the Time selection list, select Last.

    model.result("pg2").setIndex("looplevelinput", "last", 0);

//    Click to expand the Title section.
//    From the Title type list, select None.

    model.result("pg2").set("titletype", "none");

//    Locate the Plot Settings section.
//    Select the x-axis label checkbox.

    model.result("pg2").set("xlabelactive", true);

//    In the associated text field, type Vacuum wavelength (nm).

    model.result("pg2").set("xlabel", "Vacuum wavelength (nm)");

//    Select the y-axis label checkbox.

    model.result("pg2").set("ylabelactive", true);

//    In the associated text field, type Reflectance (%).

    model.result("pg2").set("ylabel", "Reflectance (%)");

//    In the Reflectance toolbar, click More Plots and choose Ray.

    model.result("pg2").create("rtp1", "Ray1D");
    model.result("pg2").feature("rtp1").set("markerpos", "datapoints");
    model.result("pg2").feature("rtp1").set("linewidth", "preference");

//    Compare the initial and current intensity to plot the reflectance at each wavelength.
//    In the Settings window for Ray, locate the y-Axis Data section.
//    In the Expression text field, type 100*(gop.relg1.I0-gop.I)/gop.relg1.I0.

    model.result("pg2").feature("rtp1").set("expr", "100*(gop.relg1.I0-gop.I)/gop.relg1.I0");

//    Locate the x-Axis Data section.
//    From the Parameter list, select Expression.

    model.result("pg2").feature("rtp1").set("xdata", "expr");

//    In the Expression text field, type gop.lambda0.

    model.result("pg2").feature("rtp1").set("xdataexpr", "gop.lambda0");

//    From the Unit list, select nm.

    model.result("pg2").feature("rtp1").set("xdataunit", "nm");

//    Click to expand the Legends section.
//    Select the Show legends checkbox.

    model.result("pg2").feature("rtp1").set("legend", true);

//    From the Legends list, select Evaluated.

    model.result("pg2").feature("rtp1").set("legendmethod", "evaluated");

//    In the Legend text field, type eval(2*Nc+1) layers.

    model.result("pg2").feature("rtp1").set("legendpattern", "eval(2*Nc+1) layers");

//    In the Reflectance toolbar, click Plot.

    model.result("pg2").run();

//    Click the Zoom Extents button in the Graphics toolbar.

    model.title("Distributed Bragg Reflector");

    model
         .description("A distributed Bragg reflector (DBR) is a periodic structure formed from alternating dielectric layers that can be used to achieve nearly total reflection within a range of frequencies, with minimal losses. In this tutorial a Bragg reflector is modeled with a central wavelength of 550\u00a0nm and stopband of 180\u00a0nm.");

    return model;
  }

  public static void main(String[] args) {
    run();
  }

}
