Skip to content

Commit 80c3fcd

Browse files
webwornclaude
andcommitted
feat: Add comprehensive turbulent flow analysis with k-omega SST support
- Add k-omega SST turbulence model support to CaseManager alongside k-epsilon - Implement Colebrook-White and Swamee-Jain friction factor calculations for rough pipes - Add PipeRoughness database with 13 standard pipe materials - Create turbulence_utils for y+ calculations and wall function validation - Add analyze_turbulent_flow MCP tool with: - Reynolds number classification and flow regime detection - Automatic turbulence model selection with justification - Smooth and rough pipe friction factor calculations - Pressure drop and head loss predictions - y+ estimation and mesh recommendations - Turbulent inlet boundary condition calculations (k, epsilon, omega) - Model comparison (k-epsilon vs k-omega SST) - Educational content with Socratic questioning - Update CaseParameters with turbulenceModel, turbulentIntensity, turbulentLengthScale, pipeRoughness - Add omega field boundary conditions with omegaWallFunction Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 17c5f22 commit 80c3fcd

File tree

10 files changed

+1968
-26
lines changed

10 files changed

+1968
-26
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,12 @@ add_executable(openfoam-mcp-server-test
121121
"src/tools/rde_3d_geometry_tool.cpp"
122122
"src/tools/rde_3d_wave_tool.cpp"
123123
"src/tools/rde_3d_performance_tool.cpp"
124+
"src/tools/turbulent_flow_tool.cpp"
124125
"src/openfoam/mesh_quality.cpp"
125126
"src/openfoam/stl_analyzer.cpp"
127+
"src/openfoam/turbulence_utils.cpp"
128+
"src/openfoam/pipe_flow.cpp"
129+
"src/openfoam/case_manager.cpp"
126130
"src/tools/rde_wave_analyzer.cpp"
127131
"src/tools/rde_3d_geometry.cpp"
128132
"src/tools/rde_3d_wave_analyzer.cpp"

src/main_test.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Foam { namespace MCP {
1111
void registerRDE3DGeometryTool(McpServer& server);
1212
void registerRDE3DWaveTool(McpServer& server);
1313
void registerRDE3DPerformanceTool(McpServer& server);
14+
void registerTurbulentFlowTool(McpServer& server);
1415
}}
1516

1617
using namespace Foam;
@@ -88,6 +89,13 @@ int main(int argc, char* argv[]) {
8889
std::cerr << "Warning: Could not register RDE 3D performance tool: " << e.what() << std::endl;
8990
}
9091

92+
// Register turbulent flow analysis tool
93+
try {
94+
registerTurbulentFlowTool(server);
95+
} catch (const std::exception& e) {
96+
std::cerr << "Warning: Could not register turbulent flow tool: " << e.what() << std::endl;
97+
}
98+
9199
std::cerr << "🔧 Registered tools: ";
92100
auto tools = server.getRegisteredTools();
93101
for (size_t i = 0; i < tools.size(); ++i) {

src/openfoam/case_manager.cpp

Lines changed: 107 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ void to_json(json& j, const CaseParameters& params) {
3939
{"writeInterval", params.writeInterval},
4040
{"boundaryConditions", params.boundaryConditions},
4141
{"physicalProperties", params.physicalProperties},
42-
{"numericalSchemes", params.numericalSchemes}};
42+
{"numericalSchemes", params.numericalSchemes},
43+
{"turbulenceModel", params.turbulenceModel},
44+
{"turbulentIntensity", params.turbulentIntensity},
45+
{"turbulentLengthScale", params.turbulentLengthScale},
46+
{"pipeRoughness", params.pipeRoughness}};
4347
}
4448

