/*
 * postbuckling_shell.java
 */

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on May 15 2026, 09:38 by COMSOL 6.4.0.421. */
public class postbuckling_shell {

  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 > Shell (shell).
//    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("shell", "Shell", "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("R", "2540[mm]");
    model.param().descr("R", "Panel radius");
    model.param().set("L", "254[mm]");
    model.param().descr("L", "Panel length");
    model.param().set("thic", "6.35[mm]");
    model.param().descr("thic", "Panel thickness");
    model.param().set("theta", "0.1[rad]");
    model.param().descr("theta", "Panel section angle");
    model.param().set("E0", "3.103[GPa]");
    model.param().descr("E0", "Young's modulus");
    model.param().set("nu0", "0.3");
    model.param().descr("nu0", "Poisson's ratio");
    model.param().set("disp", "0");
    model.param().descr("disp", "Displacement parameter");

//    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, locate the Plane Definition section.
//    From the Plane list, select xz-plane.

    model.component("comp1").geom("geom1").feature("wp1").set("quickplane", "xz");

//    Click Go to Plane Geometry.
//    In the Work Plane toolbar, click More Primitives and choose Line Segment.

    model.component("comp1").geom("geom1").feature("wp1").geom().create("ls1", "LineSegment");

//    In the Settings window for Line Segment, locate the Starting Point section.
//    From the Specify list, select Coordinates.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("ls1").set("specify1", "coord");

//    Locate the Endpoint section.
//    From the Specify list, select Coordinates.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("ls1").set("specify2", "coord");

//    Locate the Starting Point section.
//    In the yw text field, type R.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("ls1")
         .set("coord1", new String[]{"0", "R"});

//    Locate the Endpoint section.
//    In the xw text field, type L.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("ls1")
         .set("coord2", new String[]{"L", "0"});

//     and <l>yw</l> to <c>R</c>.

    model.component("comp1").geom("geom1").feature("wp1").geom().feature("ls1")
         .set("coord2", new String[]{"L", "R"});

//    Click Build Selected.

    model.component("comp1").geom("geom1").feature("wp1").geom().run("ls1");

//    In the Model Builder window, right-click Geometry 1 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("angtype", "full");

//    In the Settings window for Revolve, locate the Revolution Angles section.
//    Click the Angles button.

    model.component("comp1").geom("geom1").feature("rev1").set("angtype", "specang");

//    In the End angle text field, type theta.

    model.component("comp1").geom("geom1").feature("rev1").set("angle2", "theta");

//    Locate the Revolution Axis section.
//    Find the Direction of revolution axis subsection.
//    In the xw text field, type 1.

    model.component("comp1").geom("geom1").feature("rev1").set("axis", new double[]{1, 1});

//    In the yw text field, type 0.

    model.component("comp1").geom("geom1").feature("rev1").set("axis", new double[]{1, 0});

//    Click Build Selected.

    model.component("comp1").geom("geom1").run("rev1");

//    Click the Zoom Extents button in the Graphics toolbar.
//    In the Definitions toolbar, click Nonlocal Couplings and choose Average.

    model.component("comp1").cpl().create("aveop1", "Average");

    model.component("comp1").geom("geom1").run();

    model.component("comp1").cpl("aveop1").set("axisym", true);

//    In the Settings window for Average, locate the Source Selection section.
//    From the Geometric entity level list, select Boundary.

    model.component("comp1").cpl("aveop1").selection().geom("geom1", 2);

//    Select Boundary 1.

    model.component("comp1").cpl("aveop1").selection().set(1);

//    In the Definitions toolbar, click Nonlocal Couplings and choose Integration.

    model.component("comp1").cpl().create("intop1", "Integration");
    model.component("comp1").cpl("intop1").set("axisym", true);

//    In the Settings window for Integration, locate the Source Selection section.
//    From the Geometric entity level list, select Point.

    model.component("comp1").cpl("intop1").selection().geom("geom1", 0);

//    Select Point 4.

