Thank you for reply @dokken!
The code for the result obtained above is as follows(Reduced code as much as possible)
# Set python packages
import ufl
import numpy as np
from dolfinx import fem, mesh
from mpi4py import MPI
from petsc4py import PETSc
# Dolfinx projection function
def project_func(dfx_func, func_space):
trial_func = ufl.TrialFunction(func_space)
test_func = ufl.TestFunction(func_space)
a = trial_func * test_func * ufl.dx
l = dfx_func * test_func * ufl.dx
project_prob = fem.petsc.LinearProblem(a, l, [])
result_sol = project_prob.solve()
return result_sol
# Declare the input variables
nelx = 2
nely = 2
volfrac = 0.5
penal = 3.0
# Put MPI commands
comm = MPI.COMM_WORLD
# Setting preliminaries
sigma = lambda _u: 2.0 * mu * ufl.sym(ufl.grad(_u)) + lmd * ufl.tr(ufl.sym(ufl.grad(_u))) * ufl.Identity(len(_u))
psi = lambda _u: lmd / 2 * (ufl.tr(ufl.sym(ufl.grad(_u))) ** 2) + mu * ufl.tr(ufl.sym(ufl.grad(_u)) * ufl.sym(ufl.grad(_u)))
mu, lmd = PETSc.ScalarType(0.4), PETSc.ScalarType(0.6)
# Set mesh
msh = mesh.create_rectangle(comm, ((0.0, 0.0), (nelx, nely)), (nelx, nely), cell_type=mesh.CellType.triangle, diagonal=mesh.DiagonalType.right_left)
U = fem.VectorFunctionSpace(msh, ("CG", 1))
D = fem.FunctionSpace(msh, ("DG", 0))
u, v = ufl.TrialFunction(U), ufl.TestFunction(U)
u_sol, density = fem.Function(U), fem.Function(D)
density.x.array[:] = volfrac
print(f"Initial density on process {MPI.COMM_WORLD.rank}: \n{density.x.array[:]}\n")
# Put the dimension of domain
t_dim = msh.topology.dim
f_dim = t_dim - 1
num_cells = msh.topology.index_map(t_dim).size_local
# Define support
def left_clamp(x):
return np.isclose(x[0], 0.0)
bc_facets = mesh.locate_entities_boundary(msh, f_dim, left_clamp)
u_zero = np.array([0.0, 0.0], dtype=PETSc.ScalarType)
bc_l = fem.dirichletbc(u_zero, fem.locate_dofs_topological(U, f_dim, bc_facets), U)
bcs = [bc_l]
# Define external load
load_points = [(1, lambda x: np.logical_and(x[0]==nelx, x[1]<=2))]
facet_indices, facet_markers = [], []
for (marker, locator) in load_points:
facets = mesh.locate_entities(msh, f_dim, locator)
facet_indices.append(facets)
facet_markers.append(np.full(len(facets), marker))
facet_indices = np.array(np.hstack(facet_indices), dtype=np.int32)
facet_markers = np.array(np.hstack(facet_markers), dtype=np.int32)
sorted_facets = np.argsort(facet_indices)
facet_tag = mesh.meshtags(msh, f_dim, facet_indices[sorted_facets], facet_markers[sorted_facets])
ds = ufl.Measure("ds", domain=msh, subdomain_data=facet_tag)
f = ufl.dot(v, fem.Constant(msh, PETSc.ScalarType((0.0, -1.0)))) * ds(1)
# Set up the variational problem and solver (using SIMP)
k = ufl.inner(density**penal * sigma(u), ufl.grad(v)) * ufl.dx
problem = fem.petsc.LinearProblem(k, f, bcs)
# solve PDE
u_sol = problem.solve()
print(f"u_sol on process {MPI.COMM_WORLD.rank}: \n{u_sol.x.array[:]}\n")
# Objective & sensitivity
objective = project_func(density**penal * psi(u_sol), D).x.array[:]
print(f"Objective on process {MPI.COMM_WORLD.rank}: \n{objective}\n")
sensitivity = -penal * (density.x.array[:])**(penal-1) * project_func(psi(u_sol), D).x.array[:]
print(f"Sensitivity on process {MPI.COMM_WORLD.rank}: \n{sensitivity}\n")
To comparing the result with the code built through dolfin in the past.
MWE is
# Set python packages
from dolfin import *
from mpi4py import MPI
# Declare the input variables
nelx = 2
nely = 2
volfrac = 0.5
penal = 3.0
# Setting preliminaries
sigma = lambda _u: 2.0 * mu * sym(grad(_u)) + lmbda * tr(sym(grad(_u))) * Identity(len(_u))
psi = lambda _u: lmbda / 2 * (tr(sym(grad(_u))) ** 2) + mu * tr(sym(grad(_u)) * sym(grad(_u)))
mu, lmbda = Constant(0.4), Constant(0.6)
# Set mesh
msh = RectangleMesh(Point(0, 0), Point(nelx, nely), nelx, nely, "right/left")
U = VectorFunctionSpace(msh, "P", 1)
D = FunctionSpace(msh, "DG", 0)
u, v = TrialFunction(U), TestFunction(U)
u_sol, density = Function(U), Function(D)
density.vector()[:] = volfrac
print(f"Initial density on process {MPI.COMM_WORLD.rank}: \n{density.vector()[:]}\n")
# Define support
support = CompiledSubDomain("near(x[0], 0.0, tol) && on_boundary", tol=1e-14)
bcs = [DirichletBC(U,Constant((0.0, 0.0)), support)]
# Define external load
load_marker = MeshFunction("size_t", msh, msh.topology().dim() - 1)
CompiledSubDomain("x[0]==l && x[1]<=2", l=nelx).mark(load_marker, 1)
ds = Measure("ds")(subdomain_data=load_marker)
f = dot(v, Constant((0.0, -1.0))) * ds(1)
# Set up the variational problem and solver (using SIMP)
k = inner(density**penal*sigma(u), grad(v)) * dx
problem = LinearVariationalProblem(k, f, u_sol, bcs=bcs)
solver = LinearVariationalSolver(problem)
# solve PDE
solver.solve()
print(f"u_sol on process {MPI.COMM_WORLD.rank}: \n{u_sol.vector()[:]}\n")
# Objective & sensitivity
objective = project(density ** penal * psi(u_sol), D).vector()[:]
print(f"Objective on process {MPI.COMM_WORLD.rank}: \n{objective}\n")
sensitivity = -penal * (density.vector()[:]) ** (penal-1) * project(psi(u_sol), D).vector()[:]
print(f"Sensitivity on process {MPI.COMM_WORLD.rank}: \n{sensitivity}\n")
When the reference code is executed through mpirun -n 2~~
Initial density on process 0:
[0.5 0.5 0.5 0.5]
Initial density on process 1:
[0.5 0.5 0.5 0.5]
Process 0: Solving linear variational problem.
Process 1: Solving linear variational problem.
u_sol on process 0:
[0. 0. 0. 0. 0. 0.]
u_sol on process 1:
[ 2.19098143e+01 -6.77188329e+01 -2.78721395e-15 -6.44827586e+01
1.51458886e+01 -2.69893899e+01 -1.51458886e+01 -2.69893899e+01
-2.19098143e+01 -6.77188329e+01 -9.70784783e-16 -2.81564987e+01]
Objective on process 0:
[38.28299907 4.35108686 4.35108686 38.28299907]
Objective on process 1:
[12.13231906 11.33439076 11.33439076 12.13231906]
Sensitivity on process 0:
[-229.69799443 -26.10652119 -26.10652119 -229.69799443]
Sensitivity on process 1:
[-72.79391433 -68.00634459 -68.00634459 -72.79391433]
As shown in the following results, when objective & sensitivity
were compared with each local process, a difference was seen in the process of interpolation in the code built with dolfinx,
so I thought that the project_func
function built in dolfinx did not perform parallel calculation.
I am wondering if there is any way to solve the problem.