.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "examples/00-fluent/DOE_ML.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_examples_00-fluent_DOE_ML.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_examples_00-fluent_DOE_ML.py:

.. _doe_ml:

Design of Experiments and Machine Learning model building
---------------------------------------------------------

.. GENERATED FROM PYTHON SOURCE LINES 30-45

Objective
=====================================================================================

Water enters a Mixing Elbow from two Inlets; Hot (313 K) and Cold (293 K) and exits
from Outlet. Using PyFluent in the background, this example runs Design of Experiments
with Cold Inlet Velocity and Hot Inlet Velocity as Input Parameters and Outlet
Temperature as an Output Parameter.

Results can be visualized using a Response Surface. Finally, Supervised Machine
Learning Regression Task is performed to build the ML Model.

This example demonstrates:

* Design of Experiment, Fluent setup and simulation using PyFluent.
* Building of Supervised Machine Learning Model.

.. GENERATED FROM PYTHON SOURCE LINES 47-49

Import required libraries/modules
=================================

.. GENERATED FROM PYTHON SOURCE LINES 49-66

.. code-block:: Python


    # flake8: noqa: E402

    from pathlib import Path

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import plotly.express as px
    import plotly.graph_objects as go
    import seaborn as sns
    import tensorflow as tf
    from tensorflow import keras

    import ansys.fluent.core as pyfluent
    from ansys.fluent.core import examples


.. GENERATED FROM PYTHON SOURCE LINES 67-72

Specifying save path
====================
* save_path can be specified as Path("E:/", "pyfluent-examples-tests") or
* Path("E:/pyfluent-examples-tests") in a Windows machine for example,  or
* Path("~/pyfluent-examples-tests") in Linux.

.. GENERATED FROM PYTHON SOURCE LINES 72-81

.. code-block:: Python


    save_path = Path(pyfluent.EXAMPLES_PATH)

    import_filename = examples.download_file(
        "elbow.cas.h5",
        "pyfluent/examples/DOE-ML-Mixing-Elbow",
        save_path=save_path,
    )


.. GENERATED FROM PYTHON SOURCE LINES 82-84

Fluent Solution Setup
=====================

.. GENERATED FROM PYTHON SOURCE LINES 86-88

Launch Fluent session with solver mode and print Fluent version
===============================================================

.. GENERATED FROM PYTHON SOURCE LINES 88-97

.. code-block:: Python


    solver = pyfluent.launch_fluent(
        precision="double",
        processor_count=2,
        version="3d",
    )
    print(solver.get_fluent_version())



.. GENERATED FROM PYTHON SOURCE LINES 98-100

Read case
=========

.. GENERATED FROM PYTHON SOURCE LINES 100-103

.. code-block:: Python


    solver.settings.file.read_case(file_name=import_filename)


.. GENERATED FROM PYTHON SOURCE LINES 104-109

Design of Experiments
=====================
* Define Manual DOE as numpy arrays
* Run cases in sequence
* Populate results (Mass Weighted Average of Temperature at Outlet) in resArr

.. GENERATED FROM PYTHON SOURCE LINES 109-140

.. code-block:: Python


    coldVelArr = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7])
    hotVelArr = np.array([0.8, 1, 1.2, 1.4, 1.6, 1.8, 2.0])
    resArr = np.zeros((coldVelArr.shape[0], hotVelArr.shape[0]))

    for idx1, coldVel in np.ndenumerate(coldVelArr):
        for idx2, hotVel in np.ndenumerate(hotVelArr):
            cold_inlet = solver.settings.setup.boundary_conditions.velocity_inlet[
                "cold-inlet"
            ]
            cold_inlet.momentum.velocity.value = coldVel

            hot_inlet = solver.settings.setup.boundary_conditions.velocity_inlet[
                "hot-inlet"
            ]
            hot_inlet.momentum.velocity.value = hotVel

            solver.settings.solution.initialization.initialization_type = "standard"
            solver.settings.solution.initialization.standard_initialize()
            solver.settings.solution.run_calculation.iterate(iter_count=200)

            res_tui = solver.scheme_eval.exec(
                (
                    "(ti-menu-load-string "
                    '"/report/surface-integrals/mass-weighted-avg outlet () '
                    'temperature no")',
                )
            )
            resArr[idx1][idx2] = eval(res_tui.split(" ")[-1])



