Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 8 additions & 123 deletions iga/use_cases/toyota_3d_sbm/README.md
Original file line number Diff line number Diff line change
@@ -1,128 +1,13 @@
# 3D Toyota SBM Example
# 3D Toyota SBM Examples

This use case demonstrates a 3D immersed-body fluid analysis with the Surrogate Boundary Method (SBM) in the Kratos IGA Application. The Toyota body is not discretized with a body-fitted fluid mesh. Instead, the car surface is provided as an immersed skin in `toyota_immersed_surface_sbm.mdpa`, while the fluid is solved on a structured Cartesian background NURBS volume generated in the JSON settings.
This directory contains the shared geometry for the Toyota SBM examples together with two split use cases:

## SBM Philosophy
- [steady_stokes/README.md](/home/nantonelli/Examples/iga/use_cases/toyota_3d_sbm/steady_stokes/README.md): steady-state-style 3D Stokes example
- [transient_navier_stokes/README.md](/home/nantonelli/Examples/iga/use_cases/toyota_3d_sbm/transient_navier_stokes/README.md): transient 3D Navier-Stokes example

The main idea of SBM is to decouple the geometry description from the analysis mesh:
The shared files stored in this parent folder are:

- the immersed body is described only by a surface mesh
- the analysis domain is a simple Cartesian background volume
- boundary conditions are imposed on a surrogate boundary built from the background mesh, rather than on a body-fitted mesh
- `toyota_immersed_surface_sbm.mdpa`: common immersed Toyota surface mesh used by both subcases
- `FluidMaterials.json`: common material definition

For this kind of problem, that is useful because the geometry can come from an external triangulated surface, for example an STL-like workflow prepared outside Kratos and then exported to `.mdpa`. The analysis mesh can then be changed independently by editing the background box and its resolution directly in the parameter files.

In this example, the no-slip condition on the immersed Toyota surface is imposed weakly on `IgaModelPart.SBM_Support_inner` with `SbmFluidConditionDirichlet`. The formulation includes skew-symmetric Nitsche terms, and the example is configured in penalty-free mode on the immersed surrogate boundary through `PENALTY_FACTOR: 0.0` in `FluidMaterials.json`.

## Geometry and Modelers

Both `ProjectParameters_3D_fluid.json` and `ProjectParameters_3D_fluid_steady_state.json` follow the same three-step geometry pipeline:

1. `import_mdpa_modeler` imports `toyota_immersed_surface_sbm.mdpa` into `initial_skin_model_part_in`.
2. `NurbsGeometryModelerSbm` creates the background 3D Cartesian NURBS volume.
3. `IgaModelerSbm` builds the fluid domain and the fitted/surrogate support conditions needed by the SBM formulation.

The main model parts created by the setup are:

- `IgaModelPart.FluidDomain`: background fluid volume
- `IgaModelPart.SBM_Support_inner`: surrogate boundary associated with the immersed Toyota body
- `IgaModelPart.SBM_Support_outer`: outer wall support surfaces of the background box
- `IgaModelPart.Support_inlet`: inlet support surface
- `IgaModelPart.SupportOuterPressure`: outlet pressure support surface

## What You Can Change in the JSON

The most important SBM geometry controls are in the `NurbsGeometryModelerSbm` block:

- `input_filename`: selects the immersed surface mesh to import
- `lower_point_xyz` and `upper_point_xyz`: define the background Cartesian box
- `polynomial_order`: defines the polynomial degree of the background NURBS volume
- `number_of_knot_spans`: defines the Cartesian resolution in each direction
- `lambda_outer`, `lambda_inner`, `number_of_inner_loops`: control the SBM surrogate-boundary construction

In practice, if you want to analyze another immersed geometry, the usual workflow is:

1. generate or export a triangulated surface externally
2. convert it to an `.mdpa` skin mesh
3. replace `toyota_immersed_surface_sbm.mdpa`
4. adapt the background box and the number of knot spans in the JSON files

## Physics in This Folder

This folder contains two related fluid setups:

- `ProjectParameters_3D_fluid.json`: transient monolithic 3D Navier-Stokes case with `NavierStokesElement` and a ramped inlet velocity
- `ProjectParameters_3D_fluid_steady_state.json`: steady-state-style 3D case using `StokesElement` and a constant inlet velocity

The boundary treatment is:

- inlet velocity prescribed on `IgaModelPart.Support_inlet`
- zero outlet pressure prescribed on `IgaModelPart.SupportOuterPressure`
- outer-box support conditions imposed weakly on `IgaModelPart.SBM_Support_outer`
- immersed no-slip condition imposed weakly on `IgaModelPart.SBM_Support_inner`

The material file uses a 3D Newtonian constitutive law. In the current setup:

- `IgaModelPart` uses `DENSITY = 1.0`, `DYNAMIC_VISCOSITY = 1e-3`, and `PENALTY_FACTOR = 1e3` for the fitted support terms on the background box
- `IgaModelPart.SBM_Support_inner` uses `PENALTY_FACTOR = 0.0` for the penalty-free immersed-boundary configuration

## Files

