/*
 * helmholtz_coil.java
 */

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on May 15 2026, 13:40 by COMSOL 6.4.0.421. */
public class helmholtz_coil {

  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 AC/DC > Electromagnetic Fields > Magnetic Fields (mf).
//    Click Add.
//    In the Select Physics tree, select AC/DC > Electromagnetic Fields > Vector Formulations > Magnetic Fields, Currents Only (mfco).
//    Click Add.
//    Click Study.
//    In the Select Study tree, select General Studies > Stationary.
//    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("mf", "InductionCurrents", "geom1");
    model.component("comp1").physics().create("mfco", "MagneticFieldsCurrentsOnly", "geom1");

    model.study().create("std1");
    model.study("std1").create("stat", "Stationary");

//    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("I0", "0.25[mA]");
    model.param().descr("I0", "Coil current");

//    In the Geometry toolbar, click Work Plane.

    model.component("comp1").geom("geom1").create("wp1", "WorkPlane");
    model.component("comp1").geom("geom1").feature("wp1").set("unite", true);

//    In the Settings window for Work Plane, click Go to Plane Geometry.
//    In the Model Builder window, click Plane Geometry.
//    In the Work Plane toolbar, click Square.

    model.component("comp1").geom("geom1").feature("wp1").geom().create("sq1", "Square");

//    In the Settings window for Square, locate the Size section.
//    In the Side length text field, type 0.05.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq1").set("size", 0.05);

//    Locate the Position section.
//    From the Base list, select Center.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq1").set("base", "center");

//    In the xw text field, type -0.4.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq1").set("pos", new double[]{-0.4, 0});

//    In the yw text field, type 0.2.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq1").set("pos", new double[]{-0.4, 0.2});

//    In the Work Plane toolbar, click Square.

    model.component("comp1").geom("geom1").feature("wp1").geom().run("sq1");
    model.component("comp1").geom("geom1").feature("wp1").geom().create("sq2", "Square");

//    In the Settings window for Square, locate the Size section.
//    In the Side length text field, type 0.05.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq2").set("size", 0.05);

//    Locate the Position section.
//    From the Base list, select Center.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq2").set("base", "center");

//    In the xw text field, type -0.4.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq2").set("pos", new double[]{-0.4, 0});

//    In the yw text field, type -0.2.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("sq2").set("pos", new double[]{-0.4, -0.2});

//    In the Model Builder window, right-click Component 1 (comp1) > Geometry 1 > Work Plane 1 (wp1) and choose Revolve.

    model.component("comp1").geom("geom1").run("wp1");
    model.component("comp1").geom("geom1").feature().create("rev1", "Revolve");
    model.component("comp1").geom("geom1").feature("rev1").set("workplane", "wp1");
    model.component("comp1").geom("geom1").feature("rev1").selection("input").set("wp1");
    model.component("comp1").geom("geom1").feature("rev1").set("angtype", "full");

//    In the Geometry toolbar, click Sphere.

    model.component("comp1").geom("geom1").run("rev1");
    model.component("comp1").geom("geom1").create("sph1", "Sphere");

//    In the Settings window for Sphere, locate the Size section.
//    In the Radius text field, type 1.3.

    model.component("comp1").geom("geom1").feature("sph1").set("r", 1.3);

//    Click to expand the Layers section.
//    In the table, enter the following settings:

    model.component("comp1").geom("geom1").feature("sph1").setIndex("layer", 0.3, 0);

//    Click Build All Objects.

    model.component("comp1").geom("geom1").runPre("fin");

//    Click the Zoom Extents button in the Graphics toolbar.
//    The geometry is now complete. To see its interior, click the <l>Wireframe Rendering</l> button in the <l>Graphics</l> toolbar.

    model.component("comp1").view("view1").set("renderwireframe", true);

//    In the Geometry toolbar, click More Primitives and choose Line Segment.

