Skip to content

Commit

Permalink
Merge branch 'main' into JDBetteridge/refactor_curvefield
Browse files Browse the repository at this point in the history
  • Loading branch information
JDBetteridge committed Oct 3, 2024
2 parents 7b4f590 + 1ea4b0e commit 6e97b7f
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 15 deletions.
7 changes: 2 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,12 @@ RUN pip install numpy scipy cython mpi4py pytest pytest-mpi
RUN cd ~ && git clone https://gitlab.com/petsc/petsc.git
RUN cd ~/petsc \
&& python configure --download-chaco \
--download-cmake \
--download-eigen \
--with-openmpi=1 \
--download-hypre \
--download-metis \
--download-parmetis \
--download-ml \
--download-mumps \
--download-scalapack \
--download-superlu_dist \
--with-c2html=0 \
--with-cxx-dialect=C++11 \
--with-debugging=0 \
Expand All @@ -51,6 +47,7 @@ RUN cd ~/slepc \
&& make
#Building ngsolve
ENV LD_LIBRARY_PATH /root/petsc/linux_debug/lib
RUN pip install netgen-occt-devel netgen-occt
RUN mkdir -p ~/ngsuite \
&& cd ~/ngsuite \
&& git clone https://github.com/NGSolve/ngsolve.git ngsolve-src \
Expand All @@ -59,7 +56,7 @@ RUN mkdir -p ~/ngsuite \
&& mkdir ~/ngsuite/ngsolve-build \
&& mkdir ~/ngsuite/ngsolve-install \
&& cd ~/ngsuite/ngsolve-build \
&& cmake -DCMAKE_INSTALL_PREFIX=~/ngsuite/ngsolve-install ~/ngsuite/ngsolve-src -DUSE_MPI=ON -DBUILD_OCC=ON \
&& cmake -DCMAKE_INSTALL_PREFIX=~/ngsuite/ngsolve-install ~/ngsuite/ngsolve-src -DUSE_MPI=ON -DBUILD_OCC=OFF\
&& make && make install
#Adding NGS to PYTHONPATH
ENV PYTHONPATH /root/petsc/linux_debug/lib:/root/slepc/linux_debug/lib:/root/ngsuite/ngsolve-install/lib/python3.10/site-packages
103 changes: 97 additions & 6 deletions ngsPETSc/utils/firedrake/hierarchies.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
try:
import firedrake as fd
from firedrake.cython import mgimpl as impl
from firedrake.__future__ import interpolate
from firedrake import dmhooks
import ufl
except ImportError:
fd = None

Expand Down Expand Up @@ -31,6 +34,86 @@ def snapToNetgenDMPlex(ngmesh, petscPlex):
else:
raise NotImplementedError("Snapping to Netgen meshes is only implemented for 2D meshes.")

def snapToCoarse(coarse, linear, degree, snap_smoothing, cg):
'''
This function snaps the coordinates of a DMPlex mesh to the coordinates of a Netgen mesh.
'''
dim = linear.geometric_dimension()
if dim == 2:
space = fd.VectorFunctionSpace(linear, "CG", degree)
ho = fd.assemble(interpolate(coarse, space))
if snap_smoothing == "hyperelastic":
#Hyperelastic Smoothing
bcs = [fd.DirichletBC(space, ho, "on_boundary")]
quad_degree = 2*(degree+1)-1
d = linear.topological_dimension()
Q = fd.TensorFunctionSpace(linear, "DG", degree=0)
Jinv = ufl.JacobianInverse(linear)
hinv = fd.Function(Q)
hinv.interpolate(Jinv)
G = ufl.Jacobian(linear) * hinv
ijac = 1/abs(ufl.det(G))

def ref_grad(u):
return ufl.dot(ufl.grad(u),G)

params = {
"snes_type": "newtonls",
"snes_linesearch_type": "l2",
"snes_max_it": 50,
"snes_rtol": 1E-8,
"snes_atol": 1E-8,
"snes_ksp_ew": True,
"snes_ksp_ew_rtol0": 1E-2,
"snes_ksp_ew_rtol_max": 1E-2,
}
params["mat_type"] = "aij"
coarse = {
"ksp_type": "preonly",
"pc_type": "lu",
"pc_mat_factor_type": "mumps",
}
gmg = {
"pc_type": "mg",
"mg_coarse": coarse,
"mg_levels": {
"ksp_max_it": 2,
"ksp_type": "chebyshev",
"pc_type": "jacobi",
},
}
l = fd.mg.utils.get_level(linear)[1]
pc = gmg if l else coarse
params.update(pc)
ksp = {
"ksp_rtol": 1E-8,
"ksp_atol": 0,
"ksp_type": "minres",
"ksp_norm_type": "preconditioned",
}
params.update(ksp)
u = ho
F = ref_grad(u)
J = ufl.det(F)
psi = (1/2) * (ufl.inner(F, F)-d - ufl.ln(J**2))
U = (psi * ijac)*fd.dx(degree=quad_degree)
dU = ufl.derivative(U, u, fd.TestFunction(space))
problem = fd.NonlinearVariationalProblem(dU, u, bcs)
solver = fd.NonlinearVariationalSolver(problem, solver_parameters=params)
solver.set_transfer_manager(None)
ctx = solver._ctx
for c in problem.F.coefficients():
dm = c.function_space().dm
dmhooks.push_appctx(dm, ctx)
solver.solve()
if not cg:
element = ho.function_space().ufl_element().sub_elements[0].reconstruct(degree=degree)
space = fd.VectorFunctionSpace(linear, fd.BrokenElement(element))
ho = fd.Function(space).interpolate(ho)
else:
raise NotImplementedError("Snapping to Netgen meshes is only implemented for 2D meshes.")
return fd.Mesh(ho, comm=linear.comm, distribution_parameters=linear._distribution_parameters)

