{"id":17037047,"url":"https://github.com/bast/smeshing","last_synced_at":"2025-04-12T13:21:06.022Z","repository":{"id":53535424,"uuid":"88661878","full_name":"bast/smeshing","owner":"bast","description":"Mesh generator for unstructured triangular grids.","archived":false,"fork":false,"pushed_at":"2021-03-25T21:42:09.000Z","size":3684,"stargazers_count":11,"open_issues_count":6,"forks_count":2,"subscribers_count":2,"default_branch":"cpp-version","last_synced_at":"2025-03-26T07:51:18.792Z","etag":null,"topics":["delaunay","grid","mesh"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bast.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"COPYING.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-18T19:20:08.000Z","updated_at":"2024-08-30T11:28:23.000Z","dependencies_parsed_at":"2022-09-21T03:50:24.287Z","dependency_job_id":null,"html_url":"https://github.com/bast/smeshing","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bast%2Fsmeshing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bast%2Fsmeshing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bast%2Fsmeshing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bast%2Fsmeshing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bast","download_url":"https://codeload.github.com/bast/smeshing/tar.gz/refs/heads/cpp-version","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248571836,"owners_count":21126522,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["delaunay","grid","mesh"],"created_at":"2024-10-14T08:52:45.821Z","updated_at":"2025-04-12T13:21:06.002Z","avatar_url":"https://github.com/bast.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":".. image:: https://travis-ci.org/bast/smeshing.svg?branch=master\n   :target: https://travis-ci.org/bast/smeshing/builds\n\n.. image:: https://coveralls.io/repos/github/bast/smeshing/badge.svg?branch=master\n   :target: https://coveralls.io/github/bast/smeshing?branch=master\n\n.. image:: https://img.shields.io/badge/license-%20GPL--v3.0-blue.svg\n   :target: https://github.com/bast/smeshing/blob/master/LICENSE\n\n.. image:: https://zenodo.org/badge/88661878.svg\n   :target: https://zenodo.org/badge/latestdoi/88661878\n\n\nSimple mesh generator in Python (fork of PyDistMesh)\n====================================================\n\n.. image:: img/example.jpg\n\nThis version of the code is based on\n`PyDistMesh \u003chttps://github.com/bfroehle/pydistmesh\u003e`__ developed by\n`Bradley M. Froehle \u003chttps://github.com/bfroehle\u003e`__. This code\ngenerates unstructured triangular meshes using signed\ndistance functions. Like\n`DistMesh \u003chttp://persson.berkeley.edu/distmesh/\u003e`__ and\n`PyDistMesh \u003chttps://github.com/bfroehle/pydistmesh\u003e`__ upon which this\nwork is based, this code is distributed under the `GNU\nGPL \u003c../master/LICENSE\u003e`__.\n\n**I am in the process of rewriting this code to Rust**: https://github.com/bast/smeshing-rs\n\n.. contents:: Table of contents\n\n\nNice things about this code\n---------------------------\n\n-  Individual components live in separate libraries.\n-  A lot of effort was invested in avoiding quadratic scaling.\n-  Optimization is fully relaxed.\n-  Delaunay is performed at every step.\n-  Good memory profile (hopefully, please report if not).\n-  Gives the user a lot of flexibility to define a distance-dependent resolution.\n\n\nKnown issues\n------------\n\n-  Code uses shared-memory parallelization but the load leveling is not\n   optimal and the scaling has not been studied in detail.\n\n\nRecommended citation\n--------------------\n\nIf you use this code in a program or publication, please cite the following references:\n\nThe algorithm:\n- `P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB, SIAM\n  Review, Volume 46 (2), pp. 329-345, June\n  2004 \u003chttp://persson.berkeley.edu/distmesh/persson04mesh.pdf\u003e`__\n\nThe present code::\n\n  @misc{smeshing,\n    author    = {Bast, Radovan},\n    title     = {Smeshing: Mesh generator for unstructured triangular grids},\n    month     = {4},\n    year      = {2020},\n    publisher = {Zenodo},\n    version   = {v0.2.0},\n    doi       = {10.5281/zenodo.3774421},\n    url       = {https://doi.org/10.5281/zenodo.3774421}\n  }\n\n\nReferences\n----------\n\nThe DistMesh algorithm is described in the following two references:\n\n- `P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB, SIAM\n  Review, Volume 46 (2), pp. 329-345, June\n  2004 \u003chttp://persson.berkeley.edu/distmesh/persson04mesh.pdf\u003e`__\n- `P.-O. Persson, Mesh Generation for Implicit Geometries, Ph.D.\n  thesis, Department of Mathematics, MIT, Dec\n  2004 \u003chttp://persson.berkeley.edu/thesis/persson-thesis-color.pdf\u003e`__\n\n\nInstallation\n============\n\nInstallation using virtualenv\n-----------------------------\n\n::\n\n  virtualenv venv\n  source venv/bin/activate\n\n  pip install --process-dependency-links git+https://github.com/bast/smeshing.git\n\n  smesh --help\n\n\nInstalling dependencies for development\n---------------------------------------\n\n::\n\n  virtualenv venv\n  source venv/bin/activate\n  pip install -r requirements.txt\n\n\nInstallation on the `Stallo \u003chttps://www.sigma2.no/content/stallo\u003e`__ supercomputer\n-----------------------------------------------------------------------------------\n\n.. code-block:: bash\n\n  #!/bin/bash\n\n  #SBATCH --account=your-account\n  #SBATCH --job-name=install\n  #SBATCH --ntasks=1\n  #SBATCH --time=0-01:00:00\n  #SBATCH --partition short\n  #SBATCH --mem-per-cpu=1000MB\n  #SBATCH --mail-type=ALL\n\n  module purge\n  module load foss/2016b\n  module load Python/3.5.2-foss-2016b\n  module load CMake/3.7.1-foss-2016b\n  module load libffi/3.2.1-foss-2016b\n\n  cd ${SLURM_SUBMIT_DIR}\n\n  python3 -m venv venv\n  source venv/bin/activate\n\n  python --version\n\n  export CC=gcc\n  export CXX=g++\n  export FC=gfortran\n\n  pip install --process-dependency-links git+https://github.com/bast/smeshing.git\n\n\nRunning tests\n-------------\n\n::\n\n    py.test -vv smeshing/*.py\n\n\nHow to run the code\n===================\n\n\nLaunching the code\n------------------\n\nThe code is launched using the ``smesh`` script. Example::\n\n  $ smesh --boundary=/home/user/smeshing/data/happy-bear/boundary.txt \\\n          --islands=/home/user/smeshing/data/happy-bear/islands.txt \\\n          --config=/home/user/smeshing/data/happy-bear/config.yml \\\n          --output=data.txt\n\nFor an explanation of the options try::\n\n  $ smesh --help\n\n  Usage: smesh [OPTIONS]\n\n  Options:\n    --boundary TEXT           File containing boundary data.\n    --islands TEXT            Island file names (it is possible to use\n                              wildcards).\n    --resolution-fields TEXT  File name(s) containing resolution fields (it is\n                              possible to use wildcards).\n    --config TEXT             Read configuration from this file.\n    --output TEXT             Write output to this file.\n    --restart TEXT            Restart from this file.\n    --help                    Show this message and exit.\n\nYou can take the files here as a starting point: https://github.com/bast/smeshing/tree/master/data/happy-bear\n\n\nExample run script for the `Stallo \u003chttps://www.sigma2.no/content/stallo\u003e`__ supercomputer\n------------------------------------------------------------------------------------------\n\n.. code-block:: bash\n\n  #!/bin/bash\n\n  #SBATCH --account=your-account\n  #SBATCH --job-name=smesh\n  #SBATCH --nodes=1\n  #SBATCH --ntasks-per-node=20\n  #SBATCH --exclusive\n  #SBATCH --time=0-00:10:00\n  #SBATCH --partition short\n  #SBATCH --mem-per-cpu=500MB\n  #SBATCH --mail-type=ALL\n\n  # load a couple of modules\n  module purge\n  module load foss/2016b\n  module load Python/3.5.2-foss-2016b\n  module load libffi/3.2.1-foss-2016b\n\n  # use all available threads for shared-memory parallelization\n  export OMP_NUM_THREADS=${SLURM_TASKS_PER_NODE}\n\n  # compile the custom functions\n  cd ${SLURM_SUBMIT_DIR}\n  g++ -O3 -shared -fpic custom_functions.cpp -o libcustom_functions.so\n\n  # this will define the custom functions for the meshing code\n  export LD_PRELOAD=${SLURM_SUBMIT_DIR}/libcustom_functions.so\n\n  # load the virtual environment that contains the installation\n  source /home/user/smeshing/venv/bin/activate\n\n  # start the actual code\n  smesh --boundary=${SLURM_SUBMIT_DIR}/boundary.txt \\\n        --islands=${SLURM_SUBMIT_DIR}/islands.txt \\\n        --config=${SLURM_SUBMIT_DIR}/config.yml \\\n        --output=${SLURM_SUBMIT_DIR}/data.txt\n\n  exit 0\n\n\nHow to provide polygon data for the boundary and islands\n--------------------------------------------------------\n\nBoundary polygon data has to be in a separate file from island data but both are given\nin the same format. Island data polygons can be all in one file, or in multiple files.\nEach polygon starts with one line specifying the number of points, followed by the polygon points,\neach point in one line. First and last point of the polygon have the same coordinates.\n\nAs an example, this file contains two polygons, one with 5 points, one with 4 points::\n\n  5\n  0.0 0.0\n  1.0 0.0\n  1.0 1.0\n  0.0 1.0\n  0.0 0.0\n  4\n  5.0 0.0\n  6.0 0.0\n  6.0 1.0\n  5.0 0.0\n\nIt would be equally fine to split this file into two files if you prefer.\n\n\nConfiguration\n-------------\n\nConfiguration is given in YAML format. You can name the configuration file as\nyou like, for instance ``config.yml``.  The order of keywords does not matter\nand you can add comments as in this example:\n\n.. code-block:: yaml\n\n  # number of grid points\n  num_grid_points: 5000\n\n  # number of all boundary and coastline interpolation points\n  # these will not be part of the grid points\n  # instead of num_interpolation_points you can also provide\n  # interpolation_step_length using the same units as the coordinates of your data\n  num_interpolation_points: 1000\n\n  # number of iterations\n  num_iterations: 100\n\n\nRestart\n-------\n\nIt is possible to restart a calculation if you provide\n``--restart=/path/to/restart/file``.\n\n\nHow is the resolution computed?\n===============================\n\nThe resolution is computed as minimum of the resolution function and the\noptional resolution field (below). But this needs some explanation and background\nso let's start simple:\n\nOne approach would be to define the resolution as the distance to islands and the boundary\nbut this would lead to a couple of problems:\n\n-  Resolution would decrease to zero close to polygons and lead to numerical problems.\n-  We would see many grid points at the boundary.\n-  We would treat the entire coastline and all islands on the same footing but perhaps some portions\n   are scientifically more interesting and require a finer mesh than others?\n\nSo we decided to make two improvements:\n\n-  We wanted to be able to make some polygon points more \"attractive\" for a finer mesh than others. For this we\n   made it possible to define islands not only as points with x and y coordinates but also to give a coefficient\n   which we can use in the resolution function. For this we introduced function *g*. This function also allows\n   to cap the minimum to avoid zero resolution.\n-  We wanted to make it possible for the resolution function to depend non-linearly on the distance to the nearest\n   coastal point. For this we introduced function *h*.\n\nUser has the possibility to express *g* and *h* and the resolution is defined\nas the sum of both (see below).\n\nOne problem remains: this approach does not allow to have finer grid depending\non local features which are not related to the coastline, such as water depth\nor other local data. For this we introduced the optional resolution field (see\nbelow).\n\nIf the resolution field is provided, the code will take the resolution field\nvalue in the closest point to the reference point, the code will also compute\n*g + h* at the reference point, and use the minimum of both values as\nresolution.\n\n\nHow to express the resolution function\n--------------------------------------\n\nGrid points move depending on forces and forces depend on the resolution. You\nhave to define the resolution yourself by writing a C++ file, compiling it, and\nfeeding it to the meshing algorithm using ``LD_PRELOAD``. To get you started,\nhere is an example ``custom_functions.cpp``:\n\n.. code-block:: cpp\n\n  // provides std::max\n  #include \u003calgorithm\u003e\n\n  // The resolution is expressed as distance using the same (arbitrary)\n  // units as used by the boundary and polygons - this means that\n  // larger resolution number means that points are farther apart.\n\n  // Resolution in point r is defined as min(f(r, p)), where the miminum\n  // is taken over all boundary points p for a particular boundary point p,\n  // f is given as f(r, p) = g(d(r, p)) + h(c_p).\n  // d(r, p) is the distance r to p and function h(c_p) depends on\n  // coefficients c_p of a boundary point p. The number of coefficients\n  // per point and their meaning can be freely specified and interpreted.\n\n  // Below you are asked to specify functions g and h.\n  // You have two restrictions:\n  // 1) You have to respect is that g should not decrease for an increasing d.\n  //    In other words, for an increasing distance the resolution should not\n  //    decrease.\n  // 2) The sum g + h should never become zero since the code will divide by\n  //    the distance.\n\n  // This function only depends on the distance to a boundary point but not\n  // on coefficients at the boundary point.\n  double g_function(const double distance)\n  {\n      // this is to make sure we do not end up with zero distance\n      // and then try to divide by zero later\n      double result = std::max(0.5, distance);\n\n      return result;\n  }\n\n  // The code will give you all coefficients for a point in h_function\n  // and then you can use and combine them freely.\n  double h_function(const double coefficients[])\n  {\n      // in this example we simply return the first coefficient\n      return coefficients[0];\n  }\n\nTo see how this file can be compiled and provided to the meshing script, please\nhave a look at the run script example.\n\n\nAdding resolution fields\n------------------------\n\nSometimes the resolution should not only be dependent on the distance and the boundary\ncoefficients but also on local features. For this you can provide resolution fields\nwith the ``--resolution-fields`` flag. Point it to a file or files that contain the following\nformat::\n\n  N\n  x1 y1 r1\n  x2 y2 r2\n  ...\n  xN yN rN\n\nThe code will then use this field to interpolate a local resolution for each of\nthe resolution fields. The resolution for a grid point is then given as the\nminimum taken over all resolution fields and the distance-dependent resolution\nprovided by ``g_function + h_function``.\n\n\nDesign choices\n==============\n\n\nWhy do we need to provide islands and the boundary separately?\n--------------------------------------------------------------\n\n- We compute view vectors for nearest neighbor polygon points in view. For the boundary\n  they point to the \"inside\". For islands they point to the \"outside\".\n- During the computation we need to figure out whether points are inside or outside of polygons.\n  We want grid points to be inside the boundary but outside islands.\n\n\nPostprocessing\n==============\n\nThe repository contains a tiny script which can be used to plot the generated\ngrid::\n\n    python smeshing/plot.py data/happy-bear/result.txt example.png\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbast%2Fsmeshing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbast%2Fsmeshing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbast%2Fsmeshing/lists"}