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 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 _setup_solver(self): self.EMsolver = d.LinearVariationalSolver(self.EMproblem) self.Tsolver = d.LinearVariationalSolver(self.Tproblem) solver_info = return_solver(self.data) if solver_info is not None: for i in solver_info: self.logger.debug("Setting " + str(self.EMsolver.parameters[i]) + " as " + str(solver_info[i])) self.EMsolver.parameters[i] = solver_info[i] self.Tsolver.parameters[i] = solver_info[i]
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 linear_solver(self, phi_k): # cast params as constant functions so that, if they are set to 0, FEniCS still understand # what is being integrated mu, M = Constant(self.physics.mu), Constant(self.physics.M) lam = Constant(self.physics.lam) mn, mf = Constant(self.mn), Constant(self.mf) D = self.physics.D # boundary condition Dirichlet_bc = self.get_Dirichlet_bc() # trial and test function phi = d.TrialFunction(self.fem.S) v = d.TestFunction(self.fem.S) # r^(D-1) rD = Expression('pow(x[0],D-1)', D=D, degree=self.fem.func_degree) # bilinear form a and linear form L a = - inner( grad(phi), grad(v) ) * rD * dx + ( (mu/mn)**2 \ - 3.*lam*(mf/mn)**2*phi_k**2 ) * phi * v * rD * dx L = ((mn**(D - 2.) / (mf * M)) * self.source.rho - 2. * lam * (mf / mn)**2 * phi_k**3) * v * rD * dx # define a vector with the solution sol = d.Function(self.fem.S) # solve linearised system pde = d.LinearVariationalProblem(a, L, sol, Dirichlet_bc) solver = d.LinearVariationalSolver(pde) solver.solve() return sol
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 solve( self ): """ Overrides the base-class nonlinear solver with a linear solver for the Poisson equation Eq. :eq:`Eq_Poisson`. """ Dirichlet_bc = self.get_Dirichlet_bc() # trial and test function u = d.TrialFunction( self.fem.S ) v = d.TestFunction( self.fem.S ) PhiN = d.Function( self.fem.S ) # define equation Mn, Mp = Constant( self.Mn ), Constant( self.Mp ) r2 = Expression( 'pow(x[0],2)', degree=self.fem.func_degree ) a = - inner( grad(u), grad(v) ) * r2 * dx L = 0.5 * self.source.rho * Mn / Mp**2 * v * r2 * dx # solve eqn = d.LinearVariationalProblem( a, L, PhiN, Dirichlet_bc ) solver = d.LinearVariationalSolver( eqn ) solver.solve() # set potential and force self.PhiN = PhiN self.Newton_force = self.grad( -PhiN, radial_units='physical' )
def initial_guess(self): r""" Obtains an initial guess for the Newton solver. This is done by solving the equation of motion for :math:`\lambda=0`, which form a linear system. All other parameters are unchanged. """ # cast params as constant functions so that, if they are set to 0, # fenics still understand what it is integrating m, M, Mp = Constant(self.fields.m), Constant(self.fields.M), Constant( self.fields.Mp) alpha = Constant(self.fields.alpha) Mn, Mf1, Mf2 = Constant(self.Mn), Constant(self.Mf1), Constant( self.Mf2) # get the boundary conditions Dirichlet_bc = self.get_Dirichlet_bc() # create a vector (phi,h) with the two trial functions for the fields u = d.TrialFunction(self.V) # ... and split it into phi and h phi, h, y, z = d.split(u) # define test functions over the function space v1, v2, v3, v4 = d.TestFunctions(self.V) # r^2 r2 = Expression('pow(x[0],2)', degree=self.fem.func_degree) # define bilinear form # Eq.1 a1 = y * v1 * r2 * dx - ( m / Mn )**2 * phi * v1 * r2 * dx \ - alpha * ( Mf2/Mf1 ) * z * v1 * r2 * dx # Eq.2 a2 = z * v2 * r2 * dx - ( M / Mn )**2 * h * v2 * r2 * dx \ - alpha * ( Mf1/Mf2 ) * y * v2 * r2 * dx a3 = -inner(grad(phi), grad(v3)) * r2 * dx - y * v3 * r2 * dx a4 = -inner(grad(h), grad(v4)) * r2 * dx - z * v4 * r2 * dx # both equations a = a1 + a2 + a3 + a4 # define linear form L = self.source.rho / Mp * Mn / Mf1 * v1 * r2 * dx # define a vector with the solution sol = d.Function(self.V) # solve linearised system pde = d.LinearVariationalProblem(a, L, sol, Dirichlet_bc) solver = d.LinearVariationalSolver(pde) solver.solve() return sol
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 __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 dTt_dolfin(T, t): """ Finds dT/dt using dolfin. Arguments: T: Array representing the temperature at a specific time. t: Single value of time at which to find the derivative. Returns: The derivative of T with respect to t as an array. """ # Convert T to dolfin function from array. TOld = df.Function(funcSpace) TOld.vector()[:] = T # Solve the "linear" problem to find dT/dt. # This 'a' represents the unknown, which contains no new information, but # will eventually contribute to the solution later. TNew = df.TrialFunction(funcSpace) v = df.TestFunction(funcSpace) a = TNew * v * df.dx # 'f' here represents an expression (but not a dolfin expression) which # describes the mathematical function that calculates dT/dt from T. f = TOld * df.Constant(-0.9) # df.inner(df.grad(TOld), df.grad(TOld)) # <!> Failure here? # This 'L' represents what we know, and will be used to calculate our # solution eventually. L = f * v L *= df.dx # This is not actually the solution, but it is where the solution will end # up eventually, once the solver has done its work. solutionEventually = df.Function(funcSpace) # The problem defines what we want to know, what we do know, and where to # put the solution. The solution argument is not actually the solution # (yet), but it's where the solution will end up eventually. problem = df.LinearVariationalProblem(a, L, solutionEventually) # The solver solves the problem eventually. solver = df.LinearVariationalSolver(problem) # Now we solve the problem. solutionEventually is now populated with the # solution to the problem. solver.solve() # Convert and return our solution. return solutionEventually.vector().array()
def _setup_solver(self): self.solver = d.LinearVariationalSolver(self.problem) solver_info = return_solver(self.data) if solver_info is not None: for i in solver_info: if isinstance(solver_info[i], dict): for j in solver_info[i]: self.logger.debug("Setting [" + str(i) + "][" + str(j) + "] as " + str(solver_info[i][j])) self.solver.parameters[i][j] = solver_info[i][j] else: self.logger.debug("Setting [" + str(i) + "] as " + str(solver_info[i])) self.solver.parameters[i] = solver_info[i]
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 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_, solutes, per_tau, z, dbeta, enable_NS, enable_PF, use_iterative_solvers, q_rhs): """ Set up electrochemistry subproblem. """ F_c = [] for ci, ci_1, bi, Ki_, zi, dbetai, solute in zip(c, c_1, b, K_, z, dbeta, solutes): F_ci = (per_tau*(ci-ci_1)*bi*dx + Ki_*df.dot(df.nabla_grad(ci), df.nabla_grad(bi))*dx) if zi != 0: F_ci += Ki_*zi*ci_1*df.dot(df.nabla_grad(V), df.nabla_grad(bi))*dx if enable_PF: F_ci += Ki_*ci*dbetai*df.dot(df.nabla_grad(phi_), df.nabla_grad(bi))*dx if enable_NS: # F_ci += df.div(ci*u_1)*bi*dx F_ci += - ci*df.dot(u_1, df.grad(bi))*dx if solute[0] in q_rhs: F_ci += - q_rhs[solute[0]]*bi*dx F_c.append(F_ci) F_V = veps_*df.dot(df.nabla_grad(V), df.nabla_grad(U))*dx for boundary_name, sigma_e in neumann_bcs["V"].items(): F_V += -sigma_e*U*ds(boundary_to_mark[boundary_name]) if rho_e != 0: F_V += -rho_e*U*dx if "V" in q_rhs: F_V += q_rhs["V"]*U*dx F = sum(F_c) + F_V a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_EC, dirichlet_bcs) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "gmres" # solver.parameters["preconditioner"] = "hypre_euclid" return solver
def setup_PF(w_PF, phi, g, psi, h, dx, ds, dirichlet_bcs, neumann_bcs, boundary_to_mark, phi_1, u_1, M_1, c_1, V_1, per_tau, sigma_bar, eps, dbeta, dveps, enable_NS, enable_EC, use_iterative_solvers, q_rhs): """ Set up phase field subproblem. """ F_phi = (per_tau*(phi-unit_interval_filter(phi_1))*psi*dx + M_1*df.dot(df.grad(g), df.grad(psi))*dx) if enable_NS: F_phi += -phi*df.dot(u_1, df.grad(psi))*dx # F_phi += df.div(phi*u_1)*psi*dx F_g = (g*h*dx - sigma_bar*eps*df.dot(df.nabla_grad(phi), df.nabla_grad(h))*dx - sigma_bar/eps*( diff_pf_potential_linearised(phi, unit_interval_filter( phi_1))*h*dx)) if enable_EC: F_g += (-sum([dbeta_i*ci_1*h*dx for dbeta_i, ci_1 in zip(dbeta, c_1)]) + 0.5*dveps*df.dot(df.nabla_grad(V_1), df.nabla_grad(V_1))*h*dx) for boundary_name, costheta in neumann_bcs["phi"].items(): fw_prime = diff_pf_contact_linearised(phi, unit_interval_filter(phi_1)) # Should be just surface tension! F_g += sigma_bar*costheta*fw_prime*h*ds(boundary_to_mark[boundary_name]) if "phi" in q_rhs: F_phi += -q_rhs["phi"]*psi*dx F = F_phi + F_g a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_PF) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "gmres" # solver.parameters["preconditioner"] = "hypre_euclid" return solver
def setSolverParams(self, step=None): if self.eqn == "poisboltz": print("PoisBoltz") self.F = dolfin.action(self.F, self.u_s) J = dolfin.derivative(self.F, self.u_s, self.u) problem = dolfin.NonlinearVariationalProblem( self.F, self.u_s, self.bcs, J) self.solver = dolfin.NonlinearVariationalSolver(problem) prm = self.solver.parameters prm['newton_solver']['absolute_tolerance'] = self.max_abs_error prm['newton_solver']['relative_tolerance'] = self.max_rel_error prm['newton_solver']['maximum_iterations'] = 10000 prm['newton_solver']['relaxation_parameter'] = 0.1 prm['newton_solver']['report'] = True prm['newton_solver']['linear_solver'] = self.method prm['newton_solver']['preconditioner'] = self.preconditioner prm['newton_solver']['krylov_solver']['maximum_iterations'] = 10000 prm['newton_solver']['krylov_solver'][ 'absolute_tolerance'] = self.max_abs_error prm['newton_solver']['krylov_solver'][ 'relative_tolerance'] = self.max_rel_error prm['newton_solver']['krylov_solver']['monitor_convergence'] = True else: print("Separating LHS and RHS...") # Separate left and right hand sides of equation self.a, self.L = dolfin.lhs(self.F), dolfin.rhs(self.F) self.problem = dolfin.LinearVariationalProblem( self.a, self.L, self.u_s, self.bcs) self.solver = dolfin.LinearVariationalSolver(self.problem) dolfin.parameters['form_compiler']['optimize'] = True self.solver.parameters['linear_solver'] = self.method self.solver.parameters['preconditioner'] = self.preconditioner spec_param = self.solver.parameters['krylov_solver'] #These only accessible after spec_param available. if self.init_guess == "prev": if step == 0: spec_param['nonzero_initial_guess'] = False else: spec_param['nonzero_initial_guess'] = True elif self.init_guess == "zero": spec_param['nonzero_initial_guess'] = False spec_param['absolute_tolerance'] = self.max_abs_error spec_param['relative_tolerance'] = self.max_rel_error spec_param['maximum_iterations'] = self.max_linear_iters
def setup_PF(w_PF, phi, g, psi, h, dx, ds, dirichlet_bcs_PF, neumann_bcs, boundary_to_mark, phi_1, u_1, M_, M_1, c_1, V_1, rho_1, dt, sigma_bar, eps, drho, dbeta, dveps, grav, enable_NS, enable_EC, use_iterative_solvers, **namespace): """ Set up phase field subproblem. """ # Projected velocity (for energy stability) if enable_NS: u_proj = u_1 # - dt*phi_1*df.grad(g)/rho_1 phi_adv = phi # phi_1 F_phi = (1. / dt * (phi - phi_1) * psi * dx + M_1 * df.dot(df.grad(g), df.grad(psi)) * dx) if enable_NS: F_phi += -phi_adv * df.dot(u_proj, df.grad(psi)) * dx F_g = ( g * h * dx # - sigma_bar/eps * (phi - phi_1) * h * dx # Damping term (makes the system elliptic) - sigma_bar * eps * df.dot(df.grad(phi), df.grad(h)) * dx # - sigma_bar/eps * diff_pf_potential(phi_1)*h*dx - sigma_bar / eps * diff_pf_potential_linearised(phi, phi_1) * h * dx) # Add gravity # F_g += drho * df.dot(grav, x) * h * dx if enable_EC: F_g += (-sum( [dbeta_i * ci_1 * h * dx for dbeta_i, ci_1 in zip(dbeta, c_1)]) + 0.5 * dveps * df.dot(df.grad(V_1), df.grad(V_1)) * h * dx) F = F_phi + F_g a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_PF, dirichlet_bcs_PF) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "gmres" # "bicgstab" # "gmres" solver.parameters["preconditioner"] = "jacobi" #"amg" # solver.parameters["preconditioner"] = "hypre_euclid" return solver
def setup_EC(w_EC, c, V, b, U, rho_e, dx, ds, dirichlet_bcs_EC, neumann_bcs, boundary_to_mark, c_1, u_1, K_, veps_, phi_, rho_1, dt, z, dbeta, enable_NS, enable_PF, use_iterative_solvers, **namespace): """ Set up electrochemistry subproblem. """ F_c = [] for ci, ci_1, bi, Ki_, zi, dbetai in zip(c, c_1, b, K_, z, dbeta): u_proj_i = u_1 # - dt/rho_1*df.grad(ci) ci_adv = ci # ci_1 F_ci = (1. / dt * (ci - ci_1) * bi * dx + Ki_ * df.dot(df.nabla_grad(ci), df.nabla_grad(bi)) * dx) if zi != 0: F_ci += Ki_ * zi * ci_1 * df.dot(df.nabla_grad(V), df.nabla_grad(bi)) * dx # u_proj_i += -dt/rho_1 * zi * ci_1 * df.grad(V) if enable_PF: F_ci += Ki_ * ci * dbetai * df.dot(df.nabla_grad(phi_), df.nabla_grad(bi)) * dx # u_proj_i += -dt/rho_1 * ci_1 * dbetai*df.grad(phi_) if enable_NS: F_ci += -ci_adv * df.dot(u_proj_i, df.nabla_grad(bi)) * dx F_c.append(F_ci) F_V = veps_ * df.dot(df.nabla_grad(V), df.nabla_grad(U)) * dx for boundary_name, sigma_e in neumann_bcs["V"].items(): F_V += -sigma_e * U * ds(boundary_to_mark[boundary_name]) if rho_e != 0: F_V += -rho_e * U * dx F = sum(F_c) + F_V a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_EC, dirichlet_bcs_EC) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "gmres" solver.parameters["preconditioner"] = "amg" return solver
def compute_yukawa_force( self ): # solve an equation of motion that will give you # the force from a scalar without nonlinearities # cast params as constant functions so that, if they are set to 0, FEniCS still understand # what is being integrated mu = Constant( self.physics.mu ) mn = Constant( self.mn ) # trial and test function phi = d.TrialFunction( self.fem.S ) v = d.TestFunction( self.fem.S ) # boundary condition - always zero phiD = d.Constant( 0. ) # define 'infinity' boundary: the rightmost mesh point - within machine precision def boundary(x): return self.fem.mesh.r_max - x[0] < d.DOLFIN_EPS Dirichlet_bc = d.DirichletBC( self.fem.S, phiD, boundary, method='pointwise' ) # r^(D-1) rD = Expression('pow(x[0],D-1)', D=self.physics.D, degree=self.fem.func_degree) # m^2 = 2. a = - inner( grad(phi), grad(v) ) * rD * dx - 2. * (mu/mn)**2 * phi * v * rD * dx L = mn**(self.physics.D-2.)*self.source.rho/(self.physics.M*self.mf) * v * rD * dx # the Yukawa potential has linear matter coupling even when # the symmetron has quadratic matter coupling yukawa = d.Function( self.fem.S ) pde = d.LinearVariationalProblem( a, L, yukawa, Dirichlet_bc ) solver = d.LinearVariationalSolver( pde ) solver.solve() self.yukawa = d.Function( self.fem.S ) self.yukawa.vector()[:] = self.mf * yukawa.vector()[:]
def setup_S(w_S, u, p, v, q, p0, q0, dx, ds, normal, dirichlet_bcs, neumann_bcs, boundary_to_mark, u_1, phi_, rho_, rho_1, g_, M_, mu_, rho_e_, c_, V_, c_1, V_1, dbeta, solutes, per_tau, drho, sigma_bar, eps, dveps, grav, fric, u_comoving, enable_PF, enable_EC, use_iterative_solvers, use_pressure_stabilization, p_lagrange, q_rhs): """ Set up Stokes subproblem """ F = (per_tau * rho_1 * df.dot(u - u_1, v) * dx + mu_ * df.inner(df.grad(u), df.grad(v)) * dx - p * df.div(v) * dx + q * df.div(u) * dx - rho_ * df.dot(grav, v) * dx) print("Linear system size", w_S.function_space().dim()) a, L = df.system(F) problem = df.LinearVariationalProblem(a, L, w_S, dirichlet_bcs) solver = df.LinearVariationalSolver(problem) solver.parameters["linear_solver"] = "mumps" if use_iterative_solvers: solver.parameters["linear_solver"] = "gmres" solver.parameters["preconditioner"] = "amg" return solver
def __init__(self, gridsize=32, t_end=6, direction=1, adjoint=False): ## end time self.t_end = t_end self.u0_expr = dol.Expression('1 + 0.2*sin(pi*x[1])*sin(pi*x[0]/3)', degree=1) if adjoint: self.z0_expr = dol.Expression("0", degree=0) ## heat source term for weak formulation for Crank Nicolson, IE uses only f1 self.f1 = dol.Expression('5*pow(t,3)', t=0, degree=2) self.f2 = dol.Expression('5*pow(t,3)', t=0, degree=2) ## Size of grid, number of cells = (2*gridsize)*gridsize*2 self.gridsize = gridsize ## Mesh mesh = dol.RectangleMesh(dol.Point(0, 0), dol.Point(3, 1), 3 * self.gridsize, self.gridsize) ## Function space for solution vector self.V = dol.FunctionSpace(mesh, "CG", 1) Problem_FE.__init__(self, adjoint) ## Function space for velocity V_velo = dol.VectorFunctionSpace(mesh, "CG", 2) ## direction of velocity self.direction = direction # create dol.Measures for relevant subdomains colours = dol.MeshFunction( "size_t", mesh, dim=2) # Colouring for mesh to identify various subdomains colours.set_all(0) # default colour # heat source heat_src = dol.CompiledSubDomain( "x[0] >= 0.25 && x[0] <= 0.75 && x[1] >= 0.25 && x[1] <= 0.75" ) # identify subdomain by condition heat_src.mark(colours, 2) # change colour of domain self.dx_src = dol.Measure("dx", subdomain_data=colours)( 2) # define domain in the needed way for function definition # Area of interest subdom = dol.CompiledSubDomain( "x[0] >= 2.25 && x[0] <= 2.75 && x[1] >= 0.25 && x[1] <= 0.75") subdom.mark(colours, 1) # change colour of domain self.dx_obs = dol.Measure("dx", subdomain_data=colours)( 1) # define domain in the needed way for function definition self.dx_cont = self.dx_obs ## u used in Crank Nicolson self.ucn = 0.5 * (self.utrial + self.uold) if self.direction == 1: self.velocity = dol.interpolate( dol.Expression((' 1', '0'), degree=0), V_velo) elif self.direction == -1: self.velocity = dol.interpolate( dol.Expression(('-1', '0'), degree=0), V_velo) else: raise ValueError('invalid advection direction, please try again') self.heat_cond = dol.Constant(0.01) self.outflow = dol.Constant(0.15) self.velo = dol.Constant(0.5) ## Variational formulation for Crank Nicolson F = (dol.inner(self.v, self.utrial - self.uold) * dol.dx + self.dt * self.heat_cond * dol.inner(dol.grad(self.ucn), dol.grad(self.v)) * dol.dx - 0.5 * self.dt * dol.inner(self.f1 + self.f2, self.v) * self.dx_src + self.velo * self.dt * dol.dot(dol.grad(self.ucn), self.velocity) * self.v * dol.dx + self.dt * self.heat_cond * self.outflow * dol.inner(self.ucn, self.v) * dol.ds) prob = dol.LinearVariationalProblem(dol.lhs(F), dol.rhs(F), self.unew) self.solver = dol.LinearVariationalSolver(prob) ## Variational formulation for Implicit Euler Flow = (dol.inner(self.v, self.utrial - self.uold) * dol.dx + self.dt * self.heat_cond * dol.inner(dol.grad(self.utrial), dol.grad(self.v)) * dol.dx - self.dt * dol.inner(self.f2, self.v) * self.dx_src + self.velo * self.dt * dol.dot(dol.grad( self.utrial), self.velocity) * self.v * dol.dx + self.dt * self.heat_cond * self.outflow * dol.inner(self.utrial, self.v) * dol.ds) problow = dol.LinearVariationalProblem(dol.lhs(Flow), dol.rhs(Flow), self.ulow) self.solver_low = dol.LinearVariationalSolver(problow) if adjoint: adj_src = dol.Function(self.V) adj_src.interpolate(dol.Constant(1 / self.t_end)) self.src_weight = dol.Expression( "((0.25 < x[0]) and (0.75 > x[0]) and (0.25 < x[1]) and (0.75 > x[1]))? 1 : 0", degree=0) class LeftBoundary(dol.SubDomain): def inside(self, x, on_boundary): return on_boundary and dol.near(x[0], 0) class RightBoundary(dol.SubDomain): def inside(self, x, on_boundary): return on_boundary and dol.near(x[0], 3) left = LeftBoundary() right = RightBoundary() boundaries = dol.MeshFunction("size_t", mesh, dim=1) boundaries.set_all(0) left.mark(boundaries, 1) right.mark(boundaries, 3) ds_self = dol.Measure('ds', domain=mesh, subdomain_data=boundaries) zcn = 0.5 * (self.ztrial + self.zold) Fadj = (dol.inner(self.ztrial - self.zold, self.v) * dol.dx - self.dt * self.heat_cond * dol.inner(dol.grad(zcn), dol.grad(self.v)) * dol.dx + self.dt * dol.inner(adj_src, self.v) * self.dx_obs + self.direction * self.dt * self.velo * dol.dot(self.velocity, dol.grad(zcn)) * self.v * dol.dx - self.velo * self.dt * dol.inner(zcn, self.v) * ds_self(1) - self.velo * self.dt * dol.inner(zcn, self.v) * ds_self(3) - self.outflow * self.heat_cond * self.dt * dol.inner(zcn, self.v) * dol.ds) probadj = dol.LinearVariationalProblem(dol.lhs(Fadj), dol.rhs(Fadj), self.znew) self.solver_adj = dol.LinearVariationalSolver(probadj)
n = df.FacetNormal(mesh) chi = df.TrialFunction(S) chi_ = df.Function(S, name="chi") psi = df.TestFunction(S) ds = df.Measure("ds", domain=mesh, subdomain_data=subd) F_chi = (n[0]*psi*ds(1) + df.inner(df.grad(chi), df.grad(psi))*df.dx) a_chi, L_chi = df.lhs(F_chi), df.rhs(F_chi) problem_chi2 = df.LinearVariationalProblem(a_chi, L_chi, chi_, bcs=[]) solver_chi2 = df.LinearVariationalSolver(problem_chi2) solver_chi2.parameters["krylov_solver"]["absolute_tolerance"] = 1e-15 solver_chi2.solve() with df.XDMFFile(mesh.mpi_comm(), "chi_Pe0_b{}.xdmf".format(b)) as xdmff: xdmff.write(chi_) integral = (2*df.assemble(chi_.dx(0)*df.dx)/V_Omega + df.assemble(df.inner(df.grad(chi_), df.grad(chi_))*df.dx)/V_Omega) if rank == 0: print("b = {}, D_eff/D = {}".format(b, 1+integral))
def step(self, t0: float, t1: float) -> None: """Solve on the given time interval (t0, t1). Arguments: interval (:py:class:`tuple`) The time interval (t0, t1) for the step *Invariants* Assuming that v\_ is in the correct state for t0, gives self.vur in correct state at t1. """ timer = df.Timer("PDE step") # Extract theta and conductivities theta = self._parameters["theta"] Mi = self._M_i Me = self._M_e # Extract interval and thus time-step kn = df.Constant(t1 - t0) # Define variational formulation if self._parameters["linear_solver_type"] == "direct": v, u, l = df.TrialFunctions(self.VUR) w, q, lamda = df.TestFunctions(self.VUR) else: v, u = df.TrialFunctions(self.VUR) w, q = df.TestFunctions(self.VUR) # Get physical parameters chi = self._parameters["Chi"] capacitance = self._parameters["Cm"] Dt_v = (v - self.v_) / kn Dt_v *= chi * capacitance v_mid = theta * v + (1.0 - theta) * self.v_ # Set time t = t0 + theta * (t1 - t0) self.time.assign(t) # Define spatial integration domains: dz = df.Measure("dx", domain=self._mesh, subdomain_data=self._cell_domains) db = df.Measure("ds", domain=self._mesh, subdomain_data=self._facet_domains) # Get domain labels cell_tags = map(int, set( self._cell_domains.array())) # np.int64 does not workv facet_tags = map(int, set(self._facet_domains.array())) # Loop overe all domain labels G = Dt_v * w * dz() for key in cell_tags: G += df.inner(Mi[key] * df.grad(v_mid), df.grad(w)) * dz(key) G += df.inner(Mi[key] * df.grad(u), df.grad(w)) * dz(key) G += df.inner(Mi[key] * df.grad(v_mid), df.grad(q)) * dz(key) G += df.inner( (Mi[key] + Me[key]) * df.grad(u), df.grad(q)) * dz(key) if self._I_s is None: G -= chi * df.Constant(0) * w * dz(key) else: # _is = self._I_s.get(key, df.Constant(0)) # G -= chi*_is*w*dz(key) G -= chi * self._I_s[key] * w * dz(key) # If Lagrangian multiplier if self._parameters["linear_solver_type"] == "direct": G += (lamda * u + l * q) * dz(key) # Add applied current as source in elliptic equation if applicable if self._I_a: G -= chi * self._I_a[key] * q * dz(key) if self._ect_current is not None: for key in facet_tags: # Detfalt to 0 if not defined for that facet tag # TODO: Should I include `chi` here? I do not think so G += self._ect_current.get(key, df.Constant(0)) * q * db(key) # Define variational problem a, L = df.system(G) pde = df.LinearVariationalProblem(a, L, self.vur, bcs=self._bcs) # Set-up solver solver = df.LinearVariationalSolver(pde) solver.solve()
def setup_EC(w_EC, c, V, V0, b, U, U0, rho_e, grad_g_c, c_reg, g_c, dx, ds, normal, dirichlet_bcs_EC, neumann_bcs, boundary_to_mark, c_1, u_1, K, veps, rho_, rho_1, dt, enable_NS, solutes, use_iterative_solvers, nonlinear_EC, V_lagrange, p_lagrange, q_rhs, reactions, beta, **namespace): """ Set up electrochemistry subproblem. """ if enable_NS: # Projected velocity u_star = u_1 - dt/rho_1*sum([ci_1*grad_g_ci for ci_1, grad_g_ci in zip(c_1, grad_g_c)]) F_c = [] for ci, ci_1, bi, Ki, grad_g_ci, solute, ci_reg in zip( c, c_1, b, K, grad_g_c, solutes, c_reg): F_ci = (1./dt*(ci-ci_1)*bi*dx + Ki*ci_reg*df.dot(grad_g_ci, df.grad(bi))*dx) if enable_NS: F_ci += - ci_1*df.dot(u_star, df.grad(bi))*dx if solute[0] in q_rhs: F_ci += - q_rhs[solute[0]]*bi*dx if enable_NS: for boundary_name, value in neumann_bcs[solute[0]].iteritems(): # F_ci += df.dot(u_1, normal)*bi*ci_1*ds( # boundary_to_mark[boundary_name]) pass F_c.append(F_ci) for reaction_constant, nu in reactions: g_less = [] g_more = [] for nui, ci_1, betai in zip(nu, c_1, beta): if nui < 0: g_less.append(-nui*(df.ln(ci_1)+betai)) elif nui > 0: g_more.append(nui*(df.ln(ci_1)+betai)) g_less = sum(g_less) g_more = sum(g_more) C = reaction_constant*( df.exp(g_less) - df.exp(g_more))/(g_less - g_more) R = C*sum([nui*g_ci for nui, g_ci in zip(nu, g_c)]) for nui, bi in zip(nu, b): if nui != 0: F_c.append(nui*R*bi*dx) 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 += -rho_e*U*dx if V_lagrange: F_V += veps*V0*U*dx + veps*V*U0*dx if "V" in q_rhs: F_V += q_rhs["V"]*U*dx F = sum(F_c) + F_V if nonlinear_EC: J = df.derivative(F, w_EC) problem = df.NonlinearVariationalProblem(F, w_EC, dirichlet_bcs_EC, J) solver = df.NonlinearVariationalSolver(problem) solver.parameters["newton_solver"]["relative_tolerance"] = 1e-7 if use_iterative_solvers: solver.parameters["newton_solver"]["linear_solver"] = "bicgstab" if not V_lagrange: solver.parameters["newton_solver"]["preconditioner"] = "hypre_amg" else: a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_EC, dirichlet_bcs_EC) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "bicgstab" solver.parameters["preconditioner"] = "hypre_amg" return solver
def test_scipy_uprime_integration_with_fenics(): NB_OF_CELLS_X = NB_OF_CELLS_Y = 2 mesh = df.UnitSquare(NB_OF_CELLS_X, NB_OF_CELLS_Y) V = df.FunctionSpace(mesh, 'CG', 1) f = df.Expression("cos(t)",t=0) uprime = df.TrialFunction(V) uprev = df.interpolate(f,V) v = df.TestFunction(V) #ODE is du/dt= uprime = cos(t), exact solution is u(t)=sin(t) a = uprime*v*dx L = f*v*dx uprime_solution = df.Function(V) uprime_problem = df.LinearVariationalProblem(a, L, uprime_solution) uprime_solver = df.LinearVariationalSolver(uprime_problem) def rhs_fenics(y,t): """A somewhat strange case where the right hand side is constant and thus we don't need to use the information in y.""" #print "time: ",t uprev.vector()[:]=y f.t = t #dolfin needs to know the current time for cos(t) uprime_solver.solve() return uprime_solution.vector().array() def rhs(y,t): """ dy/dt = f(y,t) with y(0)=1 dy/dt = -2y -> solution y(t) = c * exp(-2*t)""" return math.cos(t) T_MAX=2 ts = numpy.arange(0,T_MAX+0.1,0.5) ysfenics=scipy.integrate.odeint(rhs_fenics, uprev.vector().array(), ts) def exact(t,y0=1): return y0*numpy.sin(t) print "With fenics:" err_abs = abs(ysfenics[-1][0]-exact(ts[-1])) #use value at mesh done 0 for check print "Error: abs=%g, rel=%g, y_exact=%g" % (err_abs,err_abs/exact(ts[-1]),exact(ts[-1])) fenics_error=err_abs print "Without fenics:" ys = scipy.integrate.odeint(rhs, 1, ts) err_abs = abs(ys[-1]-exact(ts[-1])) print "Error: abs=%g, rel=%g, y_exact=%g" % (err_abs,err_abs/exact(ts[-1]),exact(ts[-1])) non_fenics_error = float(err_abs) print("Difference between fenics and non-fenics calculation: %g" % abs(fenics_error-non_fenics_error)) assert abs(fenics_error-non_fenics_error)<7e-15 #should also check that solution is the same on all mesh points for i in range(ysfenics.shape[0]): #for all result rows #each row contains the data at all mesh points for one t in ts row = ysfenics[i,:] number_range = abs(row.min()-row.max()) print "row: %d, time %f, range %g" % (i,ts[i],number_range) assert number_range < 16e-15 #for debugging if False: from IPython.Shell import IPShellEmbed ipshell = IPShellEmbed() ipshell() if False: import pylab pylab.plot(ts,ys,'o') pylab.plot(ts,numpy.exp(-2*ts),'-') pylab.show()
def setup_NS(w_NS, u, p, v, q, p0, q0, dx, ds, normal, dirichlet_bcs, neumann_bcs, boundary_to_mark, u_1, phi_, rho_, rho_1, g_, M_, mu_, rho_e_, c_, V_, c_1, V_1, dbeta, solutes, per_tau, drho, sigma_bar, eps, dveps, grav, fric, u_comoving, enable_PF, enable_EC, use_iterative_solvers, use_pressure_stabilization, p_lagrange, q_rhs): """ Set up the Navier-Stokes subproblem. """ # F = ( # per_tau * rho_ * df.dot(u - u_1, v)*dx # + rho_*df.inner(df.grad(u), df.outer(u_1, v))*dx # + 2*mu_*df.inner(df.sym(df.grad(u)), df.grad(v))*dx # - p * df.div(v)*dx # + df.div(u)*q*dx # - df.dot(rho_*grav, v)*dx # ) mom_1 = rho_1 * (u_1 + u_comoving) if enable_PF: mom_1 += -M_ * drho * df.nabla_grad(g_) F = (per_tau * rho_1 * df.dot(u - u_1, v) * dx + fric * mu_ * df.dot(u + u_comoving, v) * dx + 2 * mu_ * df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx - p * df.div(v) * dx + q * df.div(u) * dx + df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 0.5 * (per_tau * (rho_ - rho_1) * df.dot(u, v) - df.dot(mom_1, df.nabla_grad(df.dot(u, v)))) * dx - rho_ * df.dot(grav, v) * dx - mu_ * df.dot(df.nabla_grad(u) * normal, v) * df.ds) for boundary_name, slip_length in neumann_bcs["u"].items(): F += 1./slip_length * \ df.dot(u, v) * ds(boundary_to_mark[boundary_name]) for boundary_name, pressure in neumann_bcs["p"].items(): F += pressure * df.dot(normal, v) * ds(boundary_to_mark[boundary_name]) # - 2*mu_*df.dot(df.dot(df.sym(df.nabla_grad(u)), v), # normal)) * ds(boundary_to_mark[boundary_name]) if enable_PF: F += phi_ * df.dot(df.nabla_grad(g_), v) * dx if enable_EC: for ci_, ci_1, dbetai, solute in zip(c_, c_1, dbeta, solutes): zi = solute[1] F += df.dot(df.grad(ci_), v)*dx \ + zi*ci_1*df.dot(df.grad(V_), v)*dx if enable_PF: F += ci_ * dbetai * df.dot(df.grad(phi_), v) * dx 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) problem = df.LinearVariationalProblem(a, L, w_NS, dirichlet_bcs) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers and use_pressure_stabilization: solver.parameters["linear_solver"] = "gmres" #solver.parameters["preconditioner"] = "jacobi" #solver.parameters["preconditioner"] = "ilu" return solver
mu = dolfin.Constant(E/2./(1.+nu)) lambda_ = dolfin.Constant(E*nu/(1.+nu)/(1.-2.*nu)) def strain_displacement(u): return dolfin.sym(dolfin.grad(u)) def stress_strain(eps): return lambda_*dolfin.tr(eps)*I2+2*mu*eps bilinear_form = dolfin.inner(stress_strain(strain_displacement(u_trial)), strain_displacement(v))*dolfin.dx traction = dolfin.Expression(('x[0] < x_right ? 0.0 : -12.*M/d/d/d*x[1]', '0.0'), x_right=ell-atol, M=1.0, d=d, degree=degree) linear_form = dolfin.dot(traction, v)*dolfin.ds u_prescribed = dolfin.Constant((0., 0.)) boundary_condition_left = dolfin.DirichletBC(V, u_prescribed, left) boundary_conditions = [boundary_condition_left] problem = dolfin.LinearVariationalProblem(bilinear_form, linear_form, u, boundary_conditions) solver = dolfin.LinearVariationalSolver(problem) solver.solve() dolfin.plot(u/u.vector().max(),mode="displacement") plt.savefig("u.png") with dolfin.XDMFFile(mesh.mpi_comm(), "output/u.xdmf") as file: file.write(u, 0)
def _setup_problem(self): """ Method setting up solver objects of the stationary problem. """ assert hasattr(self, "_mesh") assert hasattr(self, "_boundary_markers") self._setup_function_spaces() self._setup_boundary_conditions() # creating test function self._v = dlfn.TestFunction(self._Vh) self._u = dlfn.TrialFunction(self._Vh) # solution self._solution = dlfn.Function(self._Vh) # volume element self._dV = dlfn.Measure("dx", domain=self._mesh) self._dA = dlfn.Measure("ds", domain=self._mesh, subdomain_data=self._boundary_markers) # setup the parameters for the elastic law self._elastic_law.set_parameters(self._mesh, self._C) # virtual work if self._elastic_law.linearity_type == "Linear": self._dw_int = self._elastic_law.dw_int(self._u, self._v) * self._dV elif self._elastic_law.linearity_type == "Nonlinear": self._dw_int = self._elastic_law.dw_int(self._solution, self._v) * self._dV # virtual work of external forces self._dw_ext = dlfn.dot(self._null_vector, self._v) * self._dV # add body force term if hasattr(self, "_body_force"): assert hasattr(self, "_D"), "Dimensionless parameter related to" + \ "the body forces is not specified." self._dw_ext += self._D * dot(self._body_force, self._v) * self._dV # add boundary tractions if hasattr(self, "_traction_bcs"): for bc in self._traction_bcs: # unpack values if len(bc) == 3: bc_type, bndry_id, traction = bc elif len(bc) == 4: bc_type, bndry_id, component_index, traction = bc if bc_type is TractionBCType.constant: assert isinstance(traction, (tuple, list)) const_function = dlfn.Constant(traction) self._dw_ext += dot(const_function, self._v) * self._dA(bndry_id) elif bc_type is TractionBCType.constant_component: assert isinstance(traction, float) const_function = dlfn.Constant(traction) self._dw_ext += const_function * self._v[ component_index] * self._dA(bndry_id) elif bc_type is TractionBCType.function: assert isinstance(traction, dlfn.Expression) self._dw_ext += dot(traction, self._v) * self._dA(bndry_id) elif bc_type is TractionBCType.function_component: assert isinstance(traction, dlfn.Expression) self._dw_ext += traction * self._v[ component_index] * self._dA(bndry_id) if self._elastic_law.linearity_type == "Linear": # linear variational problem self._problem = dlfn.LinearVariationalProblem( self._dw_int, self._dw_ext, self._solution, self._dirichlet_bcs) # setup linear variational solver self._solver = dlfn.LinearVariationalSolver(self._problem) elif self._elastic_law.linearity_type == "Nonlinear": self._Form = self._dw_int - self._dw_ext self._J_newton = dlfn.derivative(self._Form, self._solution) self._problem = dlfn.NonlinearVariationalProblem( self._Form, self._solution, self._dirichlet_bcs, J=self._J_newton) # setup linear variational solver self._solver = dlfn.NonlinearVariationalSolver(self._problem)
- half / dt * dot(v00, del_v) * dV #============================================================================== pvd_velocity = dlfn.File("results_{1}/Re_{0:d}/solution_velocity_Re_{0:d}.pvd".\ format(int(reynolds), "FEniCS")) pvd_pressure = dlfn.File("results_{1}/Re_{0:d}/solution_pressure_Re_{0:d}.pvd".\ format(int(reynolds), "FEniCS")) #============================================================================== # time loop dlfn.tic() t = 0. cnt = 0 n_steps = 5000 t_end = 80. while t < t_end: #and cnt <= n_steps: problem = dlfn.LinearVariationalProblem(lhs, rhs, sol, bcs=bcs) solver = dlfn.LinearVariationalSolver(problem) solver.solve() v, p = sol.split() if cnt % 3200 == 0: print "t = {0:6.4f}".format(t) pvd_velocity << (v, t) pvd_pressure << (p, t) cd, cl = integrateFluidStress(v, p, nu, space_dim) drag_coeff_list.append(cd) lift_coeff_list.append(cl) iter_list.append(cnt) t_dim = t * t_ref t_list.append(t_dim) # update for next iteration sol00.assign(sol0) sol0.assign(sol)