    model.component("comp1").cpl("intop1").selection().set(4);

//    In the Definitions toolbar, click Local Variables.

    model.component("comp1").variable().create("var1");

//    In the Settings window for Variables, locate the Variables section.
//    In the table, enter the following settings:

    model.component("comp1").variable("var1").set("w_center", "-intop1(w)");
    model.component("comp1").variable("var1").descr("w_center", "Vertical displacement at shell center");

//    In the Model Builder window, under Component 1 (comp1) > Shell (shell), click Thickness and Offset 1.
//    In the Settings window for Thickness and Offset, locate the Thickness and Offset section.
//    In the \[d_0\] text field, type thic.

    model.component("comp1").physics("shell").feature("to1").set("d", "thic");

//    In the Physics toolbar, click Edges and choose Symmetry.

    model.component("comp1").physics("shell").create("sym1", "SymmetrySolid1", 1);

//    Select Edges 3, 4.

    model.component("comp1").physics("shell").feature("sym1").selection().set(3, 4);

//    In the Physics toolbar, click Edges and choose Pinned.

    model.component("comp1").physics("shell").create("pin1", "Pinned", 1);

//    Select Edge 2.

    model.component("comp1").physics("shell").feature("pin1").selection().set(2);

//    In the Physics toolbar, click Points and choose Point Load.

    model.component("comp1").physics("shell").create("pl1", "PointLoad", 0);

//    Select Point 4.

    model.component("comp1").physics("shell").feature("pl1").selection().set(4);

//    Apply 1/4th of the total load because of the double symmetry used in this model.
//    In the Settings window for Point Load, locate the Force section.
//    Specify the \[\mathbf{F}_{\mathrm{P}}\] vector as

    model.component("comp1").physics("shell").feature("pl1").set("forcePoint", new String[]{"0", "0", "-P/4"});

//    Click the Show More Options button in the Model Builder toolbar.
//    In the Show More Options dialog, in the tree, select the checkbox for the Physics > Equation Contributions node.
//    Click OK.
//    In the Physics toolbar, click Global and choose Global Equations.

    model.component("comp1").physics("shell").create("ge1", "GlobalEquations", -1);

//    In the Settings window for Global Equations, locate the Global Equations section.
//    In the table, enter the following settings:

    model.component("comp1").physics("shell").feature("ge1").setIndex("name", "P", 0, 0);
    model.component("comp1").physics("shell").feature("ge1").setIndex("equation", "aveop1(-w)-disp", 0, 0);
    model.component("comp1").physics("shell").feature("ge1").setIndex("description", "Force at shell center", 0, 0);

//    Locate the Units section.
//    Click Select Dependent Variable Quantity.
//    In the Physical Quantity dialog, type force in the text field.
//    In the tree, select General > Force (N).
//    Click OK.

    model.component("comp1").physics("shell").feature("ge1").set("DependentVariableQuantity", "force");

//    In the Settings window for Global Equations, locate the Units section.
//    Click Select Source Term Quantity.
//    In the Physical Quantity dialog, type displacement in the text field.
//    In the tree, select General > Displacement (m).
//    Click OK.

    model.component("comp1").physics("shell").feature("ge1").set("SourceTermQuantity", "displacement");

//    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[]{"0"});

//    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 Settings window for Distribution, locate the Distribution section.
//    In the Number of elements text field, type 10.

    model.component("comp1").mesh("mesh1").feature("map1").feature("dis1").set("numelem", 10);

//    Click Build Selected.

    model.component("comp1").mesh("mesh1").run("map1");

//    In the Model Builder window, click Study 1.
//    In the Settings window for Study, type Postbuckling Study in the Label text field.

    model.study("std1").label("Postbuckling Study");

//    Set up an auxiliary continuation sweep for the <l>disp</l> parameter.
//    In the Model Builder window, under Postbuckling Study, click Step 1: Stationary.
//    In the Settings window for Stationary, click to expand the Study Extensions section.
//    Select the Auxiliary sweep checkbox.

    model.study("std1").feature("stat").set("useparam", true);

//    Click Add.