- `ProjectParameters_3D_fluid.json`: transient fluid setup
- `ProjectParameters_3D_fluid_steady_state.json`: steady-state fluid setup
- `FluidMaterials.json`: 3D Newtonian material data and SBM penalty settings
- `toyota_immersed_surface_sbm.mdpa`: immersed Toyota skin used by the SBM modeler
- `run_and_post_nurbs_time.py`: runs the transient case and generates postprocessed GIFs
- `run_and_post_nurbs_steady_state.py`: runs the steady case and generates final plots
- `plot_conditions.py`: visualizes the surrogate faces created by the geometry/modeler setup

## Python Dependencies

The post-processing scripts use:

- `numpy`
- `matplotlib`
- `imageio` for GIF writing in the transient script

If a `latex` executable is available, the plotting scripts can use Computer Modern style math text. Otherwise they fall back to standard matplotlib text rendering.

## Run

Transient case:

```bash
cd /home/nantonelli/Examples/iga/use_cases/toyota_3d_sbm
python3 run_and_post_nurbs_time.py
```

Steady-state case:

```bash
cd /home/nantonelli/Examples/iga/use_cases/toyota_3d_sbm
python3 run_and_post_nurbs_steady_state.py
```

Geometry / surrogate-condition plot:

```bash
cd /home/nantonelli/Examples/iga/use_cases/toyota_3d_sbm
python3 plot_conditions.py
```

## Outputs

Transient script:

- `particles_trails.gif`
- `cut_contour_x_lt_0.gif`
- `plane_x_eq_0_contour.gif`

Steady-state script:

- `steady_3d_velocity_pressure.png`
- `steady_plane_x0_velocity.png`
- `steady_plane_x0_pressure.png`

Geometry helper:

- `surrogate_faces_plot.png`
The split layout avoids duplicating the immersed `.mdpa` file while keeping the steady and transient examples documented separately.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"echo_level": 1,
"parallel_type": "OpenMP",
"start_time": 0.0,
// "end_time": 9.0
"end_time": 5.0
},

Expand All @@ -17,7 +16,7 @@
"model_part_name": "IgaModelPart",
"domain_size": 3,
"model_import_settings": { "input_type": "use_input_model_part" },
"material_import_settings": { "materials_filename": "FluidMaterials.json" },
"material_import_settings": { "materials_filename": "../FluidMaterials.json" },
"linear_solver_settings": { "solver_type": "bicgstab", "tolerance": 1.0e-14, "max_iteration": 1000, "scaling": true, "preconditioner_type": "ilu0"},
// "linear_solver_settings":{
// // "solver_type": "LinearSolversApplication.sparse_lu"
Expand All @@ -44,7 +43,7 @@
"modeler_name" : "import_mdpa_modeler",
"kratos_module" : "KratosMultiphysics",
"Parameters" : {
"input_filename" : "toyota_immersed_surface_sbm",
"input_filename" : "../toyota_immersed_surface_sbm",
"model_part_name" : "initial_skin_model_part_in"
}
},
Expand Down Expand Up @@ -139,8 +138,6 @@
{
"variable_name": "BODY_FORCE",
"value": ["0", "0", "0"]
// NAVIER STOKES
// "value": ["(cosh(x)*sinh(x)*cosh(y)*cosh(y)*cosh(z)*cosh(z) + cosh(x)*sinh(x)*sinh(y)*cosh(z)*sinh(z-y) - cosh(x)*sinh(x)*sinh(y)*cosh(y)*cosh(z)*sinh(z)) + cosh(x) - 3*cosh(x)*cosh(y)*cosh(z)", "(cosh(x)*cosh(x)*cosh(y)*cosh(z)*sinh(z-y) - sinh(x)*sinh(x)*sinh(z-y)*cosh(z-y) - sinh(x)*sinh(x)*sinh(y)*cosh(z)*cosh(z-y)) + sinh(y) - 3*sinh(x)*sinh(z-y)", "(-cosh(x)*cosh(x)*cosh(y)*sinh(y)*cosh(z)*cosh(z) - sinh(x)*sinh(x)*sinh(z-y)*cosh(y)*cosh(z) + sinh(x)*sinh(x)*sinh(y)*sinh(y)*cosh(z)*sinh(z)) + cosh(z) + 3*sinh(x)*sinh(y)*cosh(z)"]
}
]
},
Expand All @@ -154,7 +151,6 @@
"0.0",
"0.0"
]
// "value": ["cosh(x)*cosh(y)*cosh(z)","sinh(x)*sinh(z-y)","-sinh(x)*sinh(y)*cosh(z)"]
}]
},
{
Expand All @@ -167,7 +163,6 @@
"0.0",
"2.0"
]
// "value": ["cosh(x)*cosh(y)*cosh(z)","sinh(x)*sinh(z-y)","-sinh(x)*sinh(y)*cosh(z)"]
}]
},
{
Expand All @@ -176,7 +171,6 @@
{
"variable_name": "PRESSURE",
"value": "0.0"
// "value": "sinh(x) + cosh(y) + sinh(z)"
},
{
"variable_name": "NORMAL_STRESS",
Expand All @@ -203,7 +197,6 @@
"0.0",
"0.0"
]
// "value": ["cosh(x)*cosh(y)*cosh(z)","sinh(x)*sinh(z-y)","-sinh(x)*sinh(y)*cosh(z)"]
}
}
],
Expand Down
Loading
Loading