I still try to solve the issue. Here is a min example where the sensitivities are calculated.
Then the solution is gathered in order to compare the results.
import numpy as np
import pandas as pd
from mpi4py import MPI
from dolfinx import mesh, fem, default_scalar_type, nls, plot
from dolfinx.mesh import create_mesh, create_unit_cube
from dolfinx.fem import functionspace
from dolfinx import *
import dolfinx.nls.petsc
import ufl
from ufl import SpatialCoordinate
import pyvista
from mmapy import gcmmasub, mmasub, subsolv, asymp, concheck, raaupdate
import sys
import matplotlib.pyplot as plt
from petsc4py import PETSc
#create mesh / create_unit_cube: cubic mesh with corners [0,0,0] and [1,1,1]
domain = mesh.create_unit_cube(MPI.COMM_WORLD, 3, 3, 3, mesh.CellType.hexahedron, ghost_mode=dolfinx.cpp.mesh.GhostMode.shared_facet)
#domain = mesh.create_unit_cube(MPI.COMM_WORLD, 20, 20, 20, mesh.CellType.hexahedron, ghost_mode=dolfinx.cpp.mesh.GhostMode.none)
tdim = domain.topology.dim
fdim = tdim - 1
#domain.topology.create_entities(fdim)
#domain.topology.create_connectivity(fdim, tdim)
#define function space
V = functionspace(domain, ("Lagrange", 1))
#concentration c, porosity eps
c = fem.Function(V)
eps = fem.Function(V) #design variable
phi = ufl.TestFunction(V)
eps.x.array[:] = 0.5 #uD = fem.Function(V)
#Parameter
D0 = 1.0
k0 = -1.0
eta2 = 2.0
gamma = 2.0
for loop in range(0,31):
f = fem.Constant(domain, default_scalar_type(0))
R = ufl.inner(D0*eps**eta2*ufl.grad(c), ufl.grad(phi))*ufl.dx - ufl.inner(k0*(1-eps)**gamma*c,phi)*ufl.dx - ufl.inner(f,phi)*ufl.ds
def on_boundary(x):
return np.isclose(x[0], 0)
dofs_L = fem.locate_dofs_geometrical(V , on_boundary)
bc_L = fem.dirichletbc(default_scalar_type(1), dofs_L, V)
#Forming and solving the linear system
problem_u = fem.petsc.NonlinearProblem(R, c, bcs=[bc_L])
solver = nls.petsc.NewtonSolver(MPI.COMM_WORLD,problem_u)
solver.rtol = 1e-16
solver.solve(c)
#solving objective function
J = -ufl.inner((k0*(1-eps)**gamma),c)*ufl.dx #Objective function
J_form = fem.form(J)
J_old = fem.assemble_scalar(J_form)
#solving the adjoint vector
lhs = ufl.adjoint(ufl.derivative(R,c))
rhs = -ufl.derivative(J,c)
def on_boundary_1(x):
return np.isclose(x[0], 0)
dofs_L_adj = fem.locate_dofs_geometrical(V , on_boundary_1)
bc_L_adj = fem.dirichletbc(default_scalar_type(0), dofs_L_adj, V) ##Dirichlet = 1
bcs_adjoint = [bc_L_adj]
#adjective problem
problem_adj = fem.petsc.LinearProblem(lhs, rhs, bcs_adjoint, petsc_options={"ksp_type": "gmres", "pc_type": "lu","pc_factor_mat_solver_type": "mumps"})
lamda = problem_adj.solve()
##### CALCULATE SENSITIVITY #####
dJde = dolfinx.fem.Expression(-(k0*gamma*((1-eps)**(gamma-1))*c+ufl.dot(D0*eta2*(eps**(eta2-1))*ufl.grad(c),ufl.grad(lamda))+ufl.inner(k0*gamma*((1-eps)**(gamma-1))*c,lamda)), V.element.interpolation_points(),MPI.COMM_WORLD)
sens = fem.Function(V)
sens.interpolate(dJde)
if domain.comm.rank == 0:
# Mesh on one proc
mesh0 = mesh.create_unit_cube(MPI.COMM_SELF, 3, 3, 3, mesh.CellType.hexahedron, ghost_mode=dolfinx.cpp.mesh.GhostMode.shared_facet)
V0 = functionspace(mesh0, ("Lagrange", 1))
x0 = V0.tabulate_dof_coordinates()
u0 = fem.Function(V0)
imapsens = sens.function_space.dofmap.index_map
local_rangesens = np.asarray(imapsens.local_range, dtype=np.int32) * \
sens.function_space.dofmap.index_map_bs
size_globalsens = imapsens.size_global * sens.function_space.dofmap.index_map_bs
rangessens = domain.comm.gather(local_rangesens, root=0)
datasens = domain.comm.gather(sens.x.petsc_vec.array, root=0)
xsens = V.tabulate_dof_coordinates()[:imapsens.size_local]
xsens_glob = domain.comm.gather(xsens, root=0)
if domain.comm.rank == 0:
global_arraysens = np.zeros(size_globalsens)
for rsens, dsens in zip(rangessens, datasens):
global_arraysens[rsens[0]:rsens[1]] = dsens
global_xsens = np.zeros((size_globalsens, 3))
for rsens, xsens_ in zip(rangessens, xsens_glob):
global_xsens[rsens[0]:rsens[1], :] = xsens_
serial_to_globalsens = []
for coord in x0:
serial_to_globalsens.append(np.abs(global_xsens-coord).sum(axis=1).argmin())
# Create sorted array from
u_from_globalsens = np.zeros(global_arraysens.shape)
for serialsens, globsens in enumerate(serial_to_globalsens):
u_from_globalsens[serialsens] = global_arraysens[globsens]
sens_d = u_from_globalsens
np.save('sens_d4',sens_d)
Now, when I run the code on 1 core and on 4 cores and then compare the sensitivity values, there are some values being different, e.g the second value (which is not the case for c, J or lamda).
Is there anything wrong with the interpolation?
The ouput arrays are:
for -n 1
array([0.62576823, 0.51721359, 0.62576823, 0.51721359, 0.62576823,
0.51721359, 0.62576823, 0.51721359, 0.4534996 , 0.4534996 ,
0.4534996 , 0.4534996 , 0.62576823, 0.51721359, 0.62576823,
0.51721359, 0.62576823, 0.51721359, 0.62576823, 0.51721359,
0.40495807, 0.40495807, 0.40495807, 0.40495807, 0.4534996 ,
0.4534996 , 0.4534996 , 0.4534996 , 0.62576823, 0.51721359,
0.62576823, 0.51721359, 0.62576823, 0.51721359, 0.62576823,
0.51721359, 0.62576823, 0.51721359, 0.40495807, 0.40495807,
0.40495807, 0.40495807, 0.4534996 , 0.4534996 , 0.4534996 ,
0.4534996 , 0.4534996 , 0.62576823, 0.51721359, 0.62576823,
0.51721359, 0.40495807, 0.40495807, 0.40495807, 0.40495807,
0.40495807, 0.4534996 , 0.4534996 , 0.62576823, 0.51721359,
0.40495807, 0.40495807, 0.4534996 , 0.40495807])
for -n 4
array([0.62576823, 0.25951964, 0.62576823, 0.51721359, 0.62576823,
0.25951964, 0.62576823, 0.51721359, 0.34898583, 0.34898583,
0.34898583, 0.4534996 , 0.62576823, 0.51721359, 0.62576823,
0.51721359, 0.62576823, 0.51721359, 0.62576823, 0.25951964,
0.40495807, 0.40495807, 0.40495807, 0.40495807, 0.4534996 ,
0.4534996 , 0.34898583, 0.4534996 , 0.62576823, 0.51721359,
0.62576823, 0.51721359, 0.62576823, 0.51721359, 0.62576823,
0.51721359, 0.62576823, 0.25951964, 0.40495807, 0.40495807,
0.40495807, 0.40495807, 0.4534996 , 0.4534996 , 0.4534996 ,
0.34898583, 0.4534996 , 0.62576823, 0.25951964, 0.62576823,
0.25951964, 0.40495807, 0.40495807, 0.40495807, 0.40495807,
0.40495807, 0.34898583, 0.4534996 , 0.62576823, 0.51721359,
0.40495807, 0.40495807, 0.34898583, 0.40495807])
Many thanks!