Adaptive mesh refinement with MPI (UPDATED)

Im trying to convert the example for adaptive mesh refinement [1] to working with MPI, but im getting a segmentation fault when im calling the function

mesh.Refine()

What is the correct way to do this? Do i need to ‘collect’ the mesh from the different cores, and run mesh.Refine() only on the rank=0 core (corresponding to that the mesh is distributed between the workers in the beginning)?

1: When run on two or more cores (mpirun -np 2 python3 adaptive.py), it creases with an segfault when the code reaches the line mesh.Refine().

[1] Adaptive mesh refinement — NGS-Py 6.2.1808 documentation

CODE

[code]from ngsolve import *
import ngsolve as ng
from netgen.geom2d import SplineGeometry
from ngsolve.krylovspace import CGSolver
from mpi4py import MPI

comm = MPI.COMM_WORLD

point numbers 0, 1, … 11

sub-domain numbers (1), (2), (3)

7-------------6

| |

| (2) |

| |

3------4-------------5------2

| |

| 11 |

| / \ |

| 10 (3) 9 |

| \ / (1) |

| 8 |

| |

0---------------------------1

def make_geometry():
geometry = SplineGeometry()

# point coordinates ...
pnts = [ (0,0), (1,0), (1,0.6), (0,0.6), \
         (0.2,0.6), (0.8,0.6), (0.8,0.8), (0.2,0.8), \
         (0.5,0.15), (0.65,0.3), (0.5,0.45), (0.35,0.3) ]
pnums = [geometry.AppendPoint(*p) for p in pnts]

# start-point, end-point, boundary-condition, domain on left side, domain on right side:
lines = [ (0,1,1,1,0), (1,2,2,1,0), (2,5,2,1,0), (5,4,2,1,2), (4,3,2,1,0), (3,0,2,1,0), \
          (5,6,2,2,0), (6,7,2,2,0), (7,4,2,2,0), \
          (8,9,2,3,1), (9,10,2,3,1), (10,11,2,3,1), (11,8,2,3,1) ]
    
for p1,p2,bc,left,right in lines:
    geometry.Append( ["line", pnums[p1], pnums[p2]], bc=bc, leftdomain=left, rightdomain=right)
return geometry

if comm.size > 1:
if comm.rank == 0:
mesh = make_geometry().GenerateMesh(maxh=0.2)
mesh = ng.Mesh(mesh.Distribute(comm))
else:
mesh = ng.Mesh(netgen.meshing.Mesh.Receive(comm))
else:
mesh = ng.Mesh(make_geometry().GenerateMesh(maxh=0.2))

vtk = ng.VTKOutput(
ma=mesh,
coefs=,
names=,
filename=f"mesh-rank-{comm.rank}",
subdivision=0)
vtk.Do()

fes = H1(mesh, order=3, dirichlet=[1])
u = fes.TrialFunction()
v = fes.TestFunction()

one heat conductivity coefficient per sub-domain

lam = CoefficientFunction([1, 1000, 10])

a = BilinearForm(fes, symmetric=False)

a += SymbolicBFI(lam*grad(u)*grad(v))

a = BilinearForm(lam*grad(u)*grad(v) * dx)
pre = ng.Preconditioner(a, “local”)

a.Assemble()

heat-source in sub-domain 3

f = LinearForm(fes)
f += SymbolicLFI(CoefficientFunction([0, 0, 1])*v)

c = Preconditioner(a, type=“multigrid”, inverse = “sparsecholesky”)

gfu = GridFunction(fes)

Draw(gfu)

finite element space and gridfunction to represent

the heatflux:

space_flux = HDiv(mesh, order=2)
gf_flux = GridFunction(space_flux, “flux”)

def SolveBVP(i):
fes.Update()
gfu.Update()
a.Assemble()
f.Assemble()
inv = CGSolver(a.mat, pre.mat, printrates=comm.rank == 0, maxiter=200, tol=1e-8)
gfu.vec.data = inv * f.vec
vtk = ng.VTKOutput(
ma=mesh,
coefs=[gfu],
names=[“Temperature (K)”],
filename=f"results-{i}",
subdivision=0)
vtk.Do()
# Redraw(blocking=True)

l =

def CalcError():
space_flux.Update()
gf_flux.Update()

flux = lam * grad(gfu)
# interpolate finite element flux into H(div) space:
gf_flux.Set(flux)

# Gradient-recovery error estimator
err = 1/lam*(flux-gf_flux)*(flux-gf_flux)
elerr = Integrate (err, mesh, VOL, element_wise=True)

if len(elerr) == 0:
    maxerr = 0
else:
    maxerr = max(elerr)

maxerr = comm.allreduce(maxerr, MPI.MAX)
comm.Barrier()

l.append ( (fes.ndof, sqrt(sum(elerr)) ))

i = 0
i_nr = 0
for el in mesh.Elements():
    i_nr += 1
    if elerr[el.nr] > 0.25*maxerr:
        i += 1
    mesh.SetRefinementFlag(el, elerr[el.nr] > 0.25*maxerr)
print("# ", i, "number of elements refined. total=", i_nr)

with TaskManager():
i = 0
while fes.ndof < 100000:
print(i)
i += 1
if i == 20:
break

    SolveBVP(i)
    CalcError()
    print("before", comm.rank)
    mesh.Refine()
    print("after", comm.rank)
    print()
    print("# num elements after refinement =", len(list(mesh.Elements())))

    vtk = ng.VTKOutput(
        ma=mesh,
        coefs=,
        names=,
        filename=f"mesh-{i}",
        subdivision=0)
    vtk.Do()

import matplotlib.pyplot as plt

plt.yscale(‘log’)
plt.xscale(‘log’)
plt.xlabel(“ndof”)
plt.ylabel(“H1 error-estimate”)
ndof,err = zip(l)
plt.plot(ndof,err, "-
")

plt.ion()
plt.savefig(“hei.pdf”)[/code]