• CFD, Fluid Flow, FEA, Heat/Mass Transfer

Macros in Java for STAR-CCM+

Example Scripts to Automate Simulations

This page example functions and approach to automate simulation process partially or fully. It is not intended to created a push-button simulation example. Not all the codes have been tested in live STAR-CCM+ session and hence some bugs can be found.


Table of Contents:

Store common variables for mesh generation, boundary conditions, material properties, solver settings, post-processing and report generation in separate file. The constants and variables are stored in file simVars.java and the main function and methods are stored in file named solverSettingsSTAR.java. The two files need to be compiled together: javac solverSettingsSTAR.java simVars.java
Variables to be copied into public void execute(). The variables are defined to be same as in PyFLUENT example and hence they can be use by removing the qualifier 'double' and semi-colons. The values are in default units (which is SI or MKS unless user has changed to any other such as FPS system). github.com/frkasper/MacroUtils/.../UserDeclarations.java is a good example to declare variables as per project specific requirements.
  double max_cell_quality = 0.10;
  double max_allowed_skew = 75.0;
  double max_volm_change  = 0.01;
  
  // Boundary conditions
  double[] gravity = { 0.0, -9.806, 0.0 };
  double[] v_init = { 0.1, 0.0, 0.0 };
  double radEmissivity = 0.80;
  
  // Porous resistances
  double i_res           = 2500;
  double v_res           = 50;
  
  // Solver settings
  double n_iter          = 4000;
  double t_step          = 1.0e-3;
  double duration        = 10.0;
  double iter_per_step   = 20;
  double count_t_steps   = duration / t_step;

  // Reference and limiting values
  double ref_den         = 1.225;
  double Tref            = 300;
  double t_max           = 500;
  double t_min           = 273;
  double p_min           = 100;
