def solve_thermal(self): """ Solve the thermal diffusion problem. Both ice and solution. """ ### Solve heat equation alphalog_i = dolfin.project(dolfin.Expression('astar*exp(-2.*x[0])',degree=1,astar=self.astar_i),self.ice_V) # Set up the variational form for the current mesh location F_i = (self.u_i-self.u0_i)*self.v_i*dolfin.dx + self.dt*dolfin.inner(dolfin.grad(self.u_i), dolfin.grad(alphalog_i*self.v_i))*dolfin.dx a_i = dolfin.lhs(F_i) L_i = dolfin.rhs(F_i) # Solve ice temperature dolfin.solve(a_i==L_i,self.T_i,[self.bc_inf,self.bc_iWall]) # Update previous profile to current self.u0_i.assign(self.T_i) diff_ratio = (self.ks*const.rhoi*const.ci)/(const.ki*self.rhos*self.cs) alphalog_s = dolfin.project(dolfin.Expression('astar*exp(-2.*x[0])',degree=1,astar=self.astar_i),self.sol_V) # Set up the variational form for the current mesh location F_s = (self.u_s-self.u0_s)*self.v_s*dolfin.dx + self.dt*dolfin.inner(dolfin.grad(self.u_s), dolfin.grad(alphalog_s*diff_ratio*self.v_s))*dolfin.dx #- self.dt*(self.Q_sol*self.t0/abs(self.T_inf)/(const.rhoi*const.ci))*self.v_s*dolfin.dx #TODO: check this solution source term # TODO: Center heat flux #F_s -= (self.Q_center/(self.ks*diff_ratio*2.*np.pi*abs(self.T_inf)))*self.v_s*self.sds(2) a_s = dolfin.lhs(F_s) L_s = dolfin.rhs(F_s) # Solve solution temperature dolfin.solve(a_s==L_s,self.T_s,self.bc_sWall) # Update previous profile to current self.u0_s.assign(self.T_s)
def solve_initial_pressure(w_NSp, p, q, u, v, bcs_NSp, M_, g_, phi_, rho_, rho_e_, V_, drho, sigma_bar, eps, grav, dveps, enable_PF, enable_EC): V = u.function_space() grad_p = df.TrialFunction(V) grad_p_out = df.Function(V) F_grad_p = (df.dot(grad_p, v) * df.dx - rho_ * df.dot(grav, v) * df.dx) if enable_PF: F_grad_p += -drho * M_ * df.inner(df.grad(u), df.outer(df.grad(g_), v)) * df.dx F_grad_p += -sigma_bar * eps * df.inner( df.outer(df.grad(phi_), df.grad(phi_)), df.grad(v)) * df.dx if enable_EC and rho_e_ != 0: F_grad_p += rho_e_ * df.dot(df.grad(V_), v) * df.dx if enable_PF and enable_EC: F_grad_p += dveps * df.dot(df.grad(phi_), v) * df.dot( df.grad(V_), df.grad(V_)) * df.dx info_red("Solving initial grad_p...") df.solve(df.lhs(F_grad_p) == df.rhs(F_grad_p), grad_p_out) F_p = (df.dot(df.grad(q), df.grad(p)) * df.dx - df.dot(df.grad(q), grad_p_out) * df.dx) info_red("Solving initial p...") df.solve(df.lhs(F_p) == df.rhs(F_p), w_NSp, bcs_NSp)
def __init__(self, t_end=None, func=None): Problem_verification.__init__(self, t_end, func) self.u0_expr = dol.Constant(1) self.V = dol.FunctionSpace(dol.UnitIntervalMesh(1), 'DG', 0) # rhs self.f1 = dol.Expression('pow(t, 2)', t=0, degree=2) self.f2 = dol.Expression('pow(t, 2)', t=0, degree=2) Problem_FE.__init__(self) # CN, higher order F = (dol.inner( self.v, self.utrial - self.uold + self.dt * 0.5 * (self.uold + self.utrial)) * dol.dx - 0.5 * self.dt * dol.inner(self.f1 + self.f2, self.v) * dol.dx) prob = dol.LinearVariationalProblem(dol.lhs(F), dol.rhs(F), self.unew) self.solver = dol.LinearVariationalSolver(prob) # IE, lower order Flow = (dol.inner( self.v, self.utrial - self.uold + self.dt * self.utrial) * dol.dx - self.dt * dol.inner(self.f2, self.v) * dol.dx) problow = dol.LinearVariationalProblem(dol.lhs(Flow), dol.rhs(Flow), self.ulow) self.solver_low = dol.LinearVariationalSolver(problow)
def setupSolver(self): if type(self.f) == type([]): self.n = len(self.f) if type(d.lhs(self.f[0]).integrals()[0].integrand()) == type( UFL.constantvalue.Zero() ): # Not particularly elegant. Should check for another solution. self.rank = 1 else: self.rank = 2 else: self.n = 1 if type(d.lhs(self.f).integrals()[0].integrand()) == type( UFL.constantvalue.Zero() ): # Not particularly elegant. Should check for another solution. self.rank = 1 else: self.rank = 2 # Set appropriate solver if self.rank == 2: d.info("Using LU-solver to solve linear systems.") self.linear = True self.solver = d.LUSolver() else: d.info("Using Newton-solver to solve nonlinear systems.") self.linear = False self.solver = d.NewtonSolver()
def setup_NSu(w_NSu, u, v, dx, ds, normal, dirichlet_bcs_NSu, neumann_bcs, boundary_to_mark, u_, p_, u_1, p_1, rho_, rho_1, mu_, c_1, grad_g_c_, dt, grav, enable_EC, trial_functions, use_iterative_solvers, mesh, density_per_concentration, viscosity_per_concentration, K, **namespace): """ Set up the Navier-Stokes velocity subproblem. """ solvers = dict() mom_1 = rho_1 * u_1 if enable_EC and density_per_concentration is not None: for drhodci, ci_1, grad_g_ci_, Ki in zip(density_per_concentration, c_1, grad_g_c_, K): if drhodci > 0.: mom_1 += -drhodci * Ki * ci_1 * grad_g_ci_ F_predict = ( 1. / dt * rho_1 * df.dot(u - u_1, v) * dx + df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 2 * mu_ * df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx + 0.5 * (1. / dt * (rho_ - rho_1) * df.dot(u, v) - df.inner(mom_1, df.grad(df.dot(u, v)))) * dx - p_1 * df.div(v) * dx - rho_ * df.dot(grav, v) * dx) for boundary_name, pressure in neumann_bcs["p"].iteritems(): F_predict += pressure * df.inner(normal, v) * ds( boundary_to_mark[boundary_name]) if enable_EC: F_predict += sum([ ci_1 * df.dot(grad_g_ci_, v) * dx for ci_1, grad_g_ci_ in zip(c_1, grad_g_c_) ]) a_predict, L_predict = df.lhs(F_predict), df.rhs(F_predict) # if not use_iterative_solvers: problem_predict = df.LinearVariationalProblem(a_predict, L_predict, w_NSu, dirichlet_bcs_NSu) solvers["predict"] = df.LinearVariationalSolver(problem_predict) if use_iterative_solvers: solvers["predict"].parameters["linear_solver"] = "bicgstab" solvers["predict"].parameters["preconditioner"] = "amg" F_correct = (rho_ * df.inner(u - u_, v) * dx - dt * (p_ - p_1) * df.div(v) * dx) a_correct, L_correct = df.lhs(F_correct), df.rhs(F_correct) problem_correct = df.LinearVariationalProblem(a_correct, L_correct, w_NSu, dirichlet_bcs_NSu) solvers["correct"] = df.LinearVariationalSolver(problem_correct) if use_iterative_solvers: solvers["correct"].parameters["linear_solver"] = "bicgstab" solvers["correct"].parameters["preconditioner"] = "amg" #else: # solver = df.LUSolver("mumps") # # solver.set_operator(A) # return solver, a, L, dirichlet_bcs_NS return solvers
def __init__(self, t_end = None, func = None, para_stiff = None, adjoint = False): Problem_Basic.__init__(self, t_end = t_end, func = func, para_stiff = para_stiff) self.k = dol.Constant(self.k) self.u0_expr = dol.Constant(self.u0) # initial value mesh = dol.UnitIntervalMesh(1) R_elem = dol.FiniteElement("R", mesh.ufl_cell(), 0) V_elem = dol.MixedElement([R_elem, R_elem]) self.V = dol.FunctionSpace(mesh, V_elem) if adjoint: self.z0_expr = dol.Constant(np.array([0., 0.])) # initial value adj Problem_FE.__init__(self, adjoint) (self.v1 , self.v2) = dol.split(self.v) (self.u1trial, self.u2trial) = dol.split(self.utrial) (self.u1old , self.u2old) = dol.split(self.uold) (self.u1low , self.u2low) = dol.split(self.ulow) ## Crank nicolson weak formulation F = (dol.inner(self.v1, self.u1trial - self.u1old + self.dt * (0.5 * (self.u1old + self.u1trial) - 0.5 * (self.u2old + self.u2trial)))*dol.dx + dol.inner(self.v2, self.u2trial - self.u2old - self.k * self.dt * 0.5 * (self.u2old + self.u2trial))*dol.dx) prob = dol.LinearVariationalProblem(dol.lhs(F), dol.rhs(F), self.unew) self.solver = dol.LinearVariationalSolver(prob) ## Implicit Euler weak formulation for error estimation Flow = (dol.inner(self.v1, self.u1trial - self.u1old + self.dt * (self.u1trial - self.u2trial))*dol.dx + dol.inner(self.v2, self.u2trial - self.u2old - self.k * self.dt * self.u2trial)*dol.dx) problow = dol.LinearVariationalProblem(dol.lhs(Flow), dol.rhs(Flow), self.ulow) self.solver_low = dol.LinearVariationalSolver(problow) if adjoint: (self.z1old , self.z2old) = dol.split(self.zold) (self.z1trial, self.z2trial) = dol.split(self.ztrial) if self.func not in [1, 2]: raise ValueError('DWR not (yet) implemented for this functional') adj_src = dol.Function(self.V) if self.func == 1: adj_src.interpolate(dol.Constant((1, 0))) elif self.func == 2: adj_src.interpolate(dol.Constant((0, 1))) src1, src2 = dol.split(adj_src) Fadj = (dol.inner(self.z1trial - self.z1old + 0.5 * self.dt * (-self.z1trial - self.z1old + 2*src1), self.v1)*dol.dx + dol.inner(self.z2trial - self.z2old + 0.5 * self.dt * ( self.z1trial + self.z1old + self.k*(self.z2trial + self.z2old) + 2*src2), self.v2)*dol.dx) prob_adj = dol.LinearVariationalProblem(dol.lhs(Fadj), dol.rhs(Fadj), self.znew) self.solver_adj = dol.LinearVariationalSolver(prob_adj)
def test_lhs_rhs_simple(): """Test taking lhs/rhs of DOLFIN specific forms (constants without cell). """ mesh = RectangleMesh.create(MPI.comm_world, [Point(0, 0), Point(2, 1)], [3, 5], CellType.Type.triangle) V = FunctionSpace(mesh, "CG", 1) f = 2.0 g = 3.0 v = TestFunction(V) u = TrialFunction(V) F = inner(g * grad(f * v), grad(u)) * dx + f * v * dx a, L = system(F) Fl = lhs(F) Fr = rhs(F) assert (Fr) a0 = inner(grad(v), grad(u)) * dx n = assemble(a).norm("frobenius") # noqa nl = assemble(Fl).norm("frobenius") # noqa n0 = 6.0 * assemble(a0).norm("frobenius") # noqa assert round(n - n0, 7) == 0 assert round(n - nl, 7) == 0
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) mu = Constant(parameters["viscosity [Pa*s]"]) dt = Constant(parameters["dt [s]"]) u, u_1, u_k, vu = domain.u, domain.u_1, domain.u_k, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) acceleration = rho*inner((u-u_1)/dt, vu) * dx convection = dot(div(rho*outer(u_k, u)), vu) * dx convection = rho*dot(dot(u_k, nabla_grad(u)), vu) * dx pressure = (inner(p_1, div(vu))*dx - dot(p_1*n, vu)*ds) diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx) # good # diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx # + dot(mu * (grad(u) + grad(u).T)*n, vu)*ds) # very slow! # F_impl = acceleration + convection + pressure + diffusion # dot(u_1, nabla_grad(u_1)) works # dot(u, nabla_grad(u_1)) does not change! u_mid = (u + u_1) / 2.0 F_impl = rho*dot((u - u_1) / dt, vu)*dx \ + rho*dot(dot(u_1, nabla_grad(u_1)), vu)*dx \ + inner(sigma(u_mid, p_1, mu), epsilon(vu))*dx \ + dot(p_1*n, vu)*ds - dot(mu*nabla_grad(u_mid)*n, vu)*ds self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def __init__(self, domain): rho, mu, dt, g = domain.rho, domain.mu, domain.dt, domain.g u, u_1, vu = domain.u, domain.u_1, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) acceleration = rho * inner((u - u_1) / dt, vu) * dx pressure = inner(p_1, div(vu)) * dx - dot(p_1 * n, vu) * ds body_force = dot(g*rho, vu)*dx \ + dot(Constant((0.0, 0.0)), vu) * ds # diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu))*dx # + dot(mu * (grad(u_1) + grad(u_1).T)*n, vu)*ds) # just fine # diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx) # just fine # just fine, but horribly slow in combination with ??? -> not reproducable diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu)) * dx + dot(mu * (grad(u) + grad(u).T) * n, vu) * ds) # convection = rho*dot(dot(u, nabla_grad(u_1)), vu) * dx # no vortices convection = rho * dot(dot(u_1, nabla_grad(u)), vu) * dx # stabilization = -gamma*psi_p*p_1 # convection = dot(div(rho * outer(u_1, u_1)), vu) * dx # not stable! # convection = rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx # just fine F_impl = -acceleration - convection + diffusion + pressure + body_force self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def setup_EC(w_EC, c, V, b, U, rho_e, dx, ds, dirichlet_bcs, neumann_bcs, boundary_to_mark, c_1, u_1, K_, veps_, phi_, per_tau, z, dbeta, enable_NS, enable_PF, use_iterative_solvers): """ Set up electrochemistry subproblem. """ F_V = veps_*df.dot(df.grad(V), df.grad(U))*dx for boundary_name, sigma_e in neumann_bcs["V"].iteritems(): F_V += -sigma_e*U*ds(boundary_to_mark[boundary_name]) if rho_e != 0: F_V += -V*U*dx F = F_V a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_EC, dirichlet_bcs) solver = df.LinearVariationalSolver(problem) for ci, ci_1, bi, Ki_, zi, dbetai in zip(c, c_1, b, K_, z, dbeta): ??
def stokes(self): P2 = df.VectorElement("CG", self.mesh.ufl_cell(), 2) P1 = df.FiniteElement("CG", self.mesh.ufl_cell(), 1) TH = P2 * P1 VQ = df.FunctionSpace(self.mesh, TH) mf = self.mf self.no_slip = df.Constant((0., 0)) U0_str = "4.*U_m*x[1]*(.41-x[1])/(.41*.41)" U0 = df.Expression((U0_str, "0"), U_m=self.U_m, degree=2) bc0 = df.DirichletBC(VQ.sub(0), df.Constant((0, 0)), mf, self.bc_dict["obstacle"]) bc1 = df.DirichletBC(VQ.sub(0), df.Constant((0, 0)), mf, self.bc_dict["channel_walls"]) bc2 = df.DirichletBC(VQ.sub(0), U0, mf, self.bc_dict["inlet"]) bc3 = df.DirichletBC(VQ.sub(1), df.Constant(0), mf, self.bc_dict["outlet"]) bcs = [bc0, bc1, bc2, bc3] vup = df.TestFunction(VQ) up = df.TrialFunction(VQ) up_ = df.Function(VQ) u, p = df.split(up) # Trial vu, vp = df.split(vup) # Test u_, p_ = df.split(up_) # Function holding the solution inner, grad, dx, div = df.inner, df.grad, df.dx, df.div F = self.mu*inner(grad(vu), grad(u))*dx - inner(div(vu), p)*dx \ - inner(vp, div(u))*dx df.solve(df.lhs(F) == df.rhs(F), up_, bcs=bcs) self.u_.assign(df.project(u_, self.V)) self.p_.assign(df.project(p_, self.Q)) return
def EvaluateImpl(self, inputs): """ """ m = dl.Function(self.V) m.vector().set_local(inputs[0]) p_n = dl.interpolate(m, self.V) p_nm1 = dl.interpolate(m, self.V) p_trial = self.p_trial v = self.v F = (self.c**2) * (self.dt**2) * dl.inner( dl.grad(p_trial), dl.grad(v) ) * dl.dx - 2. * p_n * v * dl.dx + p_trial * v * dl.dx + p_nm1 * v * dl.dx a, L = dl.lhs(F), dl.rhs(F) # Time-stepping p = dl.Function(self.V) t = 0 for n in range(self.numSteps): # Update current timtime t += self.dt # Compute solution dl.solve(a == L, p) # Update previous solution p_nm1.assign(p_n) p_n.assign(p) out = p.vector().array()[:] self.outputs = [out]
def solve_petsc(self): """ Solves the linear problem using PETSc interface, and manipulates with PETSc matrices. :return: list[state vectors] """ form = self.forms._rhs_forms( shift=self.frequency) + self.forms._lhs_forms() w = dolf.Function(self.forms.function_space) lhs_matrix = dolf.PETScMatrix() lhs_matrix = dolf.assemble(dolf.lhs(form), tensor=lhs_matrix) for bc in self.forms.dirichlet_boundary_conditions(): bc.apply(lhs_matrix) lhs_matrix = lhs_matrix.mat() averaged_boundary_terms = self.forms.boundary_averaged_velocity() if averaged_boundary_terms: lhs_matrix.axpy(-1.0, averaged_boundary_terms) solver = self.create_ksp_solver(lhs_matrix) rhs_vector = dolf.assemble(dolf.rhs(form)) for bc in self.forms.dirichlet_boundary_conditions(): bc.apply(rhs_vector) solver.solve( dolf.as_backend_type(rhs_vector).vec(), dolf.as_backend_type(w.vector()).vec(), ) state = w.split(True) return state
def solveFwd(self, state, x): """ Solve the possibly nonlinear forward problem: Given :math:`m`, find :math:`u` such that .. math:: \\delta_p F(u, m, p;\\hat{p}) = 0,\\quad \\forall \\hat{p}.""" if self.solver is None: self.solver = self._createLUSolver() if self.is_fwd_linear: u = dl.TrialFunction(self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, m, 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) self.solver.set_operator(A) self.solver.solve(state, b) else: u = vector2Function(x[STATE], self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, m, p) dl.solve(res_form == 0, u, self.bc) state.zero() state.axpy(1., u.vector())
def stokes(self): P2 = VectorElement("CG", self.mesh.ufl_cell(), 2) P1 = FiniteElement("CG", self.mesh.ufl_cell(), 1) TH = P2 * P1 VQ = FunctionSpace(self.mesh, TH) mf = self.mf self.no_slip = Constant((0., 0)) self.topflow = Expression(("-x[0] * (x[0] - 1.0) * 6.0 * m", "0.0"), m=self.U_m, degree=2) bc0 = DirichletBC(VQ.sub(0), self.topflow, mf, self.bc_dict["top"]) bc1 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["left"]) bc2 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["bottom"]) bc3 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["right"]) # bc4 = DirichletBC(VQ.sub(1), Constant(0), mf, self.bc_dict["top"]) bcs = [bc0, bc1, bc2, bc3] vup = TestFunction(VQ) up = TrialFunction(VQ) # the solution will be in here: up_ = Function(VQ) u, p = split(up) # Trial vu, vp = split(vup) # Test u_, p_ = split(up_) # Function holding the solution F = self.mu*inner(grad(vu), grad(u))*dx - inner(div(vu), p)*dx \ - inner(vp, div(u))*dx + dot(self.g*self.rho, vu)*dx solve(lhs(F) == rhs(F), up_, bcs=bcs) self.u_.assign(project(u_, self.V)) self.p_.assign(project(p_, self.Q)) return
def create_lhs(self): self.a = self.create_a() if self.stab_enable == True: if self.stab_type == 'cip': self.a += self.apply_stabilization() elif self.stab_type == 'gls': self.a += df.lhs(self.apply_stabilization())
def setup_NS(w_NS, u, p, v, q, p0, q0, dx, ds, normal, dirichlet_bcs_NS, neumann_bcs, boundary_to_mark, u_1, rho_, rho_1, mu_, c_1, grad_g_c_, dt, grav, enable_EC, trial_functions, use_iterative_solvers, p_lagrange, mesh, q_rhs, density_per_concentration, K, **namespace): """ Set up the Navier-Stokes subproblem. """ mom_1 = rho_1 * u_1 if enable_EC and density_per_concentration is not None: for drhodci, ci_1, grad_g_ci_, Ki in zip( density_per_concentration, c_1, grad_g_c_, K): if drhodci > 0.: mom_1 += -drhodci*Ki*ci_1*grad_g_ci_ F = (1./dt * rho_1 * df.dot(u - u_1, v) * dx + df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 2*mu_*df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx + 0.5*( 1./dt * (rho_ - rho_1) * df.inner(u, v) - df.inner(mom_1, df.nabla_grad(df.dot(u, v)))) * dx - p * df.div(v) * dx - q * df.div(u) * dx - rho_ * df.dot(grav, v) * dx) for boundary_name, pressure in neumann_bcs["p"].iteritems(): F += pressure * df.inner( normal, v) * ds(boundary_to_mark[boundary_name]) if enable_EC: F += sum([ci_1*df.dot(grad_g_ci_, v)*dx for ci_1, grad_g_ci_ in zip(c_1, grad_g_c_)]) if p_lagrange: F += (p*q0 + q*p0)*dx if "u" in q_rhs: F += -df.dot(q_rhs["u"], v)*dx a, L = df.lhs(F), df.rhs(F) if not use_iterative_solvers: problem = df.LinearVariationalProblem(a, L, w_NS, dirichlet_bcs_NS) solver = df.LinearVariationalSolver(problem) else: solver = df.LUSolver("mumps") # solver.set_operator(A) return solver, a, L, dirichlet_bcs_NS return solver
def solve(self): super(backwardEuler, self).solve() # Array for storing the stage values X = [self.u.copy(deepcopy=True)] # Get the variational linear/nonlinear variational forms # and embed them in respective solver class if self.linear: l = self.getLinearVariationalForms(X) p = [linearStage(d.lhs(l[0]), d.rhs(l[0]), self.bcs, self.solver)] else: l = self.getNonlinearVariationalForms(X) a = [d.derivative(l[0], X[0], self.U)] p = [nonlinearStage(a[0], l[0], self.bcs)] # Initialize save/plot of function(s) self.figureHandling(Init=True) # Time stepping loop while True: timestepStart = time.time() # Update time dependent functions for i in range(len(self.tdfButcher)): for j in range(0, 1): self.tdfButcher[i][j].t = self.t + self.dt # Update time dependent functions on boundary for F in self.tdfBC: F.t = self.t + self.dt # Solve for implicit stages if self.linear: p[0].solve(X[0].vector()) else: self.solver.solve(p[0], X[0].vector()) # Constant step size integration self.u.vector()[:] = X[0].vector()[:] self.t += self.dt self.nAcc += 1 if self.parameters['verbose']: self.printProgress(self.estimateRuntime) # Update / save plots self.figureHandling(Update=True) # Break if this is final time step if self.breakTimeLoop: terminateReason = "Success" break self.timestepTimer = time.time() - timestepStart self.verifyStepsize() super(backwardEuler, self).terminateTimeLoop(terminateReason)
def get_system(self, t): kappa.t = t f.t = t n = FacetNormal(self.V.mesh()) u = TrialFunction(self.V) v = TestFunction(self.V) F = inner(kappa * grad(u), grad(v / self.rho_cp)) * dx \ - inner(kappa * grad(u), n) * v / self.rho_cp * ds \ - f * v / self.rho_cp * dx return assemble(lhs(F)), assemble(rhs(F))
def __init__(self, t_end=None, func=None): Problem_verification.__init__(self, t_end, func) self.u0_expr = dol.Constant(1) self.V = dol.FunctionSpace(dol.UnitIntervalMesh(1), 'DG', 0) Problem_FE.__init__(self) # CN, higher order F = dol.inner( self.v, self.utrial - self.uold + self.dt * 0.5 * (self.uold + self.utrial)) * dol.dx prob = dol.LinearVariationalProblem(dol.lhs(F), dol.rhs(F), self.unew) self.solver = dol.LinearVariationalSolver(prob) # IE, lower order Flow = dol.inner( self.v, self.utrial - self.uold + self.dt * self.utrial) * dol.dx problow = dol.LinearVariationalProblem(dol.lhs(Flow), dol.rhs(Flow), self.ulow) self.solver_low = dol.LinearVariationalSolver(problow)
def solve(self): form = self.forms._rhs_forms( shift=self.frequency) + self.forms._lhs_forms() w = dolf.Function(self.forms.function_space) dolf.solve( dolf.lhs(form) == dolf.rhs(form), w, self.forms.dirichlet_boundary_conditions(), solver_parameters={"linear_solver": "mumps"}, ) state = w.split(True) return state
def navier_stokes_IPCS(mesh, dt, parameter): """ fenics code: weak form of the problem. """ mu, rho, nu = parameter V = VectorFunctionSpace(mesh, 'P', 2) Q = FunctionSpace(mesh, 'P', 1) bc0 = DirichletBC(V, Constant((0, 0)), cylinderwall) bc1 = DirichletBC(V, Constant((0, 0)), topandbottom) bc2 = DirichletBC(V, U0, inlet) bc3 = DirichletBC(Q, Constant(1), outlet) bcs = [bc0, bc1, bc2, bc3] # ds is needed to compute drag and lift. Not used here. ASD1 = AutoSubDomain(topandbottom) ASD2 = AutoSubDomain(cylinderwall) mf = MeshFunction("size_t", mesh, 1) mf.set_all(0) ASD1.mark(mf, 1) ASD2.mark(mf, 2) ds_ = ds(subdomain_data=mf, domain=mesh) vu, vp = TestFunction(V), TestFunction(Q) # for integration u_, p_ = Function(V), Function(Q) # for the solution u_1, p_1 = Function(V), Function(Q) # for the prev. solution u, p = TrialFunction(V), TrialFunction(Q) # unknown! bcu = [bcs[0], bcs[1], bcs[2]] bcp = [bcs[3]] n = FacetNormal(mesh) u_mid = (u + u_1) / 2.0 F1 = rho*dot((u - u_1) / dt, vu)*dx \ + rho*dot(dot(u_1, nabla_grad(u_1)), vu)*dx \ + inner(sigma(u_mid, p_1, mu), epsilon(vu))*dx \ + dot(p_1*n, vu)*ds - dot(mu*nabla_grad(u_mid)*n, vu)*ds a1 = lhs(F1) L1 = rhs(F1) # Define variational problem for step 2 a2 = dot(nabla_grad(p), nabla_grad(vp)) * dx L2 = dot(nabla_grad(p_1), nabla_grad(vp)) * dx - ( rho / dt) * div(u_) * vp * dx # rho missing in FEniCS tutorial # Define variational problem for step 3 a3 = dot(u, vu) * dx L3 = dot(u_, vu) * dx - dt * dot(nabla_grad(p_ - p_1), vu) * dx # Assemble matrices A1 = assemble(a1) A2 = assemble(a2) A3 = assemble(a3) # Apply boundary conditions to matrices [bc.apply(A1) for bc in bcu] [bc.apply(A2) for bc in bcp] return u_, p_, u_1, p_1, L1, A1, L2, A2, L3, A3, bcu, bcp
def lhs(self): """ Constructs the LHS matrix (spatial components), AA of the eigenvalue problem. """ lhs_matrix = dolf.PETScMatrix() lhs_forms = -self.forms._lhs_forms() - self.forms._rhs_forms( shift=self.complex_shift) lhs_matrix = dolf.assemble(dolf.lhs(lhs_forms), tensor=lhs_matrix) for bc in self.forms.dirichlet_boundary_conditions(is_linearised=True): bc.apply(lhs_matrix) return lhs_matrix.mat()
def soln_fwd(self): """ Solve the forward equation. F = 0 """ # 5. Solve (non)linear variational problem # df.solve(self.F==0,self.states_fwd,self.ess_bc,J=self.dFdstates) # self.states_fwd = df.Function(self.W) df.solve(df.lhs(self.F)==df.rhs(self.F),self.states_fwd,self.ess_bc) # df.solve(self.a==self.L,self.states_fwd,self.ess_bc) self.soln_count[0] += 1 u_fwd, l_fwd = df.split(self.states_fwd) return u_fwd, l_fwd
def lhs(form): """ Wrapper for the DOLFIN lhs function. Correctly handles QForm s. """ if not isinstance(form, ufl.form.Form): raise InvalidArgumentException("form must be a Form") nform = dolfin.lhs(form) if isinstance(form, QForm): return QForm(nform, quadrature_degree = form_quadrature_degree(form)) else: return nform
def initialize_solver(self, form, bcs, solver_type="mumps"): """ Performs solver initialization and matrix factorization is stored. As discussed at https://fenicsproject.org/docs/dolfin/dev/python/demos/elastodynamics/demo_elastodynamics.py.html: 'Since the system matrix to solve is the same for each time step (constant time step), it is not necessary to factorize the system at each increment. It can be done once and for all and only perform assembly of the varying right-hand side and backsubstitution to obtain the solution much more efficiently. This is done by defining a LUSolver object while PETSc handles caching factorizations.' """ self.bilinear_form = dolf.assemble(dolf.lhs(form)) for bc in bcs: bc.apply(self.bilinear_form) self.LUSolver = dolf.LUSolver(self.bilinear_form, solver_type)
def __init__(self, domain): rho, mu, dt = domain.rho, domain.mu, domain.dt u, u_1, p_1, vu = domain.u, domain.u_1, domain.p_1, domain.vu n = FacetNormal(domain.mesh) acceleration = rho * inner((u - u_1) / dt, vu) * dx diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu)) * dx + dot(mu * (grad(u_1) + grad(u_1).T) * n, vu) * ds) pressure = inner(p_1, div(vu)) * dx - dot(p_1 * n, vu) * ds convection = rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx F_impl = -acceleration - convection + diffusion + pressure self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def assemble_lui_stiffness(self, g, f, mesh, robin_boundary): V = FunctionSpace(mesh, "Lagrange", self.p) u = TrialFunction(V) v = TestFunction(V) n = FacetNormal(mesh) robin = MeshFunction('size_t', mesh, mesh.topology().dim() - 1) robin_boundary.mark(robin, 1) ds = Measure('ds', subdomain_data=robin) a = inner(grad(u), grad(v)) * dx b = (1 - g) * (inner(grad(u), n)) * v * ds(1) c = f * u * v * ds(1) k = lhs(a + b - c) K = PETScMatrix() assemble(k, tensor=K) return K, V
def setup_NSp(w_NSp, p, q, dirichlet_bcs_NSp, dt, u_, p_1, rho_0, use_iterative_solvers, **namespace): """ Set up Navier-Stokes pressure subproblem. """ F = (df.dot(df.nabla_grad(p - p_1), df.nabla_grad(q)) * df.dx + 1. / dt * rho_0 * df.div(u_) * q * df.dx) a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_NSp, dirichlet_bcs_NSp) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "bicgstab" solver.parameters["preconditioner"] = "amg" return solver
def setup_NSp(w_NSp, p, q, dx, ds, dirichlet_bcs_NSp, neumann_bcs, boundary_to_mark, u_, u_1, p_, p_1, rho_, dt, rho_min, use_iterative_solvers, **namespace): F = (df.dot(df.nabla_grad(p - p_1), df.nabla_grad(q)) * df.dx + 1. / dt * rho_min * df.div(u_) * q * df.dx) a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_NSp, dirichlet_bcs_NSp) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "gmres" solver.parameters["preconditioner"] = "hypre_amg" # "amg" # solver.parameters["preconditioner"] = "hypre_euclid" return solver
def EvaluateImpl(self, inputs): """ """ numObs = self.numObs numSteps = self.numSteps # Each output = np.zeros((numObs * numSteps)) m = dl.Function(self.V) m.vector().set_local(inputs[0]) p_n = dl.Function(self.V) p_nm1 = dl.Function(self.V) p_n.assign(m) p_nm1.assign(m) p_trial = self.p_trial v = self.v F = (self.c**2) * (self.dt**2) * dl.inner( dl.grad(p_trial), dl.grad(v) ) * dl.dx - 2. * p_n * v * dl.dx + p_trial * v * dl.dx + p_nm1 * v * dl.dx a, L = dl.lhs(F), dl.rhs(F) # Time-stepping p = dl.Function(self.V) t = 0 output[0:numObs] = self.ObservationOperator(p_nm1) output[numObs:2 * numObs] = self.ObservationOperator(p_n) for n in range(2, self.numSteps): # Update current timtime t += self.dt # Compute solution dl.solve(a == L, p) # nb.plot(p) # plt.title("p") # plt.show() output[n * numObs:(n + 1) * numObs] = self.ObservationOperator(p) # Update previous solution p_nm1.assign(p_n) p_n.assign(p) self.outputs = [output]
def algo_fvs_to_cell_averages(self, mesh_util, bcdata, fv_adjacent_cells_function, target_unit=None): '''Algorithm for turning BC data into cell averages. Parameters ---------- mesh_util: :py:class:`.mesh_util.MeshUtil` Mesh utilities and data. bcdata: dict Mapping `{expr: {(facet_value, sign), ...}}`. target_unit: optional Unit to ``expr`` to in the ``bcdict`` argument. fv_adjacent_cells_function: :py:class:`dolfin.Function` DG0 function containing ones and zeros; ones iff the cell is adjacent to a BC. ''' mu = mesh_util dless = mu.unit_registry('dimensionless') DG0 = mu.space.DG0 dx = mu.dx u = dolfin.TrialFunction(DG0) v = dolfin.TestFunction(DG0) form = DelayedForm() for expr, fvss in bcdata.items(): expr = dless * expr.object if target_unit is None: target_unit = expr.units expr_ = expr.m_as(target_unit) for fv, sign in fvss: # TODO: figure out what to do with the sign - relevant # for internal boundary conditions form += mu.ds(subdomain_id=fv) * v('+') * (u('+') - expr_) if target_unit is None: target_unit = dless form += dx * u * v * (1.0 - fv_adjacent_cells_function) form = form.delete_units().to_ufl().m u = dolfin.Function(DG0) dolfin.solve(dolfin.lhs(form) == dolfin.rhs(form), u, []) return target_unit * u
def __init__( self, Q, kappa, rho, cp, convection, source, dirichlet_bcs=None, neumann_bcs=None, robin_bcs=None, my_dx=dx, my_ds=ds, stabilization=None, ): super(Heat, self).__init__() self.Q = Q dirichlet_bcs = dirichlet_bcs or [] neumann_bcs = neumann_bcs or {} robin_bcs = robin_bcs or {} self.convection = convection u = TrialFunction(Q) v = TestFunction(Q) # If there are sharp temperature gradients, numerical oscillations may # occur. This happens because the resulting matrix is not an M-matrix, # caused by the fact that A1 puts positive elements in places other # than the main diagonal. To prevent that, it is suggested by # Großmann/Roos to use a vertex-centered discretization for the mass # matrix part. # Check # https://bitbucket.org/fenics-project/ffc/issues/145/uflacs-error-for-vertex-quadrature-scheme # self.M = assemble( u * v * dx, form_compiler_parameters={ "representation": "quadrature", "quadrature_rule": "vertex", }, ) mesh = Q.mesh() r = SpatialCoordinate(mesh)[0] self.F0 = F( u, v, kappa, rho, cp, convection, source, r, neumann_bcs, robin_bcs, my_dx, my_ds, stabilization, ) self.dirichlet_bcs = dirichlet_bcs self.A, self.b = assemble_system(-lhs(self.F0), rhs(self.F0)) return
def stokes_solve(up_out, mu, u_bcs, p_bcs, f, my_dx=dx): # Some initial sanity checks. assert mu > 0.0 WP = up_out.function_space() # Translate the boundary conditions into the product space. new_bcs = helpers.dbcs_to_productspace(WP, [u_bcs, p_bcs]) # TODO define p*=-1 and reverse sign in the end to get symmetric system? # Define variational problem (u, p) = TrialFunctions(WP) (v, q) = TestFunctions(WP) mesh = WP.mesh() r = SpatialCoordinate(mesh)[0] # build system f = F(u, p, v, q, f, r, mu, my_dx) a = lhs(f) L = rhs(f) A, b = assemble_system(a, L, new_bcs) mode = "lu" assert mode == "lu" solve(A, up_out.vector(), b, "lu") # TODO Krylov solver for Stokes # assert mode == 'gmres' # # For preconditioners for the Stokes system, see # # # # Fast iterative solvers for discrete Stokes equations; # # J. Peters, V. Reichelt, A. Reusken. # # # prec = mu * inner(r * grad(u), grad(v)) * 2 * pi * my_dx \ # - p * q * 2 * pi * r * my_dx # P, _ = assemble_system(prec, L, new_bcs) # solver = KrylovSolver('tfqmr', 'hypre_amg') # # solver = KrylovSolver('gmres', 'hypre_amg') # solver.set_operators(A, P) # solver.parameters['monitor_convergence'] = verbose # solver.parameters['report'] = verbose # solver.parameters['absolute_tolerance'] = 0.0 # solver.parameters['relative_tolerance'] = tol # solver.parameters['maximum_iterations'] = maxiter # # Solve # solver.solve(up_out.vector(), b) # elif mode == 'fieldsplit': # # For an assortment of preconditioners, see # # # # Performance and analysis of saddle point preconditioners # # for the discrete steady-state Navier-Stokes equations; # # H.C. Elman, D.J. Silvester, A.J. Wathen; # # Numer. Math. (2002) 90: 665-688; # # <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.145.3554>. # # # # Set up field split. # W = SubSpace(WP, 0) # P = SubSpace(WP, 1) # u_dofs = W.dofmap().dofs() # p_dofs = P.dofmap().dofs() # prec = PETScPreconditioner() # prec.set_fieldsplit([u_dofs, p_dofs], ['u', 'p']) # PETScOptions.set('pc_type', 'fieldsplit') # PETScOptions.set('pc_fieldsplit_type', 'additive') # PETScOptions.set('fieldsplit_u_pc_type', 'lu') # PETScOptions.set('fieldsplit_p_pc_type', 'jacobi') # # Create Krylov solver with custom preconditioner. # solver = PETScKrylovSolver('gmres', prec) # solver.set_operator(A) return
def get_system(self, t): # Don't use assemble_system()! See bugs # <https://bitbucket.org/fenics-project/dolfin/issue/257/system_assembler-bilinear-and-linear-forms>, # <https://bitbucket.org/fenics-project/dolfin/issue/78/systemassembler-problem-with-subdomains-on>. return assemble(lhs(self.F0)), assemble(rhs(self.F0))
b = d.Constant((1.0,0.,0.)) # Elasticity parameters: E, nu = 10., 0.3 mu, lambda_param = E / (2. * (1.+nu)), E * nu / ((1. + nu) * (1.-2. * nu)) # Stress tensor: # + usually of form \sigma_{ij} = \lambda e_{kk}\delta_{ij} + 2\mu e_{ij}, # + or = \lambda Tr(e_{ij})I + 2\mu e_{ij}, for e_{ij} the strain tensor. sigma = lambda_param*d.tr(d.grad(u)) * d.Identity(w.cell().d) + 2 * mu * d.sym(d.grad(u)) # Governing balance equation: F = d.inner(sigma, d.grad(w)) * d.dx - d.dot(b,w)*d.dx # Extract the bi- and linear forms from F: a = d.lhs(F) L = d.rhs(F) # Dirichlet BC on entire boundary: c = d.Constant((0.,0.,0.)) bc = d.DirichletBC(V, c, d.DomainBoundary()) ## Testing some new boundary definitions: def bzo_boundary(r_vec, on_boundary): # NB: input r_vec is a position vector r,theta,z = cart_to_cyl(x) # NB: check the function cart_to_cyl can take non-tuple collecs. return d.near(r,bzo_radius) ## Testing some differing-boundary BCs: bzo = d.DirichletBC(V, u_bzo, bzo_boundary)