.. GENERATED FROM PYTHON SOURCE LINES 141-143

Close the session
=================

.. GENERATED FROM PYTHON SOURCE LINES 143-146

.. code-block:: Python


    solver.exit()


.. GENERATED FROM PYTHON SOURCE LINES 147-149

Plot Response Surface using Plotly
==================================

.. GENERATED FROM PYTHON SOURCE LINES 149-175

.. code-block:: Python


    fig = go.Figure(data=[go.Surface(z=resArr.T, x=coldVelArr, y=hotVelArr)])

    fig.update_layout(
        title={
            "text": "Mixing Elbow Response Surface",
            "y": 0.9,
            "x": 0.5,
            "xanchor": "center",
            "yanchor": "top",
        }
    )

    fig.update_layout(
        scene=dict(
            xaxis_title="Cold Inlet Vel (m/s)",
            yaxis_title="Hot Inlet Vel (m/s)",
            zaxis_title="Outlet Temperature (K)",
        ),
        width=600,
        height=600,
        margin=dict(l=80, r=80, b=80, t=80),
    )
    fig.show()



.. GENERATED FROM PYTHON SOURCE LINES 176-178

Supervised ML for a Regression Task
===================================

.. GENERATED FROM PYTHON SOURCE LINES 180-182

Create Pandas Dataframe for ML Model Input
==========================================

.. GENERATED FROM PYTHON SOURCE LINES 182-201

.. code-block:: Python

    coldVelList = []
    hotVelList = []
    ResultList = []

    for idx1, coldVel in np.ndenumerate(coldVelArr):
        for idx2, hotVel in np.ndenumerate(hotVelArr):
            coldVelList.append(coldVel)
            hotVelList.append(hotVel)
            ResultList.append(resArr[idx1][idx2])

    tempDict = {"coldVel": coldVelList, "hotVel": hotVelList, "Result": ResultList}

    df = pd.DataFrame.from_dict(tempDict)

    from sklearn.compose import ColumnTransformer
    from sklearn.model_selection import train_test_split
    from sklearn.pipeline import Pipeline
    from sklearn.preprocessing import PolynomialFeatures, StandardScaler


.. GENERATED FROM PYTHON SOURCE LINES 202-207

Using scikit-learn
==================
* Prepare Features (X) and Label (y) using a Pre-Processing Pipeline
* Train-Test (80-20) Split
* Add Polynomial Features to improve ML Model

.. GENERATED FROM PYTHON SOURCE LINES 207-236

.. code-block:: Python


    poly_features = PolynomialFeatures(degree=2, include_bias=False)

    transformer1 = Pipeline(
        [
            ("poly_features", poly_features),
            ("std_scaler", StandardScaler()),
        ]
    )


    x_ct = ColumnTransformer(
        [
            ("transformer1", transformer1, ["coldVel", "hotVel"]),
        ],
        remainder="drop",
    )

    train_set, test_set = train_test_split(df, test_size=0.2, random_state=42)

    X_train = x_ct.fit_transform(train_set)
    X_test = x_ct.fit_transform(test_set)

    y_train = train_set["Result"]
    y_test = test_set["Result"]
    y_train = np.ravel(y_train.T)
    y_test = np.ravel(y_test.T)



.. GENERATED FROM PYTHON SOURCE LINES 237-242

* Define functions for:
* Cross-Validation and Display Scores (scikit-learn)
* Training the Model (scikit-learn)
* Prediction on Unseen/Test Data (scikit-learn)
* Parity Plot (Matplotlib and Seaborn)

.. GENERATED FROM PYTHON SOURCE LINES 242-321

