feat(mesh): non conforming vacuum

stroid can now generate non uniformly refined vacuum meshes. Note we still enforce that the stellar domain is fully conforming.
This commit is contained in:
2026-09-09 12:39:27 -04:00
parent 2347ae152f
commit a0421d5ddc
30 changed files with 1641 additions and 133 deletions

122
readme.md
View File

@@ -103,11 +103,11 @@ smoothstep = true
<!-- Table of what these parameters do -->
| Parameter | Description | Default |
|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| refinement_levels | Number of uniform refinement levels to apply to the mesh after generation | 4 |
| refinement_levels | Stellar minimum depth, or uniform depth when vacuum overrides are omitted | 4 |
| order | The polynomial order of the finite elements in the mesh | 3 |
| include_external_domain | Whether to include an external domain extending to r_infinity | true |
| r_core | The radius of the core region of the star | 1.5 |
| r_star | The radius of the star | 5.0 |
| r_core | The radius of the core region of the star | 0.25 |
| r_star | The radius of the star | 1.0 |
| flattening | The flattening factor of the star (0 for spherical, >0 for oblate) | 0 |
| r_infinity | The outer radius of the external domain (if included) | 6.0 |
| r_instability | The radius at which no transformations are applied to the initial topology (to avoid singularities) | 1e-14 |
@@ -123,7 +123,11 @@ smoothstep = true
If no configuration file is provided, stroid will use the default parameters listed above. Further, configuration files
need only include parameters that differ from the defaults, any parameters not specified will use the default values.
need only include parameters that differ from the defaults. For compatibility with older TOML files,
an omitted `core_mapping` uses `"spherified"`, and omitted TMOP controls leave optimization disabled.
Set `core_mapping = "multi_block"` explicitly to use the conditioned mapping in a TOML file.
Default-constructed C++ and Python `MeshConfig` objects select `"multi_block"`; other omitted TOML
geometry fields use the defaults from `MeshConfig`.
### Conditioned core mapping
@@ -148,32 +152,98 @@ build/tools/geometry_quality_experiment --orders 4 --refinements 2 \
--contraction-probe --probe-order 3 --output core_comparison.csv
```
### Nonconforming vacuum refinement
Stroid can keep the star and both ends of the vacuum well resolved while using
coarser elements in the vacuum interior. Refinement is isotropic: each refinement
splits a hexahedron into eight children. Note however that only one geometric polynomial `order` applies
to every region.
```toml
[main]
refinement_levels = 4
vacuum_refinement_levels = 2
# Optional: omitted outer depth inherits refinement_levels (4 here).
# vacuum_outer_refinement_levels = 4
order = 3
include_external_domain = true
core_mapping = "multi_block"
[main.optimization_methods]
tmop = false
smoothstep = true
```
`configs/nonconforming_vacuum.toml` provides a complete example. The three depth
settings are absolute minimum targets measured from the initial block topology:
| Setting | Applies to | Default |
|----------------------------------|------------------------------------------|-----------------------------|
| `refinement_levels` | Core and envelope | `4` |
| `vacuum_refinement_levels` | Vacuum interior | Inherit `refinement_levels` |
| `vacuum_outer_refinement_levels` | Cells touching the vacuum outer boundary | Inherit `refinement_levels` |
Omitting both vacuum overrides preserves uniform generation. Supplying either
activates the local refinement policy and requires `include_external_domain = true`.
All levels must be nonnegative integers.
Stroid enforces that vacuum cells touching the stellar surface match the stellar face subdivision. That is to say that
the inner boundary of the vacuum region is conforming to the outer boundary of the stellar region. Further, the
outer-boundary cells receive the outer target, and automatic grading limits neighboring refinement depths to one level.
This two layer approach is intended to allow for refinement when using compactification maps.
```python
import stroid
cfg = stroid.config.MeshConfig(
refinement_levels=4,
vacuum_refinement_levels=2,
vacuum_outer_refinement_levels=None, # Inherit stellar depth.
order=3,
core_mapping="multi_block",
optimization_methods=stroid.config.OptimizationMethods(tmop=False),
)
mesh = stroid.GenerateMesh(cfg)
features = stroid.stats.MESH_STAT_DEFAULT | stroid.stats.MeshStatFeatures.ELEMENT_COUNT
stats = stroid.stats.ComputeMeshStats(mesh, features)
print(stats.element_counts.vacuum)
print(stats.refinement.vacuum.min_depth, stats.refinement.vacuum.max_depth)
print(stats.refinement.geometry_dofs, stats.refinement.geometry_true_dofs)
print(stats.conformity.conforming, stats.conformity.n_nonconforming_faces)
stroid.IO.SaveStroidMesh(mesh, "graded.stroid")
restored = stroid.IO.LoadStroidMesh("graded.stroid")
stroid.refinement.UniformRefinement(restored, 1)
```
The `UniformRefinement(mesh, n)` function adds `n` levels to every current leaf while preserving the
existing grading, and rebuilds the geometry and exterior coordinate. Note that this means that a non-conforming mesh
that has been Uniformly refined will still be non-conforming, but the refinement will be applied to all leaves.
#### Viewing curved meshes in GLVis
It is important to note --- and potentially confusing if not understood --- that GLVis approximates curved faces with
flat triangles. At a hanging interface, the same subdivision count on a coarse face and its finer neighbors samples the
curved surface at different locations. This can produce apparent gaps even when the finite-element face transformations
agree. These gaps are not indications that the mesh itself is non-conforming; rather, they are a visualization artifact.
### C++ Interface
Stroid can be used as a library in C++ projects. After installation, include the stroid header and link against the stroid library.
A basic example of using stroid in C++ is shown below (note that you will need a glvis instance running on localhost:19916 to visualize the mesh):
```c++
#include <memory>
#include "mfem.hpp"
#include "stroid/config/config.h"
#include "stroid/IO/mesh.h"
#include "stroid/topology/curvilinear.h"
#include "stroid/topology/topology.h"
#include "fourdst/config/config.h"
#include "stroid/stroid.h"
int main() {
const fourdst::config::Config<stroid::config::MeshConfig> cfg;
stroid::config::MeshConfig cfg;
cfg.refinement_levels = 4;
cfg.vacuum_refinement_levels = 2;
cfg.optimization_methods = stroid::config::OptimizationMethods{false, true};
const std::unique_ptr<mfem::Mesh> mesh = stroid::topology::BuildSkeleton(cfg);
stroid::topology::Finalize(*mesh, cfg);
stroid::topology::PromoteToHighOrder(*mesh, cfg);
stroid::topology::ProjectMesh(*mesh, cfg);
stroid::topology::OptimizeMesh(*mesh, cfg);
stroid::IO::ViewMesh(*mesh, "Spheroidal Mesh", stroid::IO::VISUALIZATION_MODE::BOUNDARY_ELEMENT_ID);
auto mesh = stroid::GenerateMesh(cfg);
stroid::IO::SaveStroidMesh(mesh, "graded.stroid");
stroid::IO::ViewMesh(mesh, "Spheroidal Mesh", stroid::IO::VISUALIZATION_MODE::ELEMENT_ID, "localhost", 19916);
}
```
@@ -184,8 +254,12 @@ An example mesh with the default configuration parameters is shown below (colora
The legacy spherified core mapping strategy is shown below as well
![Example Spheried Mesh](assets/imgs/ExampleMesh_spherified.png)
Note that both of these meshes are shown with 3 levels of refinement and polynomial order 3. Blue shows the stellar
domain while purple shows the vacuum domain.
An example of a non-conforming mesh generated with stroid. Note that the gaps between elements are a visualization artifact
rather than true gaps within the mesh.
![Non Conforming Mesh](assets/imgs/ExampleMesh_NC.png)
Note that both of these meshes are shown with 3 levels of refinement and polynomial order 3. Blue shows the core
domain, yellow shows the envelope domain, while purple shows the vacuum domain.
## Funding