Пример #1
0
    def runNextStep(self):
        self.coupled_problem = df.NonlinearVariationalProblem(self.R, self.U, bcs=[self.dbc0, self.dbc1, self.dbc3],
                                                              J=self.J)
        self.coupled_problem.set_bounds(self.l_bound, self.u_bound)
        self.coupled_solver = df.NonlinearVariationalSolver(self.coupled_problem)

        # Optimizations in fenics optimizations
        set_solver_options(self.coupled_solver)

        try:
            self.coupled_solver.solve(set_solver_options())
        except:
            self.coupled_solver.parameters['snes_solver']['error_on_nonconvergence'] = False
            self.assigner.assign(self.U, [self.zero_sol, self.zero_sol, self.H0])
            self.coupled_solver.solve()
            self.coupled_solver.parameters['snes_solver']['error_on_nonconvergence'] = True

        self.assigner_inv.assign([self.un, self.u2n, self.H0], self.U)
        self.times.append(self.t)

        self.BB.append(df.project(self.strs.B).compute_vertex_values())
        self.HH.append(self.strs.H0.compute_vertex_values())
        self.TD.append(df.project(self.strs.tau_d_plot).compute_vertex_values())
        self.TB.append(df.project(self.strs.tau_b_plot).compute_vertex_values())
        self.TX.append(df.project(self.strs.tau_xx_plot).compute_vertex_values())
        self.TY.append(df.project(self.strs.tau_xy_plot).compute_vertex_values())
        self.TZ.append(df.project(self.strs.tau_xz_plot).compute_vertex_values())
        self.us.append(df.project(self.strs.u(0)).compute_vertex_values())
        self.ub.append(df.project(self.strs.u(1)).compute_vertex_values())

        self.t += self.dtFloat

        return self.BB[-1], self.HH[-1], self.TD[-1], self.TB[-1], self.TX[-1], self.TY[-1], self.TZ[-1], self.us[-1], \
               self.ub[-1]
Пример #2
0
def setup_NSPFEC(w_NSPFEC, w_1NSPFEC, bcs_NSPFEC, trial_func_NSPFEC, v, q, psi,
                 h, b, U, u_, p_, phi_, g_, c_, V_, u_1, p_1, phi_1, g_1, c_1,
                 V_1, M_, nu_, veps_, rho_, K_, rho_e_, M_1, nu_1, veps_1,
                 rho_1, K_1, rho_e_1, dbeta, dveps, drho, per_tau, sigma_bar,
                 eps, grav, z, enable_NS, enable_PF, enable_EC,
                 use_iterative_solvers):
    """ The full problem of electrohydrodynamics in two pahase.
    Note that it is possioble to trun off the dirffent parts at will.
    """

    F_imp = NSPFEC_action(u_, u_1, phi_, phi_1, c_, c_1, u_, p_, phi_, g_, c_,
                          V_, v, q, psi, h, b, U, rho_, M_, nu_, rho_e_, K_,
                          veps_, drho, grav, sigma_bar, eps, dveps, dbeta, z,
                          per_tau, enable_NS, enable_PF, enable_EC)
    F_exp = NSPFEC_action(u_, u_1, phi_, phi_1, c_, c_1, u_1, p_1, phi_1, g_1,
                          c_1, V_1, v, q, psi, h, b, U, rho_1, M_1, nu_1,
                          rho_e_1, K_1, veps_1, drho, grav, sigma_bar, eps,
                          dveps, dbeta, z, per_tau, enable_NS, enable_PF,
                          enable_EC)
    F = 0.5 * (F_imp + F_exp)
    J = df.derivative(F, w_NSPFEC)

    problem_NSPFEC = df.NonlinearVariationalProblem(F, w_NSPFEC, bcs_NSPFEC, J)
    solver_NSPFEC = df.NonlinearVariationalSolver(problem_NSPFEC)
    if use_iterative_solvers:
        solver_NSPFEC.parameters['newton_solver']['linear_solver'] = 'gmres'
        solver_NSPFEC.parameters['newton_solver']['preconditioner'] = 'ilu'

    return solver_NSPFEC
Пример #3
0
def equilibrium_EC(w_, test_functions,
                   solutes,
                   permittivity,
                   dx, ds, normal,
                   dirichlet_bcs, neumann_bcs, boundary_to_mark,
                   use_iterative_solvers,
                   V_lagrange,
                   **namespace):
    """ Electrochemistry equilibrium solver. Nonlinear! """
    num_solutes = len(solutes)

    cV = df.split(w_["EC"])
    c, V = cV[:num_solutes], cV[num_solutes]
    if V_lagrange:
        V0 = cV[-1]

    b = test_functions["EC"][:num_solutes]
    U = test_functions["EC"][num_solutes]
    if V_lagrange:
        U0 = test_functions["EC"][-1]

    z = []  # Charge z[species]
    K = []  # Diffusivity K[species]

    for solute in solutes:
        z.append(solute[1])
        K.append(solute[2])

    rho_e = sum([c_e*z_e for c_e, z_e in zip(c, z)])

    veps = permittivity[0]

    F_c = []
    for ci, bi, Ki, zi in zip(c, b, K, z):
        grad_g_ci = df.grad(alpha_c(ci) + zi*V)
        F_ci = Ki*max_value(ci, 0.)*df.dot(grad_g_ci, df.grad(bi))*dx
        F_c.append(F_ci)

    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

    F = sum(F_c) + F_V
    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"

    solver.solve()
    def solve_molecular(self,rho_solute=const.rhom):
        """
        Solve the molecular diffusion problem
        if 'solve_sol_mol' is not in the flags list this will be an instantaneous mixing problem.
        """

        # Solve solution concentration
        # Diffusivity
        ramp = dolfin.Expression('x[0] > minR ? 100. : 1.',minR=np.log(self.Rstar)-0.5,degree=1)
        self.Dstar = dolfin.project(dolfin.Expression('ramp*diff_ratio*exp(-2.*x[0])',degree=1,ramp=ramp,diff_ratio=self.astar_i/self.Lewis),self.sol_V)
        # calculate solute flux (this is like the Stefan condition for the molecular diffusion problem
        Dwall = self.Dstar(self.sol_coords[self.sol_idx_wall])
        self.solFlux = -(self.C_wall/Dwall)*(self.dR/self.dt)
        # Set the concentration for points that moved out of the grid to match the solute flux
        u0_c_hold = self.u0_c.vector()[:].copy()
        u0_c_hold[~self.sol_idx_extrapolate] = self.C_wall+self.solFlux*(np.exp(self.sol_coords[~self.sol_idx_extrapolate,0])-self.Rstar)
        u0_c_hold[u0_c_hold<0.]=0.
        self.u0_c.vector()[:] = u0_c_hold[:]
        # Variational Problem
        F_c = (self.u_s-self.u0_c)*self.v_s*dolfin.dx + \
                self.dt*dolfin.inner(dolfin.grad(self.u_s), dolfin.grad(self.Dstar*self.v_s))*dolfin.dx - \
                self.dt*self.solFlux*self.v_s*self.sds(1)
        F_c = dolfin.action(F_c,self.C)
        # First derivative
        J = dolfin.derivative(F_c, self.C, self.u_s)
        # handle the bounds
        lower = dolfin.project(dolfin.Constant(0.0),self.sol_V)
        upper = dolfin.project(dolfin.Constant(rho_solute),self.sol_V)
        # set bounds and solve
        snes_solver_parameters = {"nonlinear_solver": "snes",
                                  "snes_solver": {"linear_solver": "lu",
                                                  "maximum_iterations": 20,
                                                  "report": True,
                                                  "error_on_nonconvergence": False}}
        problem = dolfin.NonlinearVariationalProblem(F_c, self.C, J=J)
        problem.set_bounds(lower, upper)
        solver = dolfin.NonlinearVariationalSolver(problem)
        solver.parameters.update(snes_solver_parameters)
        dolfin.info(solver.parameters, True)
        (iter, converged) = solver.solve()
        self.u0_c.assign(self.C)

        # Recalculate the freezing temperature
        self.Tf_last = self.Tf
        self.Tf = Tf_depression(self.C.vector()[self.sol_idx_wall,0],linear=True)
        # Get the updated solution properties
        self.rhos = dolfin.project(dolfin.Expression('C + rhow*(1.-C/rho_solute)',
            degree=1,C=self.C,rhow=const.rhow,rho_solute=rho_solute),self.sol_V)
        self.cs = dolfin.project(dolfin.Expression('ce*(C/rho_solute) + cw*(1.-C/rho_solute)',
            degree=1,C=self.C,cw=const.cw,ce=const.ce,rho_solute=rho_solute),self.sol_V)
        self.ks = dolfin.project(dolfin.Expression('ke*(C/rho_solute) + kw*(1.-C/rho_solute)',
            degree=1,C=self.C,kw=const.kw,ke=const.ke,rho_solute=rho_solute),self.sol_V)
        self.rhos_wall = self.rhos.vector()[self.sol_idx_wall]
        self.cs_wall = self.cs.vector()[self.sol_idx_wall]
        self.ks_wall = self.ks.vector()[self.sol_idx_wall]
Пример #5
0
def run_dolfin():

    import dolfin as df

    x_array = np.linspace(-49.5, 49.5, 100)

    mesh = df.IntervalMesh(100, -50, 50)

    Delta = np.sqrt(A / K)
    xi = 2 * A / D

    Delta_s = Delta * 1e9

    V = df.FunctionSpace(mesh, "Lagrange", 1)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)
    u_ = df.Function(V)
    F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \
        (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx
    F = df.action(F, u_)

    J = df.derivative(F, u_, u)

    # the boundary condition is from equation (8)
    theta0 = np.arcsin(Delta / xi)
    ss = 'x[0]<0? %g: %g ' % (-theta0, theta0)

    u0 = df.Expression(ss)

    def u0_boundary(x, on_boundary):
        return on_boundary

    bc = df.DirichletBC(V, u0, u0_boundary)

    problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J)
    solver = df.NonlinearVariationalSolver(problem)
    solver.solve()

    u_array = u_.vector().array()

    mx_df = []
    for x in x_array:
        mx_df.append(u_(x))

    return mx_df