.. code-block:: Python


    # from pprint import pprint

    # from sklearn.ensemble import RandomForestRegressor
    # from sklearn.linear_model import LinearRegression
    from sklearn.metrics import r2_score
    from sklearn.model_selection import RepeatedKFold, cross_val_score
    from xgboost import XGBRegressor

    np.set_printoptions(precision=2)


    def display_scores(scores):
        """Display scores."""
        print("\nCross-Validation Scores:", scores)
        print("Mean:%0.2f" % (scores.mean()))
        print("Std. Dev.:%0.2f" % (scores.std()))


    def fit_and_predict(model):
        """Fit abd predict."""
        cv = RepeatedKFold(n_splits=5, n_repeats=3, random_state=42)
        cv_scores = cross_val_score(
            model, X_train, y_train, scoring="neg_mean_squared_error", cv=cv
        )
        rmse_scores = np.sqrt(-cv_scores)
        display_scores(rmse_scores)

        model.fit(X_train, y_train)
        train_predictions = model.predict(X_train)
        test_predictions = model.predict(X_test)
        print(train_predictions.shape[0])
        print("\n\nCoefficient Of Determination")
        print("Train Data R2 Score: %0.3f" % (r2_score(train_predictions, y_train)))
        print("Test Data R2 Score: %0.3f" % (r2_score(test_predictions, y_test)))
        print(
            "\n\nPredictions - Ground Truth (Kelvin): ", (test_predictions - y_test), "\n"
        )
        #    print("\n\nModel Parameters:")
        #    pprint(model.get_params())

        com_train_set = train_set
        com_test_set = test_set

        train_list = []
        for i in range(train_predictions.shape[0]):
            train_list.append("Train")

        test_list = []
        for i in range(test_predictions.shape[0]):
            test_list.append("Test")

        com_train_set["Result"] = train_predictions.tolist()
        com_train_set["Set"] = train_list
        com_test_set["Result"] = test_predictions.tolist()
        com_test_set["Set"] = test_list

        df_combined = pd.concat([com_train_set, com_test_set])

        df_combined.to_csv("PyFluent_Output.csv", header=True, index=False)

        fig = plt.figure(figsize=(12, 5))

        fig.add_subplot(121)
        sns.regplot(x=y_train, y=train_predictions, color="g")
        plt.title("Train Data", fontsize=16)
        plt.xlabel("Ground Truth", fontsize=12)
        plt.ylabel("Predictions", fontsize=12)

        fig.add_subplot(122)
        sns.regplot(x=y_test, y=test_predictions, color="g")
        plt.title("Unseen Data", fontsize=16)
        plt.xlabel("Ground Truth", fontsize=12)
        plt.ylabel("Predictions", fontsize=12)

        plt.tight_layout()
        plt.show()



.. GENERATED FROM PYTHON SOURCE LINES 322-325

Select the Model from Linear, Random Forest or XGBoost
======================================================
* Call fit_and_predict

.. GENERATED FROM PYTHON SOURCE LINES 325-334

.. code-block:: Python


    # model = LinearRegression()
    model = XGBRegressor(
        n_estimators=100, max_depth=10, eta=0.3, subsample=0.8, random_state=42
    )
    # model = RandomForestRegressor(random_state=42)

    fit_and_predict(model)


.. GENERATED FROM PYTHON SOURCE LINES 335-337

Show graph
==========

.. GENERATED FROM PYTHON SOURCE LINES 337-340

.. code-block:: Python


    plt.show()


.. GENERATED FROM PYTHON SOURCE LINES 341-344

.. image:: ../../_static/doe_ml_predictions_regression.png
   :align: center
   :alt: Regression Model Predictions

.. GENERATED FROM PYTHON SOURCE LINES 346-347

Regression Model Predictions

.. GENERATED FROM PYTHON SOURCE LINES 349-351

3D Visualization of Model Predictions on Train & Test Set
=========================================================

.. GENERATED FROM PYTHON SOURCE LINES 351-383

.. code-block:: Python


    df = pd.read_csv("PyFluent_Output.csv")

    fig = px.scatter_3d(df, x="coldVel", y="hotVel", z="Result", color="Set")
    fig.update_traces(marker=dict(size=4))
    fig.update_layout(legend=dict(yanchor="top", y=1, xanchor="left", x=0.0))

    fig.add_traces(go.Surface(z=resArr.T, x=coldVelArr, y=hotVelArr))

    fig.update_layout(
        title={
            "text": "Mixing Elbow Response Surface",
            "y": 0.9,
            "x": 0.5,
            "xanchor": "center",
            "yanchor": "top",
        }
    )

    fig.update_layout(
        scene=dict(
            xaxis_title="Cold Inlet Vel (m/s)",
            yaxis_title="Hot Inlet Vel (m/s)",
            zaxis_title="Outlet Temperature (K)",
        ),
        width=500,
        height=500,
        margin=dict(l=80, r=80, b=80, t=80),
    )

    fig.show()


