Targeting resolutions#

ResolutionSpecs have many attributes that allow them to be targeted.

import shapely

from meshwell.cad import cad
from meshwell.mesh import mesh
from meshwell.polysurface import PolySurface
from meshwell.resolution import ConstantInField, ThresholdField
from meshwell.visualization import plot2D

Filtering by mass#

ResolutionSpecs can be selectively applied given the “mass” of the entity (total lengths of curves, total area of surfaces, total volumes of volumes).

# Create two boxes of different sizes
small_box = shapely.box(0, 0, 1, 1)
large_box = shapely.box(3, 0, 5, 2)

# Combine into multipolygon
multi = shapely.MultiPolygon([small_box, large_box])

# Create polysurface with filtered resolution specs
polysurface = PolySurface(
    polygons=multi,
    physical_name="filtered_boxes",
)

cad(
    entities_list=[polysurface],
    output_file="filtering_model.xao",
)

output_mesh = mesh(
    dim=2,
    input_file="filtering_model.xao",
    output_file="mass_unfiltered.msh",
    default_characteristic_length=2,
)

plot2D(output_mesh, wireframe=True, title="Reference Resolution Example")

output_mesh = mesh(
    dim=2,
    input_file="filtering_model.xao",
    output_file="mass_filtered.msh",
    default_characteristic_length=2,
    resolution_specs={
        "filtered_boxes": [
            # Fine resolution for small curves
            ConstantInField(
                resolution=0.1,
                apply_to="surfaces",
                max_mass=4,  # Only applies to curves with perimeter < 4
            ),
        ],
    },
)


plot2D(output_mesh, wireframe=True, title="Mass-filtered Resolution Example")
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : [  0%] Union                                                                                  
Info    : [ 10%] Union - Performing intersection of shapes                                                                                
Info    : [ 80%] Union - Building splits of containers                                                                                
                                                                                
Info    : Writing 'filtering_model.xao'...
Info    : Done writing 'filtering_model.xao'
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : Reading 'filtering_model.xao'...
Info    : Done reading 'filtering_model.xao'
_images/ffe840e48cccdccaa14eb35cd2576028d3bbd6f8ae91406aca3db2207d382aaf.png
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : Reading 'filtering_model.xao'...
Info    : Done reading 'filtering_model.xao'
_images/b7cafc1551a76b7909c6f24d09f70ba64998d5c390f35987f66400b0f1de8557.png

Filtering the application by sharing/not sharing#

For surfaces/curves/points, the ResolutionSpec can be applied if the entity is touching (or not touching) another entity.

Restricting the evaluation of the field#

Once applied, a field can be restricted in its evaluation to specific entities using the restrict_to parameter. This allows you to control which entities the resolution field affects, even when the field is defined on one entity.

# Create geometry: outer square with two inner squares
large_rect = 20
small_rect = 5

# Create outer square
outer_square = shapely.Polygon(
    [[0, 0], [large_rect, 0], [large_rect, large_rect], [0, large_rect], [0, 0]],
)

# Create smaller square that will be duplicated
inner_square = shapely.Polygon(
    [
        [large_rect / 2 - small_rect / 2, large_rect / 2 - small_rect / 2],
        [large_rect / 2 + small_rect / 2, large_rect / 2 - small_rect / 2],
        [large_rect / 2 + small_rect / 2, large_rect / 2 + small_rect / 2],
        [large_rect / 2 - small_rect / 2, large_rect / 2 + small_rect / 2],
        [large_rect / 2 - small_rect / 2, large_rect / 2 - small_rect / 2],
    ],
)

# Example 1: Field restricted to inner_left only
poly_outer = PolySurface(
    polygons=outer_square,
    mesh_order=2,
    physical_name="outer",
)

poly_left = PolySurface(
    polygons=shapely.affinity.translate(inner_square, xoff=-3.1),
    mesh_order=1,
    physical_name="inner_left",
)

poly_right = PolySurface(
    polygons=shapely.affinity.translate(inner_square, xoff=3.1),
    mesh_order=1,
    physical_name="inner_right",
)