Пример #6
0
    def get_solver(self, bcs):
        df.parameters["form_compiler"]["quadrature_degree"] = 2

        v = df.TestFunction(self.W)
        F = df.inner(self.eps(v), (1.0 - omega(self.kappa())) * self.sigma()) * df.dx
        J = df.derivative(F, self.d)

        problem = df.NonlinearVariationalProblem(F, self.d, bcs, J=J)
        solver = df.NonlinearVariationalSolver(problem)
        solver.parameters["nonlinear_solver"] = "snes"
        solver.parameters["symmetric"] = True
        solver.parameters["snes_solver"]["error_on_nonconvergence"] = False
        solver.parameters["snes_solver"]["line_search"] = "bt"
        solver.parameters["snes_solver"]["linear_solver"] = "mumps"
        solver.parameters["snes_solver"]["maximum_iterations"] = 10
        solver.parameters["snes_solver"]["report"] = False

        return solver
Пример #7
0
 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 solve_system(self, rhs, factor, u0, t):
        """
        Dolfin's linear solver for (M-factor*A)u = rhs

        Args:
            rhs (dtype_f): right-hand side for the nonlinear system
            factor (float): abbrev. for the node-to-node stepsize (or any other factor required)
            u0 (dtype_u): initial guess for the iterative solver (not used here so far)
            t (float): current time

        Returns:
            dtype_u: solution as mesh
        """

        sol = self.dtype_u(self.V)

        self.w.assign(sol.values)

        # fixme: is this really necessary to do each time?
        q1, q2 = df.TestFunctions(self.V)
        w1, w2 = df.split(self.w)
        r1, r2 = df.split(rhs.values)
        F1 = w1 * q1 * df.dx - factor * self.F1 - r1 * q1 * df.dx
        F2 = w2 * q2 * df.dx - factor * self.F2 - r2 * q2 * df.dx
        F = F1 + F2
        du = df.TrialFunction(self.V)
        J = df.derivative(F, self.w, du)

        problem = df.NonlinearVariationalProblem(F, self.w, [], J)
        solver = df.NonlinearVariationalSolver(problem)

        prm = solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-09
        prm['newton_solver']['relative_tolerance'] = 1E-08
        prm['newton_solver']['maximum_iterations'] = 100
        prm['newton_solver']['relaxation_parameter'] = 1.0

        solver.solve()

        sol.values.assign(self.w)

        return sol
