Skip to content

New tabulation framework#23

Open
EvertBunschoten wants to merge 43 commits into
developfrom
fix_LUT_twophase
Open

New tabulation framework#23
EvertBunschoten wants to merge 43 commits into
developfrom
fix_LUT_twophase

Conversation

@EvertBunschoten

@EvertBunschoten EvertBunschoten commented Jun 24, 2026

Copy link
Copy Markdown
Member

Proposed Changes

Improved the code structure for table generation, made the table generators for NICFD and FGM more object-oriented, allowing for easier integration of new refinement methods and applications, and makes the code easier to read and use.

New features to the tabulation base class:

  • Supports 2D and 3D tables depending on the number of controlling variables in the config.
  • Refine 2D table or table level based on target number of nodes, making it easier to control the size of the table.
  • Refine within specified bounds of thermochemical variables interpolated on the table nodes.
  • Option to smooth the data in the table in order to improve convergence in CFD simulations.
  • Manually specify table level values for 3D tables.
  • Write VTK file of the 2D table or table levels so the table content can be inspected with ParaView.

New features to the FGM tabulation class:

  • Scale refinement based on the gradients of thermochemical state variables. This can be useful for things like chemical source terms, which are difficult to interpolate accurately.
  • Apply additional refinement in chemical equilibrium.

PR Checklist

Put an X by all that apply. You can fill this out after submitting the PR. If you have any questions, don't hesitate to ask! We want to help. These are a guide for you to know what the reviewers will be looking for in your contribution.

  • I am submitting my contribution to the develop branch.
  • I have updated the list of python modules in required_packages.txt and environment.yml, if necessary.
  • I have properly commented my changes.
  • I have updated the documentation, if necessary.
  • I have added a test case that demonstrates my contribution, if necessary.

@EvertBunschoten EvertBunschoten changed the title Fix lut twophase New tabulation framework Jun 24, 2026
@EvertBunschoten EvertBunschoten self-assigned this Jun 24, 2026
@EvertBunschoten EvertBunschoten added the enhancement New feature or request label Jul 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new object-oriented tabulation framework (shared base + per-application generators) and updates tutorials/tests/docs to use the new API, aiming to make table generation/refinement extensible for NICFD and FGM workflows.

Changes:

  • Adds a new shared SU2TableGenerator_Base and new meshing utilities to support 2D/3D tables, refinement criteria, smoothing, and VTK export.
  • Refactors NICFD/FGM table generators to build on the base implementation and updates call sites to the new method names.
  • Updates documentation, tutorials, and regression/test cases to demonstrate the new framework and behaviors.

Reviewed changes

Copilot reviewed 37 out of 58 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
Tutorials/FGM/01_methane_tabulation/01_generate_config.py Adds tutorial script to generate an FGM config for methane LUT workflow.
Tutorials/FGM/01_methane_tabulation/02_accumulate_flamelets.py Adds tutorial script to concatenate flamelet point-cloud data for LUT generation.
Tutorials/FGM/01_methane_tabulation/03_generate_table.py Adds tutorial script using new FGM table generator API (refinement/smoothing/export).
TestCases/NICFD/LUT_Twophase/generate_table.py Updates NICFD two-phase LUT test to new generator API and refinement options.
TestCases/LUT/Flamelet_Table_H2/0_generate_config.py Adds H2 LUT test config generator script.
TestCases/LUT/Flamelet_Table_H2/1_generate_flamelet_data.py Adds H2 LUT flamelet data generation script (with thread limiting).
TestCases/LUT/Flamelet_Table_H2/2_optimize_progress_variabele.py Adds PV optimization script for H2 LUT test case.
TestCases/LUT/Flamelet_Table_H2/3_collect_flamelet_data.py Adds flamelet concatenation script for H2 LUT test case.
TestCases/LUT/Flamelet_Table_H2/4_generate_table.py Adds LUT generation/export script for H2 LUT test case.
TestCases/LUT/Flamelet_Table_H2/.gitignore Ignores generated flamelet_data directory for H2 LUT test case.
TestCases/LUT/Flamelet_Table_CH4_phi080/3_generate_table.py Replaces legacy CH4 LUT generator usage with new TableGenerator_FGM workflow.
TestCases/Flamelet_Table_H2/generate_table.py Renames legacy API calls to new generateTableNodes() / writeSU2Table() methods.
TestCases/FGM/hydrogen_LUT/1_generate_config.py Adds hydrogen FGM config generator script using new config API.
TestCases/FGM/hydrogen_LUT/3_accumulate_flamelets.py Adds hydrogen flamelet concatenation script with PV definition loading.
TestCases/FGM/hydrogen_LUT/3_generate_table.py Adds hydrogen LUT generation script using new FGM generator API.
RegressionTests/TableGeneration/NICFD/twophase_lut.py Updates regression test table generation to new NICFD generator API and exports.
RegressionTests/FluidTraining/MM_PINN/train_MLP.py Adjusts training regression test (removes inline data generation, tweaks grid size).
RegressionTests/FluidTraining/MM_PINN/SU2_MLP.mlp Updates stored MLP weights/normalization used in regression tests.
RegressionTests/FluidTraining/MM_PINN/SU2_MLP_ref.mlp Updates reference MLP weights/normalization used in regression tests.
RegressionTests/FluidTraining/MM_PINN/fluid_data_test.csv Adds fixed fluid dataset for regression testing/training.
RegressionTests/FluidTraining/MM_PINN/.gitignore Stops ignoring fluid_data files (to allow committed test dataset).
Manifold_Generation/LUT/MeshTools.py Adds new gmsh-based 2D meshing utilities (hull, refinement callback, saturation handling).
Manifold_Generation/LUT/LUTGenerators.py Refactors NICFD/FGM table generators onto the new base generator architecture.
Manifold_Generation/LUT/LUTGenerator_Base.py Adds new shared base class implementing table-level meshing, interpolation, smoothing, and export.
Manifold_Generation/LUT/FlameletTableGeneration.py Updates legacy flamelet-table generator to new Invdisttree API/method naming.
Documentation/source/Tutorials/NICFD/tablegeneration.rst Updates NICFD tutorial to new API and adds sections on limits/refinement/smoothing.
Documentation/source/Tutorials/FGM/methane_LUT/methane_LUT_tutorial.rst Adds a new methane FGM LUT end-to-end tutorial for the new framework.
Documentation/source/Tutorials/FGM/index.rst Adds methane LUT tutorial to the FGM tutorials index.
Documentation/source/documentation/tabulation/tabulationbase.rst Adds base tabulation documentation page for the new framework.
Documentation/source/documentation/tabulation/NICFD.rst Updates NICFD tabulation docs to new API names and refinement methods.
Documentation/source/documentation/tabulation/index.rst Adds tabulation base page to the tabulation documentation index.
Data_Generation/DataGenerator_NICFD.py Adjusts NICFD data generation (transport indentation fix, saturation sampling parameter).
Data_Generation/DataGenerator_FGM.py Handles equal mixture bounds by generating a single mixture point instead of linspace.
Common/Interpolators.py Refactors inverse-distance interpolator API (Invdisttree.query, fluidDataInterpolator).
Common/DataDrivenConfig.py Changes FGM config synchronization to auto-select 2D vs 3D controlling variables.
Common/CommonMethods.py Moves shared geometry/math utilities (shoelace, finite-difference derivative) into common module.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Common/Interpolators.py
Comment on lines +122 to +129
def __format_query_input(self, unformatted_query_samples:np.ndarray[float]):
number_of_dimensions = unformatted_query_samples.ndim
if number_of_dimensions == 1:
self.__single_query_sample = True
return np.expand_dims(unformatted_query_samples, -1)
else:
self.__single_query_sample = False
return unformatted_query_samples
Comment on lines +37 to +48
def generateMesh(self):
self.__checkPlanarCoords()