cad(
    entities_list=[poly_outer, poly_left, poly_right],
    output_file="restricted_field_model.xao",
)

output_mesh = mesh(
    dim=2,
    input_file="restricted_field_model.xao",
    output_file="restricted_field_inner_only.msh",
    default_characteristic_length=2,
    resolution_specs={
        "inner_left": [
            ThresholdField(
                sizemin=0.3,
                distmax=10,
                sizemax=1.5,
                apply_to="curves",
                restrict_to=["inner_left"],  # Field only affects inner_left
            )
        ],
    },
)

plot2D(output_mesh, wireframe=True, title="Field Restricted to Inner Left Only")

# Example 2: Field restricted to both inner_left and outer

output_mesh = mesh(
    dim=2,
    input_file="restricted_field_model.xao",
    output_file="restricted_field_inner_and_outer.msh",
    default_characteristic_length=2,
    resolution_specs={
        "inner_left": [
            ThresholdField(
                sizemin=0.3,
                distmax=10,
                sizemax=1.5,
                apply_to="curves",
                restrict_to=[
                    "inner_left",
                    "outer",
                ],  # Field affects both inner_left and outer
            )
        ],
    },
)

plot2D(output_mesh, wireframe=True, title="Field Restricted to Inner Left and Outer")
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : [  0%] Difference                                                                                  
Info    : [ 10%] Difference - Performing intersection of shapes                                                                                
Info    : [ 80%] Difference - Building splits of containers                                                                                
                                                                                
Info    : [  0%] Fragments                                                                                  
Info    : [ 10%] Fragments - Performing intersection of shapes                                                                                
Info    : [ 80%] Fragments - Building splits of containers                                                                                
                                                                                
Info    : [  0%] Fragments                                                                                  
Info    : [ 10%] Fragments - Performing intersection of shapes                                                                                
Info    : [ 80%] Fragments - Building splits of containers                                                                                
                                                                                
Info    : [  0%] Difference                                                                                  
Info    : [ 10%] Difference                                                                                  
Info    : [ 20%] Difference                                                                                  
Info    : [ 30%] Difference                                                                                  
Info    : [ 40%] Difference                                                                                  
Info    : [ 50%] Difference                                                                                  
Info    : [ 60%] Difference                                                                                  
Info    : [ 70%] Difference                                                                                  
Info    : [ 80%] Difference - Making faces                                                                                
Info    : [ 90%] Difference - Adding holes                                                                                
Info    : [  0%] Fragments                                                                                  
Info    : [ 10%] Fragments                                                                                  
Info    : [ 40%] Fragments                                                                                  
Info    : [ 70%] Fragments                                                                                  
Info    : [ 80%] Fragments - Splitting faces                                                                                
                                                                                
Info    : [  0%] Fragments                                                                                  
Info    : [ 10%] Fragments                                                                                  
Info    : [ 40%] Fragments                                                                                  
Info    : [ 70%] Fragments                                                                                  
Info    : [ 80%] Fragments - Splitting faces                                                                                
                                                                                
Info    : Writing 'restricted_field_model.xao'...
Info    : Done writing 'restricted_field_model.xao'
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : Reading 'restricted_field_model.xao'...
Info    : Done reading 'restricted_field_model.xao'
_images/6e791a805501c140d322c9331ab9136c76cf437ee53276024e8c0ab95b613bc6.png
Info    : Clearing all models and views...
Info    : Done clearing all models and views
Info    : Reading 'restricted_field_model.xao'...
Info    : Done reading 'restricted_field_model.xao'
_images/db687b0bd320d488e8668ad932e0fa50096f77cdb2a76d84fe01f78f3a7ac684.png

In the first example, the threshold field only affects the inner_left square, resulting in refined mesh elements only around that entity. In the second example, the field affects both the inner_left square and the outer square, causing mesh refinement to propagate through the outer square as well. The inner_right square maintains the default mesh size in both cases since it’s not included in the restrict_to list.