Пример #9
0
def setup_PFEC(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

    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_1 * df.dot(u_proj, df.grad(psi)) * dx
    F_g = (g * h * dx -
           sigma_bar * eps * df.dot(df.grad(phi), df.grad(h)) * dx -
           sigma_bar / eps *
           (diff_pf_potential_c(phi) - diff_pf_potential_e(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)

    J = df.derivative(F, w_PF)

    problem = df.NonlinearVariationalProblem(F, w_PF, dirichlet_bcs_PF, J)
    solver = df.NonlinearVariationalSolver(problem)

    solver.parameters["newton_solver"]["relative_tolerance"] = 1e-5

    if use_iterative_solvers:
        solver.parameters["newton_solver"][
            "linear_solver"] = "bicgstab"  # "gmres"
        solver.parameters["newton_solver"]["preconditioner"] = "jacobi"  #"amg"
        # solver.parameters["preconditioner"] = "hypre_euclid"

    return solver
    def solve_system(self, rhs, factor, u0, t):
        """
        Dolfin's weak solver for (M-dtA)u = rhs

        Args:
            rhs (dtype_f): right-hand side for the nonlinear system
            factor (float): abbrev. for the node-to-node stepsize (or any other factor required)
            u0 (dtype_u_: initial guess for the iterative solver (not used here so far)
            t (float): current time

        Returns:
            dtype_u: solution as mesh
        """

        sol = self.dtype_u(self.V)

        self.g.t = t
        self.w.assign(sol.values)

        v = df.TestFunction(self.V)
        F = self.w * v * df.dx - factor * self.a_K - rhs.values * v * df.dx

        du = df.TrialFunction(self.V)
        J = df.derivative(F, self.w, du)

        problem = df.NonlinearVariationalProblem(F, self.w, self.bc, J)
        solver = df.NonlinearVariationalSolver(problem)

        prm = solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-12
        prm['newton_solver']['relative_tolerance'] = 1E-12
        prm['newton_solver']['maximum_iterations'] = 25
        prm['newton_solver']['relaxation_parameter'] = 1.0

        # df.set_log_level(df.PROGRESS)

        solver.solve()

        sol.values.assign(self.w)

        return sol
Пример #11
0
    def inbuilt_newton_solver(self):
        V = self.my_function_space_cls.V
        F = self.my_var_prob_cls.F
        self.u = self.my_var_prob_cls.u
        du = df.TrialFunction(V)  #TrialFunctions --> wrong, without 's'
        Jac = df.derivative(F, self.u, du)

        #user given solver parameters
        abs_tol = self.my_input_cls['newton_abs_tol']
        rel_tol = self.my_input_cls['newton_rel_tol']
        max_itr = self.my_input_cls['newton_max_itr']
        step_size = self.my_input_cls['newton_relaxation_parameter']

        problem = df.NonlinearVariationalProblem(F, self.u, [], Jac)
        solver = df.NonlinearVariationalSolver(problem)
        solver.parameters['newton_solver']['linear_solver'] = 'mumps'
        solver.parameters['newton_solver']['absolute_tolerance'] = abs_tol
        solver.parameters['newton_solver']['relative_tolerance'] = rel_tol
        solver.parameters['newton_solver']['maximum_iterations'] = max_itr
        solver.parameters['newton_solver']['relaxation_parameter'] = step_size
        #df.solve(F == 0, self.u, [], J=Jac,  solver_parameters={'newton_solver' : {'linear_solver' : 'mumps'}})
        solver.solve()
            def stefan_form_cao():
                # Temperature transforming model (Cao,1991)

                (T, bcs, theta, _theta, theta_) = stefan_function_spaces()

                theta_k = dolfin.project(theta_analytic,
                                         T,
                                         solver_type="cg",
                                         preconditioner_type="hypre_amg")

                q_form, q_form_k, bc_form = stefan_boundary_values(theta_, bcs)

                # Cao formulation source term
                def s(theta, theta0=prm.theta_m, eps=em.EPS):
                    return dolfin.conditional(
                        abs(theta - theta0) < eps,
                        prm.cp_m * eps + prm.L_m / 2,
                        dolfin.conditional(theta > theta0,
                                           prm.cp_s * eps + prm.L_m,
                                           prm.cp_s * eps))

                # Fully implicit time discretization scheme
                F = k_eff(theta, deg='C0') * dolfin.inner(
                    dolfin.grad(theta),
                    dolfin.grad(theta_)) * dx + prm.rho / dt * (
                        c_p_eff(theta, deg='disC') * (theta - prm.theta_m) +
                        s(theta) - c_p_eff(theta_k, deg='disC') *
                        (theta_k - prm.theta_m) -
                        s(theta_k)) * theta_ * dx - sum(q_form)

                # Full THETA time dicretization scheme
                # F = prm.rho/dt*(c_p_eff(theta,deg='disC')*(theta - prm.theta_m) + s(theta) - c_p_eff(theta_k,deg='disC')*(theta_k - prm.theta_m) - s(theta_k))*theta_*dx + (THETA*(k_eff(theta,deg='C0')*dolfin.inner(dolfin.grad(theta),dolfin.grad(theta_))*dx - sum(q_form)) + (1-THETA)*(k_eff(theta_k,deg='C0')*dolfin.inner(dolfin.grad(theta_k),dolfin.grad(theta_))*dx - sum(q_form_k)))

                problem = dolfin.NonlinearVariationalProblem(
                    F, theta, bcs=bc_form, J=dolfin.derivative(F, theta))
                solver = dolfin.NonlinearVariationalSolver(problem)
                solver.parameters["newton_solver"] = NEWTON_PARAMS

                return solver, theta, theta_k
            def stefan_form_ehc():

                # Define functions and spaces:
                (T, bcs, theta, _theta, theta_) = stefan_function_spaces()

                # Set initial condition:
                theta_k = dolfin.project(theta_analytic,
                                         T,
                                         solver_type="cg",
                                         preconditioner_type="hypre_amg")

                # Set boundary terms
                q_form, q_form_k, bc_form = stefan_boundary_values(theta_, bcs)

                # Partial THETA time discretization scheme:
                F = (k_eff(theta, deg='C0') * dolfin.inner(
                    dolfin.grad(theta), dolfin.grad(theta_)) * dx +
                     prm.rho / dt *
                     (THETA * c_p_eff(theta, deg='C0') +
                      (1 - THETA) * c_p_eff(theta_k, deg='C0')) *
                     (dolfin.inner(theta, theta_) -
                      dolfin.inner(theta_k, theta_)) * dx - sum(q_form))

                # Full THETA time discretization scheme:
                # F = (THETA*(k_eff(theta, deg = 'C0')*dolfin.inner(dolfin.grad(theta), dolfin.grad(theta_))*dx +
                #             prm.rho/dt*c_p_eff(theta,deg='C0')*(dolfin.inner(theta,theta_)-dolfin.inner(theta_k,theta_))*dx - sum(q_form)) +
                #      (1-THETA)*(k_eff(theta_k, deg = 'C0')*dolfin.inner(dolfin.grad(theta_k), dolfin.grad(theta_))*dx +
                #                 prm.rho/dt*c_p_eff(theta_k,deg='C0')*(dolfin.inner(theta, theta_) - dolfin.inner(theta_k,theta_))*dx - sum(q_form_k)))

                problem = dolfin.NonlinearVariationalProblem(
                    F, theta, bcs=bc_form, J=dolfin.derivative(F, theta))

                solver = dolfin.NonlinearVariationalSolver(problem)
                solver.parameters["newton_solver"] = NEWTON_PARAMS

                return solver, theta, theta_k
Пример #14
0
def equilibrium_EC(w_, x_, test_functions, solutes, permittivity, mesh, dx, ds,
                   normal, dirichlet_bcs, neumann_bcs, boundary_to_mark,
                   use_iterative_solvers, c_lagrange, V_lagrange, **namespace):
    """ Electrochemistry equilibrium solver. Nonlinear! """
    num_solutes = len(solutes)

    cV = df.split(w_["EC"])
    c, V = cV[:num_solutes], cV[num_solutes]
    if c_lagrange:
        c0, V0 = cV[num_solutes + 1:2 * num_solutes + 1], cV[2 * num_solutes +
                                                             1]
    if V_lagrange:
        V0 = cV[-1]

    b = test_functions["EC"][:num_solutes]
    U = test_functions["EC"][num_solutes]
    if c_lagrange:
        b0, U0 = cV[num_solutes + 1:2 * num_solutes + 1], cV[2 * num_solutes +
                                                             1]
    if V_lagrange:
        U0 = test_functions["EC"][-1]

    phi = x_["phi"]

    q = []
    sum_zx = sum([solute[1] * xj for solute, xj in zip(solutes, composition)])
    for solute, xj in zip(solutes, composition):
        q.append(-xj * Q / (area * sum_zx))

    z = []  # Charge z[species]
    K = []  # Diffusivity K[species]
    beta = []
    for solute in solutes:
        z.append(solute[1])
        K.append(ramp(phi, solute[2:4]))
        beta.append(ramp(phi, solute[4:6]))

    rho_e = sum([c_e * z_e for c_e, z_e in zip(c, z)])
    veps = ramp(phi, permittivity)

    F_c = []
    for ci, bi, c0i, b0i, solute, qi, betai, Ki in zip(c, b, c0, b0, solutes,
                                                       q, beta, K):
        zi = solute[1]
        F_ci = Ki * (df.dot(
            df.nabla_grad(bi),
            df.nabla_grad(ci) + df.nabla_grad(betai) +
            zi * ci * df.nabla_grad(V))) * dx
        if c_lagrange:
            F_ci += b0i * (ci - df.Constant(qi)) * dx + c0i * bi * dx

    F_V = veps * df.dot(df.nabla_grad(U), df.nabla_grad(V)) * 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_lagrange:
        F_V += V0 * U * dx + V * U0 * dx

    F = sum(F_c) + F_V
    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"

    solver.solve()
Пример #15
0
    def __init__(self, fileName, timeEnd, timeStep, average=False):



        fc.set_log_active(False)

        self.times = []
        self.BB = []
        self.HH = []
        self.TD = []
        self.TB = []
        self.TX = []
        self.TY = []
        self.TZ = []
        self.us = []
        self.ub = []

        ##########################################################
        ################           MESH          #################
        ##########################################################
        # TODO: Probably do not have to save then open mesh
        self.mesh = df.Mesh()
        self.inFile = fc.HDF5File(self.mesh.mpi_comm(), fileName, "r")
        self.inFile.read(self.mesh, "/mesh", False)

        #########################################################
        #################  FUNCTION SPACES  #####################
        #########################################################
        self.E_Q = df.FiniteElement("CG", self.mesh.ufl_cell(), 1)
        self.Q = df.FunctionSpace(self.mesh, self.E_Q)
        self.E_V = df.MixedElement(self.E_Q, self.E_Q, self.E_Q)
        self.V = df.FunctionSpace(self.mesh, self.E_V)

        self.assigner_inv = fc.FunctionAssigner([self.Q, self.Q, self.Q], self.V)
        self.assigner = fc.FunctionAssigner(self.V, [self.Q, self.Q, self.Q])

        self.U = df.Function(self.V)
        self.dU = df.TrialFunction(self.V)
        self.Phi = df.TestFunction(self.V)
        self.u, self.u2, self.H = df.split(self.U)
        self.phi, self.phi1, self.xsi = df.split(self.Phi)

        self.un = df.Function(self.Q)
        self.u2n = df.Function(self.Q)

        self.zero_sol = df.Function(self.Q)

        self.Bhat = df.Function(self.Q)
        self.H0 = df.Function(self.Q)
        self.A = df.Function(self.Q)

        if average:
            self.inFile.read(self.Bhat.vector(), "/bedAvg", True)
            self.inFile.read(self.A.vector(), "/smbAvg", True)
            self.inFile.read(self.H0.vector(), "/thicknessAvg", True)
        else:
            self.inFile.read(self.Bhat.vector(), "/bed", True)
            self.inFile.read(self.A.vector(), "/smb", True)
            self.inFile.read(self.H0.vector(), "/thickness", True)

        self.Hmid = theta * self.H + (1 - theta) * self.H0

        self.B = softplus(self.Bhat, -rho / rho_w * self.Hmid, alpha=0.2)  # Is not the bed, it is the lower surface

        self.S = self.B + self.Hmid

        self.width = df.interpolate(Width(degree=2), self.Q)

        self.strs = Stresses(self.U, self.Hmid, self.H0, self.H, self.width, self.B, self.S, self.Phi)

        self.R = -(self.strs.tau_xx + self.strs.tau_xz + self.strs.tau_b + self.strs.tau_d + self.strs.tau_xy) * df.dx

        #############################################################################
        ########################  MASS CONSERVATION  ################################
        #############################################################################
        self.h = df.CellSize(self.mesh)
        self.D = self.h * abs(self.U[0]) / 2.
        self.area = self.Hmid * self.width

        self.mesh_min = self.mesh.coordinates().min()
        self.mesh_max = self.mesh.coordinates().max()

        # Define boundaries
        self.ocean = df.FacetFunctionSizet(self.mesh, 0)
        self.ds = fc.ds(subdomain_data=self.ocean)  # THIS DS IS FROM FENICS! border integral

        for f in df.facets(self.mesh):
            if df.near(f.midpoint().x(), self.mesh_max):
                self.ocean[f] = 1
            if df.near(f.midpoint().x(), self.mesh_min):
                self.ocean[f] = 2

        self.R += ((self.H - self.H0) / dt * self.xsi \
                   - self.xsi.dx(0) * self.U[0] * self.Hmid \
                   + self.D * self.xsi.dx(0) * self.Hmid.dx(0) \
                   - (self.A - self.U[0] * self.H / self.width * self.width.dx(0)) \
                   * self.xsi) * df.dx + self.U[0] * self.area * self.xsi * self.ds(1) \
                  - self.U[0] * self.area * self.xsi * self.ds(0)

        #####################################################################
        #########################  SOLVER SETUP   ###########################
        #####################################################################

        # Bounds
        self.l_thick_bound = df.project(Constant(thklim), self.Q)
        self.u_thick_bound = df.project(Constant(1e4), self.Q)

        self.l_v_bound = df.project(-10000.0, self.Q)
        self.u_v_bound = df.project(10000.0, self.Q)

        self.l_bound = df.Function(self.V)
        self.u_bound = df.Function(self.V)

        self.assigner.assign(self.l_bound, [self.l_v_bound] * 2 + [self.l_thick_bound])
        self.assigner.assign(self.u_bound, [self.u_v_bound] * 2 + [self.u_thick_bound])

        # This should set the velocity at the divide (left) to zero
        self.dbc0 = df.DirichletBC(self.V.sub(0), 0, lambda x, o: df.near(x[0], self.mesh_min) and o)
        # Set the velocity on the right terminus to zero
        self.dbc1 = df.DirichletBC(self.V.sub(0), 0, lambda x, o: df.near(x[0], self.mesh_max) and o)
        # overkill?
        self.dbc2 = df.DirichletBC(self.V.sub(1), 0, lambda x, o: df.near(x[0], self.mesh_max) and o)
        # set the thickness on the right edge to thklim
        self.dbc3 = df.DirichletBC(self.V.sub(2), thklim, lambda x, o: df.near(x[0], self.mesh_max) and o)

        # Define variational solver for the mass-momentum coupled problem
        self.J = df.derivative(self.R, self.U, self.dU)

        self.coupled_problem = df.NonlinearVariationalProblem(self.R, self.U, bcs=[self.dbc0, self.dbc1, self.dbc3], \
                                                              J=self.J)

        self.coupled_problem.set_bounds(self.l_bound, self.u_bound)

        self.coupled_solver = df.NonlinearVariationalSolver(self.coupled_problem)

        # Acquire the optimizations in fenics_optimizations
        set_solver_options(self.coupled_solver)

        self.t = 0
        self.timeEnd = float(timeEnd)
        self.dtFloat = float(timeStep)

        self.inFile.close()
    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)
Пример #17
0
J = df.derivative(R, U, dU)

#####################################################################
######################  Variational Solvers  ########################
#####################################################################

# Define variational problem subject to no Dirichlet BCs, but with a
# thickness bound, plus form compiler parameters for efficiency.
mass_problem = df.NonlinearVariationalProblem(
    R, U, bcs=[], J=J, form_compiler_parameters=ffc_options)
mass_problem.set_bounds(l_bound, u_bound)

# Create an instance of vinewtonrsls, PETSc's variational inequality
# solver.  Not clear that this is needed, given that the ice should never be
# negative by design.
mass_solver = df.NonlinearVariationalSolver(mass_problem)
mass_solver.parameters['nonlinear_solver'] = 'snes'
mass_solver.parameters['snes_solver']['method'] = 'vinewtonrsls'
mass_solver.parameters['snes_solver']['relative_tolerance'] = 1e-3
mass_solver.parameters['snes_solver']['absolute_tolerance'] = 1e-3
mass_solver.parameters['snes_solver']['error_on_nonconvergence'] = True
mass_solver.parameters['snes_solver']['linear_solver'] = 'mumps'
mass_solver.parameters['snes_solver']['maximum_iterations'] = 10
mass_solver.parameters['snes_solver']['report'] = False

#####################################################################
############### INITIALIZE PLOTTING AND STORAGE #####################
#####################################################################

# Basic animation utilities
if PLOT:
Пример #18
0
    def solve_nonlinear(self, inputs, outputs):

        pde_problem = self.options['pde_problem']
        state_name = self.options['state_name']
        problem_type = self.options['problem_type']
        visualization = self.options['visualization']
        state_function = pde_problem.states_dict[state_name]['function']
        for argument_name, argument_function in iteritems(
                self.argument_functions_dict):
            density_func = argument_function

        self.itr = self.itr + 1

        state_function = pde_problem.states_dict[state_name]['function']
        residual_form = pde_problem.states_dict[state_name]['residual_form']

        self._set_values(inputs, outputs)

        self.derivative_form = df.derivative(residual_form, state_function)
        df.set_log_active(True)
        if problem_type == 'linear_problem':
            if state_name == 'density':
                print('this is a variational density filter')
                df.solve(residual_form == 0,
                         state_function,
                         J=self.derivative_form,
                         solver_parameters={
                             "newton_solver": {
                                 "maximum_iterations": 1,
                                 "error_on_nonconvergence": False
                             }
                         })
            else:
                df.solve(residual_form == 0,
                         state_function,
                         bcs=pde_problem.bcs_list,
                         J=self.derivative_form,
                         solver_parameters={
                             "newton_solver": {
                                 "maximum_iterations": 1,
                                 "error_on_nonconvergence": False
                             }
                         })
        elif problem_type == 'nonlinear_problem':
            state_function.vector().set_local(
                np.zeros((state_function.function_space().dim())))
            problem = df.NonlinearVariationalProblem(residual_form,
                                                     state_function,
                                                     pde_problem.bcs_list,
                                                     self.derivative_form)
            solver = df.NonlinearVariationalSolver(problem)
            solver.parameters['nonlinear_solver'] = 'snes'
            solver.parameters["snes_solver"]["relative_tolerance"] = 5e-100
            solver.parameters["snes_solver"]["absolute_tolerance"] = 5e-50
            solver.parameters["snes_solver"]["line_search"] = 'bt'
            solver.parameters["snes_solver"][
                "linear_solver"] = 'mumps'  # "cg" "gmres"
            solver.parameters["snes_solver"]["maximum_iterations"] = 500
            solver.parameters["snes_solver"]["relative_tolerance"] = 5e-100
            solver.parameters["snes_solver"]["absolute_tolerance"] = 5e-50

            # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000
            solver.parameters["snes_solver"]["error_on_nonconvergence"] = False
            solver.solve()

        elif problem_type == 'nonlinear_problem_load_stepping':
            num_steps = 4
            state_function.vector().set_local(
                np.zeros((state_function.function_space().dim())))
            for i in range(num_steps):
                v = df.TestFunction(state_function.function_space())
                if i < (num_steps - 1):
                    residual_form = get_residual_form(
                        state_function,
                        v,
                        density_func,
                        density_func.function_space,
                        tractionBC,
                        # df.Constant((0.0, -9.e-1))
                        df.Constant((0.0, -9.e-1 / num_steps * (i + 1))),
                        'False')
                else:
                    residual_form = get_residual_form(
                        state_function,
                        v,
                        density_func,
                        density_func.function_space,
                        tractionBC,
                        # df.Constant((0.0, -9.e-1))
                        df.Constant((0.0, -9.e-1 / num_steps * (i + 1))),
                        'vol')
                problem = df.NonlinearVariationalProblem(
                    residual_form, state_function, pde_problem.bcs_list,
                    self.derivative_form)
                solver = df.NonlinearVariationalSolver(problem)
                solver.parameters['nonlinear_solver'] = 'snes'
                solver.parameters["snes_solver"]["line_search"] = 'bt'
                solver.parameters["snes_solver"][
                    "linear_solver"] = 'mumps'  # "cg" "gmres"
                solver.parameters["snes_solver"]["maximum_iterations"] = 500
                solver.parameters["snes_solver"]["relative_tolerance"] = 1e-15
                solver.parameters["snes_solver"]["absolute_tolerance"] = 1e-15

                # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000
                solver.parameters["snes_solver"][
                    "error_on_nonconvergence"] = False
                solver.solve()

        # option to store the visualization results
        if (visualization == 'True') and (self.itr % 50 == 0):
            for argument_name, argument_function in iteritems(
                    self.argument_functions_dict):
                if argument_name == 'density':

                    df.File('solutions_iterations_40ramp/{}_{}.pvd'.format(
                        argument_name, self.itr)) << df.project(
                            argument_function / (1 + 8. *
                                                 (1. - argument_function)),
                            argument_function.function_space())
                else:
                    df.File('solutions_iterations_40ramp/{}_{}.pvd'.format(
                        argument_name, self.itr)) << argument_function
            df.File('solutions_iterations_40ramp/{}_{}.pvd'.format(
                state_name, self.itr)) << state_function
        self.L = -residual_form

        outputs[state_name] = state_function.vector().get_local()
        self._set_values(inputs, outputs)
Пример #19
0
    def __init__(self, V, viscosity=1e-2, penalty=1e5):
        '''
        Parameters
        ----------
        V : dolfin.FunctionSpace
            Function space for the distance function.
        viscosity: float or dolfin.Constant
            Stabilization for the unique solution of the distance problem.
        penalty: float or dolfin.Constant
            Penalty for weakly enforcing the zero-distance boundary conditions.

        '''

        if not isinstance(V, dolfin.FunctionSpace):
            raise TypeError('Parameter `V` must be a `dolfin.FunctionSpace`')

        if not isinstance(viscosity, Constant):
            if not isinstance(viscosity, (float, int)):
                raise TypeError('`Parameter `viscosity`')
            viscosity = Constant(viscosity)

        if not isinstance(penalty, Constant):
            if not isinstance(penalty, (float, int)):
                raise TypeError('Parameter `penalty`')
            penalty = Constant(penalty)

        self._viscosity = viscosity
        self._penalty = penalty

        mesh = V.mesh()
        xs = mesh.coordinates()
        l0 = (xs.max(0) - xs.min(0)).min()

        self._d = d = Function(V)
        self._Q = dolfin.FunctionSpace(mesh, 'DG', 0)

        self._mf = dolfin.MeshFunction('size_t', mesh,
                                       mesh.geometric_dimension())
        self._dx_penalty = dx(subdomain_id=1,
                              subdomain_data=self._mf,
                              domain=mesh)

        v0 = dolfin.TestFunction(V)
        v1 = dolfin.TrialFunction(V)

        target_gradient = Constant(1.0)
        scaled_penalty = penalty / mesh.hmax()

        lhs_F0 = l0*dot(grad(v0), grad(v1))*dx \
            + scaled_penalty*v0*v1*self._dx_penalty

        rhs_F0 = v0 * target_gradient * dx

        problem = dolfin.LinearVariationalProblem(lhs_F0, rhs_F0, d)
        self._linear_solver = dolfin.LinearVariationalSolver(problem)
        self._linear_solver.parameters["symmetric"] = True

        F = v0*(grad(d)**2-target_gradient)*dx \
            + viscosity*l0*dot(grad(v0), grad(d))*dx \
            + scaled_penalty*v0*d*self._dx_penalty

        J = dolfin.derivative(F, d, v1)

        problem = dolfin.NonlinearVariationalProblem(F, d, bcs=None, J=J)
        self._nonlinear_solver = dolfin.NonlinearVariationalSolver(problem)
        self._nonlinear_solver.parameters['nonlinear_solver'] = 'newton'
        self._nonlinear_solver.parameters['symmetric'] = False

        self._solve_initdist_problem = self._linear_solver.solve
        self._solve_distance_problem = self._nonlinear_solver.solve
Пример #20
0
    def step(self, t0: float, t1: float) -> None:
        """Solve on the given time step (`t0`, `t1`).

        End users are recommended to use solve instead.

        Arguments:
            t0: Start time.
            t1: End time.
        """
        timer = df.Timer("ODE step")

        # Extract time mesh
        k_n = df.Constant(t1 - t0)

        # Extract previous solution(s)
        v_, s_ = split_function(self.vs_, self._num_states + 1)

        # Set-up current variables
        self.vs.assign(self.vs_)  # Start with good guess
        v, s = split_function(self.vs, self._num_states + 1)
        w, r = split_function(df.TestFunction(self.VS), self._num_states + 1)

        # Define equation based on cell model
        Dt_v = (v - v_) / k_n
        Dt_s = (s - s_) / k_n

        theta = self._parameters["theta"]

        # Set time (propagates to time-dependent variables defined via self.time)
        t = t0 + theta * (t1 - t0)
        self.time.assign(t)

        v_mid = theta * v + (1.0 - theta) * v_
        s_mid = theta * s + (1.0 - theta) * s_

        if isinstance(self._cell_model, MultiCellModel):
            model = self._cell_model
            mesh = model.mesh()
            dy = df.Measure("dx", domain=mesh, subdomain_data=model.markers())

            if self._I_s is None:
                self._I_s = df.Constant(0)
            rhs = self._I_s * w * dy()

            n = model.num_states()  # Extract number of global states

            # Collect contributions to lhs by iterating over the different cell models
            domains = self._cell_model.keys()
            lhs_list = list()
            for k, model_k in enumerate(model.models()):
                n_k = model_k.num_states(
                )  # Extract number of local (non-trivial) states

                # Extract right components of coefficients and test functions () is not the same as (1,)
                if n_k == 1:
                    s_mid_k = s_mid[0]
                    r_k = r[0]
                    Dt_s_k = Dt_s[0]
                else:
                    s_mid_k = df.as_vector(tuple(s_mid[j] for j in range(n_k)))
                    r_k = df.as_vector(tuple(r[j] for j in range(n_k)))
                    Dt_s_k = df.as_vector(tuple(Dt_s[j] for j in range(n_k)))

                i_k = domains[k]  # Extract domain index of cell model k

                # Extract right currents and ion channel expressions
                F_theta_k = self._F(v_mid, s_mid_k, time=self.time, index=i_k)
                I_theta_k = -self._I_ion(
                    v_mid, s_mid_k, time=self.time, index=i_k)

                # Variational contribution over the relevant domain
                a_k = ((Dt_v - I_theta_k) * w + df.inner(Dt_s_k, r_k) -
                       df.inner(F_theta_k, r_k)) * dy(i_k)

                # Add s_trivial = 0 on Omega_{i_k} in variational form:
                a_k += sum(s[j] * r[j] for j in range(n_k, n)) * dy(i_k)
                lhs_list.append(a_k)
            lhs = sum(lhs_list)
        else:
            dz, rhs = rhs_with_markerwise_field(self._I_s, self._mesh, w)

            # Evaluate currents at averaged v and s. Note sign for I_theta
            F_theta = self._F(v_mid, s_mid, time=self.time)
            I_theta = -self._I_ion(v_mid, s_mid, time=self.time)
            lhs = (Dt_v - I_theta) * w * dz + df.inner(Dt_s - F_theta, r) * dz

        # Set-up system of equations
        G = lhs - rhs

        # Solve system
        pde = df.NonlinearVariationalProblem(G,
                                             self.vs,
                                             J=df.derivative(G, self.vs))
        solver = df.NonlinearVariationalSolver(pde)
        solver_parameters = self._parameters["nonlinear_variational_solver"]
        solver_parameters["nonlinear_solver"] = "snes"
        solver_parameters["snes_solver"]["absolute_tolerance"] = 1e-13
        solver_parameters["snes_solver"]["relative_tolerance"] = 1e-13

        # Tested on Cressman
        solver_parameters["snes_solver"]["linear_solver"] = "bicgstab"
        solver_parameters["snes_solver"]["preconditioner"] = "jacobi"

        solver.parameters.update(solver_parameters)

        solver.solve()
        timer.stop()
Пример #21
0
def test_prb88_184422():
    mu0 = 4 * np.pi * 1e-7

    Ms = 8.6e5
    A = 16e-12
    D = 3.6e-3
    K = 510e3

    mesh = CuboidMesh(nx=100, dx=1, unit_length=1e-9)

    sim = Sim(mesh)

    sim.driver.set_tols(rtol=1e-10, atol=1e-14)

    sim.driver.alpha = 0.5
    sim.driver.gamma = 2.211e5
    sim.Ms = Ms
    sim.do_precession = False

    sim.set_m((0, 0, 1))

    sim.add(UniformExchange(A=A))
    sim.add(DMI(-D, type='interfacial'))
    sim.add(UniaxialAnisotropy(K, axis=(0, 0, 1)))

    sim.relax(dt=1e-13,
              stopping_dmdt=0.01,
              max_steps=5000,
              save_m_steps=None,
              save_vtk_steps=50)

    m = sim.spin

    mx, my, mz = np.split(m, 3)

    x_array = np.linspace(-49.5, 49.5, 100)

    #plt.plot(x_array, mx)
    #plt.plot(x_array, my)
    #plt.plot(x_array, mz)

    mesh = df.IntervalMesh(100, -50, 50)

    Delta = np.sqrt(A / K)
    xi = 2 * A / D

    Delta_s = Delta * 1e9

    V = df.FunctionSpace(mesh, "Lagrange", 1)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)
    u_ = df.Function(V)
    F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \
        (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx
    F = df.action(F, u_)

    J = df.derivative(F, u_, u)

    # the boundary condition is from equation (8)
    theta0 = np.arcsin(Delta / xi)
    ss = 'x[0]<0? %g: %g ' % (-theta0, theta0)

    u0 = df.Expression(ss)

    def u0_boundary(x, on_boundary):
        return on_boundary

    bc = df.DirichletBC(V, u0, u0_boundary)

    problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J)
    solver = df.NonlinearVariationalSolver(problem)
    solver.solve()

    u_array = u_.vector().array()

    mx_df = []
    for x in x_array:
        mx_df.append(u_(x))

    #plt.plot(x_array, mx_df)

    assert abs(np.max(mx - mx_df)) < 0.05
Пример #22
0
def NSPFEC_action(u_, u_1, phi_, phi_1, c_, c_1, u, p, phi, g, c, V, v, q, psi,
                  h, b, U, rho, M, nu, rho_e, K, veps, drho, grav, sigma_bar,
                  eps, dveps, dbeta, z, per_tau, enable_NS, enable_PF,
                  enable_EC):
    # The setup of the Navier-Stokes part of F
    F = []
    if enable_NS:
        F_NS = (per_tau * rho * df.dot(u_ - u_1, v) * df.dx + df.inner(
            df.grad(u), df.outer(rho * u - drho * M * df.grad(g), v)) * df.dx +
                2 * nu * df.inner(df.sym(df.grad(u)), df.grad(v)) * df.dx -
                p * df.div(v) * df.dx + df.div(u) * q * df.dx -
                df.dot(rho * grav, v) * df.dx)
        if enable_PF:
            F_NS += -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_NS += rho_e * df.dot(df.grad(V), v) * df.dx
        if enable_PF and enable_EC:
            F_NS += dveps * df.dot(df.grad(phi), v) * df.dot(
                df.grad(V), df.grad(V)) * df.dx
        F.append(F_NS)

    # The setup of the Phase feild equations
    if enable_PF:
        F_PF_phi = (per_tau * (phi_ - phi_1) * psi * df.dx +
                    M * df.dot(df.grad(g), df.grad(psi)) * df.dx)
        if enable_NS:
            F_PF_phi += df.dot(u, df.grad(phi)) * psi * df.dx

        F_PF_g = (g * h * df.dx -
                  sigma_bar * eps * df.dot(df.grad(phi), df.grad(h)) * df.dx -
                  sigma_bar / eps * diff_pf_potential(phi) * h * df.dx)
        if enable_EC:
            F_PF_g += (-sum(
                [dbeta_i * ci * h * df.dx for dbeta_i, ci in zip(dbeta, c)]) +
                       dveps * df.dot(df.grad(V), df.grad(V)) * h * df.dx)
        F_PF = F_PF_phi + F_PF_g
        F.append(F_PF)

    # The setup of the Electrochemistry
    if enable_EC:
        F_E_c = []
        for ci, ci_, ci_1, bi, Ki, zi in zip(c, c_, c_1, b, K, z):
            F_E_ci = (per_tau * (ci_ - ci_1) * bi * df.dx +
                      Ki * df.dot(df.grad(ci), df.grad(bi)) * df.dx)
            if zi != 0:
                F_E_ci += Ki * zi * ci * df.dot(df.grad(V),
                                                df.grad(bi)) * df.dx
            if enable_NS:
                F_E_ci += df.dot(u, df.grad(ci)) * bi * df.dx
            F_E_c.append(F_E_ci)
        F_E_V = veps * df.dot(df.grad(V), df.grad(U)) * df.dx
        if rho_e != 0:
            F_E_V += -rho_e * U * df.dx
        F_E = sum(F_E_c) + F_E_V
        F.append(F_E)

    F = sum(F)
    J = df.derivative(F, w_NSPFEC)

    problem_NSPFEC = df.NonlinearVariationalProblem(F, w_NSPFEC, bcs_NSPFEC, J)
    solver_NSPFEC = df.NonlinearVariationalSolver(problem_NSPFEC)
    if use_iterative_solvers:
        solver_NSPFEC.parameters['newton_solver']['linear_solver'] = 'gmres'
        solver_NSPFEC.parameters['newton_solver']['preconditioner'] = 'ilu'

    return solver_NSPFEC
Пример #23
0
    def __init__(self,
                 J,
                 U,
                 u,
                 m,
                 bcs,
                 dx_m=None,
                 dims_m=None,
                 use_nonlinear_solver=False):
        '''
        Parameters
        ----------
        J : ufl.Form
            Objective functional to maximize, e.g. linear-elastic strain energy.
        U : ufl.Form
            Linear-elastic strain energy.
        u : dolfin.Function
            Displacement field.
        m : dolfin.Function
            Vector-valued "body force" like traction field.
        bcs : (list of) dolfin.DirichletBC('s)
            Dirichlet boundary conditions.
        dx_m : dolfin.Measure or None (optional)
            "Body force" integration measure. Can be of cell type or exterior
            facet type; the default is cell type. Note, the integration measure
            can be defined on a subdomain (not necessarily on the whole domain).
        kappa : float or None (optional)
            Diffusion-like constant for smoothing the solution (`m`) increment.

        Notes
        -----
        If the "body force" integration measure `dx_m` concerns cells (as
        opposed to exterior facets), the gradient smoothing constant `kappa`
        can be `None`. Usually, `kappa` will need to be some small positive
        value if `dx_m` concerns exterior facets.

        '''

        if not isinstance(J, ufl_form_t):
            raise TypeError('Parameter `J`')

        if not isinstance(U, ufl_form_t):
            raise TypeError('Parameter `U`')

        if not isinstance(u, Function):
            raise TypeError('Parameter `u`')

        if not isinstance(m, Function):
            raise TypeError('Parameter `m`')

        if len(u) != len(m):
            raise ValueError(
                'Functions `u` and `m` must live in the same dimension space')

        if bcs is None:
            bcs = ()
        elif not isinstance(bcs, (list, tuple)):
            bcs = (bcs, )
        if not all(isinstance(bc, DirichletBC) for bc in bcs):
            raise TypeError('Parameter `bcs` must contain '
                            'homogenized `DirichletBC`(\'s)')

        if dims_m is not None:
            if not isinstance(bcs, (list, tuple, range)):
                dims_m = (dims_m, )
            if not all(isinstance(dim_i, int) for dim_i in dims_m):
                raise TypeError('Parameter `dims_m`')
            if not all(0 <= dim_i < len(m) for dim_i in dims_m):
                raise ValueError('Parameter `dims_m`')

        if dx_m is None:
            dx_m = dx
        elif not isinstance(dx_m, dolfin.Measure):
            raise TypeError('Parameter `dx_m`')

        bcs_zro = []
        for bc in bcs:
            bc_zro = DirichletBC(bc)
            bc_zro.homogenize()
            bcs_zro.append(bc_zro)

        V_u = u.function_space()
        V_m = m.function_space()

        v0_u = dolfin.TestFunction(V_u)
        v0_m = dolfin.TestFunction(V_m)

        v1_u = dolfin.TrialFunction(V_u)
        v1_m = dolfin.TrialFunction(V_m)

        self._u = u
        self._m = m
        self._z = z = Function(V_u)  # Adjoint solution

        self._J = J
        dJ_u = derivative(J, u, v0_u)
        self._dJ_m = derivative(J, m, v0_m)

        dU_u = derivative(U, u, v0_u)  # Internal force
        d2U_uu = a = derivative(dU_u, u, v1_u)  # Stiffness

        if dims_m is None: dW_u = L = dot(v0_u, m) * dx_m
        else: dW_u = L = sum(v0_u[i] * m[i] for i in dims_m) * dx_m

        self._ufl_norm_m = dolfin.sqrt(m**2) * dx_m  # equiv. L1-norm
        self._assembled_adj_dW_um = assemble(dot(v0_m, v1_u) * dx_m)
        self._dimdofs_V_m = tuple(
            np.array(V_m_sub_i.dofmap().dofs()) for V_m_sub_i in V_m.split())

        if use_nonlinear_solver:

            self._equilibrium_solver = dolfin.NonlinearVariationalSolver(
                dolfin.NonlinearVariationalProblem(dU_u - dW_u, u, bcs,
                                                   d2U_uu))

            self._adjoint_solver = dolfin.LinearVariationalSolver(
                dolfin.LinearVariationalProblem(d2U_uu, dJ_u, z, bcs_zro))
            # NOTE: `d2U_uu` is equivalent to `adjoint(d2U_uu)` due to symmetry

            self._equilibrium_solver.parameters["symmetric"] = True
            self._adjoint_solver.parameters["symmetric"] = True

        else:

            self._equilibrium_solver = LinearEquilibriumSolver(a, L, u, bcs)
            self._adjoint_solver = LinearAdjointSolver(None, dJ_u, z, bcs_zro)
            self._adjoint_solver._solver = self._equilibrium_solver.solver
            self._equilibrium_solver.parameters['symmetric'] = True
            # NOTE: `a` is equivalent to `adjoint(a)` due to symmetry; however,
            #       the LU factorization can be reused in the adjoint solver.

        if dx_m.integral_type() == 'cell':
            kappa = None
        else:
            # Compute scale factor for `kappa` based on domain size
            mesh = V_m.mesh()
            xs = mesh.coordinates()
            domain_volume = assemble(1.0 * dx(mesh))
            domain_length = (xs.max(0) - xs.min(0)).max()
            scale_factor = domain_volume / domain_length
            kappa = Constant(scale_factor * SMOOTHING_SOLVER_KAPPA)

        self._smoothing_solver = SmoothingSolver(V_m, kappa)
 def _setup_implicit_problem(self):
     assert hasattr(self, "_parameters")
     assert hasattr(self, "_mesh")
     assert hasattr(self, "_Wh")
     assert hasattr(self, "_coefficients")
     assert hasattr(self, "_one")
     assert hasattr(self, "_omega")
     assert hasattr(self, "_v0")
     assert hasattr(self, "_v00")
     assert hasattr(self, "_T0")
     assert hasattr(self, "_T00")
     print "   setup implicit problem..."
     #=======================================================================
     # retrieve imex coefficients
     a, c = self._imex_alpha, self._imex_gamma
     #=======================================================================
     # trial and test function
     (del_v, del_p, del_T) = dlfn.TestFunctions(self._Wh)
     v, p, T = dlfn.split(self._sol)
     # volume element
     dV = dlfn.Measure("dx", domain=self._mesh)
     # reference to time step
     timestep = self._timestep
     #=======================================================================
     from dolfin import dot, grad
     # 1) momentum equation
     momentum_eqn = (
         dot((a[0] * v + a[1] * self._v0 + a[2] * self._v00) / timestep,
             del_v) + dot(dot(grad(v), v), del_v) + self._coefficients[1] *
         a_op(c[0] * v + c[1] * self._v0 + c[2] * self._v00, del_v) -
         b_op(del_v, p) - b_op(v, del_p)) * dV
     # 2) momentum equation: coriolis term
     if self._parameters.rotation is True:
         assert self._coefficients[0] != 0.0
         print "   adding rotation to the model..."
         # add Coriolis term
         if self._space_dim == 2:
             momentum_eqn += self._coefficients[0] * (-v[1] * del_v[0] +
                                                      v[0] * del_v[1]) * dV
         elif self._space_dim == 3:
             assert hasattr(self, "_rotation_vector")
             assert isinstance(self._rotation_vector,
                               (dlfn.Constant, dlfn.Expression))
             from dolfin import cross
             momentum_eqn += self._coefficients[0] * dot(
                 cross(self._rotation_vector, v), del_v) * dV
     # 3) momentum equation: coriolis term
     if self._parameters.buoyancy is True:
         assert self._coefficients[2] != 0.0
         assert hasattr(self, "_gravity") and isinstance(
             self._gravity, (dlfn.Expression, dlfn.Constant))
         print "   adding buoyancy to the model..."
         # add buoyancy term
         momentum_eqn += self._coefficients[2] * T * dot(
             self._gravity, del_v) * dV
     #=======================================================================
     # 4) energy equation
     energy_eqn = (
         (a[0] * T + a[1] * self._T0 + a[2] * self._T00) / timestep * del_T
         + dot(v, grad(T)) * del_T + self._coefficients[3] *
         a_op(c[0] * T + c[1] * self._T0 + c[2] * self._T00, del_T)) * dV
     #=======================================================================
     # full problem
     self._eqn = momentum_eqn + energy_eqn
     if not hasattr(self, "_dirichlet_bcs"):
         self._setup_boundary_conditons()
     self._jacobian = dlfn.derivative(self._eqn, self._sol)
     problem = dlfn.NonlinearVariationalProblem(self._eqn,
                                                self._sol,
                                                J=self._jacobian,
                                                bcs=self._dirichlet_bcs)
     self._solver = dlfn.NonlinearVariationalSolver(problem)
     prm = self._solver.parameters
     prm["newton_solver"]["absolute_tolerance"] = 1e-6
     prm["newton_solver"]["relative_tolerance"] = 1e-9
     prm["newton_solver"]["maximum_iterations"] = 10
Пример #25
0
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
Пример #26
0
    def solve_nonlinear(self, inputs, outputs):
        pde_problem = self.options['pde_problem']
        state_name = self.options['state_name']
        problem_type = self.options['problem_type']
        visualization = self.options['visualization']
        state_function = pde_problem.states_dict[state_name]['function']
        for argument_name, argument_function in iteritems(
                self.argument_functions_dict):
            density_func = argument_function
        mesh = state_function.function_space().mesh()
        sub_domains = df.MeshFunction('size_t', mesh,
                                      mesh.topology().dim() - 1)
        upper_edge = TractionBoundary()
        upper_edge.mark(sub_domains, 6)
        dss = df.Measure('ds')(subdomain_data=sub_domains)
        tractionBC = dss(6)

        self.itr = self.itr + 1

        state_function = pde_problem.states_dict[state_name]['function']
        residual_form = get_residual_form(
            state_function,
            df.TestFunction(state_function.function_space()),
            density_func,
            density_func.function_space(),
            tractionBC,
            # df.Constant((0.0, -9.e-1))
            df.Constant((0.0, -9.e-1)),
            int(self.itr))

        self._set_values(inputs, outputs)

        self.derivative_form = df.derivative(residual_form, state_function)
        df.set_log_level(df.LogLevel.ERROR)
        df.set_log_active(True)
        # df.solve(residual_form==0, state_function, bcs=pde_problem.bcs_list, J=self.derivative_form)
        if problem_type == 'linear_problem':
            df.solve(residual_form == 0,
                     state_function,
                     bcs=pde_problem.bcs_list,
                     J=self.derivative_form,
                     solver_parameters={
                         "newton_solver": {
                             "maximum_iterations": 60,
                             "error_on_nonconvergence": False
                         }
                     })
        elif problem_type == 'nonlinear_problem':
            problem = df.NonlinearVariationalProblem(residual_form,
                                                     state_function,
                                                     pde_problem.bcs_list,
                                                     self.derivative_form)
            solver = df.NonlinearVariationalSolver(problem)
            solver.parameters['nonlinear_solver'] = 'snes'
            solver.parameters["snes_solver"]["line_search"] = 'bt'
            solver.parameters["snes_solver"][
                "linear_solver"] = 'mumps'  # "cg" "gmres"
            solver.parameters["snes_solver"]["maximum_iterations"] = 500
            solver.parameters["snes_solver"]["relative_tolerance"] = 5e-13
            solver.parameters["snes_solver"]["absolute_tolerance"] = 5e-13

            # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000
            solver.parameters["snes_solver"]["error_on_nonconvergence"] = False
            solver.solve()

        elif problem_type == 'nonlinear_problem_load_stepping':
            num_steps = 3
            state_function.vector().set_local(
                np.zeros((state_function.function_space().dim())))
            for i in range(num_steps):
                v = df.TestFunction(state_function.function_space())
                if i < (num_steps - 1):
                    residual_form = get_residual_form(
                        state_function,
                        v,
                        density_func,
                        density_func.function_space(),
                        tractionBC,
                        # df.Constant((0.0, -9.e-1))
                        df.Constant((0.0, -9.e-1 / num_steps * (i + 1))),
                        int(self.itr))
                else:
                    residual_form = get_residual_form(
                        state_function,
                        v,
                        density_func,
                        density_func.function_space(),
                        tractionBC,
                        # df.Constant((0.0, -9.e-1))
                        df.Constant((0.0, -9.e-1 / num_steps * (i + 1))),
                        int(self.itr))
                problem = df.NonlinearVariationalProblem(
                    residual_form, state_function, pde_problem.bcs_list,
                    self.derivative_form)
                solver = df.NonlinearVariationalSolver(problem)
                solver.parameters['nonlinear_solver'] = 'snes'
                solver.parameters["snes_solver"]["line_search"] = 'bt'
                solver.parameters["snes_solver"][
                    "linear_solver"] = 'mumps'  # "cg" "gmres"
                solver.parameters["snes_solver"]["maximum_iterations"] = 500
                solver.parameters["snes_solver"]["relative_tolerance"] = 1e-15
                solver.parameters["snes_solver"]["absolute_tolerance"] = 1e-15

                # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000
                solver.parameters["snes_solver"][
                    "error_on_nonconvergence"] = False
                solver.solve()

        # option to store the visualization results
        if visualization == 'True':
            for argument_name, argument_function in iteritems(
                    self.argument_functions_dict):
                df.File('solutions_iterations_3d/{}_{}.pvd'.format(
                    argument_name, self.itr)) << argument_function

        self.L = -residual_form
        self.itr = self.itr + 1
        outputs[state_name] = state_function.vector().get_local()
Пример #27
0
def setup_NSPFEC(w_NSPFEC, w_1NSPFEC,
                 dirichlet_bcs_NSPFEC,
                 neumann_bcs,
                 boundary_to_mark,
                 dx, ds, normal,
                 v, q, q0, psi, h, b, U,
                 u_, p_, p0_, phi_, g_, c_, V_,
                 u_1, p_1, p0_1, phi_1, g_1, c_1, V_1,
                 M_, nu_, veps_, rho_, K_, beta_, rho_e_,
                 dbeta, dveps, drho,
                 per_tau, sigma_bar, eps, grav, z,
                 solutes,
                 enable_NS, enable_PF, enable_EC,
                 use_iterative_solvers,
                 p_lagrange,
                 q_rhs):
    """ The full problem of electrohydrodynamics in two phases.
    Note that it is possible to turn off the different parts at will.
    """
    # Setup of the Navier-Stokes part of F
    mom_ = rho_*u_
    if enable_PF:
        mom_ += -M_*drho * df.nabla_grad(g_)
    
    F = []
    if enable_NS:
        F_NS = (per_tau * rho_ * df.dot(u_ - u_1, v) * dx
                + df.inner(df.nabla_grad(u_), df.outer(mom_, v)) * dx
                + 2*nu_*df.inner(df.sym(df.nabla_grad(u_)),
                                 df.sym(df.nabla_grad(v))) * dx
                - p_ * df.div(v) * dx
                - df.div(u_) * q * dx
                - df.dot(rho_ * grav, v) * dx)
        # if enable_PF:
        #     F_NS += - sigma_bar*eps*df.inner(
        #         df.outer(df.grad(phi_),
        #                  df.grad(phi_)), df.grad(v)) * dx
        # if enable_EC and rho_e_ != 0:
        #     F_NS += rho_e_*df.dot(df.grad(V_), v) * dx
        # if enable_PF and enable_EC:
        #     F_NS += dveps*df.dot(
        #         df.grad(phi_), v)*df.dot(df.grad(V_),
        #                                  df.grad(V_)) * dx

        if enable_PF:
            F_NS += phi_*df.dot(df.grad(g_), v) * dx

        if enable_EC:
            for ci_, dbetai, solute in zip(c_, dbeta, solutes):
                zi = solute[1]
                F_NS += df.dot(df.grad(ci_), v) * dx \
                        + ci_*dbetai*df.dot(df.grad(phi_), v) * dx \
                        + zi*ci_*df.dot(df.grad(V_), v) * dx

        # Slip boundary condition
        for boundary_name, slip_length in neumann_bcs["u"].items():
            F_NS += 1./slip_length * \
                    df.dot(u_, v) * ds(boundary_to_mark[boundary_name])

        # Pressure boundary condition
        for boundary_name, pressure in neumann_bcs["p"].items():
            F_NS += pressure * df.inner(
                normal, v) * ds(boundary_to_mark[boundary_name])

        # Lagrange pressure
        if p_lagrange:
            F_NS += (p_*q0 + q*p0_)*dx

        # RHS source terms
        if "u" in q_rhs:
            F_NS += -df.dot(q_rhs["u"], v)*dx

        F.append(F_NS)

    # Setup of the phase-field equations
    if enable_PF:
        phi_1_flt = unit_interval_filter(phi_1)
        F_PF_phi = (per_tau*(phi_-phi_1_flt)*psi*df.dx +
                    M_*df.dot(df.grad(g_), df.grad(psi)) * dx)
        if enable_NS:
            F_PF_phi += df.dot(u_, df.grad(phi_)) * psi * dx

        F_PF_g = (g_ * h * dx
                  - sigma_bar*eps*df.dot(df.grad(phi_), df.grad(h)) * dx
                  - sigma_bar/eps*diff_pf_potential(phi_) * h * dx)
        if enable_EC:
            F_PF_g += (-sum([dbeta_i * ci_ * h * dx
                             for dbeta_i, ci_ in zip(dbeta, c_)])
                       + dveps * df.dot(df.grad(V_), df.grad(V_)) * h * dx)

        # Contact angle boundary condtions
        for boundary_name, costheta in neumann_bcs["phi"].items():
            fw_prime = diff_pf_contact(phi_)
            F_PF_g += sigma_bar * costheta * fw_prime * h * ds(
                boundary_to_mark[boundary_name])

        # RHS source terms
        if "phi" in q_rhs:
            F_PF_phi += -q_rhs["phi"]*psi*dx

        F_PF = F_PF_phi + F_PF_g
        F.append(F_PF)

    # Setup of the electrochemistry
    if enable_EC:
        F_E_c = []
        for ci_, ci_1, bi, Ki_, zi, dbetai, solute in zip(
                c_, c_1, b, K_, z, dbeta, solutes):
            ci_1_flt = max_value(ci_1, 0.)
            F_E_ci = (per_tau*(ci_-ci_1_flt)*bi*df.dx
                       + Ki_*df.dot(df.grad(ci_), df.grad(bi))*df.dx)
            if zi != 0:
                F_E_ci += Ki_*zi*ci_*df.dot(df.grad(V_),
                                             df.grad(bi))*df.dx
            if enable_NS:
                F_E_ci += df.dot(u_, df.grad(ci_))*bi*df.dx

            if enable_PF:
                F_E_ci += Ki_*ci_*dbetai*df.dot(df.grad(phi_),
                                                df.grad(bi)) * dx

            if solute[0] in q_rhs:
                F_E_ci += - q_rhs[solute[0]] * bi * dx

            F_E_c.append(F_E_ci)

        F_E_V = veps_*df.dot(df.grad(V_), df.grad(U))*df.dx

        if rho_e_ != 0:
            F_E_V += -rho_e_*U*df.dx

        # Surface charge boundary condition
        for boundary_name, sigma_e in neumann_bcs["V"].items():
            F_E_V += -sigma_e*U*ds(boundary_to_mark[boundary_name])

        # RHS source terms
        if "V" in q_rhs:
            F_E_V += q_rhs["V"]*U*dx

        F_E = sum(F_E_c) + F_E_V

        F.append(F_E)

    F = sum(F)

    J = df.derivative(F, w_NSPFEC)
    problem_NSPFEC = df.NonlinearVariationalProblem(F, w_NSPFEC, dirichlet_bcs_NSPFEC, J)
    solver_NSPFEC = df.NonlinearVariationalSolver(problem_NSPFEC)
    if use_iterative_solvers:
        solver_NSPFEC.parameters['newton_solver']['linear_solver'] = 'gmres'
        solver_NSPFEC.parameters['newton_solver']['preconditioner'] = 'ilu'

    return solver_NSPFEC
Пример #28
0
def solver(interval, dt=0.1, theta=1):
    t0, t1 = interval

    mesh = get_mesh(10)
    cell_function = get_cell_function(mesh)
    model = get_models(cell_function)
    num_global_states = model.num_states()

    # Create time keepers and time step
    const_dt = df.Constant(dt)
    current_time = df.Constant(0)
    t = t0 + theta*(t1 - t0)
    current_time.assign(t)

    # Create stimulus
    stimulus = df.Constant(0)

    # Make shared function pace
    mixed_vector_function_space = df.VectorFunctionSpace(
        mesh,
        "DG",
        0,
        dim=num_global_states + 1
    )

    # Create previous solution and assign initial conditions
    previous_solution = df.Function(mixed_vector_function_space)

    # _model = xb.cellmodels.Cressman()
    # previous_solution.assign(_model.initial_conditions())        # Initial condition
    previous_solution.assign(model.initial_conditions())        # Initial condition

    v_previous, s_previous = splat(previous_solution, num_global_states + 1)

    # Create current solution
    current_solution = df.Function(mixed_vector_function_space)
    v_current, s_current = splat(current_solution, num_global_states + 1)

    # Create test functions
    test_functions = df.TestFunction(mixed_vector_function_space)
    test_v, test_s = splat(test_functions, num_global_states + 1)

    # Crate time derivatives
    Dt_v = (v_current - v_previous)/const_dt
    Dt_s = (s_current - s_previous)/const_dt

    # Create midpoint evaluations following theta rule
    v_mid = theta*v_current + (1.0 - theta)*v_previous
    s_mid = theta*s_current + (1.0 - theta)*s_previous

    if isinstance(model, xb.MultiCellModel):
        # model = xb.cellmodels.Cressman()
        # dy = df.Measure("dx", domain=mesh)
        # F_theta = model.F(v_mid, s_mid, time=current_time)
        # I_theta = -model.I(v_mid, s_mid, time=current_time)
        # lhs = (Dt_v - I_theta)*test_v
        # lhs += df.inner(Dt_s - F_theta, test_s)
        # lhs *= dy()



        dy = df.Measure("dx", domain=mesh, subdomain_data=model.markers())
        domain_indices = model.keys()
        lhs_list = list()
        for k, model_k in enumerate(model.models()):
            domain_index_k = domain_indices[k]
            F_theta = model.F(v_mid, s_mid, time=current_time, index=domain_index_k)
            I_theta = -model.I(v_mid, s_mid, time=current_time, index=domain_index_k)
            a = (Dt_v - I_theta)*test_v
            a += df.inner(Dt_s - F_theta, test_s)
            a *= dy(domain_index_k)
            lhs_list.append(a)
        # Sum the form
        lhs = sum(lhs_list)
    else:
        # Evaluate currents at averaged v and s. Note sign for I_theta
        model = xb.cellmodels.Cressman()
        dy = df.Measure("dx", domain=mesh)
        F_theta = model.F(v_mid, s_mid, time=current_time)
        I_theta = -model.I(v_mid, s_mid, time=current_time)
        lhs = (Dt_v - I_theta)*test_v
        lhs += df.inner(Dt_s - F_theta, test_s)
        lhs *= dy()
    rhs = stimulus*test_v*dy()
    G = lhs - rhs

    # Solve system
    current_solution.assign(previous_solution)
    pde = df.NonlinearVariationalProblem(
        G,
        current_solution,
        J=df.derivative(G, current_solution)
    )
    solver = df.NonlinearVariationalSolver(pde)
    solver.solve()
Пример #29
0
F_nu = geo_map.form(nu_*eta + geo_map.gab[i, j]*psi_.dx(i)*eta.dx(j))
F_nuhat = geo_map.form(nuhat_*etahat
                       + geo_map.Kab[i, j]*psi_.dx(i)*etahat.dx(j))

F = F_psi + F_mu + F_nu + F_nuhat

# a = df.lhs(F)
# L = df.rhs(F)
J = df.derivative(F, u_, du=u)

# SOLVER
# problem = df.LinearVariationalProblem(a, L, u_)
# solver = df.LinearVariationalSolver(problem)

problem = df.NonlinearVariationalProblem(F, u_, J=J)
solver = df.NonlinearVariationalSolver(problem)
solver.parameters["newton_solver"]["absolute_tolerance"] = 1e-8
solver.parameters["newton_solver"]["relative_tolerance"] = 1e-6
solver.parameters["newton_solver"]["maximum_iterations"] = 16
# solver.parameters["newton_solver"]["linear_solver"] = "gmres"
# solver.parameters["newton_solver"]["preconditioner"] = "default"
# solver.parameters["newton_solver"]["krylov_solver"]["nonzero_initial_guess"] = True
# solver.parameters["newton_solver"]["krylov_solver"]["absolute_tolerance"] = 1e-8
# solver.parameters["newton_solver"]["krylov_solver"]["monitor_convergence"] = False
# solver.parameters["newton_solver"]["krylov_solver"]["maximum_iterations"] = 1000

# solver.parameters["linear_solver"] = "gmres"
# solver.parameters["preconditioner"] = "jacobi"

df.parameters["form_compiler"]["optimize"] = True
df.parameters["form_compiler"]["cpp_optimize"] = True
Пример #30
0
def equilibrium_solver(F, u, bcs, bcs_set_values, bcs_values, **kwargs):
    '''Nonlinear solver for the hyper-elastic equilibrium problem.

    F : dolfin.Form
        Variational form of equilibrium, i.e. F(u;v)==0 forall v. Usually `F`
        is obtained by taking the derivative of the potential energy `W`, e.g.
        `F = dolfin.derivative(W, u)`
    u : dolfin.Function
        Displacement function (or a mixed field function).
    bcs : (sequence of) dolfin.DirichletBC's
        Dirichlet boundary conditions.
    bcs_set_values : function
        Called with elements of `bcs_values`.
    bcs_values : numpy.ndarray (2D)
        Sequence of displacement values.
    umin: dolfin.Expression, dolfin.Function, dolfin.GenericVector
        Enfores displacement lower bound: `u >= umin`.
    umax: dolfin.Expression, dolfin.Function, dolfin.GenericVector
        Enfores displacement upper bound: `u <= umax`.

    '''

    if not isinstance(bcs_values, np.ndarray) or bcs_values.ndim != 2:
        raise TypeError('Parameter `bcs_values` must be a 2D `numpy.ndarray`')

    try:
        bcs_set_values(bcs_values[-1])
    except:
        logger.error('Unable to set Dirichlet boundary conditions')
        raise

    dFdu = dolfin.derivative(F, u)

    nonlinear_problem = dolfin.NonlinearVariationalProblem(F, u, bcs, dFdu)
    nonlinear_solver = dolfin.NonlinearVariationalSolver(nonlinear_problem)

    update_parameters(nonlinear_solver.parameters, 
                      config.parameters_nonlinear_solver)
    
    umin = kwargs.get('umin')
    umax = kwargs.get('umax')
    
    if umax is not None or umin is not None:
        
        V = u.function_space()

        if isinstance(umin, dolfin.Function):
            umin = umin.vector()
        elif isinstance(umin, dolfin.Expression):
            umin = dolfin.interpolate(umin, V).vector()
        elif umin is None:
            umin = dolfin.Function(V).vector()
            umin[:] = -np.inf
        elif not isinstance(umin, dolfin.GenericVector) or umin.size() != V.dim():
            raise TypeError("Key-word argument `umin` must be an instance of: "
                "`dolfin.Function`, `dolfin.Expression`, or `dolfin.GenericVector` "
                "(with the correct dimension).")

        if isinstance(umax, dolfin.Function):
            umax = umax.vector()
        elif isinstance(umax, dolfin.Expression):
            umax = dolfin.interpolate(umax, V).vector()
        elif umax is None:
            umax = dolfin.Function(V).vector()
            umax[:] = np.inf
        elif not isinstance(umax, dolfin.GenericVector) or umax.size() != V.dim():
            raise TypeError("Key-word argument `umax` must be an instance of: "
                "`dolfin.Function`, `dolfin.Expression`, or `dolfin.GenericVector` "
                "(with the correct dimension).")
        
        if not (config.parameters_nonlinear_solver['nonlinear_solver'] == 'snes' and 
                config.parameters_nonlinear_solver['snes_solver']['method'] == 'vinewtonrsls'):
            logger.warning("Require \"snes\" solver and method called \"vinewtonrsls\" "
                           "to impose displacement field bounds `umin` and `umax`.")
        
        nonlinear_problem.set_bounds(umin, umax)

    def equilibrium_solve(incremental=False):

        if incremental:

            nonlocal bcs_values
            u.vector()[:] = 0.0
            u_arr_backup = None

            try:
                for i, values_i in enumerate(bcs_values):
                    logger.info(f'Solving for load {values_i}')

                    bcs_set_values(values_i)
                    nonlinear_solver.solve()

                    u_arr_backup = u.vector().get_local()

            except RuntimeError:
                logger.error('Could not solve equilibrium problem for load '
                             f'{values_i}; assuming previous load value.')

                if u_arr_backup is None:
                    raise RuntimeError('Previous load value is not available')

                u.vector()[:] = u_arr_backup
                bcs_values = bcs_values[:i]

        else:

            try:
                nonlinear_solver.solve()
            except RuntimeError:
                logger.error('Could not solve equilibrium problem; '
                             'Trying to re-load incrementally.')

                equilibrium_solve(incremental=True)

    return equilibrium_solve