def _solveTangentProblem(self, dstate, m_hat, x): """ The predictor step for the parameter continuation algorithm. """ state_fun = vector2Function(x[STATE], self.Vh[STATE]) statel_fun = vector2Function(x[STATE], self.Vh[STATE]) param_fun = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) param_hat_fun = vector2Function(m_hat, self.Vh[PARAMETER]) x_test = [ dl.TestFunction(self.Vh[STATE]), dl.TestFunction(self.Vh[PARAMETER]) ] x_trial = [ dl.TrialFunction(self.Vh[STATE]), dl.TrialFunction(self.Vh[PARAMETER]) ] res = self.model.residual(state_fun, x_test[STATE], dl.Constant(0.), param_fun, None, statel_fun, True) Aform = dl.derivative(res, state_fun, x_trial[STATE]) + dl.derivative( res, statel_fun, x_trial[STATE]) b_form = dl.derivative(res, param_fun, param_hat_fun) A, b = dl.assemble_system(Aform, b_form, self.bcs0, form_compiler_parameters=self.fcp) solver = dl.PETScLUSolver() solver.set_operator(A) solver.solve(dstate, -b)
def __init__(self, Vh, model, bcs, bcs0, initial_guess, verbose=True): """ Constructor: - Vh: a list of finite element space for the state, parameter and adjoint variables. Note that the space for the state and adjoint variables need to be the same. - model: a class that provides the weak form for the residual and Jacobian of the forward problem. See RANSModel_inadeguate_Cmu for an example. - bcs: list of essential boundary conditions for the forward problem. - bcs0: list of (homogeneus) essential boundary conditions for the adjoint and incremental problems. - initial_guess: an initial guess vector for the TransientContinuation solver """ self.Vh = Vh self.model = model self.bcs = bcs self.bcs0 = bcs0 self.initial_guess = initial_guess.copy() self.verbose = verbose self.x_cont = None self.x_latest = None self.final_norm_cont = 1e-10 self.A = [] self.Asolver = dl.PETScLUSolver() self.C = [] self.Wum = [] self.Wmm = [] self.Wuu = [] self.fcp = {} self.fcp["quadrature_degree"] = 3
def do_linear_solve(self): A, Qdu, b = self.A, self.Qdu, self.b q = self.q solver = dolfin.PETScLUSolver("umfpack") solver.solve(A, Qdu, b) ### trash not working code ### # solver = dolfin.KrylovSolver('gmres', 'ilu') # prm = solver.parameters # prm['absolute_tolerance'] = 1E-5 # prm['relative_tolerance'] = 1E-5 # prm['maximum_iterations'] = 5000 # prm["monitor_convergence"] = True # solver.solve(A, Qdu, b) # try: # solver.solve(self.A, Qdu, self.b) # except: # try: # prm['nonzero_initial_guess'] = True # solver.solve(self.A, Qdu, self.b) # except: # raise if q is not None: dolfin.as_backend_type(self.du.vector()).vec().pointwiseMult( q, Qdu.vec()) else: self.du.vector()[:] = Qdu.get_local( ) # FIXME: EXTREMELY INEFFICIENT!
def __init__(self, mesh, Vh, prior, misfit, simulation_times, wind_velocity, gls_stab): self.mesh = mesh self.Vh = Vh self.prior = prior self.misfit = misfit # Assume constant timestepping self.simulation_times = simulation_times dt = simulation_times[1] - simulation_times[0] u = dl.TrialFunction(Vh[STATE]) v = dl.TestFunction(Vh[STATE]) kappa = dl.Constant(.001) dt_expr = dl.Constant(dt) r_trial = u + dt_expr * (-ufl.div(kappa * ufl.grad(u)) + ufl.inner(wind_velocity, ufl.grad(u))) r_test = v + dt_expr * (-ufl.div(kappa * ufl.grad(v)) + ufl.inner(wind_velocity, ufl.grad(v))) h = dl.CellDiameter(mesh) vnorm = ufl.sqrt(ufl.inner(wind_velocity, wind_velocity)) if gls_stab: tau = ufl.min_value((h * h) / (dl.Constant(2.) * kappa), h / vnorm) else: tau = dl.Constant(0.) self.M = dl.assemble(ufl.inner(u, v) * dl.dx) self.M_stab = dl.assemble(ufl.inner(u, v + tau * r_test) * dl.dx) self.Mt_stab = dl.assemble(ufl.inner(u + tau * r_trial, v) * dl.dx) Nvarf = (ufl.inner(kappa * ufl.grad(u), ufl.grad(v)) + ufl.inner(wind_velocity, ufl.grad(u)) * v) * dl.dx Ntvarf = (ufl.inner(kappa * ufl.grad(v), ufl.grad(u)) + ufl.inner(wind_velocity, ufl.grad(v)) * u) * dl.dx self.N = dl.assemble(Nvarf) self.Nt = dl.assemble(Ntvarf) stab = dl.assemble(tau * ufl.inner(r_trial, r_test) * dl.dx) self.L = self.M + dt * self.N + stab self.Lt = self.M + dt * self.Nt + stab self.solver = dl.PETScLUSolver(dl.as_backend_type(self.L)) self.solvert = dl.PETScLUSolver(dl.as_backend_type(self.Lt)) # Part of model public API self.gauss_newton_approx = False
def __init__(self, Vh, varf_handler, bc, bc0, is_fwd_linear=False): self.Vh = Vh self.varf_handler = varf_handler self.bc = bc self.bc0 = bc0 self.A = [] self.At = [] self.C = [] self.Wau = [] self.Waa = [] self.Wuu = [] self.solver_fwd_inc = dl.PETScLUSolver() self.solver_adj_inc = dl.PETScLUSolver() self.is_fwd_linear = is_fwd_linear
def _set_solver(self,operator,op_name=None): """ Set the solver of an operator """ if type(operator) is df.PETScMatrix: if df.__version__<='1.6.0': solver = df.PETScLUSolver('mumps' if df.has_lu_solver_method('mumps') else 'default') solver.set_operator(operator) solver.parameters['reuse_factorization']=True else: solver = df.PETScLUSolver(self.mpi_comm,operator,'mumps' if df.has_lu_solver_method('mumps') else 'default') # solver.set_operator(operator) # solver.parameters['reuse_factorization']=True if op_name == 'K': solver.parameters['symmetric']=True else: import scipy.sparse.linalg as spsla solver = spsla.splu(operator.tocsc(copy=True)) return solver
def __init__(self,A): """ Contructor INPUT: - A: a s.p.d. finite element matrix """ self.Ainv = dl.PETScLUSolver() self.Ainv.set_operator(A) self.tmp = dl.Vector() A.init_vector(self.tmp,0)
def setLinearizationPoint(self, x): """ Set the values of the state and parameter for the incremental Fwd and Adj solvers """ u = vector2Function(x[STATE], self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = vector2Function(x[ADJOINT], self.Vh[ADJOINT]) x_fun = [u, a, p] f_form = self.varf_handler(u, a, p) g_form = [None, None, None] for i in range(3): g_form[i] = dl.derivative(f_form, x_fun[i]) self.A, dummy = dl.assemble_system(dl.derivative(g_form[ADJOINT], u), g_form[ADJOINT], self.bc0) self.At, dummy = dl.assemble_system(dl.derivative(g_form[STATE], p), g_form[STATE], self.bc0) self.C = dl.assemble(dl.derivative(g_form[ADJOINT], a)) [bc.zero(self.C) for bc in self.bc0] self.Wau = dl.assemble(dl.derivative(g_form[PARAMETER], u)) Wau_t = Transpose(self.Wau) [bc.zero(Wau_t) for bc in self.bc0] self.Wau = Transpose(Wau_t) self.Wuu = dl.assemble(dl.derivative(g_form[STATE], u)) [bc.zero(self.Wuu) for bc in self.bc0] Wuu_t = Transpose(self.Wuu) [bc.zero(Wuu_t) for bc in self.bc0] self.Wuu = Transpose(Wuu_t) self.Waa = dl.assemble(dl.derivative(g_form[PARAMETER], a)) if self.solver_fwd_inc is None: self.solver_fwd_inc = dl.PETScLUSolver() self.solver_adj_inc = dl.PETScLUSolver() self.solver_fwd_inc.set_operator(self.A) self.solver_adj_inc.set_operator(self.At)
def __init__(self, Vh, varf_handler, bc, bc0, is_fwd_linear = False): self.Vh = Vh self.varf_handler = varf_handler if type(bc) is dl.DirichletBC: self.bc = [bc] else: self.bc = bc if type(bc0) is dl.DirichletBC: self.bc0 = [bc0] else: self.bc0 = bc0 self.A = [] self.At = [] self.C = [] self.Wau = [] self.Waa = [] self.Wuu = [] self.solver_fwd_inc = dl.PETScLUSolver() self.solver_adj_inc = dl.PETScLUSolver() self.is_fwd_linear = is_fwd_linear
def solveAdj(self, adj, x, adj_rhs, tol): """ Solve the linear Adj Problem: Given a, u; find p such that \delta_u F(u,a,p;\hat_u) = 0 \for all \hat_u """ problem = NonlinearProblem(self.Vh[STATE], self.model, self.bcs, self.bcs0) problem.fcp = self.fcp extra_args = (dl.Constant(0.), vector2Function(x[PARAMETER], self.Vh[PARAMETER]), None, None, True) A = problem.Jacobian(x[STATE], extra_args) problem.applyBC0(adj_rhs) solver = dl.PETScLUSolver() solver.set_operator(A) solver.solve_transpose(x[ADJOINT], adj_rhs)
def solveAdj(self, adj, x, adj_rhs, tol): """ Solve the linear Adj Problem: Given a, u; find p such that \delta_u F(u,a,p;\hat_u) = 0 \for all \hat_u """ u = vector2Function(x[STATE], self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.Function(self.Vh[ADJOINT]) du = dl.TestFunction(self.Vh[STATE]) dp = dl.TrialFunction(self.Vh[ADJOINT]) varf = self.varf_handler(u,a,p) adj_form = dl.derivative( dl.derivative(varf, u, du), p, dp ) Aadj, dummy = dl.assemble_system(adj_form, dl.Constant(0.)*dl.inner(u,du)*dl.dx, self.bc0) solver = dl.PETScLUSolver() solver.set_operator(Aadj) solver.solve(adj, adj_rhs)
def computeTangent(self): dy = df.Measure('dx', self.mesh) vol = df.assemble(df.Constant(1.0) * dy) y = df.SpatialCoordinate(self.mesh) Eps = df.Constant(((0., 0.), (0., 0.))) # just placeholder form = self.multiscaleModel(self.mesh, self.sigmaLaw, Eps, self.others) a, f, bcs, W = form() start = timer() A = mp.block_assemble(a) if (len(bcs) > 0): bcs.apply(A) # decompose just once (the faster for single process) solver = df.PETScLUSolver('superlu') sol = mp.BlockFunction(W) end = timer() print('time assembling system', end - start) for i in range(self.nvoigt): start = timer() Eps.assign(df.Constant(macro_strain(i))) F = mp.block_assemble(f) if (len(bcs) > 0): bcs.apply(F) solver.solve(A, sol.block_vector(), F) sol.block_vector().block_function().apply("to subfunctions") sig_mu = self.sigmaLaw(df.dot(Eps, y) + sol[0]) sigma_hom = Integral(sig_mu, dy, (2, 2)) / vol self.Chom_[:, i] = sigma_hom.flatten()[[0, 3, 1]] end = timer() print('time in solving system', end - start) print(self.Chom_) # from the second run onwards, just returns self.getTangent = self.getTangent_ return self.Chom_
def __init__(self, solver_method, preconditioner=None, lu_method=None, parameters=None): """ Wrap a DOLFIN PETScKrylovSolver or PETScLUSolver You must either specify solver_method = 'lu' and give the name of the solver, e.g lu_solver='mumps' or give a valid Krylov solver name, eg. solver_method='minres' and give the name of a preconditioner, eg. preconditioner_name='hypre_amg'. The parameters argument is a *list* of dictionaries which are to be used as parameters to the Krylov solver. Settings in the first dictionary in this list will be (potentially) overwritten by settings in later dictionaries. The use case is to provide sane defaults as well as allow the user to override the defaults in the input file The reason for this wrapper is to provide easy querying of iterative/direct and not crash when set_reuse_preconditioner is run before the first solve. This simplifies usage """ self.solver_method = solver_method self.preconditioner = preconditioner self.lu_method = lu_method self.input_parameters = parameters self.is_first_solve = True self.is_iterative = False self.is_direct = False if solver_method.lower() == 'lu': solver = dolfin.PETScLUSolver(lu_method) self.is_direct = True else: precon = dolfin.PETScPreconditioner(preconditioner) solver = dolfin.PETScKrylovSolver(solver_method, precon) self._pre_obj = precon # Keep from going out of scope self.is_iterative = True for parameter_set in parameters: apply_settings(solver_method, solver.parameters, parameter_set) self._solver = solver
def forward_sensitivities(self, sm, dm): assert self.extra_args[self.parameter_location] == None assert self.extra_args[self.field_location] == None assert self.extra_args[-1] == True d_state = dl.Function( self.Vh[STATE] ).vector() dd_state = dl.Function( self.Vh[STATE] ).vector() [state_fun, m_fun] = [vector2Function(sm[ii], self.Vh[ii]) for ii in range(2)] dm_fun = vector2Function(dm, self.Vh[PARAMETER]) e_mean_fun =vector2Function(self.field.e_mean, self.Vh[FIELD]) test = dl.TestFunction(self.Vh[STATE]) trial = dl.TrialFunction(self.Vh[STATE]) self.extra_args[self.parameter_location] = m_fun self.extra_args[self.field_location] = e_mean_fun res_form = self.model.residual(state_fun, test, *self.extra_args) J_form = dl.derivative(res_form, state_fun, trial) b1_form = dl.derivative(res_form, m_fun, dm_fun) J, b1 = dl.assemble_system(J_form, b1_form, bcs = self.bcs0, form_compiler_parameters = self.fcp) Jsolver = dl.PETScLUSolver() Jsolver.set_operator(J) Jsolver.solve(d_state, -b1) d_state_fun = vector2Function(d_state, self.Vh[STATE]) b2_form = dl.derivative( dl.derivative(res_form, state_fun, d_state_fun), state_fun, d_state_fun ) \ + dl.Constant(2.)*dl.derivative( dl.derivative(res_form, state_fun, d_state_fun), m_fun, dm_fun ) \ + dl.derivative( dl.derivative(res_form, m_fun, dm_fun), m_fun, dm_fun ) b2 = dl.assemble(b2_form, form_compiler_parameters=self.fcp) [bc.apply(b2) for bc in self.bcs0] Jsolver.solve(dd_state, -b2) self.extra_args[self.parameter_location] = None self.extra_args[self.field_location] = None return d_state, dd_state
def get_tangent(self): if self.Chom_ is None: self.Chom_ = np.zeros((self.nvoigt, self.nvoigt)) dy = ufl.Measure("dx", self.mesh) vol = df.assemble(df.Constant(1.0) * dy) y = ufl.SpatialCoordinate(self.mesh) Eps = df.Constant(((0., 0.), (0., 0.))) # just placeholder form = self.multiscale_model(self.mesh, self.sigma_law, Eps, self.others) a, f, bcs, W = form() start = timer() A = mp.block_assemble(a) if len(bcs) > 0: bcs.apply(A) # decompose just once, since the matrix A is the same in every solve solver = df.PETScLUSolver("superlu") sol = mp.BlockFunction(W) end = timer() print("time assembling system", end - start) for i in range(self.nvoigt): start = timer() Eps.assign(df.Constant(self.macro_strain(i))) F = mp.block_assemble(f) if len(bcs) > 0: bcs.apply(F) solver.solve(A, sol.block_vector(), F) sol.block_vector().block_function().apply("to subfunctions") sig_mu = self.sigma_law(df.dot(Eps, y) + sol[0]) sigma_hom = self.integrate(sig_mu, dy, (2, 2)) / vol self.Chom_[:, i] = sigma_hom.flatten()[[0, 3, 1]] end = timer() print("time in solving system", end - start) return self.Chom_
def solveFwd(self, state, x, tol): """ Solve the possibly nonlinear Fwd Problem: Given a, find u such that \delta_p F(u,a,p;\hat_p) = 0 \for all \hat_p""" if self.is_fwd_linear: u = dl.TrialFunction(self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, a, p) A_form = dl.lhs(res_form) b_form = dl.rhs(res_form) A, b = dl.assemble_system(A_form, b_form, bcs=self.bc) solver = dl.PETScLUSolver() solver.set_operator(A) solver.solve(state, b) else: u = vector2Function(x[STATE], self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, a, p) dl.solve(res_form == 0, u, self.bc) state.zero() state.axpy(1., u.vector())
def PETScLUSolver(comm, method='default'): if not hasattr(dl.PETScLUSolver, 'set_operator'): dl.PETScLUSolver.set_operator = _PETScLUSolver_set_operator return dl.PETScLUSolver(comm, method)
def solveAdj(self, adj, x, adj_rhs, tol): """ Solve the linear Adj Problem: Given a, u; find p such that \delta_u F(u,a,p;\hat_u) = 0 \for all \hat_u """ assert self.extra_args[-1] == True assert self.extra_args[self.parameter_location] == None assert self.extra_args[self.field_location] == None s0_fun = vector2Function(x[STATE].s0, self.Vh[STATE]) m_fun = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) e_fun = vector2Function(self.field.e_mean, self.Vh[FIELD]) p_fun = dl.Function(self.Vh[STATE]) self.extra_args[self.parameter_location] = m_fun self.extra_args[self.field_location] = e_fun test = dl.TestFunction(self.Vh[STATE]) trial = dl.TrialFunction(self.Vh[STATE]) res_form = self.model.residual(s0_fun, p_fun, *self.extra_args) Jt_form = dl.derivative(dl.derivative(res_form, s0_fun, test), p_fun, trial) Jt = dl.assemble(Jt_form, form_compiler_parameters = self.fcp) [bc.apply(Jt) for bc in self.bcs0] Jtsolver = dl.PETScLUSolver() Jtsolver.set_operator(Jt) rhs0 = adj_rhs.s0.copy() for ii in range(self.field.n_fields): #Second order incrementals rhs = adj_rhs.s2[ii].copy() [bc.apply(rhs) for bc in self.bcs0] Jtsolver.solve(adj.s2[ii], rhs) #First order incrementals s1_fun = vector2Function(x[STATE].s1[ii], self.Vh[STATE]) de_fun = vector2Function(self.field.ei[ii], self.Vh[FIELD]) p2_fun = vector2Function(adj.s2[ii], self.Vh[ADJOINT]) res_form1 = self.model.residual(s0_fun, p2_fun, *self.extra_args) du_res_form1 = dl.derivative(res_form1, s0_fun, test) duu_res_form1 = dl.derivative(du_res_form1, s0_fun, s1_fun) due_res_form1 = dl.derivative(du_res_form1, e_fun, de_fun) rhs = dl.assemble(dl.Constant(-2.)*duu_res_form1 + dl.Constant(-2.)*due_res_form1) rhs.axpy(1., adj_rhs.s1[ii]) [bc.apply(rhs) for bc in self.bcs0] Jtsolver.solve(adj.s1[ii], rhs) #Accumulate terms for the adjoint #first term p1_fun = vector2Function(adj.s1[ii], self.Vh[ADJOINT]) res_form0a = self.model.residual(s0_fun, p1_fun, *self.extra_args) du_res_form0a = dl.derivative(res_form0a, s0_fun, test) duu_res_form0a = dl.derivative(du_res_form0a, s0_fun, s1_fun) due_res_form0a = dl.derivative(du_res_form0a, e_fun, de_fun) rhs = dl.assemble(-duu_res_form0a-due_res_form0a) rhs0.axpy(1., rhs) #second term s2_fun = vector2Function(x[STATE].s2[ii], self.Vh[STATE]) res_form0b = self.model.residual(s0_fun, p2_fun, *self.extra_args) du_res_form0b = dl.derivative(res_form0b, s0_fun, test) duu_res_form0b = dl.derivative(du_res_form0b, s0_fun, s2_fun) duuu_res_form0b = dl.derivative(dl.derivative(du_res_form0b, s0_fun, s1_fun), s0_fun, s1_fun) duue_res_form0b = dl.derivative(dl.derivative(du_res_form0b, s0_fun, s1_fun), e_fun, de_fun) duee_res_form0b = dl.derivative(dl.derivative(du_res_form0b, e_fun, de_fun), e_fun, de_fun) rhs = dl.assemble(-duu_res_form0b-duuu_res_form0b-dl.Constant(2.)*duue_res_form0b-duee_res_form0b) rhs0.axpy(1., rhs) [bc.apply(rhs0) for bc in self.bcs0] Jtsolver.solve(adj.s0, rhs0) self.extra_args[self.parameter_location] = None self.extra_args[self.field_location] = None
def solveFwd(self, state, x, tol): """ Solve the possibly nonlinear Fwd Problem: Given a, find u such that \delta_p F(u,a,p;\hat_p) = 0 \for all \hat_p""" # STEP 1. Find state0 dm_norms = [ (x[PARAMETER] - mi).norm("l2") for mi in self.continuation_ms] min_dm_norms, idx = min( (dm_norms[ii], ii) for ii in range(len(self.continuation_ms))) m_start = self.continuation_ms[idx].copy() state.s0.zero() state.s0.axpy(1., self.continuation_states[idx]) while (x[PARAMETER]-m_start).norm("l2") > dl.DOLFIN_EPS: self._fwd_cont(state.s0, m_start, x[PARAMETER]) if len(self.continuation_ms) < self.continuation_maxlen: self.continuation_states.append(state.s0.copy()) self.continuation_ms.append(x[PARAMETER].copy()) else: index = (self.continuation_i % (self.continuation_maxlen-1)) +1 self.continuation_states[index] = state.s0.copy() self.continuation_ms[index] = x[PARAMETER].copy() self.continuation_i = index # 2. Solve the first and second order incrementals s0_fun = vector2Function(state.s0, self.Vh[STATE]) m_fun = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) e_fun = vector2Function(self.field.e_mean, self.Vh[FIELD]) self.extra_args[self.parameter_location] = m_fun self.extra_args[self.field_location] = e_fun self.extra_args[-1] = True test = dl.TestFunction(self.Vh[STATE]) trial = dl.TrialFunction(self.Vh[STATE]) res_form = self.model.residual(s0_fun, test, *self.extra_args) Jform = dl.derivative(res_form ,s0_fun, trial) J = dl.assemble(Jform, form_compiler_parameters = self.fcp) [bc.apply(J) for bc in self.bcs0] Jsolver = dl.PETScLUSolver() Jsolver.set_operator(J) for ii in range(self.field.n_fields): de_fun = vector2Function(self.field.ei[ii], self.Vh[FIELD]) b1_form = dl.derivative(res_form, e_fun, de_fun) b1 = dl.assemble(b1_form, form_compiler_parameters = self.fcp) [bc.apply(b1) for bc in self.bcs0] Jsolver.solve(state.s1[ii], -b1) s1_fun = vector2Function(state.s1[ii], self.Vh[STATE]) b2_form = dl.derivative( dl.derivative(res_form, s0_fun, s1_fun), s0_fun, s1_fun) + \ dl.Constant(2.)*dl.derivative( dl.derivative(res_form, s0_fun, s1_fun), e_fun, de_fun) + \ dl.derivative( dl.derivative(res_form, e_fun, de_fun), e_fun, de_fun) b2 = dl.assemble(b2_form, form_compiler_parameters = self.fcp) [bc.apply(b2) for bc in self.bcs0] Jsolver.solve(state.s2[ii], -b2) self.extra_args[self.parameter_location] = None self.extra_args[self.field_location] = None
def _createLUSolver(self): if dlversion() <= (1,6,0): return dl.PETScLUSolver() else: return dl.PETScLUSolver(self.Vh[STATE].mesh().mpi_comm() )
def __init__(self, mesh, Vh, t_init, t_final, t_1, dt, wind_velocity, gls_stab, Prior): self.mesh = mesh self.Vh = Vh self.t_init = t_init self.t_final = t_final self.t_1 = t_1 self.dt = dt self.sim_times = np.arange(self.t_init, self.t_final + .5 * self.dt, self.dt) u = dl.TrialFunction(Vh[STATE]) v = dl.TestFunction(Vh[STATE]) kappa = dl.Constant(.001) dt_expr = dl.Constant(self.dt) r_trial = u + dt_expr * (-dl.div(kappa * dl.nabla_grad(u)) + dl.inner(wind_velocity, dl.nabla_grad(u))) r_test = v + dt_expr * (-dl.div(kappa * dl.nabla_grad(v)) + dl.inner(wind_velocity, dl.nabla_grad(v))) h = dl.CellSize(mesh) vnorm = dl.sqrt(dl.inner(wind_velocity, wind_velocity)) if gls_stab: tau = dl.Min((h * h) / (dl.Constant(2.) * kappa), h / vnorm) else: tau = dl.Constant(0.) self.M = dl.assemble(dl.inner(u, v) * dl.dx) self.M_stab = dl.assemble(dl.inner(u, v + tau * r_test) * dl.dx) self.Mt_stab = dl.assemble(dl.inner(u + tau * r_trial, v) * dl.dx) Nvarf = (dl.inner(kappa * dl.nabla_grad(u), dl.nabla_grad(v)) + dl.inner(wind_velocity, dl.nabla_grad(u)) * v) * dl.dx Ntvarf = (dl.inner(kappa * dl.nabla_grad(v), dl.nabla_grad(u)) + dl.inner(wind_velocity, dl.nabla_grad(v)) * u) * dl.dx self.N = dl.assemble(Nvarf) self.Nt = dl.assemble(Ntvarf) stab = dl.assemble(tau * dl.inner(r_trial, r_test) * dl.dx) self.L = self.M + dt * self.N + stab self.Lt = self.M + dt * self.Nt + stab boundaries = dl.FacetFunction("size_t", mesh) boundaries.set_all(0) class InsideBoundary(dl.SubDomain): def inside(self, x, on_boundary): x_in = x[0] > dl.DOLFIN_EPS and x[0] < 1 - dl.DOLFIN_EPS y_in = x[1] > dl.DOLFIN_EPS and x[1] < 1 - dl.DOLFIN_EPS return on_boundary and x_in and y_in Gamma_M = InsideBoundary() Gamma_M.mark(boundaries, 1) ds_marked = dl.Measure("ds", subdomain_data=boundaries) self.Q = dl.assemble(self.dt * dl.inner(u, v) * ds_marked(1)) self.Prior = Prior if dlversion() <= (1, 6, 0): self.solver = dl.PETScLUSolver() else: self.solver = dl.PETScLUSolver(self.mesh.mpi_comm()) self.solver.set_operator(self.L) if dlversion() <= (1, 6, 0): self.solvert = dl.PETScLUSolver() else: self.solvert = dl.PETScLUSolver(self.mesh.mpi_comm()) self.solvert.set_operator(self.Lt) self.ud = self.generate_vector(STATE) self.noise_variance = 0 # Part of model public API self.gauss_newton_approx = False
def computeTangent(self): self.readMesh() sigmaLaw = lambda u: self.lame[0] * nabla_div(u) * df.Identity( 2) + 2 * self.lame[1] * symgrad(u) dy = self.mesh.dx # specially for the case of enriched mesh, otherwise it does not work vol = df.assemble(df.Constant(1.0) * dy(0)) + df.assemble( df.Constant(1.0) * dy(1)) y = df.SpatialCoordinate(self.mesh) Eps = df.Constant(((0., 0.), (0., 0.))) # just placeholder form = self.multiscaleModel(self.mesh, sigmaLaw, Eps, self.others) a, f, bcs, W = form() start = timer() A = mp.block_assemble(a) if (len(bcs) > 0): bcs.apply(A) solver = df.PETScLUSolver('superlu') sol = mp.BlockFunction(W) if (self.model == 'lin' or self.model == 'dnn'): Vref = self.others['uD'].function_space() Mref = Vref.mesh() normal = df.FacetNormal(Mref) volMref = 4.0 B = np.zeros((2, 2)) for i in range(self.nvoigt): start = timer() if (self.model == 'lin' or self.model == 'dnn'): self.others['uD'].vector().set_local( self.others['uD{0}_'.format(i)]) B = -feut.Integral(df.outer(self.others['uD'], normal), Mref.ds, (2, 2)) / volMref T = feut.affineTransformationExpression( np.zeros(2), B, Mref) # ignore a, since the basis is already translated self.others['uD'].vector().set_local( self.others['uD'].vector().get_local()[:] + df.interpolate(T, Vref).vector().get_local()[:]) Eps.assign(df.Constant(mscm.macro_strain(i) - B)) F = mp.block_assemble(f) if (len(bcs) > 0): bcs.apply(F) solver.solve(A, sol.block_vector(), F) sol.block_vector().block_function().apply("to subfunctions") sig_mu = sigmaLaw(df.dot(Eps, y) + sol[0]) sigma_hom = sum([Integral(sig_mu, dy(i), (2, 2)) for i in [0, 1]]) / vol self.Chom_[:, i] = sigma_hom.flatten()[[0, 3, 1]] end = timer() print('time in solving system', end - start) # Time in seconds self.getTangent = self.getTangent_ # from the second run onwards, just returns return self.Chom_
def _createLUSolver(self): return dl.PETScLUSolver(self.Vh[STATE].mesh().mpi_comm())
def unconstrained_newton_solve(F,J,uh,dirichlet_bcs=None,bc0=None, linear_solver=None,opts=dict()): """ F: dl.Expression The variational form. uh : dl.Function Final solution. The initial state on entry to the function will be used as initial guess and then overwritten dirichlet_bcs : list The Dirichlet boundary conditions on the unknown u. bc0 : list The Dirichlet boundary conditions for the step (du) in the Newton iterations. """ max_iter = opts.get("max_iter",50) # exit when sqrt(g,g)/sqrt(g_0,g_0) <= rel_tolerance" rtol = opts.get("rel_tolerance",1e-8) # exit when sqrt(g,g) <= abs_tolerance atol = opts.get("abs_tolerance",1e-9) # exit when (g,du) <= gdu_tolerance gdu_tol = opts.get("gdu_tolerance",1e-14) # define armijo sufficient decrease c_armijo = opts.get("c_armijo",1e-4) # exit if max backtracking steps reached max_backtrack = opts.get("max_backtracking_iter",20) # define verbosity prt_level = opts.get("print_level",0) termination_reasons = ["Maximum number of Iteration reached", #0 "Norm of the gradient less than tolerance", #1 "Maximum number of backtracking reached", #2 "Norm of (g, du) less than tolerance", #3 "Norm of residual less than tolerance"] #4 it = 0 total_cg_iter = 0 converged = False reason = 0 if prt_level > 0: print ("Solving Nonlinear Problem") # Applying boundary conditions if dirichlet_bcs is not None: if type(dirichlet_bcs) is dl.DirichletBC: bcsl = [dirichlet_bcs] else: bcsl = dirichlet_bcs [bc.apply(uh.vector()) for bc in bcsl] if type(bc0) is dl.DirichletBC: bc0 = [bc0] # Setting variables gn = dl.assemble(F) res_func = dl.Function(uh.function_space()) res_func.assign(dl.Function(uh.function_space(),gn)) res = res_func.vector() if bc0 is not None: for bc in bc0: bc.apply(res) Fn = res.norm("l2") g0_norm = gn.norm("l2") gn_norm = g0_norm tol = max(g0_norm*rtol, atol) res_tol=max(Fn*rtol, atol) du = dl.Function(uh.function_space()).vector() if linear_solver =='PETScLU': linear_solver = dl.PETScLUSolver(uh.function_space().mesh().mpi_comm()) else: assert linear_solver is None if prt_level > 0: print( "{0:>3} {1:>6} {2:>15} {3:>15} {4:>15} {5:>15} {6:>6}".format( "Nit", "CGit", "||r||", "||g||", "(g,du)", "alpha", "Nbt") ) print("{0:3d} {1:6d} {2:15e} {3:15e} {4:15} {5:10} {6:s}".format( 0, 0, Fn, g0_norm, " NA ", " NA", "NA") ) converged = False reason = 0 nbt = 0 for it in range(max_iter): if bc0 is not None: [Hn, gn] = dl.assemble_system(J, F, bc0) else: Hn = dl.assemble(J) gn = dl.assemble(F) Hn.init_vector(du,1) if linear_solver is None: lin_it = dl.solve(Hn, du, -gn, "cg", "petsc_amg") else: linear_solver.set_operator(Hn) lin_it = linear_solver.solve(du, -gn) total_cg_iter += lin_it du_gn = du.inner(gn) alpha = 1.0 if (np.abs(du_gn) < gdu_tol): converged = True reason = 3 uh.vector().axpy(alpha,du) gn_norm = gn.norm("l2") Fn = gn_norm break uh_backtrack = uh.copy(deepcopy=True) bk_converged = False #Backtrack for nbt in range(max_backtrack): uh.assign(uh_backtrack) uh.vector().axpy(alpha,du) res = dl.assemble(F) if bc0 is not None: for bc in bc0: bc.apply(res) Fnext=res.norm("l2") #print(Fn,Fnext,Fn + alpha*c_armijo*du_gn) if Fnext < Fn + alpha*c_armijo*du_gn: #if True: Fn = Fnext bk_converged = True break alpha /= 2. if not bk_converged: reason = 2 break gn_norm = gn.norm("l2") if prt_level > 0: print("{0:3d} {1:6d} {2:15e} {3:15e} {4:15e} {5:15e} {6:3d}".format( it+1, lin_it, Fn, gn_norm, du_gn, alpha, nbt+1) ) if gn_norm < tol: converged = True reason = 1 break if Fn< res_tol: converged=True reason = 4 break if prt_level > 0: if reason is 3: print("{0:3d} {1:6d} {2:15e} {3:15e} {4:15e} {5:15e} {6:3d}".format( it+1, lin_it, Fn, gn_norm, du_gn, alpha, nbt+1) ) print( termination_reasons[reason] ) if converged: print("Newton converged in ", it, \ "nonlinear iterations and ", total_cg_iter, "linear iterations." ) else: print("Newton did NOT converge in ", it, "iterations." ) print ("Final norm of the gradient: ", gn_norm) print ("Value of the cost functional: ", Fn ) if reason in [0,2]: raise Exception(termination_reasons[reason]) return uh
def solve(self, x): rtol = self.parameters["rel_tolerance"] atol = self.parameters["abs_tolerance"] max_iter = self.parameters["max_iter"] max_backtracking = self.parameters["max_backtracking"] self.problem.applyBC(x) if self.callback is not None: self.callback(x) r = self.problem.residual(x, self.extra_args) norm_r0 = self._norm_r(r) norm_r = norm_r0 self.initial_norm = norm_r0 tol = max(atol, rtol * norm_r0) self.converged = False it = 0 d = dl.Vector() if (self.parameters["print_level"] >= 1): print "\n{0:3} {1:15} {2:15}".format("It", "||r||", "alpha") if self.parameters["print_level"] >= 1: print "{0:3d} {1:15e} {2:15e}".format(it, norm_r0, 1.) while it < max_iter and not self.converged: J = self.problem.Jacobian(x, self.extra_args) JSolver = dl.PETScLUSolver() JSolver.set_operator(J) JSolver.solve(d, -r) alpha = 1. backtracking_converged = False j = 0 while j < max_backtracking and not backtracking_converged: x_new = x + alpha * d r = self.problem.residual(x_new, self.extra_args) try: norm_r_new = self._norm_r(r) except: norm_r_new = norm_r + 1. if norm_r_new <= norm_r: x.axpy(alpha, d) norm_r = norm_r_new backtracking_converged = True else: alpha = .5 * alpha j = j + 1 if not backtracking_converged: if self.parameters["print_level"] >= 0: print "Backtracking failed at iteration", it, ". Residual norm is ", norm_r self.converged = False self.final_it = it self.final_norm = norm_r break if norm_r_new < tol: if self.parameters["print_level"] >= 0: print "Converged in ", it, "iterations with final residual norm", norm_r_new self.final_norm = norm_r_new self.converged = True self.final_it = it break it = it + 1 if self.parameters["print_level"] >= 1: print "{0:3d} {1:15e} {2:15e}".format(it, norm_r, alpha) if self.callback is not None: self.callback(x) if not self.converged: self.final_norm = norm_r_new self.final_it = it if self.parameters["print_level"] >= 0: print "Not Converged in ", it, "iterations. Final residual norm", norm_r_new
def _createLUSolver(self): if dlversion() <= (1, 6, 0): return dl.PETScLUSolver() # return dl.PETScKrylovSolver("cg", amg_method()) else: return dl.PETScLUSolver(self.Vh[STATE].mesh().mpi_comm())
# Hamiltonian and mass matrix forms h = (u_r * v_r + u_z * v_z) * r * ( drdz(0) + drdz(1)) + potential * r * u * v * r * drdz(0) m = (u * v * r) * (drdz(0) + drdz(1)) # Mass matrix M = df.PETScMatrix() df.assemble(m, tensor=M) # Hamiltonian matrix H = df.PETScMatrix() df.assemble(h, tensor=H) # Solution psi = df.Function(V) solver = df.PETScLUSolver(H) solver.parameters['symmetric'] = True solver.solve(psi.vector(), Psi0) q = psi.vector() # Do inverse iteration for k in range(5): Mq = M * q qHq = q.inner(H * q) qMq = q.inner(Mq) # Rayleigh quotient E = qHq / qMq print(E)