Skip to content

Sizing Constraints

This page documents the sizing constraint classes for local mesh refinement.

Overview

Sizing constraints define regions where specific element sizes should be used. Multiple constraints can be combined - where they overlap, the minimum size wins.

Sizing Classes

SphereSize

mmgpy.SphereSize dataclass

SphereSize(center: NDArray[float64], radius: float, size: float)

Bases: SizingConstraint

Uniform size within a spherical region.

Parameters

center : array_like Center of the sphere, shape (dim,). radius : float Radius of the sphere. Must be positive. size : float Target edge size within the sphere. Must be positive.

options: show_root_heading: true

BoxSize

mmgpy.BoxSize dataclass

BoxSize(bounds: NDArray[float64], size: float)

Bases: SizingConstraint

Uniform size within a box region.

Parameters

bounds : array_like Box bounds as [[xmin, ymin, zmin], [xmax, ymax, zmax]] for 3D or [[xmin, ymin], [xmax, ymax]] for 2D. size : float Target edge size within the box. Must be positive.

options: show_root_heading: true

CylinderSize

mmgpy.CylinderSize dataclass

CylinderSize(
    point1: NDArray[float64], point2: NDArray[float64], radius: float, size: float
)

Bases: SizingConstraint

Uniform size within a cylindrical region.

Parameters

point1 : array_like First endpoint of cylinder axis, shape (3,). point2 : array_like Second endpoint of cylinder axis, shape (3,). radius : float Radius of the cylinder. Must be positive. size : float Target edge size within the cylinder. Must be positive.

options: show_root_heading: true

PointSize

mmgpy.PointSize dataclass

PointSize(
    point: NDArray[float64], near_size: float, far_size: float, influence_radius: float
)

Bases: SizingConstraint

Distance-based sizing from a point.

Size varies linearly from near_size at the point to far_size at influence_radius distance.

Parameters

point : array_like Reference point, shape (dim,). near_size : float Target size at the reference point. Must be positive. far_size : float Target size at influence_radius distance and beyond. Must be positive. influence_radius : float Distance over which size transitions from near_size to far_size. Must be positive.

options: show_root_heading: true

SizingConstraint (Base Class)

mmgpy.SizingConstraint dataclass

SizingConstraint()

Bases: ABC

Base class for sizing constraints.

compute_sizes abstractmethod

compute_sizes(vertices: NDArray[float64]) -> NDArray[np.float64]

Compute target size at each vertex.

Parameters

vertices : NDArray[np.float64] Vertex coordinates, shape (n_vertices, dim).

Returns

NDArray[np.float64] Target size at each vertex, shape (n_vertices,). Use np.inf for vertices where this constraint doesn't apply.

options: show_root_heading: true

Mesh Methods

All mesh classes have convenience methods for adding sizing constraints:

set_size_sphere

mesh.set_size_sphere(
    center=[0.5, 0.5, 0.5],  # Center of sphere
    radius=0.2,              # Sphere radius
    size=0.01,               # Target edge size
)

set_size_box

mesh.set_size_box(
    bounds=[[0, 0, 0], [0.3, 0.3, 0.3]],  # [[min], [max]]
    size=0.01,
)

set_size_cylinder

# 3D meshes only
mesh.set_size_cylinder(
    point1=[0, 0, 0],    # First axis endpoint
    point2=[0, 0, 1],    # Second axis endpoint
    radius=0.1,          # Cylinder radius
    size=0.01,
)

set_size_from_point

mesh.set_size_from_point(
    point=[0.5, 0.5, 0.5],
    near_size=0.01,       # Size at reference point
    far_size=0.1,         # Size at influence_radius
    influence_radius=0.5,
)

clear_local_sizing

# Remove all sizing constraints
mesh.clear_local_sizing()

get_local_sizing_count

# Check number of active constraints
n = mesh.get_local_sizing_count()

apply_local_sizing

# Manually apply constraints to metric field
mesh.apply_local_sizing()

Utility Functions

mmgpy.sizing.apply_sizing_constraints

apply_sizing_constraints(
    mesh: MmgMesh3D | MmgMesh2D | MmgMeshS,
    constraints: list[SizingConstraint],
    existing_metric: NDArray[float64] | None = None,
) -> None

Apply sizing constraints to a mesh by setting its metric field.

Parameters

