Closed krober10nd closed 3 years ago
I've rethought the multiscale technique the last couple days. Now the approach is hopefully simpler and avoids any significant modification of the generate_mesh
routine or API to build meshes.
The merging operation still is buggy and needs work and we need proper tests.
Here are some key notes:
A multiscale_sizing_function
https://github.com/CHLNDDEV/oceanmesh/blob/4d25f4dc132fa61377f42c804de78635267f6214/oceanmesh/edgefx.py#L221 is generated which consists of looping over each individual function and taking the minimum value at all points in the domain. The inner nests are smoothed into the outer ones using an inverse distance weighting approach in lieu of grading the entire thing as we had done previously. Further, now there is more control regarding how the nests get blended into the parent domain as compared to the Matlab version.
A multiscale_signed_distance_function
https://github.com/CHLNDDEV/oceanmesh/blob/4d25f4dc132fa61377f42c804de78635267f6214/oceanmesh/signed_distance_function.py#L177 is created. Here there were some significant improvements by leveraging signed distance function operations (see https://github.com/CHLNDDEV/oceanmesh/blob/4d25f4dc132fa61377f42c804de78635267f6214/oceanmesh/signed_distance_function.py#L97) . For instance, the parent domain is defined as the union of all signed distance functions and the nests are defined as the difference of the domain and all the subsequent nests (this assumes the domains are listed in order of descending minimum mesh sizes).
The user calls generate_multiscale_mesh
https://github.com/CHLNDDEV/oceanmesh/blob/4d25f4dc132fa61377f42c804de78635267f6214/oceanmesh/mesh_generator.py#L83 to build the multiscale mesh, which is a thin wrapper for generate_mesh
by passing a list of signed distance functions and a list of edge length functions. The function loops over each domain and edge function and generates a mesh sequentially. In this way, we reuse a lot of code and don't introduce any logic to handle the multiscale case inside generate_mesh
. This operation of generating the nests sequentially could be parallelized whereby each domain is sent to a thread, but that would be future work. Afterwards, a merging step takes place by hot starting the mesh generation with the combination of all points from all the domains and using the parents' domain and sizing function.
import numpy as np
import oceanmesh as om
fname1 = "gshhg-shp-2.3.7/GSHHS_shp/f/GSHHS_f_L1.shp"
bbox1, min_edge_length1 = (-75.000, -70.001, 40.0001, 41.9000), 1e3
bbox2, min_edge_length2 = (
np.array(
[
[-74.25, 40.5],
[-73.75, 40.55],
[-73.75, 41],
[-74, 41],
[-74.25, 40.5],
]
),
250.0,
)
s1 = om.Shoreline(fname1, bbox1, min_edge_length1)
sdf1 = om.signed_distance_function(s1)
el1 = om.distance_sizing_function(s1, max_edge_length=5e3)
s2 = om.Shoreline(fname1, bbox2, min_edge_length2)
sdf2 = om.signed_distance_function(s2)
el2 = om.distance_sizing_function(s2)
points, cells = om.generate_multiscale_mesh([sdf1, sdf2], [el1, el2], plot=5)
om.plot_mesh(points, cells, pause=9999)
Per the original om, this PR aims to replicate the so-called "multiscale" meshing functionality.
[x] Project sizing functions and smooth sizing transitions between nests (see
edgefx.create_multiscale
).[x] Loop over all instances of
signed_distance_functions
implicitly creating a new level set representing all domains.[x] Form initial point set in accordance with multiscale domain.
[x] Testing
For the third item in the list above, perhaps the
generate_mesh
function could detect the domain is "multiscale" through thesigned_distance_function
object and call a modified initial point generator?