    model.component("comp1").geom("geom1").create("ls1", "LineSegment");

//    On the object sph1, select Point 4.

    model.component("comp1").geom("geom1").feature("ls1").selection("vertex1").set("sph1", 4);

//    In the Settings window for Line Segment, locate the Endpoint section.
//    Select the Activate Selection toggle button for End vertex.
//    On the object sph1, select Point 9.

    model.component("comp1").geom("geom1").feature("ls1").selection("vertex2").set("sph1", 9);

//    Next, define the Infinite Element Domain.
//    In the Definitions toolbar, click Infinite Element Domain.

    model.component("comp1").coordSystem().create("ie1", "InfiniteElement");

    model.component("comp1").geom("geom1").run();

//    In the Settings window for Infinite Element Domain, locate the Geometry section.
//    From the Type list, select Spherical.

    model.component("comp1").coordSystem("ie1").set("ScalingType", "Spherical");

//    Select Domains 1, 2, 3, 4, 8, 9, 10, 11.

    model.component("comp1").coordSystem("ie1").selection().set(1, 2, 3, 4, 8, 9, 10, 11);

//    In the Model Builder window, right-click View 1 and choose Hide for Physics.

    model.component("comp1").view("view1").hideEntities().create("hide1");

//    In the Settings window for Hide for Physics, locate the Geometric Entity Selection section.
//    From the Geometric entity level list, select Boundary.

    model.component("comp1").view("view1").hideEntities("hide1").geom("geom1", 2);

//    Select Boundaries 6, 10.

    model.component("comp1").view("view1").hideEntities("hide1").set(6, 10);

//    In the Physics toolbar, click Domains and choose Domain Coil.

    model.component("comp1").physics("mf").create("coil1", "Coil", 3);

//    Select Domain 6.

    model.component("comp1").physics("mf").feature("coil1").selection().set(6);

//    In the Settings window for Domain Coil, locate the Coil section.
//    From the Conductor model list, select Homogenized multiturn.

    model.component("comp1").physics("mf").feature("coil1").set("ConductorModel", "Multi");

//    From the Coil type list, select Circular.

    model.component("comp1").physics("mf").feature("coil1").set("CoilType", "Circular");

//    In the \[I_{\textrm{coil}}\] text field, type I0.

    model.component("comp1").physics("mf").feature("coil1").set("ICoil", "I0");

//    Locate the Homogenized Conductor section.
//    From the Coil wire cross-section area list, select User defined.

    model.component("comp1").physics("mf").feature("coil1").set("AreaFrom", "UserDefined");

//    Find the High-frequency effective loss subsection.
//    Clear the Include harmonic loss checkbox.

    model.component("comp1").physics("mf").feature("coil1").set("HarmonicLoss", false);

//    In order to specify the direction of the wires in the circular coil, use the <l>Coil Geometry</l> subfeature to select a group of edges forming a circle. The path of the wires will be automatically computed from the geometry of the selected edges. For the best results, the radius of the circular edges selected should be close to the average radius of the coil.
//    In the Model Builder window, click Coil Geometry 1.
//    In the Settings window for Coil Geometry, locate the Edge Selection section.
//    Click Clear Selection.
//    Select Edges 25, 26, 46, 49.

    model.component("comp1").physics("mf").feature("coil1").feature("cre1").selection().set(25, 26, 46, 49);

//    Now set up the second coil in the same way.
//    In the Physics toolbar, click Domains and choose Domain Coil.

    model.component("comp1").physics("mf").create("coil2", "Coil", 3);

//    Select Domain 7.

    model.component("comp1").physics("mf").feature("coil2").selection().set(7);

//    In the Settings window for Domain Coil, locate the Coil section.
//    From the Conductor model list, select Homogenized multiturn.

    model.component("comp1").physics("mf").feature("coil2").set("ConductorModel", "Multi");

//    From the Coil type list, select Circular.