def uniformRefinementRoutine(ngmesh, cdm):
'''
Routing called inside of NetgenHierarchy to compute refined ngmesh and plex.
Expand Down Expand Up @@ -124,6 +207,10 @@ def NetgenHierarchy(mesh, levs, flags):
tol = flagsUtils(flags, "tol", 1e-8)
refType = flagsUtils(flags, "refinement_type", "uniform")
optMoves = flagsUtils(flags, "optimisation_moves", False)
snap = flagsUtils(flags, "snap_to", "geometry")
snap_smoothing = flagsUtils(flags, "snap_smoothing", "hyperelastic")
cg = flagsUtils(flags, "cg", False)
nested = flagsUtils(flags, "nested", snap in ["coarse"])
#Firedrake quoantities
meshes = []
coarse_to_fine_cells = []
Expand All @@ -134,8 +221,8 @@ def NetgenHierarchy(mesh, levs, flags):
raise RuntimeError("Cannot refine parallel overlapped meshes ")
#We curve the mesh
if order[0]>1:
mesh = fd.Mesh(mesh.curve_field(order=order[0], tol=tol),
distribution_parameters=params, comm=comm)
ho_field = mesh.curve_field(order=order[0], tol=tol, CG=cg)
mesh = fd.Mesh(ho_field,distribution_parameters=params, comm=comm)
meshes += [mesh]
cdm = meshes[-1].topology_dm
for l in range(levs):
Expand All @@ -144,7 +231,8 @@ def NetgenHierarchy(mesh, levs, flags):
rdm, ngmesh = refinementTypes[refType][0](ngmesh, cdm)
cdm = rdm
#We snap the mesh to the Netgen mesh
snapToNetgenDMPlex(ngmesh, rdm)
if snap == "geometry":
snapToNetgenDMPlex(ngmesh, rdm)
#We construct a Firedrake mesh from the DMPlex mesh
mesh = fd.Mesh(rdm, dim=meshes[-1].ufl_cell().geometric_dimension(), reorder=False,
distribution_parameters=params, comm=comm)
Expand All @@ -159,10 +247,13 @@ def NetgenHierarchy(mesh, levs, flags):
mesh.netgen_mesh = ngmesh
#We curve the mesh
if order[l+1] > 1:
mesh = fd.Mesh(mesh.curve_field(order=order[l+1], tol=1e-8),
distribution_parameters=params, comm=comm)
if snap == "geometry":
mesh = fd.Mesh(mesh.curve_field(order=order[l+1], tol=tol),
distribution_parameters=params, comm=comm)
elif snap == "coarse":
mesh = snapToCoarse(ho_field, mesh, order[l+1], snap_smoothing, cg)
meshes += [mesh]
#We populate the coarse to fine map
coarse_to_fine_cells, fine_to_coarse_cells = refinementTypes[refType][1](meshes)
return fd.HierarchyBase(meshes, coarse_to_fine_cells, fine_to_coarse_cells,
1, nested=False)
1, nested=nested)
11 changes: 7 additions & 4 deletions ngsPETSc/utils/firedrake/meshes.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def find_permutation(points_a, points_b, tol=1e-5):


@PETSc.Log.EventDecorator()
def curveField(self, order, tol=1e-8):
def curveField(self, order, tol=1e-8, CG=False):
'''
This method returns a curved mesh as a Firedrake function.
Expand All @@ -139,9 +139,12 @@ def curveField(self, order, tol=1e-8):
geom_dim = self.geometric_dimension()

# Construct the mesh as a Firedrake function
low_order_element = self.coordinates.function_space().ufl_element().sub_elements[0]
ufl_element = low_order_element.reconstruct(degree=order)
firedrake_space = fd.VectorFunctionSpace(self, fd.BrokenElement(ufl_element))
if CG:
firedrake_space = fd.VectorFunctionSpace(self, "CG", order)
else:
low_order_element = self.coordinates.function_space().ufl_element().sub_elements[0]
ufl_element = low_order_element.reconstruct(degree=order)
firedrake_space = fd.VectorFunctionSpace(self, fd.BrokenElement(ufl_element))
new_coordinates = fd.assemble(interpolate(self.coordinates, firedrake_space))

# Compute reference points using fiat
Expand Down

0 comments on commit 6e97b7f

Please sign in to comment.