hi~
This question is an extension of the posting (The problem in a simple example I made and how to 'project' the value assigned to 'FunctionSpace' into a numpy array in dolfinx environment?) I asked before.
The dolfinx version of my laptop is
0.5.0
unknown
Thankfully, I got the desired u_sol
array through the answer as follows.
(run in single process)
[ 0.00000000e+00 0.00000000e+00 -1.51458886e+01 -2.69893899e+01
0.00000000e+00 0.00000000e+00 4.77395901e-15 -2.81564987e+01
0.00000000e+00 0.00000000e+00 1.51458886e+01 -2.69893899e+01
6.66133815e-15 -6.44827586e+01 -2.19098143e+01 -6.77188329e+01
2.19098143e+01 -6.77188329e+01]
After that, in order to perform parallel calculation, the calculation of u_sol
is performed through 2 local processes (command: mpirun -n 2 ~~
) using MPI.
[ 0.00000000e+00 0.00000000e+00 -1.51458886e+01 -2.69893899e+01
0.00000000e+00 0.00000000e+00 -2.19098143e+01 -6.77188329e+01
-4.63518113e-15 -2.81564987e+01 -1.06581410e-14 -6.44827586e+01
1.51458886e+01 -2.69893899e+01]
[ 0.00000000e+00 0.00000000e+00 1.51458886e+01 -2.69893899e+01
-4.63518113e-15 -2.81564987e+01 -1.06581410e-14 -6.44827586e+01
2.19098143e+01 -6.77188329e+01 0.00000000e+00 0.00000000e+00
-1.51458886e+01 -2.69893899e+01]
I was curious how to make the result value obtained from the code written through mpirun
command the same as the global value obtained when executing as a single process (gather in MPI) or a method of sending data to each local process for u_sol
array value calculated in a single process, respectively. (scatter in MPI)
(I am going to use gather and scatter methods to perform various analyzes with u_sol
array in code.)
I checked the posting (Gather solutions in parallel in FEniCSX) to get help, but an error occurred and I couldn’t use it. The error occurred at the following line of code.
dolfinx.cpp.la.scatter_forward(u.x)
When I followed the code, I thought that the problem was caused by the non-existence of scatter_forward
command.
As there was a question in this posting, there is a degree of freedom given to the mesh for code, so if I simply use the gather command, I had no choice but to get a different value from the result obtained in a single process. (How to simply solve this problem I think there is, but I don’t know how to do it.)
Note: Code slightly modified from previous posting (the parts for each description are same)
import ufl
import numpy as np
from dolfinx import fem, mesh
from mpi4py import MPI
from petsc4py import PETSc
nelx = 2
nely = 2
volfrac = 0.5
penal = 3
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)
msh = mesh.create_rectangle(MPI.COMM_WORLD, ((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
def left_clamp(x):
return np.isclose(x[0], 0.0)
f_dim = msh.topology.dim - 1
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]
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)
k = ufl.inner(density ** penal * sigma(u), ufl.grad(v)) * ufl.dx
problem = fem.petsc.LinearProblem(k, f, bcs)
u_sol = problem.solve()