    model.study("std1").feature("stat").setIndex("pname", "R", 0);
    model.study("std1").feature("stat").setIndex("plistarr", "", 0);
    model.study("std1").feature("stat").setIndex("punit", "m", 0);
    model.study("std1").feature("stat").setIndex("pname", "R", 0);
    model.study("std1").feature("stat").setIndex("plistarr", "", 0);
    model.study("std1").feature("stat").setIndex("punit", "m", 0);

//    In the table, enter the following settings:

    model.study("std1").feature("stat").setIndex("pname", "disp", 0);
    model.study("std1").feature("stat").setIndex("plistarr", "range(0,2e-4,1)", 0);

//    Locate the Study Settings section.
//    Select the Include geometric nonlinearity checkbox.

    model.study("std1").feature("stat").set("geometricNonlinearity", true);

//    Sometimes it is not straightforward to guess the maximum value of the parameter used. You can then instead set a stop condition for the parametric solver based on something that is known.
//    In the Study toolbar, click Show Default Solver.

    model.study("std1").showAutoSequences("all");

//    In the Model Builder window, expand the Solution 1 (sol1) node.
//    In the Model Builder window, expand the Postbuckling Study > Solver Configurations > Solution 1 (sol1) > Stationary Solver 1 node.
//    Right-click Postbuckling Study > Solver Configurations > Solution 1 (sol1) > Stationary Solver 1 > Parametric 1 and choose Stop Condition.

    model.sol("sol1").feature("s1").feature("p1").create("st1", "StopCondition");

//    In the Settings window for Stop Condition, locate the Stop Expressions section.
//    Click Add.

    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopcondarr", "", 0);
    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopcondterminateon", "true", 0);
    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopcondActive", true, 0);
    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopconddesc", "Stop expression 1", 0);
    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopcondarr", "", 0);
    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopcondterminateon", "true", 0);
    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopcondActive", true, 0);
    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopconddesc", "Stop expression 1", 0);

//    In the table, enter the following settings:

    model.sol("sol1").feature("s1").feature("p1").feature("st1").setIndex("stopcondarr", "comp1.w_center>0.035", 0);

//    Specify that the solution is to be stored just before the stop condition is reached.
//    Locate the Output at Stop section.
//    From the Add solution list, select Step before stop.

    model.sol("sol1").feature("s1").feature("p1").feature("st1").set("storestopcondsol", "stepbefore");

//    Clear the Add information checkbox.

    model.sol("sol1").feature("s1").feature("p1").feature("st1").set("stopcondwarn", false);

//    In the Model Builder window, under Postbuckling Study > Solver Configurations > Solution 1 (sol1), click Stationary Solver 1.
//    In the Settings window for Stationary Solver, click to expand the Output section.
//    Clear the Reaction forces checkbox.

    model.sol("sol1").feature("s1").set("reacf", false);

//    Click Run.

    model.sol("sol1").runAll();