4549
void from_json(const json& j, CaseParameters& params) {
@@ -52,6 +56,11 @@ void from_json(const json& j, CaseParameters& params) {
5256
j.at("boundaryConditions").get_to(params.boundaryConditions);
5357
j.at("physicalProperties").get_to(params.physicalProperties);
5458
j.at("numericalSchemes").get_to(params.numericalSchemes);
59+
// Optional turbulence parameters with defaults
60+
if (j.contains("turbulenceModel")) j.at("turbulenceModel").get_to(params.turbulenceModel);
61+
if (j.contains("turbulentIntensity")) j.at("turbulentIntensity").get_to(params.turbulentIntensity);
62+
if (j.contains("turbulentLengthScale")) j.at("turbulentLengthScale").get_to(params.turbulentLengthScale);
63+
if (j.contains("pipeRoughness")) j.at("pipeRoughness").get_to(params.pipeRoughness);
5564
}
5665

5766
void to_json(json& j, const CaseResult& result) {
@@ -248,6 +257,7 @@ void CaseManager::writeFvSchemes(const fs::path& casePath, const CaseParameters&
248257
<< " div(phi,U) bounded Gauss upwind;\n"
249258
<< " div(phi,k) bounded Gauss upwind;\n"
250259
<< " div(phi,epsilon) bounded Gauss upwind;\n"
260+
<< " div(phi,omega) bounded Gauss upwind;\n"
251261
<< " div((nuEff*dev2(T(grad(U))))) Gauss linear;\n"
252262
<< "}\n\n";
253263

@@ -306,6 +316,14 @@ void CaseManager::writeFvSolution(const fs::path& casePath, const CaseParameters
306316
<< " }\n\n";
307317

308318
file << " epsilon\n"
319+
<< " {\n"
320+
<< " solver smoothSolver;\n"
321+
<< " smoother GaussSeidel;\n"
322+
<< " tolerance 1e-05;\n"
323+
<< " relTol 0.1;\n"
324+
<< " }\n\n";
325+
326+
file << " omega\n"
309327
<< " {\n"
310328
<< " solver smoothSolver;\n"
311329
<< " smoother GaussSeidel;\n"
@@ -323,7 +341,7 @@ void CaseManager::writeFvSolution(const fs::path& casePath, const CaseParameters
323341
<< " {\n"
324342
<< " p 1e-5;\n"
325343
<< " U 1e-5;\n"
326-
<< " \"(k|epsilon)\" 1e-5;\n"
344+
<< " \"(k|epsilon|omega)\" 1e-5;\n"
327345
<< " }\n"
328346
<< "}\n\n";
329347

@@ -336,7 +354,7 @@ void CaseManager::writeFvSolution(const fs::path& casePath, const CaseParameters
336354
<< " equations\n"
337355
<< " {\n"
338356
<< " U 0.7;\n"
339-
<< " \"(k|epsilon)\" 0.7;\n"
357+
<< " \"(k|epsilon|omega)\" 0.7;\n"
340358
<< " }\n"
341359
<< "}\n\n";
342360
}
@@ -376,13 +394,24 @@ void CaseManager::writeTurbulenceProperties(const fs::path& casePath,
376394
<< " object turbulenceProperties;\n"
377395
<< "}\n\n";
378396

379-
file << "simulationType RAS;\n\n";
380-
file << "RAS\n"
381-
<< "{\n"
382-
<< " RASModel kEpsilon;\n"
383-
<< " turbulence on;\n"
384-
<< " printCoeffs on;\n"
385-
<< "}\n\n";
397+
if (params.turbulenceModel == "laminar") {
398+
file << "simulationType laminar;\n\n";
399+
} else {
400+
file << "simulationType RAS;\n\n";
401+
file << "RAS\n"
402+
<< "{\n";
403+
404+
if (params.turbulenceModel == "kOmegaSST") {
405+
file << " RASModel kOmegaSST;\n";
406+
} else {
407+
// Default to k-epsilon
408+
file << " RASModel kEpsilon;\n";
409+
}
410+
411+
file << " turbulence on;\n"
412+
<< " printCoeffs on;\n"
413+
<< "}\n\n";
414+
}
386415
}
387416

388417
void CaseManager::setupMesh(const std::string& caseId, const CaseParameters& params) const {
@@ -817,6 +846,74 @@ void CaseManager::setupBoundaryConditions(const std::string& caseId,
817846
<< " }\n"
818847
<< "}\n\n";
819848
}
849+
850+
// Add specific turbulence dissipation rate field (omega) for k-omega SST
851+
std::ofstream omegaFile(casePath / "0" / "omega");
852+
omegaFile << "FoamFile\n"
853+
<< "{\n"
854+
<< " version 2.0;\n"
855+
<< " format ascii;\n"
856+
<< " class volScalarField;\n"
857+
<< " object omega;\n"
858+
<< "}\n\n";
859+
860+
omegaFile << "dimensions [0 0 -1 0 0 0 0];\n";
861+
omegaFile << "internalField uniform 1.0;\n\n";
862+
863+
if (isExternalFlow) {
864+
omegaFile << "boundaryField\n"
865+
<< "{\n"
866+
<< " inlet\n"
867+
<< " {\n"
868+
<< " type fixedValue;\n"
869+
<< " value uniform 1.0;\n"
870+
<< " }\n"
871+
<< " outlet\n"
872+
<< " {\n"
873+
<< " type zeroGradient;\n"
874+
<< " }\n"
875+
<< " walls\n"
876+
<< " {\n"
877+
<< " type omegaWallFunction;\n"
878+
<< " value uniform 1.0;\n"
879+
<< " }\n"
880+
<< " symmetry\n"
881+
<< " {\n"
882+
<< " type symmetryPlane;\n"
883+
<< " }\n"
884+
<< " farfield\n"
885+
<< " {\n"
886+
<< " type fixedValue;\n"
887+
<< " value uniform 1.0;\n"
888+
<< " }\n"
889+
<< " frontAndBack\n"
890+
<< " {\n"
891+
<< " type empty;\n"
892+
<< " }\n"
893+
<< "}\n\n";
894+
} else {
895+
omegaFile << "boundaryField\n"
896+
<< "{\n"
897+
<< " inlet\n"
898+
<< " {\n"
899+
<< " type fixedValue;\n"
900+
<< " value uniform 1.0;\n"
901+
<< " }\n"
902+
<< " outlet\n"
903+
<< " {\n"
904+
<< " type zeroGradient;\n"
905+
<< " }\n"
906+
<< " walls\n"
907+
<< " {\n"
908+
<< " type omegaWallFunction;\n"
909+
<< " value uniform 1.0;\n"
910+
<< " }\n"
911+
<< " frontAndBack\n"
912+
<< " {\n"
913+
<< " type empty;\n"
914+
<< " }\n"
915+
<< "}\n\n";
916+
}
820917
}
821918

822919
bool CaseManager::runCase(const std::string& caseId) {

src/openfoam/case_manager.hpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,23 @@ struct CaseParameters {
4545
std::map<std::string, std::string> physicalProperties;
4646
std::map<std::string, std::string> numericalSchemes;
4747

48+
// Turbulence modeling parameters
49+
std::string turbulenceModel; // "laminar", "kEpsilon", "kOmegaSST"
50+
double turbulentIntensity; // Turbulent intensity (0-1), default 5%
51+
double turbulentLengthScale; // Turbulent length scale (m)
52+
double pipeRoughness; // Absolute pipe roughness (m), 0 = smooth
53+
4854
CaseParameters()
4955
: caseName("case"),
5056
solver("simpleFoam"),
5157
caseType("steady"),
5258
endTime(1000.0),
5359
deltaTime(1.0),
54-
writeInterval(100) {}
60+
writeInterval(100),
61+
turbulenceModel("kEpsilon"),
62+
turbulentIntensity(0.05),
63+
turbulentLengthScale(0.01),
64+
pipeRoughness(0.0) {}
5565
};
5666

5767
/*---------------------------------------------------------------------------*\

0 commit comments

Comments
 (0)