from dolfin import *from time import *# Class for interfacing with the Newton solverclass Subproblem(NonlinearProblem):def __init__(self, a, L):NonlinearProblem.__init__(self)self.L = Lself.a = adef F(self, b, x):assemble(self.L, tensor=b)def J(self, A, x):assemble(self.a, tensor=A)# Model parameters#parameters["form_compiler"]["quadrature_degree"] = 14parameters["form_compiler"]["optimize"] = Trueparameters["form_compiler"]["representation"] = 'quadrature'#parameters["form_compiler"]["representation"] = "uflacs"#parameters["form_compiler"]["quadrature_degree"] = 2parameters["form_compiler"]["cpp_optimize"] = True#parameters['form_compiler']['cpp_optimize_flags'] = '-foo'# Create mesh and define function spaceproblemit = 0subproblemit = 0time = time()# set h << epsilonh = 2 ** 7sigma = 0.0001#0.0001epsln = 1/(16 * pi)lmbda = 1 / (sigma * epsln)mesh = UnitSquareMesh(h, h)V = FunctionSpace(mesh, "CG", 1)R = FunctionSpace(mesh, "R", 0)W = V * R# Create mesh and define function space#mesh = RectangleMesh(-1, -1, 1, 1, 64, 64, 'left')e_ns = Function(V)e_ns.vector()[:] = 1.0e_n = interpolate(e_ns, V)# input dataa_1 = Constant(8.0)a_2 = Constant(1.0)#eps = 0.0000001# phi exact - for comparisionphi_exact = Expression("(x[0]-0.5)*(x[0]-0.5)/(0.05*0.05)+(x[1]-0.5)*(x[1]-0.5)/(0.2*0.2) <=1 ? k0 : k1", k0=1, k1=-1, degree= 1, domain=mesh)phi_e = interpolate(phi_exact, V)a_phi_e = a_1 * (1 + phi_e)/2 + a_2 * (1 - phi_e)/2#phi_0_e = assemble(phi_e * dx)#phi_e = phi_e - phi_0_eg_h = Expression("(near(x[0], 1) && ! near(x[1], 0))|| near(x[1], 1) ? k0 : k1", k0=-0.5, k1= 0.5, degree= 1, domain=mesh)f = Constant(0)print "assembling g"print assemble(g_h*ds)# Define variational problem(y_obs, c) = TrialFunction(W)(v, d) = TestFunctions(W)a = a_phi_e*(inner(grad(y_obs), grad(v)) + c*v + y_obs*d)*dxL = f*v*dx + g_h*v*ds# Compute solutionw = Function(W)solve(a == L, w)(y_obs, c) = w.split()#plot(y_obs, interactive=True)file = File("output.pvd", "compressed")file << y_obsprint "assembling y_obs"print assemble(y_obs*dx)# Save solution in VTK formatphi_init = Expression("(x[0]-0.5)*(x[0]-0.5)/(0.15*0.15)+(x[1]-0.5)*(x[1]-0.5)/(0.25*0.25) <=1 ? k0 : k1", k0=1, k1=-1, degree= 1, domain=mesh)phi = interpolate(phi_init, V)#plot(phi_e, title='phi', interactive=True, scale=0.0)#plot(phi, title='phi',interactive=True, scale=0.0)solving = Truewhile solving:problemit = problemit + 1a_phi = a_1 * (1 + phi)/2 + a_2 * (1 - phi)/2# Define variational problem(y, c) = TrialFunction(W)(v, d) = TestFunctions(W)a = a_phi*(inner(grad(y), grad(v)) + c*v + y*d)*dxL = f*v*dx + g_h*v*ds# Compute solutionw = Function(W)solve(a == L, w)(y, c) = w.split()# plot(y, interactive=True)# solve dual problem# Define variational problem(p, c) = TrialFunction(W)(v, d) = TestFunctions(W)a = a_phi*(inner(grad(p), grad(v)) + c*v + p*d)*dxL = (y-y_obs)*v*dx# Compute solutionw = Function(W)solve(a == L, w)(p, c) = w.split()# Plot solution# plot(p, interactive=True)# Save solution in VTK formatprint "using solver..."u = Function(V)du = TrialFunction(V)v = TestFunction(V)e_n = interpolate(Constant(1), V)F_1 = 0.5 * (u) * v *dx + 0.5 * inner(nabla_grad(u), nabla_grad(v))*dxF_2 = lmbda * ( ( (- a_1 + a_2) * 0.5 * v ) * inner(nabla_grad(y), nabla_grad(p))) *dx# F_3 = lmbda * sigma * epsln * (inner(nabla_grad(phi), nabla_grad(v)))*dxF_4 = - (1 + lmbda * sigma/epsln) * (phi * v)*dx# -a(phi,v)# F_5 = - inner(nabla_grad(phi), nabla_grad(v))*dx# F_6 = - phi * v*dxF = F_1 + F_2 + F_4# F = sigma * epsln * inner(nabla_grad(u), nabla_grad(v))*dx+sigma * epsln * inner(nabla_grad(e_n -u), nabla_grad(-v))*dx + ( - a_1 * v ) * inner(nabla_grad(y), nabla_grad(p)) *dx + sigma * epsln * (inner(nabla_grad(phi), nabla_grad(v)))*dx - sigma/epsln * (phi * v)*dx# test purpose# F = inner(nabla_grad(phi - u), nabla_grad(-v)) *dx + (phi - u ) * -v *dx# a = derivative(F, u, du)# problem = NonlinearVariationalProblem(F, u, [], a)# solver = NonlinearVariationalSolver(problem)#solver.parameters["nonlinear_solver"] = "snes"# solver.parameters["nonlinear_solver"] = "snes"# solver.parameters["snes_solver"]["linear_solver"] = "lu"# solver.parameters["snes_solver"]["method"] = "vinewtonrsls"#info(solver.parameters, verbose=True)problem = Subproblem(derivative(F, u, du), F)solver = PETScSNESSolver()solver.parameters["linear_solver"] = "lu"#solver.parameters["convergence_criterion"] = "incremental"#solver.parameters["relative_tolerance"] = 1e-6solver.parameters['maximum_iterations']= 500# vector for the lower and upper bound.lb = interpolate(Constant(-1) , V)ub = interpolate(Constant(1) , V)# solver.solve(lb.vector(), ub.vector()) # Bounded solvesolver.solve(problem, u.vector(), lb.vector(), ub.vector()) # Bounded solve# plot(phi, title='u', scale=0.0, interactive=True)u = u - phi# plot(u, title='u', scale=0.0, interactive=True)# u_0 = assemble(u*dx)# plot(u, title='u', scale=0.0)print "solver... finished"print "calculating armijo steps..."# u = u - u_0alpha = 0.5tau = 0.00001# calculate j(phi) (need to be computed only once)j_phi = assemble(0.5 * (y - y_obs) * (y - y_obs) * dx + sigma * epsln * 0.5 * inner(nabla_grad(phi), nabla_grad(phi)) * dx + ( sigma / epsln) * 0.5 * (e_n - phi * phi) * dx)print "assemlbing j(phi) is done.."# calculate j'(phi) * v (needs to be computed only once)F_a = assemble((( - a_1 * (1 + u)/2 + a_2 * (1 - u)/2 ) * inner(nabla_grad(y), nabla_grad(p)) *dx ))print "assemlbing f' (1) is done.."F_b = 0.5 * sigma * epsln * assemble(inner(nabla_grad(phi), nabla_grad(u))*dx)print "assemlbing f' (2) is done.."F_c = 0.5 * (- sigma/epsln) * assemble(phi * u*dx)print "assemlbing f' (3) is done.."max_iter = 100for i in range (0,max_iter):#set alpha due to armijo conditionalph_calc = alpha ** i# Define variational problem for new phi valuephi_2 = phi + alph_calc * ua_phi_2 = a_1 * (1 + phi_2)/2 + a_2 * (1 - phi_2)/2# Define variational problem(y_2, c) = TrialFunction(W)(v, d) = TestFunctions(W)a = a_phi_2*(inner(grad(y_2), grad(v)) + c*v + y_2*d)*dxL = f*v*dx + g_h*v*ds# Compute solutionw = Function(W)solve(a == L, w)(y_2, c) = w.split()print "solved variational problem for armijo steps.."# Plot solution# plot(y_2, interactive=True)# calculate new j(phi + alpha * v)#j_phi_new = assemble(0.5 * (y_2 - y_obs) * dx + sigma * epsln * 0.5 * inner(nabla_grad(phi_init_2), nabla_grad(phi_init_2)) * dx + ( sigma / epsln) * 0.5 * (e_n - phi_init_2 * phi_init_2) * dx)j_phi_new = assemble(0.5 * (y_2 - y_obs) * (y_2 - y_obs) * dx + sigma * epsln * 0.5 * inner(nabla_grad(phi_2), nabla_grad(phi_2)) * dx + ( sigma / epsln) * 0.5 * (e_n - phi_2 * phi_2) * dx)print "assembling j(phi_new) is done..."# multiply with alphaF = tau * alph_calc * (F_a + F_b + F_c)print "alpha * f' has been set..."#check if armijo condition is fullfilledarmijovalue = j_phi - j_phi_new + Fif armijovalue > - DOLFIN_EPS:# plot(u, title='u', scale=0.0)# plot(phi, title='phi', scale=0.0)phi = phi + alph_calc * u# print assemble(phi*dx)# test = phi - phi_eplot(phi_e - phi, title='phi', scale=0.0)breakif i == 100:print "ERROR!!!"norm = assemble(u * u *dx + inner(nabla_grad(u),nabla_grad(u))*dx)print "assembled norm - checking for convergence..."print normprint "current step"print problemitif(norm < 0.0001) :time2 = time()print "finished"solving = Falseprint "after Iteration"print problemitprint "time:"print time2 - timeinteractive()print "End of Code..."
f_29 + f_54 + -1 * f_29 in the first iteration step
f_29 + f_54 + -1 * f_29 + f_2134 + -1 * (f_29 + f_54 + -1 * f_29) in the second step
f_29 + f_54 + -1 * f_29 + f_2134 + -1 * (f_29 + f_54 + -1 * f_29) + f_3062 + -1 * (f_29 + f_54 + -1 * f_29 + f_2134 + -1 * (f_29 + f_54 + -1 * f_29)) in the third step and so on..
is it possible to pass on the value, so that it does not need to be reevaluated in every step?