    model.result().dataset().create("dset1shellshl", "Shell");
    model.result().dataset("dset1shellshl").set("data", "dset1");
    model.result().dataset("dset1shellshl").setIndex("topconst", "1", 3, 1);
    model.result().dataset("dset1shellshl").setIndex("bottomconst", "-1", 3, 1);
    model.result().dataset("dset1shellshl").setIndex("orientationexpr", "shell.nlX", 0);
    model.result().dataset("dset1shellshl").setIndex("displacementexpr", "arx", 0);
    model.result().dataset("dset1shellshl").setIndex("orientationexpr", "shell.nlY", 1);
    model.result().dataset("dset1shellshl").setIndex("displacementexpr", "ary", 1);
    model.result().dataset("dset1shellshl").setIndex("orientationexpr", "shell.nlZ", 2);
    model.result().dataset("dset1shellshl").setIndex("displacementexpr", "arz", 2);
    model.result().dataset("dset1shellshl").set("distanceexpr", "shell.z_pos");
    model.result().dataset("dset1shellshl").set("seplevels", false);
    model.result().dataset("dset1shellshl").set("resolution", 2);
    model.result().dataset("dset1shellshl").set("areascalefactor", "shell.ASF");
    model.result().dataset("dset1shellshl").set("linescalefactor", "shell.LSF");
    model.result().create("pg1", "PlotGroup3D");
    model.result("pg1").set("data", "dset1shellshl");
    model.result("pg1").setIndex("looplevel", 92, 0);
    model.result("pg1").label("Stress (shell)");
    model.result("pg1").set("showlegends", true);
    model.result("pg1").set("frametype", "spatial");
    model.result("pg1").create("surf1", "Surface");
    model.result("pg1").feature("surf1").set("expr", new String[]{"shell.misesGp"});
    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("descr", "von Mises stress");
    model.result("pg1").feature("surf1").set("colortable", "Prism");
    model.result("pg1").feature("surf1").create("def", "Deform");
    model.result("pg1").feature("surf1").feature("def").set("expr", new String[]{"shell.u", "shell.v", "shell.w"});
    model.result("pg1").feature("surf1").feature("def").set("scaleactive", true);
    model.result("pg1").feature("surf1").feature("def").set("scale", "1");
    model.result("pg1").run();

//    In the Results toolbar, click Evaluation Group.

    model.result().evaluationGroup().create("eg1", "EvaluationGroup");

//    In the Settings window for Evaluation Group, type Evaluation Group: Force vs. Displacement in the Label text field.

    model.result().evaluationGroup("eg1").label("Evaluation Group: Force vs. Displacement");

//    Right-click Evaluation Group: Force vs. Displacement and choose Point Evaluation.

    model.result().evaluationGroup("eg1").create("pev1", "EvalPoint");

//    Select Point 4.

    model.result().evaluationGroup("eg1").feature("pev1").selection().set(4);

//    In the Settings window for Point Evaluation, locate the Expressions section.
//    In the table, enter the following settings:

    model.result().evaluationGroup("eg1").feature("pev1").setIndex("expr", "w_center", 0);
    model.result().evaluationGroup("eg1").feature("pev1").setIndex("expr", "P", 1);

//    In the Model Builder window, click Evaluation Group: Force vs. Displacement.
//    In the Settings window for Evaluation Group, click to expand the Format section.
//    From the Include parameters list, select Off.

    model.result().evaluationGroup("eg1").set("includeparameters", false);

//    In the Evaluation Group: Force vs. Displacement toolbar, click Evaluate.

    model.result().evaluationGroup("eg1").run();

//    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 Force vs. Displacement in the Label text field.

    model.result("pg2").label("Force vs. Displacement");

//    Locate the Plot Settings section.
//    Select the x-axis label checkbox.

    model.result("pg2").set("xlabelactive", true);

//    In the associated text field, type Vertical displacement at shell center (m).

    model.result("pg2").set("xlabel", "Vertical displacement at shell center (m)");

//    Select the y-axis label checkbox.

    model.result("pg2").set("ylabelactive", true);

//    In the associated text field, type Force at shell center (N).

    model.result("pg2").set("ylabel", "Force at shell center (N)");

//    Right-click Force vs. Displacement and choose Table Graph.

    model.result("pg2").create("tblp1", "Table");
    model.result("pg2").feature("tblp1").set("markerpos", "datapoints");
    model.result("pg2").feature("tblp1").set("linewidth", "preference");

//    In the Settings window for Table Graph, locate the Data section.
//    From the Source list, select Evaluation group.

    model.result("pg2").feature("tblp1").set("source", "evaluationgroup");
    model.result("pg2").run();

//    In the Model Builder window, click Force vs. Displacement.
//    In the Force vs. Displacement toolbar, click Plot.

    model.result("pg2").run();

    model.title("Postbuckling Analysis of a Hinged Cylindrical Shell");

    model
         .description("This example shows how to trace a postbuckling path where neither load nor displacement is increasing monotonously. The results are compared to published values.");

    return model;
  }

  public static void main(String[] args) {
    run();
  }

}
