.. 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 ` 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 8-23 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 25-27 Import required libraries/modules ================================= .. GENERATED FROM PYTHON SOURCE LINES 27-42 .. code-block:: Python 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 43-48 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 48-57 .. 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 58-60 Fluent Solution Setup ===================== .. GENERATED FROM PYTHON SOURCE LINES 62-64 Launch Fluent session with solver mode ====================================== .. GENERATED FROM PYTHON SOURCE LINES 64-73 .. code-block:: Python solver = pyfluent.launch_fluent( precision="double", processor_count=2, version="3d", ) solver.health_check.status() .. GENERATED FROM PYTHON SOURCE LINES 74-76 Read case ========= .. GENERATED FROM PYTHON SOURCE LINES 76-79 .. code-block:: Python solver.settings.file.read_case(file_name=import_filename) .. GENERATED FROM PYTHON SOURCE LINES 80-85 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 85-116 .. 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 117-119 Close the session ================= .. GENERATED FROM PYTHON SOURCE LINES 119-122 .. code-block:: Python solver.exit() .. GENERATED FROM PYTHON SOURCE LINES 123-125 Plot Response Surface using Plotly ================================== .. GENERATED FROM PYTHON SOURCE LINES 125-151 .. 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 152-154 Supervised ML for a Regression Task =================================== .. GENERATED FROM PYTHON SOURCE LINES 156-158 Create Pandas Dataframe for ML Model Input ========================================== .. GENERATED FROM PYTHON SOURCE LINES 158-177 .. 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 178-183 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 183-212 .. 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 213-218 * 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 218-297 .. code-block:: Python from pprint import pprint # noqa: F401 from sklearn.ensemble import RandomForestRegressor # noqa: F401 from sklearn.linear_model import LinearRegression # noqa: F401 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 298-301 Select the Model from Linear, Random Forest or XGBoost ====================================================== * Call fit_and_predict .. GENERATED FROM PYTHON SOURCE LINES 301-310 .. 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 311-313 Show graph ========== .. GENERATED FROM PYTHON SOURCE LINES 313-316 .. code-block:: Python plt.show() .. GENERATED FROM PYTHON SOURCE LINES 317-320 .. image:: ../../_static/doe_ml_predictions_regression.png :align: center :alt: Regression Model Predictions .. GENERATED FROM PYTHON SOURCE LINES 322-323 Regression Model Predictions .. GENERATED FROM PYTHON SOURCE LINES 325-327 3D Visualization of Model Predictions on Train & Test Set ========================================================= .. GENERATED FROM PYTHON SOURCE LINES 327-359 .. 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 360-362 TensorFlow and Keras Neural Network Regression ============================================== .. GENERATED FROM PYTHON SOURCE LINES 362-441 .. 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 442-444 Show graph ========== .. GENERATED FROM PYTHON SOURCE LINES 444-447 .. code-block:: Python plt.show() .. GENERATED FROM PYTHON SOURCE LINES 448-451 .. image:: ../../_static/doe_ml_validation_loss.png :align: center :alt: Neural Network Validation Loss .. GENERATED FROM PYTHON SOURCE LINES 453-454 Neural Network Validation Loss .. GENERATED FROM PYTHON SOURCE LINES 456-459 .. image:: ../../_static/doe_ml_predictions_neural_network.png :align: center :alt: Neural Network Predictions .. GENERATED FROM PYTHON SOURCE LINES 461-462 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 ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: DOE_ML.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: DOE_ML.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_