Alternatively, a table can be defined such as one described below and a Java macro can be used to read and assign boundary conditions.
Zone_Name   Type    Material_Name  Density   Thermal_Conductivty   Cp       RPM    LC_I    LC_V
------------------------------------------------------------------------------------------------
Tubes       Fluid   Air            1.120       0.027               1005.5     0      0      0
...
Here LC_I and LC_V is applicable to porous zones. Similar table can be created for wall boundary types.
One can define ArrayList<String> bc_list = new ArrayList<String>(Arrays.list("inlet_1", "inlet_2", "wall_htc", "wall_rot", "outlet_p")); to create a list of names to be used in various functions. The list can be name of scenes, reports, plots, derived parts, planes, zone names... where each item can be access using get(i).
Alternatively, following class/method can be used to read variables stored in a text file in the format var_name = var_value. '=' acts as delimiter. This way, one can use the data file created for other programming language such as Python. The important point to note the value decimal and integer values are interpreted. x = 300.0 - x will be classified as variable type 'double'. x = 300 - x will be categorized as variable type 'integer'.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class readVariablesFromFile {

  public static void main(String[] args) {
    String file_name = "input.txt";
    Map<String, Object> variables = readVariablesFromFile(file_name);

    // Print the variables
    for (Map.Entry<String, Object> entry : variables.entrySet()) {
      System.out.println(entry.getKey() + " = " + entry.getValue() + 
      " (" + entry.getValue().getClass().getSimpleName() + ")");
    }
  }
  public static Map<String, Object> readVariablesFromFile(String file_name) {
    Map<String, Object> variables = new HashMap<>();

    try (BufferedReader reader = new BufferedReader(new FileReader(file_name))) {
      String line;
      while ((line = reader.readLine()) != null) {
        String[] parts = line.split("=", 2);
        if (parts.length == 2) {
          String variableName = parts[0].trim();
          String value = parts[1].trim();

          Object parsedValue = parseValue(value);
          variables.put(variableName, parsedValue);
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return variables;
  }
  private static Object parseValue(String value) {
    try {
      return Integer.parseInt(value);
    } catch (NumberFormatException e1) {
      try {
        return Double.parseDouble(value);
      } catch (NumberFormatException e2) {
        // Default is string if not an integer or double
        return value; 
      }
    }
  }
}
Methods and Classes: uncomment/comment as needed.
import java.util.*;
import star.common.*;
import star.base.neo.*;
import star.motion.*;

public class starMacroTemplate extends StarMacro {
  public void execute() {
    importCad_Mesh(Simulation simX);
    generateSrfMesh(Simulation simX);
    generateVolMesh(Simulation simX);
    defineMatProps(Simulation simX);
    defineBndConds(Boundary bndry);
    solverSettings(Simulation simX);
    defineMonitors(Simulation simX);
    defineReports(Simulation simX);
    generateReports(Simulation simX);
    defineScenes(Simulation simX);
    saveReptPlots(Simulation simX);
  }
}
  private void importCad_Mesh() {
    ...
  }
  
  private void generateSrfMesh() {
    ...
  }
  private void generateVolMesh(simX) {
    ...
    
    //Check and print mesh quality
    MinReport min_cell_q = (MinReport) simX.getReportManager().getReport("minCellQuality");
    MaxReport max_skew = (MaxReport) simX.getReportManager().getReport("maxCellSkewness");
  }
Define a continuum model class,
  public static final Class<? extends Model>[] gas_models = new Class[] {
    ThreeDimensionalModel.class,
    SteadyModel.class,
    SingleComponentGasModel.class,
    CoupledFlowModel.class,
    PolynomialDensityModel.class,
    CoupledEnergyModel.class,
    TurbulentModel.class,
    RansTurbulenceModel.class,
    KEpsilonTurbulence.class,
    RkeTwoLayerTurbModel.class,
    KeTwoLayerAllYplusWallTreatment.class,
    RadiationModel.class,
    S2sModel.class,
    ViewfactorsCalculatorModel.class,
    GrayThermalRadiationModel.class
  };
Check if a model exists
  if(continuum.getModelManager().hasModel(SingleComponentGasModel.class) != null) {
    for (Class<? extends Model> model_class : gas_models) {
      if (continuum.getModelManager().hasModel(model_class) == null) {
        return false;
      }
    return true;
  }
Create continua
  public void createContinuum() {
    PhysicsContinuum continuum = physicsContinuumCondition.getSatisfyingObject();
    if (continuum != null) {
      notifyUser("Continuum \"" + continuum.getPresentationName() + "\" already created");
      return;
    }
    createContinuum(gas_models);
  }
  private double getZones(Simulation simX, String region_type) {
    double cell_count = 0;
    ElementCountReport el_count = simX.getReportManager().createReport(ElementCountReport.clss);
    Collection<Region> all_regions = simX.getRegionManager().getRegions();
    Collection<Region> fluid_regions = simX.getRegionManager().getRegions();
    Collection<Region> solid_regions = simX.getRegionManager().getRegions();
    for (Region reg : all_regions) {
      if (reg.getRegionType() instanceof FluidRegion) {
        solid_regions.remove(reg);
        if (!(reg instanceof ShellRegion) {
          solid_regions.remove(reg);
        }
      }
      if (!(reg instanceof ShellRegion) {
        fluid_regions.remove(reg);
      }
    }
    if(region_type = "fluid") {
      elem_count.getParts().setObjects("fluid_region");
      cell_count = el_count.getReportMonitorValue();
    }
    if(region_type = "solid") {
      elem_count.getParts().setObjects("solid_region");
      cell_count = el_count.getReportMonitorValue();
    }
    simX.getReportManager().remove(el_count);
    return cell_count;
  }
  
  private static List<String> getFluidZones(Simulation simX) {
    Collection<Region> all_regions = simX.getRegionManager().getRegions();
    // List to store the names of fluid regions
    List<String> fluid_regions = new ArrayList<>();
    
    for (Region reg : all_regions) {
      // if (reg.getPhysicsContinuum().getPresentationName().equals("Fluid")) {
      if (reg.getRegionType() instanceof FluidRegion) {
        fluid_regions.add(region.getPresentationName());
      }
    }
    return fluid_regions;
  }
  
  private void defineMatProps() {
    ...
  }
  
  private void defineBndConds() {
    //Create field functions
    final double m_dot = 2.50;
    UserFieldFunction UFF_mdot = (UserFieldFunction) simX.getFieldFunctionManager().
      .getFunction("m_dot");
    UFF_mdot.setDefinition(String.valueOf(m_dot))
  }
Following code was generated by AI in Copilot. This can be tweaked to convert into a function with user-inputs taken from a text file or explicitly defined in Main function.
public class SetInletBoundary {
  public static void main(String[] args) {
    Simulation sim = getActiveSimulation();
    Region region = sim.getRegionManager().getRegion("region_name");
    Boundary inletBoundary = region.getBoundaryManager().getBoundary("b_inlet");
    double b_inlet_v  = 5.0;  // [m/s]
    double b_inlet_p  = 500;  // [Pa]
    doulbe b_inlet_t  = 300;  // [K]
    double b_inlet_mf = 0.25; // [kg/s]
    int choice = 1;
    
    switch (choice) {
      case 1:   // Set Velocity Inlet
        inletBoundary.getVelocityMagnitude().setValue(b_inlet_v);
        break;
      case 2:   // Set Pressure Inlet
        inletBoundary.getPressure().setValue(b_inlet_p);
        break;
      case 3:   // Set Mass Flow Inlet
        inletBoundary.getMassFlowRate().setValue(b_inlet_mf);
        break;
      default:
        System.out.println("Invalid choice!");
        break;
    }
    sim.saveState("Setup.sim");
  }
}
Define boundary conditions on walls:
public class SetWallBC{
  public static void main(String[] args) {
    Simulation sim = getActiveSimulation();
    Region region = sim.getRegionManager().getRegion("RegionName");
    Boundary wallBoundary = region.getBoundaryManager().getBoundary("WallBoundary");

    int choice = 1;
    switch (choice) {
      case 1:   // Set Fixed Temperature
        wallBoundary.getTemperature().setValue(temperature);
        break;
      case 2:  // Set Known Wall Flux
        wallBoundary.getHeatFlux().setValue(flux);
        break;
      case 3:  // Set HTC
        wallBoundary.getConvectiveHeatTransferCoefficient().setValue(htc);
        wallBoundary.getFreeStreamTemperature().setValue(Tref);
        break;
      case 4:  // Set Radiation
        wallBoundary.getEmissivity().setValue(emissivity);
        break;
      default:
        System.out.println("Invalid choice!");
        break;
    }
    // Set Surface Roughness
    SurfaceRoughnessProperty surfaceRoughness = (SurfaceRoughnessProperty) wallBoundary.getValues()
      .get(SurfaceRoughnessProperty.class);
    surfaceRoughness.getRoughnessHeight().setValue(w_roughness);

    // Enable Shell Conduction
    ShellConductionProperty shellConduction = (ShellConductionProperty) wallBoundary.getValues()
      .get(ShellConductionProperty.class);
    shellConduction.setEnabled(true);

    sim.saveState("Setup.sim");
  }
}
private void summarizeZones(Simulation simX, Boundary bndry) {
    Collection <Region> region_list = simX.getRegionManager().getObjects();
    System.out.println("Number of regions in model = " + region_list.size());
    
    for (Region region_i : region_list) {
      Collection <Boundary> boundary_list = simX.getBoundaryManager().getObjects();
      System.out.println("Number of boundarie in " + "region_i + " is " + 
        boundary_list.size());
    }
    Collection <Interface> iface_list = simX.getInterfaceManager().getObjects();
    integer n_iface = 0;
    for (Interface iface : iface_list) {
      n_iface = n_iface + 1;
    }
    System.out.println("Number of interfaces in domain = " + n_iface);
    
    // Ref: community.sw.siemens.com/.../getting-surface-area-using-java-api
    // Create a Surface Integral Report of the unity field funcion and then
    // use following lines to get or print on those boundaries.
    SurfaceIntegralReport surf_int = (SurfaceIntegralReport) simX.getReportManager() .getReport("Area");
    double surf_area = surf_int.getValue();
    simX.println(surf_area);
    Boundary b_wall_x = reg.getBoundaryManager().getBoundary("Wall_Pipe");
    surf_int.getParts().setObjects(b_wall_x);
    simX.println("Area of boundary is "  + area);
  }
  private void solverSettings(Simulation simX) {

    Simulation sim_1 = getActiveSimulation();
    for (int i=1; i<=3; i++) {
	  sim_1.saveState("Case_" + i + ".sim");
      
      ...
      
      StepStoppingCriterion stopCrit = (StepStoppingCriterion) 
        sim_1.getSolverStoppingCriterionManager()
        .getSolverStoppingCriterion("Maximum Steps");

      //Get max stopping criteria number and add additional iteration steps
      IntegerValue iter_count = stopCrit.getMaximumNumberStepsObject();
      double j = iter_count.getQuantity().getValue();
      iter_count.getQuantity().setValue(j);

      sim_1.getSimulationIterator().run();
    }
    // Save final sim file and exit
    sim_1.saveState("Case_" + i + "_Full.sim");
  }
}
public class CreateMonitorPoints {
  Simulation sim = getActiveSimulation();
    
  // Create mass flow monitor
  MassFlowReport mass_flow_report = sim.getReportManager()
    .createReport(MassFlowReport.class);
  mass_flow_report.setPresentationName("Mass Flow Rate Inlet");
  mass_flow_report.getParts().setObjects(sim.getRegionManager()
    .getRegion("RegionName").getBoundaryManager().getBoundary("Inlet_Boundary"));
    
  // Create energy balance monitor
  EnergyBalanceReport energyBalanceReport = sim.getReportManager()
    .createReport(EnergyBalanceReport.class);
  energyBalanceReport.setPresentationName("Energy Balance");
  energyBalanceReport.getParts().setObjects(sim.getRegionManager()
    .getRegion("Region_Name"));
    
  // Optional: Adding these reports to scalar and XY plots
  MonitorPlot massFlowRatePlot = sim.getPlotManager().createMonitorPlot();
  massFlowRatePlot.setPresentationName("Mass Flow Rate Plot");
  massFlowRatePlot.getMonitorManager().addObjects(massFlowRateReport);

  MonitorPlot energyBalancePlot = sim.getPlotManager().createMonitorPlot();
  energyBalancePlot.setPresentationName("Energy Balance Plot");
  energyBalancePlot.getMonitorManager().addObjects(energyBalanceReport);
}
public class CreateMassBalanceMonitor {
    Simulation sim = getActiveSimulation();
    // Obtain the region object
    Region region = sim.getRegionManager().getRegion(Region_Name);

    // Create mass flow monitors for all inlets and outlets
    MassFlowReport mass_flow_report_1 = sim.getReportManager()
      .createReport(MassFlowReport.class);
    mass_flow_report_1.setPresentationName("MF_inlets");

    MassFlowReport mass_flow_report_2 = sim.getReportManager()
      .createReport(MassFlowReport.class);
    mass_flow_report_2.setPresentationName("MF_outlets");

    for (Boundary boundary : region.getBoundaryManager().getBoundaries()) {
      if (boundary.getBoundaryType() instanceof InletBoundary) {
        mass_flow_report_1.getParts().addObjects(boundary);
      } else if (boundary.getBoundaryType() instanceof OutletBoundary) {
        mass_flow_report_2.getParts().addObjects(boundary);
      }
    }
    // Calculate mass balance
    ExpressionReport massBalanceReport = sim.getReportManager()
      .createReport(ExpressionReport.class);
    massBalanceReport.setPresentationName("Mass_Balance");
    massBalanceReport.setDefinition(
      "${MF_inlets.Report} - ${MF_outlets.Report}"
    );
    // Optional: Adding these reports to scalar and XY plots
    MonitorPlot massFlowRatePlot = sim.getPlotManager().createMonitorPlot();
    massFlowRatePlot.setPresentationName("Mass Flow Rate Plot");
    massFlowRatePlot.getMonitorManager().addObjects(massFlowRateReportInlet, 
      massFlowRateReportOutlet);

    MonitorPlot massBalancePlot = sim.getPlotManager().createMonitorPlot();
    massBalancePlot.setPresentationName("Mass Balance Plot");
    massBalancePlot.getMonitorManager().addObjects(massBalanceReport);
  }
}
  private void defineReports() {
    ...
  }
public void addAnnotationToScene(Simulation simX, String annoText, double xLoc, double yLoc) {

  Annotation textAnnotation = new Annotation();
  textAnnotation.setText(annoText);
  textAnnotation.setPresentationName("Annotation_1");
  simX.getAnnotationManager().getAnnotations().add(textAnnotation);

  Scene scene = simX.getSceneManager().getScene("contour_v");
  scene.getAnnotations().add(textAnnotation);

  textAnnotation.setX(xLoc);
  textAnnotation.setY(yLoc;
  textAnnotation.setFontSize(12);
  textAnnotation.setColor(new Color(0, 0, 1));
}
  private void defineScenes() {
    ...
  }
  private void generateReports(Simulation simX) {
    String rept_file = "Rep_Output.txt";
    PrintWriter out_file = new PrintWriter(new FileWriter(new File(resolvePath(rept_file))));
    Collection <Report> report_list = simX.getReportManager().getObjects();
    Iterator<Integer> rep_counter = report_list.iterator();
    while (rep_counter.hasNext()) {
      String report_name  = report_list.next().getPresentationName();
      double report_value = report_list.next().getReportMonitorValue();
      String report_units = report_list.next().getUnits().GetPresentationName();
      System.out.println(report_name + " has value " + report_value + " " 
        + report_units(); 
    }
  }
  private void saveReptPlots(Simulation simX) {
    String sep = System.getProperty("file.separator");
    for (StarPlot p : simX.getPlotManager().getObjects()) {
      simX.println("Data exported for plot: " + p.getPresentationName());
      p.export(simX.getSessionDir() + sep + p.getPresentationName() + ".csv", ",");
    }
  }
From github.com/nitronayak /StarCCMAutomation /blob /main /ExportScenesAndPlots.java
import star.common.*;
import star.vis.*;
import java.io.File;
import java.util.Scanner; 

public class ExportScenesAndPlots extends StarMacro {
  public void execute() {
    Simulation sim = getActiveSimulation();
    
    //get the name of the simulation's directory
    String dir = sim.getSessionDir(); 
    //get the right separator for your operative system
    String sep = System.getProperty("file.separator");
    File resultFolder = new File(dir + "\\" + sim + "_Results");
    resultFolder.mkdir();

    File sceneFolder = new File(resultFolder + "\\Scenes");
    sceneFolder.mkdir();
    File plotFolder = new File(resultFolder + "\\Plots");
    plotFolder.mkdir();
    
    for (Scene scn: sim.getSceneManager().getScenes()) {
      sim.println("Saving Scene: " + scn.getPresentationName());
      scn.printAndWait(resolvePath(sceneFolder + sep + scn.getPresentationName() + ".jpg"), 1,800,450);	
    }
    for (StarPlot plt : sim.getPlotManager().getObjects()) {
      sim.println("Saving Plot: " + plt.getPresentationName());
      plt.encode(resolvePath(plotFolder + sep + plt.getPresentationName() + ".jpg"), "jpg", 800, 450);
    }
  }
}
Following code is generated by AI approach: creates a short summary of simulation set-up
import star.common.*;
import star.base.neo.*;

public class SimulationSummary {

  public static void main(String[] args) {
    Simulation sim = getActiveSimulation();

    // Get basic simulation details
    String simName = sim.getPresentationName();
    String physicsContinuum = sim.getPhysicsContinuumManager().getContinuumNames().toString();
    String solver = sim.getSolverManager().getSolverNames().toString();

    // Get mesh details
    MeshPipelineController meshController = sim.get(MeshPipelineController.class);
    String meshOperation = meshController.getMeshOperation().getClass().getSimpleName();

    // Get boundary conditions summary
    StringBuilder bcSummary = new StringBuilder();
    Collection<Boundary> boundaries = sim.getRegionManager().getBoundaries();
    for (Boundary boundary : boundaries) {
      bcSummary.append(boundary.getPresentationName()).append(": ");
      bcSummary.append(boundary.getBoundaryType()).append("\n");
    }
    // Create summary string
    String summary = "Simulation Name: " + simName + "\n" +
                     "Physics Continuum: " + physicsContinuum + "\n" +
                     "Solver: " + solver + "\n" +
                     "Mesh Operation: " + meshOperation + "\n" +
                     "Boundary Conditions:\n" + bcSummary.toString();
    // Print summary to the output window
    sim.println(summary);
  }
}
Print materials defined in the set-up and their thermodynamic properties
public class printMatProps extends StarMacro { 
  public void execute() {
    Simulation sim = getActiveSimulation(); 
    Collection<Material> materials = sim.get(MaterialManager.class).getObjects(); 
    for (Material mat : materials) { 
      String matName = mat.getPresentationName(); 
      System.out.println("Material: " + matName); 
      
      Collection<MaterialProperty> properties = mat.getMaterialProperties(); 
      for (MaterialProperty property : properties) { 
        String propertyName = property.getPresentationName(); 
        double propertyValue = property.getValue(); 
        System.out.println(" Property: " + propertyName + ", Value: " + propertyValue); 
      } 
    } 
  } 
}
public class CreateHistograms extends StarMacro {
  public void execute() {
    createHistogramsMeshQuality("CellQuality");
    createHistogramsMeshQuality("Skewness");
  }
  private void createHistogramsMeshQuality(String quality_type) {
    Simulation sim = getActiveSimulation();
    
    RegionManager regionManager = sim.getRegionManager();
    Collection<Region> allRegions = regionManager.getRegions();
    List<Region> solidRegions = new ArrayList<>();
    List<Region> fluidRegions = new ArrayList<>();
    for (Region region : allRegions) {
      // Check if region contains solid cells
      if (region.getInterfaceBoundaryManager().getInterfaceBoundaries().size() > 0) {
        solidRegions.add(region);
      } else {
        fluidRegions.add(region);
      }
    }
    // Define the cell quality scalar field function
    PrimitiveFieldFunction cellQualityFunction = 
      (PrimitiveFieldFunction) sim.getFieldFunctionManager().getFunction(quality_type);

    // Create histograms for solid regions
    for (Region solidRegion : solidRegions) {
      createHistogram(sim, solidRegion, cellQualityFunction, 
        solidRegion.getPresentationName() + " " + quality_type + " Histogram";
    }
    // Create histograms for fluid regions
    for (Region fluidRegion : fluidRegions) {
      createHistogram(sim, fluidRegion, cellQualityFunction, 
        fluidRegion.getPresentationName() + " " + quality_type + " Histogram";
    }
  }
  private void createHistogram(Simulation sim, Region region, 
                 PrimitiveFieldFunction function, String plotName) {
    // Create histogram report
    HistogramReport histogramReport = sim.getReportManager()
      .createReport(HistogramReport.class);
    histogramReport.setFieldFunction(function);
    histogramReport.getParts().setObjects(region);
    histogramReport.setPresentationName(plotName);

    // Create and display the plot
    ReportPlot histogramPlot = sim.getPlotManager().createReportPlot(histogramReport);
    histogramPlot.open();
  }
}
STAR-CCM+ java code as functions to generate scalar scenes on planes aligned to Cartesian coordinate systems passing though specified point, align the view perpendicular to the plane and save the plot as PNG file.
  public void execute() {
    // Specify the point through which the planes pass and field function and range
    double[] point = {0.0, 0.0, 0.0}; 
    double[] v_range = {0.0, 10.0};
    double[] p_range = {1000, 1E6};
    double[] t_range = {300, 400};
    String scalarFieldFunctionName = "VelocityMagnitude"; 
    createScalarSceneOnPlane("X", point, "Pressure", p_range);
    createScalarSceneOnPlane("Y", point, "Temperature", t_range);
    createScalarSceneOnPlane("Z", point, "Velocity", v_range);
  }
  private void createScalarSceneOnPlane(String planeAxis, double[] point, 
    String scalarFF, double[] scalarRange) {
    Simulation sim = getActiveSimulation();
    
    ScalarScene scalarScene = sim.getSceneManager().createScalarScene("Scalar Scene", "Scalar Scene");
    scalarScene.initializeAndWait();
    FieldFunction scalarFieldFunction = sim.getFieldFunctionManager().getFunction(scalarFF);
    scalarScene.getDisplayerManager().getScalarDisplayers().get(0)
      .getScalarDisplayQuantity().setFieldFunction(scalarFieldFunction);

    // Set the number of color bands to 11
    scalarScene.getDisplayerManager().getScalarDisplayers().get(0)
      .getScalarDisplayQuantity().getColorMap().setNumberOfColors(11);
    scalarScene.getDisplayerManager().getScalarDisplayers().get(0)
      .getScalarDisplayQuantity().setRange(scalarRange);

    // Create and set plane section
    PlaneSection planeSection = (PlaneSection) sim.getPartManager().createImplicitPart(new 
      NeoObjectVector(new Object[] {}), new NeoObjectVector(new Object[] {}), "PlaneSection", 0, 0, 0, 0);
    planeSection.getInputParts().setObjects(sim.getRegionManager().getRegions());
    planeSection.getOriginCoordinate().setCoordinate(point[0], point[1], point[2]);

    // Set plane normal based on the specified axis
    if (planeAxis.equalsIgnoreCase("X")) {
      planeSection.getOrientationCoordinate().setCoordinate(1, 0, 0);
    } else if (planeAxis.equalsIgnoreCase("Y")) {
      planeSection.getOrientationCoordinate().setCoordinate(0, 1, 0);
    } else if (planeAxis.equalsIgnoreCase("Z")) {
      planeSection.getOrientationCoordinate().setCoordinate(0, 0, 1);
    }

    // Add plane section to scalar scene
    scalarScene.getDisplayerManager().getPartDisplayer("Scalar Scene 1")
      .getInputParts().setObjects(planeSection);

    // Align view perpendicular to the plane and zoom to fit window (reset camera)
    if (planeAxis.equalsIgnoreCase("X")) {
      scalarScene.open(true);
      scalarScene.resetCamera();
      scalarScene.getViewManager().getAxesOrientation().setCoordinateSystemView(
        scalarScene.getActiveCamera(), CoordinateSystemViewType.XY);
    } else if (planeAxis.equalsIgnoreCase("Y")) {
      scalarScene.open(true);
      scalarScene.resetCamera();
      scalarScene.getViewManager().getAxesOrientation().setCoordinateSystemView(
        scalarScene.getActiveCamera(), CoordinateSystemViewType.YZ);
    } else if (planeAxis.equalsIgnoreCase("Z")) {
      scalarScene.open(true);
      scalarScene.resetCamera();
      scalarScene.getViewManager().getAxesOrientation().setCoordinateSystemView(
        scalarScene.getActiveCamera(), CoordinateSystemViewType.ZX);
    }
    String file_name = scalarFF + "_" + planeAxis + "_"+ point[0] + "_"point[1] +
      "_" + point[2] + ".png";
    scalarScene.printAndWait(resolvePath(file_name), 1, 800, 600);
    scalarScene.close();
  }
Process all *.sim files stored in a specified folder.
public class ProcessSimFiles {

  public static void main(String[] args) {
    // Folder containing the *.sim files
    File folder = new File("E:/CFD_Projects");
    String b_inlet = "inlet;
    
    // List all .sim files in the folder
    File[] files = folder.listFiles((dir, name)->name.toLowerCase().endsWith(".sim"));
    if (files == null || files.length == 0) {
      System.out.println("No .sim files found.");
      return;
    }
    Simulation sim = StarCCM.getNewSimulation();
    for (File f : files) {
      postProcesSim(sim, f, b_inlet);
    }
  }
  private static void postProcesSim(Simulation sim, File file, String b_inlet) {
    try {
      // Clear the previous simulation data and read a new simulation
      sim.getSimulationIterator().clearSimulation();
      sim.getSimulationIterator().readSimulation(file.getAbsolutePath()); 
      
      // Create a scene (e.g. Scalar Scene)
      Scene scene = sim.getSceneManager().createScalarScene("Scalar Scene", "Outline", "Scalar");
      scene.initializeAndWait();
      
      // Generate mass flow rate at the specified boundary
      String boundaryName = b_inlet;
      Boundary boundary = sim.getRegionManager().getBoundary(boundaryName);
      MassFlowRateReport massFlowRate = sim.getReportManager().createReport(MassFlowRateReport.class);
      massFlowRate.setObjects(boundary);
      massFlowRate.printReport();
      
      // Get the maximum and minimum values of field variables
      for (FieldFunction field : sim.getFieldFunctionManager().getObjects()) {
        PrimitiveFieldFunction primitiveField = (PrimitiveFieldFunction) field;
        
        MinReport minReport = sim.getReportManager().createReport(MinReport.class);
        minReport.setFieldFunction(primitiveField);
        minReport.printReport();
        
        MaxReport maxReport = sim.getReportManager().createReport(MaxReport.class);
        maxReport.setFieldFunction(primitiveField);
        maxReport.printReport();
      }
      sim.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
Java code for STAR-CCM+ to report mesh quality summary to a text file. The text file includes tabular data of the region name, mesh quality parameter, and the worst value of that mesh quality.
import star.common.*;
import star.meshing.*;
public class MeshQualityReport {

  public static void main(String[] args) {
    // Path to the output text file
    String outputFilePath = "mesh_q_rep.txt";
    
    // Start a new session
    Simulation sim = StarCCM.getNewSimulation();
    
    try (FileWriter writer = new FileWriter(outputFilePath)) {
      // Write the header
      writer.write("Region Name\tMesh Quality Parameter\tWorst Value\n");
      
      // Iterate over all regions
      for (Region region : sim.getRegionManager().getRegions()) {
        String regionName = region.getPresentationName();
        
        // Mesh quality parameters to check
        String[] qualityParameters = {"Aspect Ratio", "Skewness", "Orthogonality"};
        
        for (String parameter : qualityParameters) {
          double worstValue = getWorstMeshQuality(region, parameter);
          writer.write(regionName + "\t" + parameter + "\t" + worstValue + "\n");
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      // Close the session
      sim.close();
    }
  }
  private static double getWorstMeshQuality(Region region, String parameter) {
    double worstMeshQuality = Double.NaN;
    
    // Assume we have methods to calculate mesh quality
    switch (parameter) {
      case "Aspect Ratio":
        worstMeshQuality = getWorstAspectRatio(region);
        break;
      case "Skewness":
        worstMeshQuality = getWorstSkewness(region);
        break;
      case "Orthogonality":
        worstMeshQuality = getWorstOrthogonality(region);
        break;
      default:
        break;
    }
    return worstMeshQuality;
  }
  /*SkewnessAngleFunction skew_func = (SkewnessAngleFunction) 
      simX.getFieldFunctionManager().getFunction("SkewnessAngle");
    VolumeChangeFunction skew_func = (VolumeChangeFunction) 
      simX.getFieldFunctionManager().getFunction("VolumeChange);*/
  private static double getWorstAspectRatio(Region region) {
    double highestAspectRatio = -1.0;
    // Iterate over all cells in the region
    for (Cell cell : region.getCells()) {
      double aspectRatio = cell.getAspectRatio();
      if (aspectRatio > highestAspectRatio) {
        highestAspectRatio = aspectRatio;
      }
    }
    return highestAspectRatio;
  }
  private static double getWorstSkewness(Region region) {
    double worstSkewness = -1.0;
    // Iterate over all cells in the region
    for (Cell cell : region.getCells()) {
      double cellSkew = cell.getSkewness();
      if (cellSkew > worstSkewness) {
        worstSkewness = cellSkew;
      }
    }
    return worstSkewness;
  }
  private static double getWorstOrthogonality(Region region) {
    double worstOrtho = 10.0;
    // Iterate over all cells in the region
    for (Cell cell : region.getCells()) {
      double cellOrtho = cell.getOrthogonality();
      if (cellOrtho < worstOrtho) {
        worstOrtho = cellOrtho;
      }
    }
    return worstOrtho;
  }
}
Create Animation from a Transient Run
public void CreateAnimation (Simulation sim, double fps, Scene sc_name, String field_var) {
  
  // Set up the time steps for the animation
  SolutionHistory solutionHistory = (SolutionHistory) sim.get(SolutionHistoryManager.class)
    .getObjects().iterator().next();
  RecordedSolutionView recordedSolutionView = solutionHistory.getRecordedSolutionViewManager().createView();
  recordedSolutionView.setMode(RecordedSolutionViewMode.DISPLAY_EVERY_STEP);
  
  // Create an animation from the recorded solution view
  Animation animation = 
    (Animation) sim.getRepresentationManager().createRepresentation(Animation.class, "Animation", "");
  animation.setFramesFromView(recordedSolutionView);
  
  // Set the scalar scene for the animation
  Scene scene = sim.getSceneManager().getScenes().get(sc_name);
  ScalarDisplayer scalarDisplayer = 
    (ScalarDisplayer) scene.getDisplayerManager().getDisplayer(field_var);
  scalarDisplayer.setRepresentation(animation);
  
  // Set the animation properties
  animation.setFramesPerSecond(fps);
  animation.setStartFrame(0);
  animation.setEndFrame(recordedSolutionView.getLastFrame());
  
  // Export the animation as a video
  File animationFile = new File("STAR-animation.mp4");
  File exportFile = new File(animationFile.getAbsolutePath());
  sim.getAnimationExporterManager().exportVideo(animation, exportFile, "mp4");
  }
}
Create Sweep Animation of an XY-Plane
public void SweepAnimation (Simulation sim, Scene sc_name, double fps, double z0,
  double zn, double dz) {   
  // Create a new XY-Plane section at origin
  PartManager partManager = simulation.getPartManager();
  plane_xy plane_xy = (plane_xy) partManager.createImplicitPart(new NeoObjectVector(
    new Object[]{}), new DoubleVector(new double[]{0.0, 0.0, 1.0}), 
    new DoubleVector(new double[]{0.0, 0.0, 0.0}));
  plane_xy.getOrientationCoordinate().setCoordinate(new DoubleVector(new double[] {0.0, 0.0, 1.0}));
  plane_xy.getPositionCoordinate().setCoordinate(new DoubleVector(new double[] {0.0, 0.0, 0.0}));
  plane_xy.getInputParts().setQuery(null);
  
  // Add the plane section to the scene and set the displayer
  sc_name.setInputParts(new NeoObjectVector(new Object[] {plane_xy}));
  sc_name.open();
  ScalarDisplayer scalarDisplayer = sc_name.getDisplayerManager()
    .createDisplayer(ScalarDisplayer.class);
  scalarDisplayer.getInputParts().setQuery(null);
  scalarDisplayer.getInputParts().setObjects(plane_xy);
  
  // Set up the animation properties
  Animation animation = simulation.getRepresentationManager().createRepresentation(
    Animation.class, "Sweep Animation", "");
  animation.setFramesPerSecond(fps);
  
  // Loop through the range and update plane position
  for (double zp = z0; zp <= zn; zp += dz) {
    plane_xy.getPositionCoordinate().setCoordinate(new DoubleVector(new double[] {0.0, 0.0, zp}));
    sc_name.printAndWait();
    animation.addFrame(scene);
  }

  // Export the animation as a video
  File animationFile = new File("sweep_animation.mp4");
  File exportFile = new File(animationFile.getAbsolutePath());
  simulation.getAnimationExporterManager().exportVideo(animation, exportFile, "mp4");
  }
}
Create a tabulated summary of maximum temperature at the outer walls of each solid zone:
  public static void zoneWallsMaxT(Simulation sim, String field_name) {
    Map<String, Double> solidZoneMaxT = new HashMap<>();

    SimulationPartManager partManager = sim.getPartManager();
    FieldFunctionManager fieldManager = sim.getFieldFunctionManager();
    FieldFunction field_var = fieldManager.getFieldFunction(field_name);

    for (Region region : sim.getRegionManager().getRegions()) {
      if (region.getEntityType() == Region.SOLID) {
        double maxTemperature = Double.NEGATIVE_INFINITY;
        
        for (SolidBoundary boundary : region.getSolidBoundaries()) {
          SimulationIterator iterator = boundary.getSimulationIterator(field_var);
          while (iterator.hasNext()) {
            double field_value = iterator.next(FieldFunctionUnits.CELSIUS); 
            if (field_value > maxTemperature) {
              maxTemperature = field_value;
            }
          }
        }
        for (PartSurface surface : region.getPartSurfaces()) {
          SimulationIterator iterator = surface.getSimulationIterator(field_var);
          while (iterator.hasNext()) {
            double field_value = iterator.next(FieldFunctionUnits.CELSIUS);
            if (field_value > maxTemperature) {
              maxTemperature = field_value;
            }
          }
        }
        solidZoneMaxT.put(region.getPresentationName(), maxTemperature);
      }
    }

    System.out.println("Summary of Maximum Temperatures in Solid Zones:");
    System.out.println("---------------------------------------------");
    for (Map.Entry<String, Double> entry : solidZoneMaxT.entrySet()) {
      System.out.printf("%-20s: %.2f °C%n", entry.getKey(), entry.getValue());
    }
  }
Contact us
Disclaimers and Policies

The content on CFDyna.com is being constantly refined and improvised with on-the-job experience, testing, and training. Examples might be simplified to improve insight into the physics and basic understanding. Linked pages, articles, references, and examples are constantly reviewed to reduce errors, but we cannot warrant full correctness of all content.