Feature neo hookean - #4
Conversation
…cs where considered in the same code block. a clear bug. corrected it. added constants to make bc type more clear and coder-friendly
…onduction_Convection and Adiabatic are running into bugs. I need to take a look at it. Commiting this dirty version
…cs where considered in the same code block. a clear bug. corrected it. added constants to make bc type more clear and coder-friendly (NatLabRockies#19) Co-authored-by: SreejithNREL <sreejith.nadakkalappukuttan@nlr.gov>
* corrected bug about temperature bcs. Earlier periodic and adiabatic bcs where considered in the same code block. a clear bug. corrected it. added constants to make bc type more clear and coder-friendly * corrected a bug where in splines were using a wrong stencil for periodic bcs --------- Co-authored-by: SreejithNREL <sreejith.nadakkalappukuttan@nlr.gov>
There was a problem hiding this comment.
Pull request overview
This PR introduces a Neo-Hookean constitutive model into the MPM solver while also updating several preprocessing scripts/configs (notably adding configurable particle density and standardizing some test preprocessing behaviors), and refining temperature boundary-condition handling.
Changes:
- Add Neo-Hookean solid support (constitutive model ID 2) in particle stress update and particle-file parsing.
- Update temperature BC handling and convective BC formulation to use node conductivity-derived Biot number.
- Update multiple test preprocessors/configs (density parameter, HDF5 defaults, auto-tag behavior, cleanup/removal of unused helper functions).
Reviewed changes
Copilot reviewed 26 out of 27 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/Elastic_disk_collision/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/Elastic_disk_collision/PreProcess/config.json | Add density field; update output_tag/build_system metadata. |
| Tests/Dam_Break/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/Dam_Break/PreProcess/config.json | Add density field; update output_tag/build_system metadata. |
| Tests/Dam_Break_With_Obstacles/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers; adjust EB-related inputs. |
| Tests/2D_Heat_Conduction/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/2D_Heat_Conduction/PreProcess/config.json | Add density; switch preprocessing output to HDF5 and enable HDF5 build. |
| Tests/2D_Heat_Conduction_Cylinder_Dirichlet/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/2D_Heat_Conduction_Cylinder_Dirichlet/PreProcess/config.json | Add density field. |
| Tests/1D_Heat_Conduction/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/1D_Heat_Conduction/PreProcess/config.json | Add density; switch preprocessing output to HDF5 and enable HDF5 build. |
| Tests/1D_Heat_Conduction_HeatFlux/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/1D_Heat_Conduction_HeatFlux/PreProcess/config.json | Add density; update build_system/output_tag metadata. |
| Tests/1D_Heat_Conduction_Convective/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/1D_Heat_Conduction_Convective/PreProcess/config.json | Add density; adjust ppc/boundary_conditions; update build_system/output_tag metadata. |
| Tests/1D_Heat_Conduction_Convective/Generate_MPs_and_InputFiles.sh | Update how the preprocessing script is invoked. |
| Tests/1D_Axial_Bar_Vibration/PreProcess/Generate_MPs_Inputfile_Generic.py | Thread density from config into particle generation; remove unused legacy generation/plotting helpers. |
| Tests/1D_Axial_Bar_Vibration/PreProcess/config.json | Add density; switch preprocessing output to HDF5 and enable HDF5 build. |
| Source/utilities.cpp | Simplify Apply_Nodal_BCs_Temperature flow and pass through dirichlet_only to EB temperature BCs. |
| Source/nodal_data_ops.cpp | Use node conductivity-derived Biot number for convective temperature BCs. |
| Source/mpm_specs.H | Map temperature BC strings to named BC constants instead of hard-coded integers. |
| Source/mpm_particle_timestep.cpp | Include constitutive model ID 2 in timestep wave-speed logic. |
| Source/mpm_particle_container.cpp | Add Neo-Hookean constitutive model branch using deformation gradient. |
| Source/mpm_init.cpp | Parse constitutive model ID 2 from particle files and read E/nu for it. |
| Source/constitutive_models.H | Update plane-strain components; add Neo-Hookean stress implementation and supporting tensor helper. |
| Developer_Tools/Run_All_Tests.py | Include density in generated configs; adjust parameter sweep spaces and enable additional sweeps. |
| .gitignore | Ignore Python __pycache__ and sweep output file. |
Suppressed comments (1)
Source/mpm_particle_timestep.cpp:63
- Calculate_time_step() treats constitutive_model==2 (neo-Hookean) like a fluid and computes Cs from Bulk_modulus, but particles with constitutive_model==2 are initialized with Bulk_modulus = 0.0 (see mpm_init.cpp:1072). This makes Cs=0 and can produce an overly large timestep.
if (p.idata(intData::constitutive_model) == 1 or
p.idata(intData::constitutive_model) == 2)
{
Cs = std::sqrt(p.rdata(realData::Bulk_modulus) /
p.rdata(realData::density));
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| 0.0, | ||
| 0.0 | ||
| ], | ||
| "density": 1.0, |
| left_cauchy_green(const amrex::Real F[NCOMP_FULLTENSOR], | ||
| amrex::Real b[NCOMP_TENSOR]) | ||
| { | ||
| constexpr int d = AMREX_SPACEDIM; // stride into F, NOT 3 |
| #if (AMREX_SPACEDIM == 1) | ||
| detF = F[0]; | ||
| #elif (AMREX_SPACEDIM == 2) | ||
| detF = F[0] * F[3] - F[1] * F[2]; |
| * | ||
| * Implements compressible neo-hookean elasticity in 1D, 2D, or 3D depending on | ||
| * AMREX_SPACEDIM. Uses Young’s modulus (E) and Poisson’s ratio (v) to form | ||
| * the constitutive matrix and multiplies it by the strain tensor eps[]. | ||
| * |
| nodal_bcs_temperature( | ||
| geom, nodaldata, specs.bclo_temp.data(), specs.bchi_temp.data(), | ||
| specs.bc_temp_T_wall_lo.data(), specs.bc_temp_T_wall_hi.data(), | ||
| specs.bc_temp_flux_lo.data(), specs.bc_temp_flux_hi.data(), | ||
| specs.bc_temp_h_lo.data(), specs.bc_temp_h_hi.data(), | ||
| specs.bc_temp_Tinf_lo.data(), specs.bc_temp_Tinf_hi.data()); | ||
| compute_udf_temp_at_nodes(geom, specs, t); | ||
| apply_udf_nodal_bcs_temperature(geom, nodaldata, specs); |
| @@ -1 +1 @@ | |||
| python3 ./PreProcess/Generate_MPs_Inputfile_Generic.py --config ./PreProcess/config.json | |||
| python ./PreProcess/Generate_MPs_Inputfile_Generic.py --config ./PreProcess/config.json | |||
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 27 changed files in this pull request and generated 4 comments.
Suppressed comments (5)
Tests/Elastic_disk_collision/PreProcess/config.json:97
- This duplicates the top-level
densitykey already set to997.0on line 73. Python'sjson.loadsilently keeps this later value, so manual preprocessing generates the elastic disks at density1.0instead of the intended997.0. Remove this duplicate entry.
"density": 1.0,
Tests/1D_Heat_Conduction_Convective/Generate_MPs_and_InputFiles.sh:1
- Use
python3here, as the other generator scripts do (for exampleTests/1D_Heat_Conduction/Generate_MPs_and_InputFiles.sh:1). Many supported environments providepython3without apythonalias, so the changed command can fail before preprocessing starts.
python ./PreProcess/Generate_MPs_Inputfile_Generic.py --config ./PreProcess/config.json
Source/utilities.cpp:232
dirichlet_onlyno longer affects configured domain boundaries. On MUSL's first thermal pass (main.cpp:103-104), this now applies heat-flux and convection conditions even though that pass is explicitly Dirichlet-only, before applying the full conditions again on the second pass. Restore the filtered boundary-type arrays when this flag is true.
nodal_bcs_temperature(
geom, nodaldata, specs.bclo_temp.data(), specs.bchi_temp.data(),
specs.bc_temp_T_wall_lo.data(), specs.bc_temp_T_wall_hi.data(),
specs.bc_temp_flux_lo.data(), specs.bc_temp_flux_hi.data(),
specs.bc_temp_h_lo.data(), specs.bc_temp_h_hi.data(),
Source/constitutive_models.H:139
- This out-of-plane component mixes a 3D deviatoric correction (
trace/3) with the in-plane components above, which use the 2D correction (trace/2). Consequently the viscous deviatoric stress is not trace-free, contrary to the documented2μ ε̇_devmodel. Use one consistent 2D convention, or switch all three plane-strain components to the 3D trace correction.
sigma[ZZ] = 2 * dyn_visc * (epsdot[ZZ] - trace_epsdot / 3.0) - pressure;
Source/constitutive_models.H:204
- The new constitutive model has no automated case that selects constitutive-model ID 2 or verifies its stress response; the existing test configurations cover only elastic and fluid models. Add a finite-deformation regression that exercises initialization, CFL calculation, and Neo-Hookean stress in a supported dimension/output format.
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void
neo_hookean(amrex::Real sigma[NCOMP_TENSOR],
const amrex::Real F[NCOMP_FULLTENSOR],
amrex::Real E,
amrex::Real v)
| if (p.idata(intData::constitutive_model) == 1 or | ||
| p.idata(intData::constitutive_model) == 2) | ||
| { | ||
| Cs = std::sqrt(p.rdata(realData::Bulk_modulus) / | ||
| p.rdata(realData::density)); |
| else if (p.idata(intData::constitutive_model) == 2) | ||
| { | ||
| safe_read(ifs, p.rdata(realData::E), "Error reading E"); | ||
| safe_read(ifs, p.rdata(realData::nu), "Error reading nu"); | ||
| p.rdata(realData::Bulk_modulus) = 0.0; |
| matpt_filename = cfg["materialpoint_filename"] | ||
| plot_to_check = cfg["plot_to_check"] | ||
| CFL = cfg["CFL"] | ||
| density = cfg["density"] |
| else if (p.idata(intData::constitutive_model) == 2) | ||
| { | ||
| // Neo-Hookean solid | ||
| neo_hookean(stress, deformation_gradient, | ||
| p.rdata(realData::E), |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 27 changed files in this pull request and generated no new comments.
Suppressed comments (15)
Source/utilities.cpp:229
- When
dirichlet_onlyis true (the first MUSL thermal pass), this now passes the full BC arrays, so heat-flux and convection conditions are applied during the predictor pass and then again during the second pass. Preserve the filtering for domain BCs just asnodal_levelset_bcs_temperaturedoes.
geom, nodaldata, specs.bclo_temp.data(), specs.bchi_temp.data(),
Tests/Elastic_disk_collision/PreProcess/config.json:97
- This file now contains two root-level
densitykeys (997.0 at line 73 and 1.0 here). Python's JSON loader silently keeps the latter, so the elastic-disk particles are generated at density 1.0 instead of the intended 997.0.
"density": 1.0,
Tests/Dam_Break_With_Obstacles/PreProcess/Generate_MPs_Inputfile_Generic.py:1210
- All three obstacle configurations omit
density, so this required lookup raisesKeyErrorbefore particle generation. Add density to every obstacle config or retain the previous 997.0 default here.
density = cfg["density"]
Tests/1D_Heat_Conduction_Convective/Generate_MPs_and_InputFiles.sh:1
- The other test launchers consistently use
python3; changing this one topythonbreaks generation on systems where no unversioned Python executable is installed.
python ./PreProcess/Generate_MPs_Inputfile_Generic.py --config ./PreProcess/config.json
Source/constitutive_models.H:139
- This out-of-plane term uses a 3D
trace/3correction while the in-plane terms above still use the 2Dtrace/2correction. The resulting viscous deviator is not traceless. Keepsigma[ZZ]zero for the existing 2D formulation, or consistently convert all three normal components to a plane-strain 3D formulation.
sigma[ZZ] = 2 * dyn_visc * (epsdot[ZZ] - trace_epsdot / 3.0) - pressure;
Source/constitutive_models.H:204
- The new Neo-Hookean path has no integration or unit test: repository test configurations still select only
elasticorfluid. Add a case that loads model ID 2 and verifies zero stress at identity plus a known finite deformation, so the preprocessing, HDF5/ASCII loading, and constitutive formula are exercised.
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void
neo_hookean(amrex::Real sigma[NCOMP_TENSOR],
const amrex::Real F[NCOMP_FULLTENSOR],
amrex::Real E,
amrex::Real v)
Tests/Elastic_disk_collision/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/Dam_Break/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/Dam_Break_With_Obstacles/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/2D_Heat_Conduction/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/2D_Heat_Conduction_Cylinder_Dirichlet/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/1D_Heat_Conduction/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/1D_Heat_Conduction_HeatFlux/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/1D_Heat_Conduction_Convective/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Tests/1D_Axial_Bar_Vibration/PreProcess/Generate_MPs_Inputfile_Generic.py:1205
- Blank output tags now call
make_auto_tag_from_cfg, but that helper indexes root-levelconstitutive_modelandtemperaturekeys while this script's configs store both underbodies. A blank tag therefore raisesKeyErrorinstead of being generated.
if(output_tag==""):
output_tag = make_auto_tag_from_cfg(cfg)
Neo Hookean constitutive model