    model.component("comp1").physics("mf").feature("coil2").set("CoilType", "Circular");

//    In the \[I_{\textrm{coil}}\] text field, type I0.

    model.component("comp1").physics("mf").feature("coil2").set("ICoil", "I0");

//    Locate the Homogenized Conductor section.
//    From the Coil wire cross-section area list, select User defined.

    model.component("comp1").physics("mf").feature("coil2").set("AreaFrom", "UserDefined");

//    Find the High-frequency effective loss subsection.
//    Clear the Include harmonic loss checkbox.

    model.component("comp1").physics("mf").feature("coil2").set("HarmonicLoss", false);

//    In the Model Builder window, click Coil Geometry 1.
//    In the Settings window for Coil Geometry, locate the Edge Selection section.
//    Click Clear Selection.
//    Select Edges 30, 31, 72, 75.

    model.component("comp1").physics("mf").feature("coil2").feature("cre1").selection().set(30, 31, 72, 75);

//    In the Model Builder window, under Component 1 (comp1), click Magnetic Fields, Currents Only (mfco).
//    In the Physics toolbar, click Domains and choose Conductor.

    model.component("comp1").physics("mfco").create("cond1", "Conductor", 3);

//    Select Domain 6.

    model.component("comp1").physics("mfco").feature("cond1").selection().set(6);

//    In the Model Builder window, expand the Conductor 1 node, then click Terminal 1.
//    Select Boundary 13.

    model.component("comp1").physics("mfco").feature("cond1").feature("term1").selection().set(13);

//    In the Settings window for Terminal, locate the Terminal section.
//    In the \[I_0\] text field, type 10*I0.

    model.component("comp1").physics("mfco").feature("cond1").feature("term1").set("I0", "10*I0");

//    In the Physics toolbar, click Domains and choose Conductor.

    model.component("comp1").physics("mfco").create("cond2", "Conductor", 3);

//    Select Domain 7.

    model.component("comp1").physics("mfco").feature("cond2").selection().set(7);

//    In the Model Builder window, expand the Conductor 2 node, then click Terminal 1.
//    Select Boundary 20.

    model.component("comp1").physics("mfco").feature("cond2").feature("term1").selection().set(20);

//    In the Settings window for Terminal, locate the Terminal section.
//    In the \[I_0\] text field, type 10*I0.

    model.component("comp1").physics("mfco").feature("cond2").feature("term1").set("I0", "10*I0");

//    Define the insulating material for the coils.
//    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, type Coil Insulator in the Label text field.

    model.component("comp1").material("mat1").label("Coil Insulator");

//    Select Domains 6, 7.

    model.component("comp1").material("mat1").selection().set(6, 7);

//    Locate the Material Contents section.
//    In the table, enter the following settings:

    model.component("comp1").material("mat1").propertyGroup("def").set("relpermeability", new String[]{"1"});
    model.component("comp1").material("mat1").propertyGroup("def").set("relpermittivity", new String[]{"1"});
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("electricconductivity", new String[]{"6e7[S/m]"});

//    Next, set up the mesh.
//    In the Mesh toolbar, click More Generators and choose Edge.

    model.component("comp1").mesh("mesh1").create("edg1", "Edge");

//    Select Edge 40.

    model.component("comp1").mesh("mesh1").feature("edg1").selection().set(40);

//    Right-click Edge 1 and choose Distribution.

    model.component("comp1").mesh("mesh1").feature("edg1").create("dis1", "Distribution");

//    In the Settings window for Distribution, locate the Distribution section.
//    In the Number of elements text field, type 50.

    model.component("comp1").mesh("mesh1").feature("edg1").feature("dis1").set("numelem", 50);

//    In the Mesh toolbar, click Free Tetrahedral.

    model.component("comp1").mesh("mesh1").create("ftet1", "FreeTet");

//    In the Settings window for Free Tetrahedral, locate the Domain Selection section.
//    From the Geometric entity level list, select Domain.