self._initializeGmesh()
self.__createGeometry()

if self.__use_target_node_count:
self.__optimizeMeshResolution()

self.__meshNodes, self.__connectivity, self.__hullNodeIDs = self.__mesh2D()
self._gmsh_geo.synchronize()
return
Comment on lines +157 to +161
def __filterNansFromPointCloud(self, point_cloud_3D:np.ndarray[float]):
unique_pts_init = np.unique(point_cloud_3D, axis=0)
nans = np.isnan(unique_pts_init).all(1)
pts_wo_nans = unique_pts_init[np.invert(nans)]
return pts_wo_nans
Comment on lines +389 to +392
hull_pts_orig = concave_hull(self._pointCloud_hullNodes, length_threshold=self._base_cell_size)
ref_area = shoelace(hull_pts_orig)
within_hull = np.zeros(len(self.__saturation_curve_points),dtype=np.bool)

Comment on lines +405 to +422
def __writeParaViewVTK(self, cv_coordinates:np.ndarray[float], table_data:pandas.DataFrame, connectivity:np.ndarray[int], file_name_out:str):

pts = cv_coordinates
conn = np.asarray(connectivity, dtype=np.int64)
if conn.min() == 1:
conn = conn - 1
point_data = {}
for var in self._table_vars:
point_data[var] = np.asarray(table_data[var])

mesh = meshio.Mesh(
points=pts,
cells=[("triangle", conn)],
point_data=point_data
)
mesh.write("%s.vtk" % file_name_out)

return
Comment on lines +928 to +931
if self.__mix_status_lower==self.__mix_status_upper:
self.SetControllingVariables([FGMVars.ProgressVariable.name, FGMVars.EnthalpyTot.name])
else:
self.SetControllingVariables([FGMVars.ProgressVariable.name, FGMVars.EnthalpyTot.name, FGMVars.MixtureFraction.name])
@@ -0,0 +1,22 @@
# Generate flamelet data for a single phi = 0.80 methane-air flame
Comment on lines +7 to +13
# Methane-air flamelets at a single equivalence ratio phi = 0.80
Config.SetFuelDefinition(fuel_species=["H2"], fuel_weights=[1.0])
Config.SetReactionMechanism('h2o2.yaml')

# Single phi = 0.80 → single mixture fraction point (min == max)
Config.SetMixtureBounds(0.30, 2.0)
Config.SetNpMix(20)
Comment thread Common/Interpolators.py
Comment on lines 201 to 205
# nnear nearest neighbours of each query point --
q = np.asarray(q)
max_nnear = max(max(nnear_vals), 2)
qdim = q.ndim
if qdim == 1:
Comment on lines +111 to +115
def __createHullPerimiter(self):
self._pointCloud_hullNodes = self.__findHullNodes()
planeCurvLoop, perimiterTags = self.__createHullCurvLoop(self._pointCloud_hullNodes)
self.__perimiter_tag = self._gmsh_geo.addPhysicalGroup(1, perimiterTags, name="perimiter")
return planeCurvLoop, perimiterTags
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants