Skip to content

Commit 83de5f8

Browse files
authored
Merge pull request #101 from DataAnalyticsEngineering/FANS-v0.5.0
2 parents c9ac254 + 94d5ea6 commit 83de5f8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3551
-3142
lines changed

.github/workflows/build_and_test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
uses: actions/checkout@v5
3434

3535
- name: Set up pixi
36-
uses: prefix-dev/setup-pixi@v0.9.1
36+
uses: prefix-dev/setup-pixi@v0.9.2
3737
with:
3838
environments: dashboard
3939

.github/workflows/pixi_build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
uses: actions/checkout@v5
2424

2525
- name: Set up pixi
26-
uses: prefix-dev/setup-pixi@v0.9.1
26+
uses: prefix-dev/setup-pixi@v0.9.2
2727
with:
2828
environments: default
2929

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ test/input_files/**/*.json
206206
!test_PseudoPlastic.json
207207
!test_J2Plasticity.json
208208
!test_MixedBCs.json
209+
!test_CompressibleNeoHookean.json
210+
!test_MixedBCs_LargeStrain.json
209211

210212
# pixi environments
211213
.pixi

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# FANS Changelog
22

3+
## v0.5.0
4+
5+
- Add explicit FE types (HEX8, HEX8R, BBAR) to JSON input [#96](https://github.com/DataAnalyticsEngineering/FANS/pull/96)
6+
- Introduce finite strain support along with Saint-Venant Kirchhoff, compressible Neohookean hyperelastic models [#95](https://github.com/DataAnalyticsEngineering/FANS/pull/95)
7+
- Fix some memory leaks [#93](https://github.com/DataAnalyticsEngineering/FANS/pull/93)
8+
39
## v0.4.3
410

511
- Introduce a Pixi dev environment [#89](https://github.com/DataAnalyticsEngineering/FANS/pull/89)

CMakeLists.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.21)
55
# ##############################################################################
66

77
project(FANS
8-
VERSION 0.4.3
8+
VERSION 0.5.0
99
LANGUAGES C CXX
1010
)
1111

@@ -20,6 +20,15 @@ set(CMAKE_CXX_EXTENSIONS OFF)
2020
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
2121
set(CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})
2222

23+
# Memory leak detection with AddressSanitizer and LeakSanitizer
24+
option(FANS_ENABLE_SANITIZERS "Enable AddressSanitizer and LeakSanitizer for memory leak detection" OFF)
25+
if (FANS_ENABLE_SANITIZERS)
26+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,leak -fno-omit-frame-pointer -g")
27+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,leak")
28+
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,leak")
29+
message(STATUS "Memory sanitizers enabled: AddressSanitizer and LeakSanitizer")
30+
endif()
31+
2332
# IPO
2433
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.9")
2534
cmake_policy(SET CMP0069 NEW)
@@ -155,6 +164,9 @@ set_property(TARGET FANS_FANS PROPERTY PUBLIC_HEADER
155164
include/material_models/LinearElastic.h
156165
include/material_models/PseudoPlastic.h
157166
include/material_models/J2Plasticity.h
167+
168+
include/material_models/SaintVenantKirchhoff.h
169+
include/material_models/CompressibleNeoHookean.h
158170
)
159171

160172
# version.h is generated and added to the build include directory

FANS_Dashboard/FANS_Dashboard.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"import numpy as np\n",
5454
"from fans_dashboard.core.utils import *\n",
5555
"from fans_dashboard.core.postprocessing import compute_rank2tensor_measures\n",
56-
"from fans_dashboard.plotting.h52xdmf import write_xdmf\n",
56+
"from MSUtils.general.h52xdmf import write_xdmf\n",
5757
"from fans_dashboard.plotting.plotting import plot_subplots"
5858
]
5959
},

FANS_Dashboard/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "fans-dashboard"
7-
version = "0.4.3"
7+
version = "0.5.0"
88
requires-python = ">=3.9"
99
dependencies = [
1010
"numpy",

README.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,9 @@ FANS requires a JSON input file specifying the problem parameters. Example input
175175
### Problem Type and Material Model
176176
177177
```json
178+
"problem_type": "mechanical",
178179
"matmodel": "LinearElasticIsotropic",
180+
"strain_type": "small",
179181
"material_properties": {
180182
"bulk_modulus": [62.5000, 222.222],
181183
"shear_modulus": [28.8462, 166.6667]
@@ -185,20 +187,24 @@ FANS requires a JSON input file specifying the problem parameters. Example input
185187
- `problem_type`: This defines the type of physical problem you are solving. Common options include `thermal` problems and `mechanical` problems.
186188
- `matmodel`: This specifies the material model to be used in the simulation. Examples include
187189
188-
- `LinearThermalIsotropic` for linear isotropic conductive material model
189-
- `LinearThermalTriclinic` for linear triclinic conductive material model
190-
- `GBDiffusion` for diffusion model with transversely isotropic grain boundary and isotropic bulk for polycrystalline materials
190+
- `LinearThermalIsotropic` for linear isotropic conductive material model.
191+
- `LinearThermalTriclinic` for linear triclinic conductive material model.
192+
- `GBDiffusion` for diffusion model with transversely isotropic grain boundary and isotropic bulk for polycrystalline materials.
191193
192-
- `LinearElasticIsotropic` for linear isotropic elastic material model
193-
- `LinearElasticTriclinic` for linear triclinic elastic material model
194-
- `PseudoPlasticLinearHardening` / `PseudoPlasticNonLinearHardening` for plasticity mimicking model with linear/nonlinear hardening
194+
- `LinearElasticIsotropic` for linear isotropic elastic material model.
195+
- `LinearElasticTriclinic` for linear triclinic elastic material model.
196+
- `PseudoPlasticLinearHardening` / `PseudoPlasticNonLinearHardening` for plasticity mimicking model with linear/nonlinear hardening.
195197
- `J2ViscoPlastic_LinearIsotropicHardening` / `J2ViscoPlastic_NonLinearIsotropicHardening` for rate-independent / dependent J2 plasticity model with kinematic and linear/nonlinear isotropic hardening.
198+
- `SaintVenantKirchhoff` for the hyperelastic Saint Venant-Kirchhoff material model.
199+
- `CompressibleNeoHookean` for the compressible Neo-Hookean material model.
196200
201+
- `strain_type`: This indicates whether the problem is formulated using infinitesimal (`small`) strain or finite (`large`) strain theory.
197202
- `material_properties`: This provides the necessary material parameters for the chosen material model. For thermal problems, you might specify `conductivity`, while mechanical problems might require `bulk_modulus`, `shear_modulus`, and more properties for advanced material models. These properties can be defined as arrays to represent multiple phases within the microstructure.
198203
199204
### Solver Settings
200205
201206
```json
207+
"FE_type": "HEX8",
202208
"method": "cg",
203209
"error_parameters":{
204210
"measure": "Linfinity",
@@ -208,6 +214,10 @@ FANS requires a JSON input file specifying the problem parameters. Example input
208214
"n_it": 100,
209215
```
210216
217+
- `FE_type`: This specifies the type of finite element to be used. Common options include:
218+
- `HEX8`: Standard trilinear hexahedral elements with full integration (8 Gauss points). Suitable for most problems but may exhibit volumetric locking for nearly incompressible materials (Poisson's ratio ~ 0.5).
219+
- `BBAR`: B-bar elements with selective reduced integration to mitigate volumetric locking. Recommended for materials with high Poisson's ratios (0.4 to 0.5).
220+
- `HEX8R`: Reduced integration elements with a single Gauss point at the element center. Use with caution as they may lead to hourglassing and less accurate results.
211221
- `method`: This indicates the numerical method to be used for solving the system of equations. `cg` stands for the Conjugate Gradient method, and `fp` stands for the Fixed Point method.
212222
- `error_parameters`: This section defines the error parameters for the solver. Error control is applied to the finite element nodal residual of the problem.
213223
- `measure`: Specifies the norm used to measure the error. Options include `Linfinity`, `L1`, or `L2`.
@@ -234,9 +244,10 @@ FANS requires a JSON input file specifying the problem parameters. Example input
234244
],
235245
```
236246
237-
- `macroscale_loading`: This defines the external loading applied to the microstructure. It is an array of arrays, where each sub-array represents a loading condition applied to the system. The format of the loading array depends on the problem type:
238-
- For `thermal` problems, the array typically has 3 components, representing the temperature gradients in the $x$, $y$, and $z$ directions.
239-
- For `mechanical` problems, the array must have 6 components, corresponding to the components of the strain tensor in Mandel notation (e.g., $[\varepsilon_{11}, \varepsilon_{22}, \varepsilon_{33}, \sqrt{2}\varepsilon_{12}, \sqrt{2}\varepsilon_{13}, \sqrt{2}\varepsilon_{23}]$).
247+
- `macroscale_loading`: This defines the external loading applied to the microstructure. It is an array of arrays, where each sub-array represents a load path applied to the system. The format of the load path depends on the problem type:
248+
- For `thermal` problems, the array typically has 3 components, representing the temperature gradients in the $x$, $y$, and $z$ directions.
249+
- For `small` strain `mechanical` problems, the array must have 6 components, corresponding to the components of the strain tensor in Mandel notation (e.g., $[\varepsilon_{11}, \varepsilon_{22}, \varepsilon_{33}, \sqrt{2}\varepsilon_{12}, \sqrt{2}\varepsilon_{13}, \sqrt{2}\varepsilon_{23}]$).
250+
- For `large` strain `mechanical` problems, the array must have 9 components, corresponding to the deformation gradient tensor components (e.g., $[F_{11}, F_{12}, F_{13}, F_{21}, F_{22}, F_{23}, F_{31}, F_{32}, F_{33}]$).
240251
241252
In the case of path/time-dependent loading, as shown, for example, in plasticity problems, the `macroscale_loading` array can include multiple steps with corresponding loading conditions.
242253
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Minimal LSAN suppression file to expose FANS code memory leaks
2+
3+
# OpenMPI initialization - essential for MPI programs
4+
leak:libopen-rte.so*
5+
leak:libmpi.so*
6+
7+
# hwloc topology detection - essential for parallel programs
8+
leak:libhwloc.so*
9+
10+
# AddressSanitizer itself - not application bugs
11+
leak:libasan.so*

include/LargeStrainMechModel.h

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#ifndef LARGESTRAINMECHMODEL_H
2+
#define LARGESTRAINMECHMODEL_H
3+
4+
#include "matmodel.h"
5+
6+
/**
7+
* @brief Base class for large strain mechanical material models
8+
* This class provides the kinematic framework for finite deformation mechanics.
9+
* Derived classes only need to implement the constitutive response (S from E).
10+
*/
11+
class LargeStrainMechModel : public Matmodel<3, 9> {
12+
public:
13+
LargeStrainMechModel(const Reader &reader)
14+
: Matmodel(reader)
15+
{
16+
Construct_B();
17+
}
18+
19+
protected:
20+
// ============================================================================
21+
// Kinematic helper functions
22+
// ============================================================================
23+
24+
/**
25+
* @brief Extract deformation gradient from eps vector at Gauss point
26+
* @param i Index in eps array (should be n_str * gauss_point)
27+
* @return 3×3 deformation gradient matrix F
28+
*/
29+
inline Matrix3d extract_F(int i) const
30+
{
31+
Matrix3d F;
32+
F << eps(i), eps(i + 1), eps(i + 2),
33+
eps(i + 3), eps(i + 4), eps(i + 5),
34+
eps(i + 6), eps(i + 7), eps(i + 8);
35+
return F;
36+
}
37+
/**
38+
* @brief Store 1st Piola-Kirchhoff stress in sigma array
39+
* @param i Index in sigma array (should be n_str * gauss_point)
40+
* @param P 3×3 1st Piola-Kirchhoff stress tensor
41+
*/
42+
inline void store_P(int i, const Matrix3d &P)
43+
{
44+
sigma(i) = P(0, 0);
45+
sigma(i + 1) = P(0, 1);
46+
sigma(i + 2) = P(0, 2);
47+
sigma(i + 3) = P(1, 0);
48+
sigma(i + 4) = P(1, 1);
49+
sigma(i + 5) = P(1, 2);
50+
sigma(i + 6) = P(2, 0);
51+
sigma(i + 7) = P(2, 1);
52+
sigma(i + 8) = P(2, 2);
53+
}
54+
55+
inline Matrix3d compute_C(const Matrix3d &F) const
56+
{
57+
return F.transpose() * F; // C = F^T F
58+
}
59+
inline Matrix3d compute_E(const Matrix3d &C) const
60+
{
61+
return 0.5 * (C - Matrix3d::Identity()); // E = 0.5 * (C - I)
62+
}
63+
inline Matrix3d compute_E_from_F(const Matrix3d &F) const
64+
{
65+
return compute_E(compute_C(F)); // E = 0.5 * (F^T F - I)
66+
}
67+
inline Matrix3d push_forward(const Matrix3d &F, const Matrix3d &S) const
68+
{
69+
return F * S; // P = F S
70+
}
71+
72+
// ============================================================================
73+
// Virtual functions for derived material models to implement
74+
// ============================================================================
75+
76+
/**
77+
* @brief Compute 2nd Piola-Kirchhoff stress and material tangent C = dS/dE from deformation gradient
78+
*
79+
* This is the core constitutive function that derived classes must implement.
80+
* It should compute S based on the material's constitutive law.
81+
* @param F Deformation gradient (3×3)
82+
* @param mat_index Material index
83+
* @param element_idx Element index
84+
* @return 2nd Piola-Kirchhoff stress S (symmetric 3×3)
85+
* @return the 6×6 material tangent C = dS/dE in Mandel notation: Ordering: (11, 22, 33, sqrt(2)·12, sqrt(2)·13, sqrt(2)·23)
86+
*/
87+
virtual Matrix3d compute_S(const Matrix3d &F, int mat_index, ptrdiff_t element_idx) = 0;
88+
virtual Matrix<double, 6, 6> compute_material_tangent(const Matrix3d &F, int mat_index) = 0;
89+
90+
/**
91+
* @brief Convert material tangent C (dS/dE) to spatial tangent A (dP/dF)
92+
*
93+
* Computes the spatial tangent dP/dF from the material tangent dS/dE.
94+
*
95+
* The full expression is:
96+
* dP_iJ/dF_kL = δ_ik S_LJ + F_iM * dS_MJ/dE_PQ * dE_PQ/dF_kL
97+
* where:
98+
* dE_PQ/dF_kL = 0.5 * (F_kP δ_QL + F_kQ δ_PL)
99+
*
100+
* @param F Deformation gradient (3×3)
101+
* @param S 2nd Piola-Kirchhoff stress (3×3 symmetric)
102+
* @param C_mandel Material tangent dS/dE in Mandel notation (6×6)
103+
* @return Spatial tangent A = dP/dF in full notation (9×9)
104+
*/
105+
inline Matrix<double, 9, 9> compute_spatial_tangent(const Matrix3d &F,
106+
const Matrix3d &S,
107+
const Matrix<double, 6, 6> &C_mandel) const
108+
{
109+
Matrix<double, 9, 9> A = Matrix<double, 9, 9>::Zero();
110+
111+
// Mandel to tensor index mapping
112+
int mandel_to_ij[6][2] = {{0, 0}, {1, 1}, {2, 2}, {0, 1}, {0, 2}, {1, 2}};
113+
114+
// Compute A_iJkL = dP_iJ/dF_kL
115+
for (int i = 0; i < 3; ++i) {
116+
for (int J = 0; J < 3; ++J) {
117+
int row = 3 * i + J; // Index for P_iJ
118+
119+
for (int k = 0; k < 3; ++k) {
120+
for (int L = 0; L < 3; ++L) {
121+
int col = 3 * k + L; // Index for F_kL
122+
123+
// First term: δ_ik S_LJ
124+
if (i == k) {
125+
A(row, col) += S(L, J);
126+
}
127+
128+
// Second term: F_iM * C_MJPQ * dE_PQ/dF_kL
129+
for (int M = 0; M < 3; ++M) {
130+
// Find MJ in Mandel notation
131+
int MJ_mandel = -1;
132+
for (int idx = 0; idx < 6; ++idx) {
133+
if ((mandel_to_ij[idx][0] == M && mandel_to_ij[idx][1] == J) ||
134+
(mandel_to_ij[idx][0] == J && mandel_to_ij[idx][1] == M)) {
135+
MJ_mandel = idx;
136+
break;
137+
}
138+
}
139+
if (MJ_mandel < 0)
140+
continue;
141+
142+
for (int P = 0; P < 3; ++P) {
143+
for (int Q = P; Q < 3; ++Q) { // Q >= P due to symmetry
144+
// Find PQ in Mandel notation
145+
int PQ_mandel = -1;
146+
for (int idx = 0; idx < 6; ++idx) {
147+
if ((mandel_to_ij[idx][0] == P && mandel_to_ij[idx][1] == Q) ||
148+
(mandel_to_ij[idx][0] == Q && mandel_to_ij[idx][1] == P)) {
149+
PQ_mandel = idx;
150+
break;
151+
}
152+
}
153+
if (PQ_mandel < 0)
154+
continue;
155+
156+
// Get C_MJPQ and account for Mandel factors
157+
double C_val = C_mandel(MJ_mandel, PQ_mandel);
158+
if (MJ_mandel >= 3)
159+
C_val /= sqrt(2.0);
160+
if (PQ_mandel >= 3)
161+
C_val /= sqrt(2.0);
162+
163+
// Compute dE_PQ/dF_kL = 0.5 * (F_kP δ_QL + F_kQ δ_PL)
164+
double dE_dF = 0.0;
165+
if (Q == L)
166+
dE_dF += 0.5 * F(k, P);
167+
if (P == L)
168+
dE_dF += 0.5 * F(k, Q);
169+
170+
A(row, col) += F(i, M) * C_val * dE_dF;
171+
}
172+
}
173+
}
174+
}
175+
}
176+
}
177+
}
178+
179+
return A;
180+
}
181+
182+
// ============================================================================
183+
// Standard interface implementation
184+
// ============================================================================
185+
186+
/**
187+
* @brief Compute B matrix for deformation gradient (9×24)
188+
* Returns B_F matrix that relates nodal displacements to F components:
189+
*/
190+
Matrix<double, 9, 24> Compute_B(const double x, const double y, const double z) override;
191+
192+
/**
193+
* @brief Compute stress at Gauss point (implements base class interface)
194+
* This function:
195+
* 1. Extracts F from eps
196+
* 2. Calls compute_S(F) - material model implements this
197+
* 3. Computes P = F S
198+
* 4. Stores P in sigma
199+
*/
200+
void get_sigma(int i, int mat_index, ptrdiff_t element_idx) override final
201+
{
202+
Matrix3d F = extract_F(i); // Extract deformation gradient
203+
Matrix3d S = compute_S(F, mat_index, element_idx); // Material model computes 2nd PK stress from F
204+
Matrix3d P = push_forward(F, S); // Push forward to 1st PK stress
205+
store_P(i, P); // Store in sigma array
206+
}
207+
};
208+
209+
inline Matrix<double, 9, 24> LargeStrainMechModel::Compute_B(const double x, const double y, const double z)
210+
{
211+
Matrix<double, 9, 24> B_F = Matrix<double, 9, 24>::Zero();
212+
Matrix<double, 3, 8> dN = Matmodel<3, 9>::Compute_basic_B(x, y, z);
213+
214+
for (int i = 0; i < 3; ++i) { // Displacement component
215+
for (int J = 0; J < 3; ++J) { // Material coordinate derivative
216+
int row = 3 * i + J; // Row-major: F_iJ
217+
for (int node = 0; node < 8; ++node) {
218+
int col = 3 * node + i; // Column: DOF for u_i at node
219+
B_F(row, col) = dN(J, node);
220+
}
221+
}
222+
}
223+
224+
return B_F;
225+
}
226+
227+
#endif // LARGESTRAINMECHMODEL_H

0 commit comments

Comments
 (0)