    model.component("comp1").mesh("mesh1").feature("ftet1").selection().geom("geom1", 3);

//    Select Domains 5, 6, 7.

    model.component("comp1").mesh("mesh1").feature("ftet1").selection().set(5, 6, 7);

//    Right-click Free Tetrahedral 1 and choose Size.

    model.component("comp1").mesh("mesh1").feature("ftet1").create("size1", "Size");

//    Select Domains 6, 7.

    model.component("comp1").mesh("mesh1").feature("ftet1").feature("size1").selection().set(6, 7);

//    In the Settings window for Size, locate the Element Size section.
//    Click the Custom button.

    model.component("comp1").mesh("mesh1").feature("ftet1").feature("size1").set("custom", true);

//    Locate the Element Size Parameters section.
//    Select the Maximum element size checkbox.

    model.component("comp1").mesh("mesh1").feature("ftet1").feature("size1").set("hmaxactive", true);

//    In the associated text field, type 0.05.

    model.component("comp1").mesh("mesh1").feature("ftet1").feature("size1").set("hmax", 0.05);

//    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");

//    Right-click Distribution 1 and choose Build All.

    model.component("comp1").mesh("mesh1").run();

//    In the Study toolbar, click Stationary.

    model.study("std1").create("stat2", "Stationary");
    model.study("std1").feature("stat").setSolveFor("/physics/mfco", false);

//    In the Model Builder window, click Step 1: Stationary.
//    In the Settings window for Stationary, locate the Physics and Variables Selection section.
//    In the Solve for column of the table, under Component 1 (comp1), clear the checkbox for Magnetic Fields, Currents Only (mfco).

    model.study("std1").feature("stat2").setSolveFor("/physics/mf", false);

//    In the Model Builder window, click Step 2: Stationary 2.
//    In the Settings window for Stationary, locate the Physics and Variables Selection section.
//    In the Solve for column of the table, under Component 1 (comp1), clear the checkbox for Magnetic Fields (mf).
//    In the Model Builder window, click Study 1.
//    In the Settings window for Study, locate the Study Settings section.
//    Clear the Generate default plots checkbox.

    model.study("std1").setGenPlots(false);

//    In the Study toolbar, click Compute.

    model.study("std1").createAutoSequences("all");

    model.sol("sol1").runAll();

//    Add a selection to the computed dataset to exclude the outer boundaries.
//    In the Definitions toolbar, click Explicit.

    model.component("comp1").selection().create("sel1", "Explicit");

//    Select Domains 6, 7.

    model.component("comp1").selection("sel1").set(6, 7);

//    In the Settings window for Explicit, locate the Output Entities section.
//    From the Output entities list, select Adjacent boundaries.

    model.component("comp1").selection("sel1").geom("geom1", 3, 2, new String[]{"exterior"});
    model.component("comp1").selection("sel1").set(6, 7);

//    In the Label text field, type Coils.

    model.component("comp1").selection("sel1").label("Coils");

//    Now add the plots.
//    In the Model Builder window, expand the Results node.
//    In the Model Builder window, expand the Results > Datasets node, then click Study 1/Solution 1 (sol1).
//    In the Results toolbar, click Attributes and choose Selection.
//    In the Settings window for Selection, locate the Geometric Entity Selection section.
//    From the Geometric entity level list, select Boundary.

    model.result().dataset("dset1").selection().geom("geom1", 2);

//    From the Selection list, select Coils.

    model.result().dataset("dset1").selection().named("sel1");

//    In the Results toolbar, click 3D Plot Group.

    model.result().create("pg1", "PlotGroup3D");
    model.result("pg1").run();

//    In the Settings window for 3D Plot Group, type Magnetic Flux Density, MF in the Label text field.

    model.result("pg1").label("Magnetic Flux Density, MF");

//    Right-click Magnetic Flux Density, MF and choose Slice.