mesh : MmgMesh3D | MmgMesh2D | MmgMeshS Mesh to apply sizing to. constraints : list[SizingConstraint] List of sizing constraints. existing_metric : NDArray[np.float64] | None Existing metric field to combine with. If provided, minimum size wins.

options: show_root_heading: true

mmgpy.sizing.compute_sizes_from_constraints

compute_sizes_from_constraints(
    vertices: NDArray[float64], constraints: list[SizingConstraint]
) -> NDArray[np.float64]

Compute combined sizing from multiple constraints.

Multiple constraints are combined by taking the minimum size at each vertex (finest mesh wins).

Parameters

vertices : NDArray[np.float64] Vertex coordinates, shape (n_vertices, dim). constraints : list[SizingConstraint] List of sizing constraints.

Returns

NDArray[np.float64] Combined target size at each vertex, shape (n_vertices,).

options: show_root_heading: true

mmgpy.sizing.sizes_to_metric

sizes_to_metric(sizes: NDArray[float64]) -> NDArray[np.float64]

Convert scalar sizes to metric tensor format.

Parameters

sizes : NDArray[np.float64] Target sizes at each vertex, shape (n_vertices,).

Returns

NDArray[np.float64] Metric field suitable for mesh["metric"], shape (n_vertices, 1).

options: show_root_heading: true

Usage Examples

Basic Usage

import mmgpy

mesh = mmgpy.read("input.mesh")

# Add refinement region
mesh.set_size_sphere(center=[0.5, 0.5, 0.5], radius=0.2, size=0.01)

# Remesh (sizing constraints applied automatically)
result = mesh.remesh(hmax=0.1)

Multiple Regions

# Fine region
mesh.set_size_sphere(center=[0.3, 0.5, 0.5], radius=0.1, size=0.005)

# Medium region
mesh.set_size_box(bounds=[[0.5, 0, 0], [1, 1, 1]], size=0.02)

# Graded region
mesh.set_size_from_point(
    point=[0.8, 0.5, 0.5],
    near_size=0.01,
    far_size=0.05,
    influence_radius=0.3,
)

result = mesh.remesh(hmax=0.1)

Direct Class Usage

from mmgpy import SphereSize, BoxSize
from mmgpy.sizing import apply_sizing_constraints
import numpy as np

mesh = mmgpy.read("input.mesh")

constraints = [
    SphereSize(
        center=np.array([0.5, 0.5, 0.5]),
        radius=0.2,
        size=0.01,
    ),
    BoxSize(
        bounds=np.array([[0, 0, 0], [0.3, 0.3, 0.3]]),
        size=0.02,
    ),
]

apply_sizing_constraints(mesh, constraints)
result = mesh.remesh(hmax=0.1)

Workflow with Validation

import mmgpy

mesh = mmgpy.read("input.mesh")

# Add sizing constraints
mesh.set_size_sphere(center=[0.5, 0.5, 0.5], radius=0.2, size=0.01)

# Check constraint count
print(f"Active constraints: {mesh.get_local_sizing_count()}")

# Preview metric field
mesh.apply_local_sizing()
metric = mesh["metric"]
print(f"Metric sizes: {metric.min():.4f} to {metric.max():.4f}")

# Remesh
result = mesh.remesh(hmax=0.1, verbose=-1)

# Clear for next iteration
mesh.clear_local_sizing()

How Sizing Works

  1. Constraint Definition: Each constraint defines a region and target size
  2. Size Computation: For each vertex, compute size from all constraints
  3. Minimum Selection: Where constraints overlap, minimum size wins
  4. Metric Conversion: Sizes are converted to isotropic metric tensors
  5. Remeshing: MMG uses the metric field to guide remeshing
from mmgpy.sizing import compute_sizes_from_constraints, sizes_to_metric
import numpy as np

# Get vertex coordinates
vertices = mesh.get_vertices()

# Compute sizes from constraints
constraints = [SphereSize(...), BoxSize(...)]
sizes = compute_sizes_from_constraints(vertices, constraints)

# Convert to metric field
metric = sizes_to_metric(sizes)

# Apply to mesh
mesh["metric"] = metric

Tips

  1. Constraint Order: Order doesn't matter - minimum size wins everywhere
  2. Performance: Many constraints have minimal overhead
  3. Clearing: Always clear constraints between different remeshing runs if needed
  4. Debugging: Use apply_local_sizing() to preview the metric field before remeshing