.. GENERATED FROM PYTHON SOURCE LINES 384-386

TensorFlow and Keras Neural Network Regression
==============================================

.. GENERATED FROM PYTHON SOURCE LINES 386-465

.. code-block:: Python


    print("TensorFlow version is:", tf.__version__)
    keras.backend.clear_session()
    np.random.seed(42)
    tf.random.set_seed(42)

    model = keras.models.Sequential(
        [
            keras.layers.Dense(
                20,
                activation="relu",
                input_shape=X_train.shape[1:],
                kernel_initializer="lecun_normal",
            ),
            keras.layers.BatchNormalization(),
            keras.layers.Dense(20, activation="relu", kernel_initializer="lecun_normal"),
            keras.layers.BatchNormalization(),
            keras.layers.Dense(20, activation="relu", kernel_initializer="lecun_normal"),
            keras.layers.BatchNormalization(),
            keras.layers.Dense(1),
        ]
    )

    optimizer = tf.keras.optimizers.Adam(learning_rate=0.1, beta_1=0.9, beta_2=0.999)

    model.compile(loss="mean_squared_error", optimizer=optimizer)
    checkpoint_cb = keras.callbacks.ModelCheckpoint(
        "my_keras_model.h5", save_best_only=True
    )
    early_stopping_cb = keras.callbacks.EarlyStopping(
        patience=30, restore_best_weights=True
    )

    model.summary()

    # keras.utils.plot_model(model, show_shapes=True,) # to_file='dot_img.png', )

    history = model.fit(
        X_train,
        y_train,
        epochs=250,
        validation_split=0.2,
        callbacks=[checkpoint_cb, early_stopping_cb],
    )
    model = keras.models.load_model("my_keras_model.h5")

    print(history.params)

    pd.DataFrame(history.history).plot(figsize=(8, 5))
    plt.grid(True)
    plt.show()

    train_predictions = model.predict(X_train)
    test_predictions = model.predict(X_test)
    train_predictions = np.ravel(train_predictions.T)
    test_predictions = np.ravel(test_predictions.T)
    print(test_predictions.shape)

    print("\n\nTrain R2: %0.3f" % (r2_score(train_predictions, y_train)))
    print("Test R2: %0.3f" % (r2_score(test_predictions, y_test)))
    print("Predictions - Ground Truth (Kelvin): ", (test_predictions - y_test))

    fig = plt.figure(figsize=(12, 5))

    fig.add_subplot(121)
    sns.regplot(x=y_train, y=train_predictions, color="g")
    plt.title("Train Data", fontsize=16)
    plt.xlabel("Ground Truth", fontsize=12)
    plt.ylabel("Predictions", fontsize=12)

    fig.add_subplot(122)
    sns.regplot(x=y_test, y=test_predictions, color="g")
    plt.title("Test/Unseen Data", fontsize=16)
    plt.xlabel("Ground Truth", fontsize=12)
    plt.ylabel("Predictions", fontsize=12)

    plt.tight_layout()



.. GENERATED FROM PYTHON SOURCE LINES 466-468

Show graph
==========

.. GENERATED FROM PYTHON SOURCE LINES 468-471

.. code-block:: Python


    plt.show()


.. GENERATED FROM PYTHON SOURCE LINES 472-475

.. image:: ../../_static/doe_ml_validation_loss.png
   :align: center
   :alt: Neural Network Validation Loss

.. GENERATED FROM PYTHON SOURCE LINES 477-478

Neural Network Validation Loss

.. GENERATED FROM PYTHON SOURCE LINES 480-483

.. image:: ../../_static/doe_ml_predictions_neural_network.png
   :align: center
   :alt: Neural Network Predictions

.. GENERATED FROM PYTHON SOURCE LINES 485-486

Neural Network Predictions


.. _sphx_glr_download_examples_00-fluent_DOE_ML.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: DOE_ML.ipynb <DOE_ML.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: DOE_ML.py <DOE_ML.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: DOE_ML.zip <DOE_ML.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_