    model.result("pg1").create("slc1", "Slice");
    model.result("pg1").feature("slc1").set("evaluationsettings", "parent");

//    In the Settings window for Slice, locate the Plane Data section.
//    From the Plane list, select xy-planes.

    model.result("pg1").feature("slc1").set("quickplane", "xy");

//    In the Planes text field, type 1.

    model.result("pg1").feature("slc1").set("quickznumber", 1);

//    Click Replace Expression in the upper-right corner of the Expression section.
//    From the menu, choose Component 1 (comp1) > Magnetic Fields > Magnetic > mf.normB - Magnetic flux density norm - T.

    model.result("pg1").feature("slc1").set("expr", "mf.normB");
    model.result("pg1").feature("slc1").set("descr", "Magnetic flux density norm");

//    In the Magnetic Flux Density, MF toolbar, click Plot.

    model.result("pg1").run();
    model.result("pg1").run();

//    In the Model Builder window, right-click Magnetic Flux Density, MF and choose Arrow Volume.

    model.result("pg1").create("arwv1", "ArrowVolume");
    model.result("pg1").feature("arwv1").set("evaluationsettings", "parent");

//    In the Settings window for Arrow Volume, click Replace Expression in the upper-right corner of the Expression section.
//    From the menu, choose Component 1 (comp1) > Magnetic Fields > Magnetic > mf.Hx,mf.Hy,mf.Hz - Magnetic field.

    model.result("pg1").feature("arwv1").set("expr", new String[]{"mf.Hx", "mf.Hy", "mf.Hz"});
    model.result("pg1").feature("arwv1").set("descr", "Magnetic field");

//    Locate the Arrow Positioning section.
//    Find the x grid points subsection.
//    In the Points text field, type 24.

    model.result("pg1").feature("arwv1").set("xnumber", 24);

//    Find the y grid points subsection.
//    In the Points text field, type 10.

    model.result("pg1").feature("arwv1").set("ynumber", 10);

//    Find the z grid points subsection.
//    In the Points text field, type 1.

    model.result("pg1").feature("arwv1").set("znumber", 1);

//    Locate the Coloring and Style section.
//    Select the Scale factor checkbox.

    model.result("pg1").feature("arwv1").set("scaleactive", true);

//    In the associated text field, type 25.

    model.result("pg1").feature("arwv1").set("scale", 25);

//    In the Magnetic Flux Density, MF toolbar, click Plot.

    model.result("pg1").run();

//    To make the coil look like a solid object, you can add a surface plot on its boundaries.

    model.result("pg1").run();

//    Right-click Magnetic Flux Density, MF and choose Surface.

    model.result("pg1").create("surf1", "Surface");
    model.result("pg1").feature("surf1").set("evaluationsettings", "parent");

//    In the Settings window for Surface, locate the Expression section.
//    In the Expression text field, type 1.

    model.result("pg1").feature("surf1").set("expr", "1");

//    Locate the Coloring and Style section.
//    From the Coloring list, select Uniform.

    model.result("pg1").feature("surf1").set("coloring", "uniform");

//    From the Color list, select White.

    model.result("pg1").feature("surf1").set("color", "white");

//    Next, compare the results of <c>By</c> and <c>Byy</c> calculated from the two interfaces.
//    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 Comparison of By in the Label text field.

    model.result("pg2").label("Comparison of By");

//    Right-click Comparison of By and choose Line Graph.

    model.result("pg2").create("lngr1", "LineGraph");
    model.result("pg2").feature("lngr1").set("markerpos", "datapoints");
    model.result("pg2").feature("lngr1").set("linewidth", "preference");
    model.result("pg2").feature("lngr1").set("evaluationsettings", "parent");

//    Select Edge 40.

    model.result("pg2").feature("lngr1").selection().set(40);

//    In the Settings window for Line Graph, locate the y-Axis Data section.
//    In the Expression text field, type mf.By.

    model.result("pg2").feature("lngr1").set("expr", "mf.By");

//    Locate the x-Axis Data section.
//    From the Parameter list, select Expression.

