@dokken
I’m really sorry for that, here i tried again and something went wrong at def update_eps , I’ve been stuck here for many days and i can’t update the eps until now. Could you please help me.
and here is the research i try following https://www.sciencedirect.com/science/article/pii/S0017931022011930
import dolfinx
import ufl
from dolfinx.plot import vtk_mesh
import pyvista
from ufl import Measure, inner, grad, div, TestFunction, TrialFunction, adjoint, derivative
from dolfinx.mesh import CellType, create_rectangle
from dolfinx import fem, nls, io
from mpi4py import MPI
from petsc4py import PETSc
import numpy as np
import time
from matplotlib import*
from ufl import SpatialCoordinate, TestFunction, TrialFunction, dot, ds, dx, grad, inner
import dolfinx.nls.petsc
import dolfinx.fem.petsc
from dolfinx.fem import (Constant, Function, FunctionSpace,
assemble_scalar, dirichletbc, form, locate_dofs_geometrical)
from dolfinx import default_scalar_type
from dolfinx import *
import numpy as np
from mpi4py import MPI
import dolfinx
from ufl import grad, dot
import os
from dolfinx.cpp.mesh import CellType
from dolfinx.io import XDMFFile
import dolfinx.nls.petsc
import dolfinx.fem.petsc
#from dolfinx import has_patsc_complex
#Parameter
D0 = 1;
k0 = -1.0;
eta = 2.0;
gamma = 2.0;
# mesh and function space
mesh = create_rectangle(MPI.COMM_WORLD, [[0, 0], [1, 1]], [20, 20], CellType.triangle)
V = fem.FunctionSpace(mesh, ("CG", 1))
c = fem.Function(V)
phi = TestFunction(V)
# The eps is the design variable
eps = fem.Function(V)
eps.x.array[:] = 0.8
dx = Measure("dx") ##integration over different parts of the domain
x = SpatialCoordinate(mesh)
gu = Constant(mesh, default_scalar_type(0)) ##Neauman = 0
# Residual of the variational form of Poisson problem
R = inner(D0*eps**eta*grad(c), grad(phi))*dx - inner(k0*(1-eps)**gamma*c,phi)*dx - inner(gu,phi) *ds
##Dirichlet
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) ##Dirichlet = 1
bcs = [bc_L]
#Forming and solving the linear system
problem_u = fem.petsc.NonlinearProblem(R, c, bcs)
solver = nls.petsc.NewtonSolver(MPI.COMM_WORLD,problem_u)
solver.rtol = 1e-16
solver.solve(c)
#how big is the solution
J = ufl.inner(k0*(1-eps)**gamma,c)*dx ##Objective function
J_form = fem.form(J)
J_old = fem.assemble_scalar(J_form)
#solve the adjoint vector
lhs = ufl.adjoint(ufl.derivative(R,c))
rhs = -ufl.derivative(J,c)
bc = []
#Adjective problem
problem_adj = dolfinx.fem.petsc.LinearProblem(lhs, rhs, bcs=bc, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
#solve adj problem in lamda (lamda is adjoint variable)
lamda = problem_adj.solve()
# dJde is objactive function / eps
dJde_form = dolfinx.fem.form(ufl.derivative(J, eps, ufl.conj(ufl.TestFunction(eps.function_space))))
dJde = dolfinx.fem.petsc.assemble_vector(dJde_form)
dJde.assemble()
# dRde is the equation accounting for the transport of the species / eps
dRde_form = fem.form(adjoint(derivative(R,eps)))
dRde = dolfinx.fem.petsc.assemble_matrix(dRde_form)
dRde.assemble()
B = dolfinx.fem.petsc.assemble_vector(dJde_form)
B.assemble()
dRde.mult(lamda.vector, B)
# Update dJde
dJde += B
dJde.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
# Function to compute the objective
def J_eps(m_n):
eps = m_n.x.array[:]
solver.solve(c)
J_old = fem.assemble_scalar(J_form)
return J_old
# Function to compute the gradient of the reaction rate w.r.t. eps
def grad_J(m_n,dJde=dJde):
eps = m_n.x.array[:]
# Direct solution
solver.solve(c)
# Adjoint solution
lamda = problem_adj.solve()
# Reassemble dRde
dRde.zeroEntries()
fem.petsc.assemble_matrix(dRde, dRde_form)
dRde.assemble()
# Compute gradient
# zero gradient first
with dJde.localForm() as dJde_loc:
dJde_loc.set(0)
fem.petsc.assemble_vector(dJde, dJde_form)
dJde.assemble()
B = dolfinx.fem.petsc.assemble_vector(dJde_form)
B.assemble()
dRde.mult(lamda.vector, B)
dJde += B
dJde.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
return dJde
def update_eps(m_n,result_grad_J):
eps = m_n.x.array[:]
eps_new = fem.Function(V)
eps_new.x.array[:] = eps.x.array - 10**17*result_grad_J.x.array
m_n.x.array[:] = eps_new
return m_n
loop = 10
mn = fem.Function(V)
mn.x.array[:] = 0.5
result_grad_J = fem.Function(V)
for i in range(loop):
#solve obj
J_eps(mn)
print("J_eps: ",J_eps(mn))
#solve gradient
grad_J(mn,dJde=dJde)
result_grad_J.x.array[:] = grad_J(mn,dJde=dJde)
print("grad_J: ",result_grad_J.x.array)
#update eps
update_eps(mn,result_grad_J)
mn = update_eps(mn, result_grad_J)
print("eps: ",mn.x.array.tolist())
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[7], line 18
14 result_grad_J.x.array[:] = grad_J(mn,dJde=dJde)
15 #print("grad_J: ",result_grad_J.x.array)
16
17 #update eps
---> 18 update_eps(mn,result_grad_J)
19 mn = update_eps(mn, result_grad_J)
20 print("eps: ",mn.x.array.tolist())
Cell In[3], line 42, in update_eps(m_n, result_grad_J)
40 eps = m_n.x.array[:]
41 eps_new = fem.Function(V)
---> 42 eps_new.x.array[:] = eps.x.array - 10**17*result_grad_J.x.array
43 m_n.x.array[:] = eps_new
44 return m_n
AttributeError: 'numpy.ndarray' object has no attribute 'x'