Skip to content

Commit

Permalink
Resolve Gmsh issues
Browse files Browse the repository at this point in the history
- Limit Gmsh to < 4.0
  Gmsh 4.0 doesn't partition correctly
  Addresses #697
- Export ghosts with Gmsh 4.x
  [Ghosts are broken](https://gitlab.onelab.info/gmsh/gmsh/issues/733),
  but export them anyway.
- Change refinement metric
- Limit refinements
  Gmsh refinement seems to stall out
- Don't partition tiny meshes
- Tolerate mangled Gmsh version string

  Assume Gmsh 3.0 if we can't parse the useless nonsense
  that Gmsh stuffs into stderr
- Ensure GmshMesh uses correct communicator

  More than one overlap will "downgrade" to a serial communicator
  because Gmsh doesn't give us more than one layer of ghosts
  • Loading branch information
guyer committed Jan 27, 2020
1 parent 5ddeb08 commit 4571de9
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 14 deletions.
5 changes: 3 additions & 2 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ install:
- cmd: conda.exe config --add channels conda-forge

# Configure the VM.
- cmd: if "%TARGET_ARCH%" == "x64" if "%CONDA_PY%" == "27" conda.exe install --quiet --name root --only-deps python=2.7 fipy
- cmd: if "%TARGET_ARCH%" == "x64" if "%CONDA_PY%" == "36" conda.exe install --quiet --name root --only-deps python=3.6 fipy
- cmd: if "%TARGET_ARCH%" == "x64" if "%CONDA_PY%" == "27" conda.exe install --quiet --name root python=2.7 fipy
- cmd: if "%TARGET_ARCH%" == "x64" if "%CONDA_PY%" == "36" conda.exe install --quiet --name root python=3.6 fipy "gmsh<4.0"
- cmd: conda.exe remove --quiet --force fipy
# FIXME: fipy recipe on conda-forge doesn't have gmsh compatible with Python 2.7
- ps: |
$ErrorActionPreference = "Stop";
Expand Down
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ commands:
- run:
name: Create Conda Environment
command: |
conda create -v --quiet --prefix << parameters.condaenv >> --show-channel-urls --channel conda-forge --only-deps << parameters.packages >>
conda create -v --quiet --prefix << parameters.condaenv >> --show-channel-urls --channel conda-forge << parameters.packages >> "gmsh<4.0"
source activate ~/project/<< parameters.condaenv >>
pip install future
pip install scikit-fmm
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ before_install:
- hash -r
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
- conda create --quiet --name test-environment --show-channel-urls --channel conda-forge --only-deps python=$TRAVIS_PYTHON_VERSION fipy;
- conda create --quiet --name test-environment --show-channel-urls --channel conda-forge python=$TRAVIS_PYTHON_VERSION fipy "gmsh<4.0";
- source activate test-environment
# Useful for debugging any issues with conda
- conda info -a
Expand Down
2 changes: 2 additions & 0 deletions INSTALLATION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ Gmsh
http://www.geuz.org/gmsh/

:term:`Gmsh` is an application that allows the creation of irregular meshes.
When running in parallel, :term:`FiPy` requires a version of :term:`Gmsh`
>= 2.5 and < 4.0.

SciPy
=====
Expand Down
43 changes: 33 additions & 10 deletions fipy/meshes/gmshMesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,15 @@ def gmshVersion(communicator=parallelComm):

def _gmshVersion(communicator=parallelComm):
version = gmshVersion(communicator) or "0.0"
return StrictVersion(version)
try:
version = StrictVersion(version)
except ValueError:
# gmsh returns the version string in stderr,
# which means it's often unparsable due to irrelevant warnings
# assume it's OK and move on
version = StrictVersion("3.0")

return version

def openMSHFile(name, dimensions=None, coordDimensions=None, communicator=parallelComm, order=1, mode='r', background=None):
"""Open a Gmsh `MSH` file
Expand Down Expand Up @@ -164,8 +172,8 @@ def openMSHFile(name, dimensions=None, coordDimensions=None, communicator=parall
gmshFlags = ["-%d" % dimensions, "-nopopup"]

if communicator.Nproc > 1:
if version < StrictVersion("2.5"):
warnstr = "Cannot partition with Gmsh version < 2.5. " \
if not (StrictVersion("2.5") < version <= StrictVersion("4.0")):
warnstr = "Cannot partition with Gmsh version < 2.5 or >= 4.0. " \
+ "Reverting to serial."
warnings.warn(warnstr, RuntimeWarning, stacklevel=2)
communicator = serialComm
Expand All @@ -176,6 +184,11 @@ def openMSHFile(name, dimensions=None, coordDimensions=None, communicator=parall
raise ValueError("'dimensions' must be specified to generate a mesh from a geometry script")
else: # gmsh version is adequate for partitioning
gmshFlags += ["-part", "%d" % communicator.Nproc]
if version >= StrictVersion("4.0"):
# Gmsh 4.x needs to be told to generate ghost cells
# Unfortunately, the ghosts are broken
# https://gitlab.onelab.info/gmsh/gmsh/issues/733
gmshFlags += ["-part_ghosts"]

gmshFlags += ["-format", "msh2"]

Expand Down Expand Up @@ -1514,23 +1527,24 @@ class Gmsh2D(Mesh2D):
>>> from fipy import CellVariable, numerix
>>> std = []
>>> error = []
>>> bkg = None
>>> from builtins import range
>>> for refine in range(4):
... square = Gmsh2D(geo, background=bkg) # doctest: +GMSH
... x, y = square.cellCenters # doctest: +GMSH
... bkg = CellVariable(mesh=square, value=abs(x / 4) + 0.01) # doctest: +GMSH
... std.append((numerix.sqrt(2 * square.cellVolumes) / bkg).std()) # doctest: +GMSH
... error.append(((2 * numerix.sqrt(square.cellVolumes) / bkg - 1)**2).cellVolumeAverage) # doctest: +GMSH
Check that the mesh is monotonically approaching the desired density
Check that the mesh is (semi)monotonically approaching the desired density
(the first step may increase, depending on the number of partitions)
>>> print(numerix.greater(std[:-1], std[1:]).all()) # doctest: +GMSH
>>> print(numerix.greater(error[:-1], error[1:]).all()) # doctest: +GMSH
True
and that the final density is close enough to the desired density
>>> print(std[-1] < 0.2) # doctest: +GMSH
>>> print(error[-1] < 0.02) # doctest: +GMSH
True
The initial mesh doesn't have to be from Gmsh
Expand Down Expand Up @@ -1578,6 +1592,10 @@ def __init__(self,
mode='r',
background=background)

# openMSHFile may have "downgraded" the communicator
# if, e.g., too many overlaps were requested
communicator = self.mshFile.communicator

(verts,
faces,
cells,
Expand Down Expand Up @@ -1947,6 +1965,10 @@ def __init__(self, arg, communicator=parallelComm, order=1, background=None):
mode='r',
background=background)

# openMSHFile may have "downgraded" the communicator
# if, e.g., too many overlaps were requested
communicator = self.mshFile.communicator

(verts,
faces,
cells,
Expand Down Expand Up @@ -2225,7 +2247,7 @@ def _test(self):
>>> yogmsh.cellCenters.value.size == yogrid.cellCenters.value.size # doctest: +GMSH
True
>>> mesh = GmshGrid2D(nx=2, ny=2) # doctest: +GMSH
>>> mesh = GmshGrid2D(nx=2, ny=2, communicator=serialComm) # doctest: +GMSH
>>> mesh.numberOfCells == 4 # doctest: +GMSH
True
Expand Down Expand Up @@ -2310,7 +2332,8 @@ def _test(self):
>>> numerix.allclose(yogmsh._faceAreas, yogrid._faceAreas) # doctest: +GMSH
True
>>> mesh = GmshGrid3D(nx=2, ny=2, nz=2) # doctest: +GMSH
>>> mesh = GmshGrid3D(nx=2, ny=2, nz=2,
... communicator=serialComm) # doctest: +GMSH
>>> ccs = [[ 0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5],
... [ 0.5, 0.5, 1.5, 1.5, 0.5, 0.5, 1.5, 1.5],
Expand Down

0 comments on commit 4571de9

Please sign in to comment.