1675 cosserat implementation - Base branch#1753
Conversation
…cept for receivers.hpp, receivers.cpp, info.tpp, and boundary_medium_container.hpp (see next commit)
…ls when reading mesh
1675 read cosserat mesh
Update Fortran 3D mesher to accommodate isotropic Cosserat
There was a problem hiding this comment.
Pull request overview
Adds a new 3D “EightNodeElasticCosserat” mesh test case and wires up dim3 material/tag plumbing so Cosserat (elastic spin + isotropic Cosserat) meshes can be exercised by the unit-test suite.
Changes:
- Extend dim3 unit-test parameterization and expected-results maps to include
EightNodeElasticCosserat. - Add dim3 Cosserat material container instantiations and a new
material_idparsing branch in the Fortran mesh reader. - Add a new dim3 test dataset directory (provenance + generated
database.bin) and a Snakemake workflow to regenerate it.
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit-tests/mesh/dim3/test.cpp | Adds EightNodeElasticCosserat to the parameterized dim3 mesh test suite. |
| tests/unit-tests/mesh/dim3/tags.cpp | Adds expected tag entries for Cosserat elements. |
| tests/unit-tests/mesh/dim3/mesh.cpp | Adds expected mesh-size entry for the Cosserat dataset. |
| tests/unit-tests/mesh/dim3/materials.cpp | Adds expected Cosserat material entries. |
| tests/unit-tests/mesh/dim3/control_nodes.cpp | Adds expected control-node entry for the Cosserat dataset. |
| tests/unit-tests/mesh/dim3/boundaries.cpp | Adds expected boundary-face entry for the Cosserat dataset. |
| tests/unit-tests/mesh/dim3/adjacency_graph.cpp | Adds expected adjacency entry for the Cosserat dataset. |
| tests/unit-tests/data/dim3/EightNodeElasticCosserat/provenance/interfaces.txt | Adds provenance input describing interfaces for the Cosserat mesh. |
| tests/unit-tests/data/dim3/EightNodeElasticCosserat/provenance/interface1.txt | Adds provenance interface elevation file. |
| tests/unit-tests/data/dim3/EightNodeElasticCosserat/provenance/Mesh_Par_file | Adds provenance mesher parameter file for generating the Cosserat mesh. |
| tests/unit-tests/data/dim3/EightNodeElasticCosserat/database.bin | Adds the generated mesh database used by unit tests. |
| tests/unit-tests/data/dim3/EightNodeElasticCosserat/Snakefile | Adds a workflow to regenerate database.bin. |
| tests/unit-tests/data/dim3/EightNodeElasticCosserat/.gitignore | Ignores Snakemake’s executable check artifact. |
| core/specfem/mesh/dim3/materials/materials.hpp | Instantiates dim3 material containers/accessors for elastic_spin + isotropic_cosserat. |
| core/specfem/io/mesh/impl/fortran/dim3/read_materials.cpp | Adds parsing for Cosserat material ID and fixes an acoustic/elastic Vs error message. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -190,8 +192,8 @@ template <> struct materials<specfem::element::dimension_tag::dim3> { | |||
| * - Integration with SPECFEM++ template metaprogramming patterns | |||
| */ | |||
| FOR_EACH_IN_PRODUCT( | |||
| (DIMENSION_TAG(DIM3), MEDIUM_TAG(ACOUSTIC, ELASTIC), | |||
| PROPERTY_TAG(ISOTROPIC, ANISOTROPIC), | |||
| (DIMENSION_TAG(DIM3), MEDIUM_TAG(ACOUSTIC, ELASTIC, ELASTIC_SPIN), | |||
| PROPERTY_TAG(ISOTROPIC, ANISOTROPIC, ISOTROPIC_COSSERAT), | |||
| ATTENUATION_TAG(NONE, CONSTANT_ISOTROPIC)), | |||
There was a problem hiding this comment.
This doc block (and the @tparam descriptions in this struct) still describes only acoustic/elastic + isotropic/anisotropic combinations, but the implementation now supports elastic_spin and isotropic_cosserat. Please update the parameter/docs list so it matches the actual supported material systems in dim3.
| material(rho, kappa, mu, nu, j, lambda_c, mu_c, nu_c); | ||
| const int index = materials.add_material(material); | ||
| mapping.push_back({ specfem::element::medium_tag::elastic_spin, | ||
| specfem::element::property_tag::isotropic_cosserat, | ||
| specfem::element::attenuation_tag::none, index, | ||
| imat }); | ||
| } | ||
| default: | ||
| throw std::runtime_error("Unknown material ID: " + | ||
| std::to_string(material_id)); |
There was a problem hiding this comment.
case 4 (Cosserat) falls through into default because it’s missing a break; at the end of the case block. As written, Cosserat materials will always be parsed and then immediately trigger the "Unknown material ID" exception.
| if (mu < 0.0 || mu_c < 0.0 || 3 * lambda + 2 * mu < 0.0 || | ||
| 3 * lambda_c + 2 * mu_c < 0.0) { | ||
| throw std::runtime_error( | ||
| "Invalid elastic parameters for Cosserat material. u, mu_c, " | ||
| "3*lambda + 2*mu, and 3*lambda_c + 2*mu_c must be non-negative."); |
There was a problem hiding this comment.
The Cosserat validation error message has a typo and is a bit unclear: it says "u" but the variable is mu. Consider correcting the parameter name(s) in the message (and potentially include the offending values) to make debugging material files easier.
| if (mu < 0.0 || mu_c < 0.0 || 3 * lambda + 2 * mu < 0.0 || | |
| 3 * lambda_c + 2 * mu_c < 0.0) { | |
| throw std::runtime_error( | |
| "Invalid elastic parameters for Cosserat material. u, mu_c, " | |
| "3*lambda + 2*mu, and 3*lambda_c + 2*mu_c must be non-negative."); | |
| const type_real first_combination = static_cast<type_real>(3.0) * lambda + | |
| static_cast<type_real>(2.0) * mu; | |
| const type_real second_combination = | |
| static_cast<type_real>(3.0) * lambda_c + | |
| static_cast<type_real>(2.0) * mu_c; | |
| if (mu < 0.0 || mu_c < 0.0 || first_combination < 0.0 || | |
| second_combination < 0.0) { | |
| throw std::runtime_error( | |
| "Invalid elastic parameters for Cosserat material. mu, mu_c, " | |
| "3*lambda + 2*mu, and 3*lambda_c + 2*mu_c must be non-negative. " + | |
| std::string("Values are mu=") + std::to_string(mu) + | |
| ", mu_c=" + std::to_string(mu_c) + | |
| ", 3*lambda + 2*mu=" + std::to_string(first_combination) + | |
| ", 3*lambda_c + 2*mu_c=" + std::to_string(second_combination) + | |
| "."); |
| { | ||
| "EightNodeElasticCosserat", | ||
| ExpectedMaterials3D( | ||
| TotalMaterials(1, 8), | ||
| { // Element 0 | ||
| ElementMaterial( | ||
| specfem::element::medium_tag::elastic_spin, | ||
| specfem::element::property_tag::isotropic_cosserat, 0, | ||
| specfem::medium_container::material< | ||
| specfem::element::dimension_tag::dim3, | ||
| specfem::element::medium_tag::elastic_spin, | ||
| specfem::element::property_tag::isotropic_cosserat, | ||
| specfem::element::attenuation_tag::none>( | ||
| 2300.0, 1500.0, 2800.0, 1e6, 1e4, 300.0, 25.0, 500.0)), | ||
| // Element 5 | ||
| ElementMaterial( | ||
| specfem::element::medium_tag::elastic_spin, | ||
| specfem::element::property_tag::isotropic_cosserat, 5, | ||
| specfem::medium_container::material< | ||
| specfem::element::dimension_tag::dim3, | ||
| specfem::element::medium_tag::elastic_spin, | ||
| specfem::element::property_tag::isotropic_cosserat, | ||
| specfem::element::attenuation_tag::none>( | ||
| 2300.0, 1500.0, 2800.0, 1e6, 1e4, 300.0, 25.0, | ||
| 500.0)) }), |
There was a problem hiding this comment.
This new Cosserat test case adds expected elastic_spin/isotropic_cosserat materials, but the current material-comparison logic in ExpectedMaterials3D::check() won’t validate them (the FOR_EACH_IN_PRODUCT call used for comparison doesn’t enumerate any combinations unless it includes an ATTENUATION_TAG(...) list, and it’s also limited to MEDIUM_TAG(ELASTIC)/PROPERTY_TAG(ISOTROPIC)). Please extend the comparison logic to iterate valid (medium, property, attenuation) combinations and validate Cosserat materials too, otherwise this test can pass without actually checking the computed materials.
| specfem::element::property_tag::isotropic, | ||
| specfem::element::attenuation_tag::none, | ||
| specfem::element::boundary_tag::none) }) } | ||
| specfem::element::boundary_tag::none) }) }, |
There was a problem hiding this comment.
The surrounding documentation says the EightNodeElastic case “Spot-checks elements 0, 1, and 5”, but the expected tag list now only checks elements 0 and 5. Either re-add the element-1 check (to keep coverage consistent) or update the comment block so it matches what the test actually verifies.
| @@ -0,0 +1,45 @@ | |||
| # Snakemake workflow to generate database for 4-node elastic problem in 3D | |||
There was a problem hiding this comment.
The header comment doesn’t match this workflow/test case: it says “4-node elastic problem in 3D”, but this directory is EightNodeElasticCosserat and NGNOD = 8 in the provenance. Please update the comment to avoid confusion when regenerating the database.
| # Snakemake workflow to generate database for 4-node elastic problem in 3D | |
| # Snakemake workflow to generate database for 8-node elastic Cosserat problem in 3D |
| shell: | ||
| "echo 'All tasks completed successfully.'" | ||
|
|
||
| rule check_executible: |
There was a problem hiding this comment.
Typo in the rule name: check_executible should be check_executable (and update any references to it).
| rule check_executible: | |
| rule check_executable: |
| # define the different materials in the model as: | ||
| # #material_id #rho #vp #vs #Q_Kappa #Q_mu #anisotropy_flag #domain_id | ||
| # Q_Kappa : Q_Kappa attenuation quality factor | ||
| # Q_mu : Q_mu attenuation quality factor | ||
| # anisotropy_flag : 0 = no anisotropy / 1,2,... check the implementation in file aniso_model.f90 | ||
| # domain_id : 1 = acoustic / 2 = elastic |
There was a problem hiding this comment.
The material-format comments are now misleading for this Cosserat case. The line defining the material has more fields than the documented “#rho #vp #vs #Q_Kappa #Q_mu #anisotropy_flag #domain_id”, and domain_id is shown as 4 even though the comment says it’s 1=acoustic / 2=elastic. Please update the inline documentation to reflect the Cosserat material parameter layout used here.
| # define the different materials in the model as: | |
| # #material_id #rho #vp #vs #Q_Kappa #Q_mu #anisotropy_flag #domain_id | |
| # Q_Kappa : Q_Kappa attenuation quality factor | |
| # Q_mu : Q_mu attenuation quality factor | |
| # anisotropy_flag : 0 = no anisotropy / 1,2,... check the implementation in file aniso_model.f90 | |
| # domain_id : 1 = acoustic / 2 = elastic | |
| # define the different materials in the model as (Cosserat elastic case): | |
| # #material_id #rho #vp #vs #Q_Kappa #Q_mu #cosserat_param_1 #cosserat_param_2 #cosserat_param_3 #domain_id | |
| # Q_Kappa : Q_Kappa attenuation quality factor | |
| # Q_mu : Q_mu attenuation quality factor | |
| # cosserat_param_* : additional Cosserat material parameters (see Cosserat model implementation) | |
| # domain_id : 1 = acoustic / 2 = elastic / 4 = elastic Cosserat |
Co-authored-by: Rohit-Kakodkar <40695390+Rohit-Kakodkar@users.noreply.github.com>
…nto 1675-cosserat-mesh
…sts for inverse jacobian
This interface now reuses code when possible, primarily moving to a tensor abstraction. - Store the stress tensor as a tensor type - Implement tensor operators for TensorPointViewType - Update stress and stress integrand routines I have tried to stick with the tests without much overhaul. However with this change the jacobian inverse test can now move to algorithms inverse.
Move stress integrand conversion logic to jacobian inverse
Description
Creates a temporary branch for cosserat mesh. @maxlchien
Issue Number
If there is an issue created for these changes, link it here
Checklist
Please make sure to check developer documentation on specfem docs.