Hi,
I am trying to manipulate the arrays in order to create a boundary condition that gets data from another application. I have been successful with manipulating the underlying vector, but it causes my code to hang in certain cases.
I have set up the situation using my approach using the example Poisson example code. I create a special boundary at the bottom of the domain and write values in the corresponding array depending on the rank of the respective process. This works fine for serial computations, but when I use MPI it fails as soon as there is a process that does not contain any part of the bottom boundary.
The code below works for me when run with 1 or 2 processes, but hangs for 3 processes. In the latter case one process does not contain any part of the bottom boundary. I am using FEniCS/Dolfing 2019.1.0 from the Ubuntu PPA.
#!/usr/bin/env python3
#
# This example is based on
# https://fenicsproject.org/docs/dolfin/2019.1.0/python/demos/poisson/demo_poisson.py.html
#
# We set the bottom boundary to artificial values based on the process' rank
#
from dolfin import *
import numpy as np
comm = MPI.comm_world
rank = comm.Get_rank()
size = comm.Get_size()
print("Rank {} of {}".format(rank, size))
# Create mesh and define function space
mesh = UnitSquareMesh(32, 32)
V = FunctionSpace(mesh, "Lagrange", 1)
# Define Dirichlet boundary (x = 0 or x = 1)
def boundary(x):
return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS
def bottom_boundary(x):
return x[1] < DOLFIN_EPS
# Define own boundary condition
class BottomBoundaryCondition(UserExpression):
def __init__(self, val_new, **kwargs):
self.val = val_new
super().__init__(**kwargs)
def eval_cell(self, values, x, ufc_cell):
values[0] = self.val(x)
def value_shape(self):
return ()
# Define boundary condition
u0 = Constant(0.0)
bc = DirichletBC(V, u0, boundary)
# Find points on bottom boundary
marker_bottom = Constant(100)
bc_bottom = DirichletBC(V, marker_bottom, bottom_boundary)
u_bottom = Function(V)
bc_bottom.apply(u_bottom.vector())
#Extract dof indices such that we can set them later
bottom_dofs = np.where(u_bottom.vector() == 100)
bottom_ndofs = len(bottom_dofs[0])
print( "{}: Has {} dofs at bottom".format(rank, bottom_ndofs ) )
# Create boundary condition at bottom based on UserExpression and rank
values_bottom = np.ones(bottom_ndofs) * (rank)
u_bottom.vector()[bottom_dofs[0]] = values_bottom
tmp = BottomBoundaryCondition(u_bottom)
bc_bottom = DirichletBC(V, tmp, bottom_boundary)
# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)", degree=2)
g = Expression("sin(5*x[0])", degree=2)
a = inner(grad(u), grad(v))*dx
L = f*v*dx + g*v*ds
# Compute solution
u = Function(V)
solve(a == L, u, [bc, bc_bottom])
# Save solution in VTK format
file = File("poisson.pvd")
file << u
# Plot solution
import matplotlib.pyplot as plt
plot(u)
plt.show()
Could you give me a hint what I am doing wrong?
Any help would be appreciated!