    model.result("pg2").feature("lngr1").set("xdata", "expr");

//    In the Expression text field, type y.

    model.result("pg2").feature("lngr1").set("xdataexpr", "y");

//    Click to expand the Coloring and Style section.
//    Find the Line markers subsection.
//    From the Marker list, select Cycle.

    model.result("pg2").feature("lngr1").set("linemarker", "cycle");

//    From the Positioning list, select Interpolated.

    model.result("pg2").feature("lngr1").set("markerpos", "interp");

//    Click to expand the Legends section.
//    Select the Show legends checkbox.

    model.result("pg2").feature("lngr1").set("legend", true);

//    From the Legends list, select Manual.

    model.result("pg2").feature("lngr1").set("legendmethod", "manual");

//    In the table, enter the following settings:

    model.result("pg2").feature("lngr1").setIndex("legends", "Magnetic Fields interface", 0);

//    Right-click Line Graph 1 and choose Duplicate.

    model.result("pg2").feature().duplicate("lngr2", "lngr1");
    model.result("pg2").run();

//    In the Settings window for Line Graph, locate the y-Axis Data section.
//    In the Expression text field, type mfco.By.

    model.result("pg2").feature("lngr2").set("expr", "mfco.By");

//    Click to expand the Title section.
//    From the Title type list, select None.

    model.result("pg2").feature("lngr2").set("titletype", "none");

//    Locate the Legends section.
//    In the table, enter the following settings:

    model.result("pg2").feature("lngr2").setIndex("legends", "Magnetic Fields, Currents Only interface", 0);
    model.result("pg2").run();

//    In the Model Builder window, click Comparison of By.
//    In the Settings window for 1D Plot Group, locate the Legend section.
//    From the Position list, select Upper middle.

    model.result("pg2").set("legendpos", "uppermiddle");

//    In the Comparison of By toolbar, click Plot.

    model.result("pg2").run();

//    Right-click Comparison of By and choose Duplicate.

    model.result().duplicate("pg3", "pg2");
    model.result("pg3").run();

//    In the Model Builder window, click Comparison of By 1.
//    In the Settings window for 1D Plot Group, type Comparison of Byy in the Label text field.

    model.result("pg3").label("Comparison of Byy");

//    Locate the Legend section.
//    From the Position list, select Lower right.

    model.result("pg3").set("legendpos", "lowerright");
    model.result("pg3").run();

//    In the Model Builder window, click Line Graph 1.
//    In the Settings window for Line Graph, locate the y-Axis Data section.
//    In the Expression text field, type d(laginterp(2,mf.By),y).

    model.result("pg3").feature("lngr1").set("expr", "d(laginterp(2,mf.By),y)");

//    The <c>mf</c> interface is using Curl shape functions and the higher order spatial derivative is not available in postprocessing. In this case, use the <c>laginterp</c> operator.

    model.result("pg3").run();

//    In the Model Builder window, click Line Graph 2.
//    In the Settings window for Line Graph, locate the y-Axis Data section.
//    In the Expression text field, type d(mfco.By,y).

    model.result("pg3").feature("lngr2").set("expr", "d(mfco.By,y)");

//    The <c>mfco</c> interface is using secondary order Lagrange shape functions and the second derivative is available. The curves of <c>Byy</c> can be improved by using cubic elements.
//    In the Comparison of Byy toolbar, click Plot.

    model.result("pg3").run();
    model.result("pg1").run();

    model.title("Magnetic Field of a Helmholtz Coil");

    model
         .description("A Helmholtz coil is a parallel pair of identical circular coils spaced one radius apart and wound so that the current flows through both coils in the same direction. This winding results in a uniform magnetic field between the coils with the primary component parallel to the axes of the two coils. The model shows how to compute the magnetic field and its higher derivatives using two different interfaces.");

    return model;
  }

  public static void main(String[] args) {
    run();
  }

}
