# LCMsim_v2.jl
**Repository Path**: num3/LCMsim_v2.jl
## Basic Information
- **Project Name**: LCMsim_v2.jl
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: GPL-3.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-07-17
- **Last Updated**: 2026-07-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# LCMsim_v2.jl
## Allowed mesh formats
LCMsim_v2.jl does not include mesh generation. A 3-node triangular shell mesh with the pre-defined regions must be generated with a meshing tool before starting the filling simulation. The authors used Altair HyperWorks but also free software tools such as SALOME-MECA, GMSH or NETGEN can be used.
The shell mesh is created on the part's mid-surface. Mid-surface models are often available in composite manufacturing since computational stress analysis for thin-walled parts is performed on the part’s mid-surface too.
Currently it is possible to use meshes generated by:
- Nastran format (as created by Altair HyperMesh), with set definitions (.dat)
- Gmsh, with physical part ids (.bdf)
- Abaqus, with Element Sets (.inp)
## Part description file
The parts defined by the meshfile need additional parameters for the simulation. These have to be provided via a .csv-file with the following columns and one row per part.
| Column name | Description | Value range |
| :--- | :--- | :--- |
| name | Name of the part. Will be used later on
to match action to inlets/ outlets | freely choosable (be reasonable) |
| type | Type of this part | {base, inlet, outlet, patch} |
| part_id | The physical part ID assigned to the part in the mesh file | determined by mesh file |
| thickness | | |
| permeability | | |
| permeability_noise | standard deviation applied to permeability values with a normal distribution | 0 - 0.5 (no definitive cap but unrealistic values break simulation) |
| porosity | | |
| porosity_noise | standard deviation applied to porosity values with a normal distribution | 0 - 0.5 (no definitive cap but unrealistic values break simulation) |
| porosity_1 | reference porosity at pressure p_1 | |
| p_1 | reference pressure| |
| alpha | | |
| refdir_1 | | |
| refdir_2 | | |
| refdir_3 | | |
## Simulation parameter file
The parameters for the simulation need to be provided as a .csv-file with the following columns.
| Column name | Description |
| :--- | :--- |
| p_ref | |
|rho_ref | |
| gamma | |
| mu_resin | viscosity of the resin|
| p_a | intial pressure at the inlets |
| p_init | initial cavity pressure |
| rho_0_air | density of the air |
| rho_0_oil | density of the resin |
## Programming Interface
The public interface of LCMsim_v2.jl is designed mainly for two purposes:
- solving cases via simple scripts
- being able to embed the solver in bigger programs
The availabe functions and their intended usage are descibed in the following sections.
However, since not every possible usecase could be foreseen and most of the internal functions are
documented, you should be able to adapt the program to your custom needs.
### Data structures and artifacts
When working with LCMsim_v2, you will encounter different in-program data structures and/ or file formats to persistently save simulation results.
Data structures:
- ModelType
- LcmMesh/ LcmCell
- State
- AbstractModel
- LcmCase
Two file formats are used:
- human-readable results (HDF)
- binary dump (JLD2)
#### ModelType
```
@enum ModelType begin
model_1 = 1
model_2 = 2
model_3 = 3
end
````
This enum lets you choose which physical model is applied by the solver. You'll need to pass it to the `create` function.
#### LcmMesh/ LcmCell
```
struct LcmMesh
N::Int
vertices::Vector{Point3{Float64}}
cells::Vector{LcmCell}
...
end
```
```
struct LcmCell
id::Int
# basic cell geometry
vertex_ids::Tuple{Int, Int, Int}
...
# cell parameters
thickness::Float64
area::Float64
volume::Float64
permeability::Float64
porosity::Float64
...
end
```
`LcmMesh` represents a mesh, which mainly consists of a vector of `LcmCell`. Most of the information should not be relevant for most users, so it's not included here (extensive documentation can be found in code).
If you want to visualize the mesh directly from the struct, you will need the `vertices` field of `LcmMesh` for the vertex coordinates and the connectivity information. This can be retrieved by iterating over the cells and retrieving each cell's `vertex_ids`, which defines the three vertices making up this cell.
Some cell wise properties possibly interesting for plots can be retrieved in the same manner, for example the permeabilities, porosities, ...
Disclaimer: It is more convenient to create plots from the HDF-files, so this is usually the way to go.
#### State
```
struct State
t::Float64
iter::Int
deltat::Float64
p::Vector{Float64}
gamma::Vector{Float64}
rho::Vector{Float64}
u::Vector{Float64}
v::Vector{Float64}
viscosity::Vector{Float64}
porosity_times_porosity::Vector{Float64}
end
```
The state struct describes the time varying variables of a simulation case. The vectorial fields can be matched to the cells of the mesh that this state has been created from.
#### LcmCase
```
mutable struct LcmCase
mesh::LcmMesh
model::AbstractModel
state::State
end
```
This struct describes the state of a simulation entirely and can be used to start solving. `model` will be a concrete subtype of `AbstractModel` that is determined by the input settings and influences the behaviour of the solver.
#### HDF
The module will generate HDF files of the following structure:
- mesh
- cells
- vertices
- properties
- part_id
- permeability
- porosity
- thickness
- type
- volume
- area
- reference_direction
- ap
- cp
- alpha
- for each unique part_id
- Attribute: :[name]
- e.g. 1:base
- state000000001
- cellporositytimecellporosity
- gamma
- p
- rho
- u
- v
- viscosity
- Attributes: [deltat, iter, t]
- state...
`mesh/vertices` is a 3 by *M* float field, where *M* is the number of vertices. Each 3-entry line describes the x, y, and z coordinates of the vertex associated with this line's index. Note that, since julia is 1-indexed, we use 1-indexing for the HDF-files too, even though most HDF viewers display 0-based indices.
`mesh/cells` is a 3 by *N* integer field, where *N* is the number of cells. Each 3-entry line indicates which 3 vertices make up this cell.
Depending on the setup of the simulation, a varying number of states will be created. The name of a state indicates the iteration counter.
All datasets in `properties` and `stateXXXXXXXXX` refer to the cells of the mesh.
In code usage:
```
using HDF5
# load case from the hdf5 file
case, states = load_project(path) # case::LcmCase, states::Vector{State}
# save case to hdf5 file
save_project(case, states, path)
```
#### JLD2
The binary files created by LCMsim_v2 contain an entire `LcmCase` struct. There are convenience functions to create such a file and start/ continue a simulation directly from the file path.
The results are not human readable but can be retrieved via a Julia script (you'll need to include this module!).
Example for loading:
```
# load the jld2 file
jld2file = JLD2.load(path)
# extract the LcmCase object
case = jld2file["LcmCase"]
# get state from case
state = case.state
```
### Functions
#### create
```
create(
meshfile::String,
partfile::String,
simfile::String,
i_model::ModelType,
)::LcmCase
```
Function for in-program usage. Takes paths to the meshfile, the part description file and the simulation parameter file. Returns a LcmCase instance.
```
create(
meshfile::String,
partfile::String,
simfile::String,
i_model::ModelType,
save_path::String,
save_binary::Bool=true,
save_hdf::Bool=true
)::LcmCase
```
Function to also save the results as `data.h5` / `data.jld2` at the given `save_path`.
#### solve
```
solve(
case::LcmCase,
t_max::Float64
)::State
```
Solve the given LcmCase up to the specified end time. If you want to receive simulation results at certain point in time, the usual usage would be to call this function repeatedly while incrementing `t_max` and passing the returned State back in (by replacing `case.state`). If your use case only requires the results at the end, you would invoke the solver only once.
```
solve!(
case::LcmCase,
t_max::Float64,
actions::Vector{Tuple{String, Float64}},
verbosity=silent::Verbosity
)::State
```
Applies pressure actions and solves the problem for the given LcmCase up to the specified end time.
One action is a tuple of a part name and a pressure value.
For every existing inlet and outlet, an action needs to be provided.
Mutates the given LcmCase by replacing the state, but does not mutate the old state itself.
Returns the new state.
```
solve(
source_path::String,
save_path::String,
t_max::Float64,
t_step::Float64,
verbosity=verbose::Verbosity,
save_binary::Bool=true,
save_hdf::Bool=true
)::Nothing
```
This is a convenience function to start/ continue a simulation from a previously saved LcmCase. `source_path` needs to point to an appropriate .jld2-file. Then the problem up is solved to the specified `t_max`. Results are saved in hdf5 format every `t_step` seconds. If `t_step <= 0.0` is provided, it is set to t_max, aka the results are only saved at the end. Additionally saves the resulting LcmCase as binary in jld2 format.
#### create_and_solve
```
create_and_solve(
save_path::String,
meshfile::String,
partfile::String,
simfile::String,
i_model::ModelType,
t_max::Float64,
t_step::Float64,
verbosity=verbose::Verbosity,
save_binary::Bool=true,
save_hdf::Bool=true
)::Nothing
````
Convenience function the behaves like `create` and `solve`.
#### continue_and_solve
```
continue_and_solve(
source_path::String,
save_path::String,
meshfile::String,
partfile::String,
simfile::String,
i_model::ModelType,
t_max::Float64,
output_intervals::Int,
verbosity=verbose::Verbosity,
save_binary::Bool=true,
save_hdf::Bool=true
)::Nothing
```
This function allows to continue a simulation.
A new LcmCase is created but the initial values are from the a saved LcmCase
Creates a mesh, a model and an initial state from the given files.
The model is chosen according to the given i_model.
Then solves the problem up to the specified end time.
Saves results in hdf5 format at the specified output intervals.
If t_step is not given, it is set to t_max, aka the results are only saved at the end.
Additionally saves the resulting LcmCase as binary in jld2 format.
### HDF interface
There is currently no function to solve a case directly from an HDF file. However, with the provided functions to load and save projects, you can easily implement this behaviour yourself.