Beispiel #1
0
def fenics_solve(f):
    u = fn.Function(V, name="State")
    v = fn.TestFunction(V)
    F = (ufl.inner(ufl.grad(u), ufl.grad(v)) - f * v) * ufl.dx
    bcs = [fn.DirichletBC(V, 0.0, "on_boundary")]
    fn.solve(F == 0, u, bcs)
    return u, F, bcs
Beispiel #2
0
def project_gradient_neumann(
        f0,
        degree=None,
        mesh=None,
        solver_type='gmres',
        preconditioner_type='default'
    ):
    """Find an approximation to f0 that has the same gradient

    The resulting function also satisfies homogeneous Neumann boundary
    conditions.

    Parameters:    
    f0: the function to approximate
    mesh=None: the mesh on which to approximate it If not provided, the
        mesh is extracted from f0.
    degree=None: degree of the polynomial approximation. extracted
        from f0 if not provided. 
    solver_type='gmres': The linear solver type to use.
    preconditioner_type='default': Preconditioner type to use
    """
    if not mesh: mesh = f0.function_space().mesh()
    element = f0.ufl_element()
    if not degree:
        degree = element.degree()
    CE = FiniteElement('CG', mesh.ufl_cell(), degree)
    CS = FunctionSpace(mesh, CE)
    DE = FiniteElement('DG', mesh.ufl_cell(), degree)
    DS = FunctionSpace(mesh, DE)
    CVE = VectorElement('CG', mesh.ufl_cell(), degree - 1)
    CV = FunctionSpace(mesh, CVE)
    RE = FiniteElement('R', mesh.ufl_cell(), 0)
    R = FunctionSpace(mesh, RE)
    CRE = MixedElement([CE, RE])
    CR = FunctionSpace(mesh, CRE)
    f = fe.project(f0, CS,
                   solver_type=solver_type,
                   preconditioner_type=preconditioner_type)
    g = fe.project(fe.grad(f), CV,
                   solver_type=solver_type,
                   preconditioner_type=preconditioner_type)
    lf = fe.project(fe.nabla_div(g), CS,
                    solver_type=solver_type,
                    preconditioner_type=preconditioner_type)
    tf, tc = TrialFunction(CR)
    wf, wc = TestFunctions(CR)
    dx = Measure('dx', domain=mesh,
                 metadata={'quadrature_degree': min(degree, 10)})
    a = (fe.dot(fe.grad(tf), fe.grad(wf)) + tc * wf + tf * wc) * dx
    L = (f * wc - lf * wf) * dx
    igc = Function(CR)
    fe.solve(a == L, igc,
             solver_parameters={'linear_solver': solver_type,
                                 'preconditioner': preconditioner_type}
    )
    ig, c = igc.sub(0), igc.sub(1)
    igd = fe.project(ig, DS,
                     solver_type=solver_type,
                     preconditioner_type=preconditioner_type)
    return igd
Beispiel #3
0
def Newton_manual(F, vd, bcs, J, atol, rtol, max_it, lmbda\
                 , vd_res):
    #Reset counters
    Iter      = 0
    residual   = 1
    rel_res    = residual
    while rel_res > rtol and residual > atol and Iter < max_it:
        A = assemble(J, keep_diagonal = True)
        A.ident_zeros()
        b = assemble(-F)

        [bc.apply(A, b, vd.vector()) for bc in bcs]

        #solve(A, vd_res.vector(), b, "superlu_dist")
        #solve(A, vd_res.vector(), b, "mumps")
        solve(A, vd_res.vector(), b)

        vd.vector().axpy(1., vd_res.vector())
        [bc.apply(vd.vector()) for bc in bcs]
        rel_res = norm(vd_res, 'l2')
        residual = b.norm('l2')

        if MPI.rank(mpi_comm_world()) == 0:
            print "Newton iteration %d: r (atol) = %.3e (tol = %.3e), r (rel) = %.3e (tol = %.3e) " \
        % (Iter, residual, atol, rel_res, rtol)
        Iter += 1

    #Reset
    residual   = 1
    rel_res    = residual
    Iter = 0

    return vd
Beispiel #4
0
def Newton_manual(F, udp, bcs, atol, rtol, max_it, lmbda, udp_res, VVQ):
    #Reset counters
    Iter = 0
    residual = 1
    rel_res = residual
    dw = TrialFunction(VVQ)
    Jac = derivative(F, udp, dw)  # Jacobi

    while rel_res > rtol and residual > atol and Iter < max_it:
        A = assemble(Jac)
        A.ident_zeros()
        b = assemble(-F)

        [bc.apply(A, b, udp.vector()) for bc in bcs]

        #solve(A, udp_res.vector(), b, "superlu_dist")

        solve(A, udp_res.vector(), b)  #, "mumps")

        udp.vector()[:] = udp.vector()[:] + lmbda * udp_res.vector()[:]
        #udp.vector().axpy(1., udp_res.vector())
        [bc.apply(udp.vector()) for bc in bcs]
        rel_res = norm(udp_res, 'l2')
        residual = b.norm('l2')

        if MPI.rank(mpi_comm_world()) == 0:
            print "Newton iteration %d: r (atol) = %.3e (tol = %.3e), r (rel) = %.3e (tol = %.3e) " \
        % (Iter, residual, atol, rel_res, rtol)
        Iter += 1

    return udp
Beispiel #5
0
def solver(f, u_D, bc_funs, ndim, length, nx, ny, nz=None, degree=1):
    """Fenics 求解器

    Args:
        f (Expression): [description]
        u_D (Expression): [description]
        bc_funs (List[Callable]): [description]
        ndim (int): [description]
        length (float): [description]
        nx (int): [description]
        ny (int): [description]
        nz (int, optional): [description]. Defaults to None.
        degree (int, optional): [description]. Defaults to 1.

    Returns:
        Function: 解 u
    """

    mesh = get_mesh(length, nx, ny, nz)
    V = fs.FunctionSpace(mesh, "P", degree)
    bcs = [fs.DirichletBC(V, u_D, bc) for bc in bc_funs]
    u = fs.TrialFunction(V)
    v = fs.TestFunction(V)
    FF = fs.dot(fs.grad(u), fs.grad(v)) * fs.dx - f * v * fs.dx
    a = fs.lhs(FF)
    L = fs.rhs(FF)
    u = fs.Function(V)
    fs.solve(a == L, u, bcs)
    return u
Beispiel #6
0
    def eva(self, num):
        # construct basis functions, Set num points corresponding to num basis functions
        basPoints = np.linspace(0, 1, num)
        dx = basPoints[1] - basPoints[0]
        aa, bb, cc = -dx, 0.0, dx
        for x_p in basPoints:
            self.theta.append(
                fe.interpolate(
                    fe.Expression(
                        'x[0] < a || x[0] > c ? 0 : (x[0] >=a && x[0] <= b ? (x[0]-a)/(b-a) : 1-(x[0]-b)/(c-b))',
                        degree=2,
                        a=aa,
                        b=bb,
                        c=cc), self.Vc))
            aa, bb, cc = aa + dx, bb + dx, cc + dx

        u_trial, u_test = fe.TrialFunction(self.Vu), fe.TestFunction(self.Vu)
        left = fe.inner(self.al * fe.nabla_grad(u_trial),
                        fe.nabla_grad(u_test)) * fe.dx
        right = self.f * u_test * fe.dx

        def boundaryD(x, on_boundary):
            return on_boundary and fe.near(x[1], 1.0)

        for i in range(num):
            uH = fe.Function(self.Vu)
            bcD = fe.DirichletBC(self.Vu, self.theta[i], boundaryD)
            left_m, right_m = fe.assemble_system(left, right, bcD)
            fe.solve(left_m, uH.vector(), right_m)
            self.sol.append(uH)
Beispiel #7
0
    def run(self):
        domain = self._create_domain()
        mesh = generate_mesh(domain, MESH_PTS)
        
        # fe.plot(mesh)
        # plt.show()

        self._create_boundary_expression()
        
        Omega = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
        R = fe.FiniteElement("Real", mesh.ufl_cell(), 0)
        W = fe.FunctionSpace(mesh, Omega*R)
        Theta, c = fe.TrialFunction(W)
        v, d = fe.TestFunctions(W)
        sigma = self.conductivity
        
        LHS = (sigma * fe.inner(fe.grad(Theta), fe.grad(v)) + c*v + Theta*d) * fe.dx
        RHS = self.boundary_exp * v * fe.ds

        w = fe.Function(W)
        fe.solve(LHS == RHS, w)
        Theta, c = w.split()
        print(c(0, 0))

        # fe.plot(Theta, "solution", mode='color', vmin=-3, vmax=3)
        # plt.show()

        plot(fe.interpolate(Theta, fe.FunctionSpace(mesh, Omega)), mode='color')
        plt.show()
Beispiel #8
0
    def solve(self, **arguments):

        t_start = time.clock()

        # definig Function space on this mesh using Lagrange
        #polynoimals of degree 1.
        H = FunctionSpace(self.mesh, "CG", 1)

        # Setting up the variational problem
        v = TrialFunction(H)
        w = TestFunction(H)

        epsilon = Constant(arguments[Components().Diffusion])
        f = Constant(0)

        a = (epsilon * inner(grad(v), grad(w)) + inner(v, w)) * dx
        #Still have to figure it how to use a Neumann Condition here
        L = f * w * dx

        # solving the variational problem.
        v = Function(H)
        solve(a == L, v)

        self.solution.extend(v.vector().array())

        return [self.solution, time.clock() - t_start]
Beispiel #9
0
    def __call__(self, u_test, return_sol=False, return_permeability=False):

        # Variables
        x, y = sym.symbols('x[0], x[1]', real=True, positive=True)

        # Diffusivities
        diff_1 = np.exp(u_test[0])
        diff_2 = np.exp(u_test[1])

        # Interfaces
        ix = u_test[2]
        iy = u_test[3]

        # Diffusivity
        diff = sym.Piecewise((sym.Piecewise(
            (diff_1, y <= iy), (diff_2, True)), x <= ix), (diff_2, True))
        # if return_permeability:
        # return sym.lambdify((x, y), diff)

        ccode_coeff = sym.ccode(diff)
        diff = fen.Expression(ccode_coeff, degree=2)
        if return_permeability:
            return diff

        # Define bilinear form in variational problem
        a_bil = diff * fen.dot(fen.grad(self.trial_f), fen.grad(
            self.test_f)) * fen.dx

        # Compute solution
        sol = fen.Function(self.f_space)
        fen.solve(a_bil == self.lin_func, sol, self.bound_cond)

        evaluations = [sol(xi, yi) for xi, yi in zip(self.x_obs, self.y_obs)]
        return sol if return_sol else np.array(evaluations)
Beispiel #10
0
 def solve_pde(self):
     u = fe.Function(self.function_space)
     v = fe.TestFunction(self.function_space)
     u_old = fe.project(self.u_0, self.function_space)
     # Todo: Average right hand side if we choose it non-constant
     flux = self.dt * fe.dot(
         self.composed_diff_coef *
         (fe.grad(u) + self.drift_function(u)), fe.grad(v)) * fe.dx
     bilin_part = u * v * fe.dx + flux
     funtional_part = self.rhs * v * self.dt * fe.dx + u_old * v * fe.dx
     full_form = bilin_part - funtional_part
     num_steps = int(self.T / self.dt) + 1
     bc = fe.DirichletBC(self.function_space, self.u_boundary,
                         MembraneSimulator.full_boundary)
     for n in range(num_steps):
         print("Step %d" % n)
         self.time += self.dt
         fe.solve(full_form == 0, u, bc)
         # fe.plot(u)
         # plt.show()
         # print(fe.errornorm(u_old, u))
         u_old.assign(u)
         self.file << (u, self.time)
     f = fe.plot(u)
     plt.rc('text', usetex=True)
     plt.colorbar(f, format='%.0e')
     plt.title(r'Macroscopic density profile of $u(x,t)$ at $t=1$')
     plt.xlabel(r'$x_1$')
     plt.ylabel(r'$x_2$')
     plt.show()
Beispiel #11
0
 def run(self, fields: Fields):
     # res = fenics.assemble(self.L_form)
     # self.boundary_conditions[0].apply(res)
     # self.solver.solve(self.K, fields.u_new.vector(), res)
     # print('a')
     fenics.solve(self.a_form == self.L_form, fields.u_new,
                  self.boundary_conditions[0])
Beispiel #12
0
def solver_nonlinear(G, d_, w_, wd_, bcs, T, dt, action=None, **namespace):
    dis_x = []; dis_y = []; time = []
    solver_parameters = {"newton_solver": \
                          {"relative_tolerance": 1E-8,
                           "absolute_tolerance": 1E-8,
                           "maximum_iterations": 100,
                           "relaxation_parameter": 1.0}}
    t = 0
    while t <= T:
        solve(G == 0, wd_["n"], bcs, solver_parameters=solver_parameters)

        # Update solution
        times = ["n-3", "n-2", "n-1", "n"]
        for i, t_tmp in enumerate(times[:-1]):
            wd_[t_tmp].vector().zero()
            wd_[t_tmp].vector().axpy(1, wd_[times[i+1]].vector())
            w_[t_tmp], d_[t_tmp] = wd_[t_tmp].split(True)

        # Get displacement
        if callable(action):
            action(wd_, t)

        t += dt
        if MPI.rank(mpi_comm_world()) == 0:
            print "Time: ", t
Beispiel #13
0
    def solve(self, **arguments):

        t_start = time.clock()

        # definig Function space on this mesh using Lagrange
        #polynoimals of degree 1.
        H = FunctionSpace(self.mesh, "CG", 1)

        # Setting up the variational problem
        v = TrialFunction(H)
        w = TestFunction(H)

        epsilon = Constant(arguments[Components().Diffusion])
        f = Expression("(1 - epsilon*4*pow(pi,2))*cos(2*pi*x[0])",\
                       epsilon=epsilon, degree=1)

        a = (epsilon * inner(grad(v), grad(w)) + inner(v, w)) * dx
        L = f * w * dx

        # solving the variational problem.
        v = Function(H)
        solve(a == L, v)

        self.solution.extend(v.vector().array())

        return [self.solution, time.clock() - t_start]
Beispiel #14
0
    def solve_problem(self):

        '''
        Boundary conditions
        '''
        fe.solve(self.bilinear_form == self.rhs,\
                self.u, self.boundary_conditions)
Beispiel #15
0
def solver_nonlinear(G, d_, w_, wd_, bcs, T, dt, action=None, **namespace):
    dis_x = []; dis_y = []; time = []
    solver_parameters = {"newton_solver": \
                          {"relative_tolerance": 1E-8,
                           "absolute_tolerance": 1E-8,
                           "maximum_iterations": 100,
                           #"krylov_solver": {"monitor_convergence": True},
                           #"linear_solver": {"monitor_convergence": True},
                           "relaxation_parameter": 0.9}}
    t = 0
    while t < (T - dt*DOLFIN_EPS):
        solve(G == 0, wd_["n"], bcs, solver_parameters=solver_parameters)

        # Update solution
        times = ["n-3", "n-2", "n-1", "n"]
        for i, t_tmp in enumerate(times[:-1]):
            wd_[t_tmp].vector().zero()
            wd_[t_tmp].vector().axpy(1, wd_[times[i+1]].vector())
            w_[t_tmp], d_[t_tmp] = wd_[t_tmp].split(True)

        # Get displacement
        if callable(action):
            action(wd_, t)

        t += dt
        if MPI.rank(mpi_comm_world()) == 0:

            print "Time: ",t #,"dis_x: ", d(coord)[0], "dis_y: ", d(coord)[1]

    return dis_x, dis_y, time
def run_fokker_planck(nx, num_steps, t_0 = 0, t_final=10):

    # define mesh
    mesh = IntervalMesh(nx, -200, 200)
    # define function space. 
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Homogenous Neumann BCs don't have to be defined as they are the default in dolfin
    # define parameters.
    dt = (t_final-t_0) / num_steps

    # set mu and sigma 
    mu = Constant(-1)
    D = Constant(1)

    # define initial conditions u_0
    u_0 = Expression('x[0]', degree=1)

    # set U_n to be the interpolant of u_0 over the function space V. Note that 
    # u_n is the value of u at the previous timestep, while u is the current value. 
    u_n = interpolate(u_0, V)

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    F = u*v*dx + dt*inner(D*grad(u), grad(v))*dx + dt*mu*grad(u)[0]*v*dx - inner(u_n, v)*dx

    # isolate the bilinear and linear forms. 
    a, L = lhs(F), rhs(F)

    # initialize function to capture solution. 
    t = 0 
    u_h = Function(V)

    plt.figure(figsize=(15, 15))

    # time-stepping section
    for n in range(num_steps):
        t += dt 

        # compute solution 
        solve(a == L, u_h)
        u_n.assign(u_h)

        # Plot solutions intermittently
        if n % (num_steps // 10) == 0 and num_steps > 0:

            plot(u_h, label='t = %s' % t)
    
    plt.legend() 
    plt.grid()
    plt.title("Finite Element Solutions to Fokker-Planck Equation with $\mu(x, t) = -(x+1)$ , $D(x, t) = e^t x^2$, $t_n$ = %s" % t_final)
    plt.ylabel("$u(x, t)$")
    plt.xlabel("x")
    plt.savefig("fpe/fokker-planck-solutions-mu.png")
    plt.clf() 

    # return the approximate solution evaluated on the coordinates, and the actual coordinates. 
    return u_n.compute_vertex_values(), mesh.coordinates() 
Beispiel #17
0
def fenics_solve(u_prev, timestep):
    # Define and solve one step of the Burgers equation
    u = fn.Function(V)
    F = (
        Dt(u, u_prev, timestep) * v + a * u * u.dx(0) * v + nu * u.dx(0) * v.dx(0)
    ) * ufl.dx
    fn.solve(F == 0, u, bcs)
    return u, F, bcs
Beispiel #18
0
def impl_dyn(w0, dt=1.e-5, t_end=1.e-4, show_plots=False):

    (u0, p0, v0) = fe.split(w0)

    bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_upv.sub(0), V_upv.sub(1),
                                            V_upv.sub(2), boundaries)

    # Lagrange function (without constraint)

    (u1, p1, v1) = fe.TrialFunctions(V_upv)
    (eta, q, xi) = fe.TestFunctions(V_upv)

    F = deformation_grad(u1)
    I_1, I_2, J = invariants(F)
    F_iso = isochronic_deformation_grad(F, J)
    #I_1_iso, I_2_iso  = invariants(F_iso)[0:2]

    W = material_mooney_rivlin(I_1, I_2, c_10, c_01)
    g = incompr_constr(J)
    L = -W
    P = first_piola_stress(L, F)
    G = incompr_stress(g, F)

    a_dyn_u = inner(u1 - u0, eta) * dx - dt * inner(v1, eta) * dx
    a_dyn_p = inner(g, q) * dx
    a_dyn_v = rho * inner(v1 - v0, xi) * dx + dt * (inner(
        P, grad(xi)) * dx + inner(p1 * G, grad(xi)) * dx - inner(B, xi) * dx)

    a = a_dyn_u + a_dyn_p + a_dyn_v

    w1 = fe.Function(V_upv)

    sol = []

    t = 0
    while t < t_end:
        print("progress: %f" % (100. * t / t_end))

        fe.solve(a == 0, w1, bcs_u + bcs_p + bcs_v)

        if fe.norm(w1.vector()) > 1e7:
            print('ERROR: norm explosion')
            break

        # update initial values for next step
        w0.assign(w1)
        t += dt

        if show_plots:
            # plot result
            fe.plot(w0.sub(0), mode='displacement')
            plt.show()

        # save solutions
        sol.append(Solution(t=t))
        sol[-1].upv.assign(w0)

    return sol, W, kappa
Beispiel #19
0
 def solve_problem_variational_form(self):
     u = fa.Function(self.V)
     du = fa.TrialFunction(self.V)
     v = fa.TestFunction(self.V)
     E = self._energy_density(u) * fa.dx
     dE = fa.derivative(E, u, v)
     jacE = fa.derivative(dE, u, du)
     fa.solve(dE == 0, u, self.bcs, J=jacE)
     return u
Beispiel #20
0
def vjp_solve_eval_impl(
    g: np.array,
    fenics_solution: fenics.Function,
    fenics_residual: ufl.Form,
    fenics_inputs: List[FenicsVariable],
    bcs: List[fenics.DirichletBC],
) -> Tuple[np.array]:
    """Computes the gradients of the output with respect to the inputs."""
    # Convert tangent covector (adjoint) to a FEniCS variable
    adj_value = numpy_to_fenics(g, fenics_solution)
    adj_value = adj_value.vector()

    F = fenics_residual
    u = fenics_solution
    V = u.function_space()
    dFdu = fenics.derivative(F, u)
    adFdu = ufl.adjoint(
        dFdu, reordered_arguments=ufl.algorithms.extract_arguments(dFdu)
    )

    u_adj = fenics.Function(V)
    adj_F = ufl.action(adFdu, u_adj)
    adj_F = ufl.replace(adj_F, {u_adj: fenics.TrialFunction(V)})
    adj_F_assembled = fenics.assemble(adj_F)

    if len(bcs) != 0:
        for bc in bcs:
            bc.homogenize()
        hbcs = bcs

        for bc in hbcs:
            bc.apply(adj_F_assembled)
            bc.apply(adj_value)

    fenics.solve(adj_F_assembled, u_adj.vector(), adj_value)

    fenics_grads = []
    for fenics_input in fenics_inputs:
        if isinstance(fenics_input, fenics.Function):
            V = fenics_input.function_space()
        dFdm = fenics.derivative(F, fenics_input, fenics.TrialFunction(V))
        adFdm = fenics.adjoint(dFdm)
        result = fenics.assemble(-adFdm * u_adj)
        if isinstance(fenics_input, fenics.Constant):
            fenics_grad = fenics.Constant(result.sum())
        else:  # fenics.Function
            fenics_grad = fenics.Function(V, result)
        fenics_grads.append(fenics_grad)

    # Convert FEniCS gradients to jax array representation
    jax_grads = (
        None if fg is None else np.asarray(fenics_to_numpy(fg)) for fg in fenics_grads
    )

    jax_grad_tuple = tuple(jax_grads)

    return jax_grad_tuple
Beispiel #21
0
    def test_DoGIP_vs_FEniCS(self):
        print(
            '\n== testing DoGIP vs. FEniCS for problem of weighted projection ===='
        )

        for dim, pol_order in itertools.product([2, 3], [1, 2]):
            print('dim={}; pol_order={}'.format(dim, pol_order))
            N = 2
            # creating MESH, defining MATERIAL and SOURCE
            if dim == 2:
                mesh = UnitSquareMesh(N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*x[1]*(1-x[1])",
                               degree=3)  # material coefficients
                f = Expression("x[0]*x[0]*x[1]", degree=2)
            elif dim == 3:
                mesh = UnitCubeMesh(N, N, N)
                m = Expression("1+100*x[0]*(1-x[0])*x[1]*x[2]",
                               degree=2)  # material coefficients
                f = Expression("(1-x[0])*x[1]*x[2]", degree=2)

            mesh.coordinates()[:] += 0.1 * np.random.random(
                mesh.coordinates().shape)  # mesh perturbation

            ## standard approach with FEniCS #############################################
            V = FunctionSpace(mesh, "CG", pol_order)  # original FEM space
            u, v = TrialFunction(V), TestFunction(V)
            u_fenics = Function(V)
            solve(m * u * v * dx == m * f * v * dx, u_fenics)

            ## DoGIP - double-grid integration with interpolation-projection #############
            W = FunctionSpace(mesh, "CG", 2 * pol_order)  # double-grid space
            w = TestFunction(W)
            A_dogip = assemble(
                m * w *
                dx).get_local()  # diagonal matrix of material coefficients
            b = assemble(m * f * v * dx)  # vector of right-hand side

            # assembling interpolation-projection matrix B
            B = get_B(V, W, problem=0)

            # # linear solver on double grid, standard
            Afun = lambda x: B.T.dot(A_dogip * B.dot(x))

            Alinoper = linalg.LinearOperator((V.dim(), V.dim()),
                                             matvec=Afun,
                                             dtype=np.float)
            x, info = linalg.cg(Alinoper,
                                b.get_local(),
                                x0=np.zeros(V.dim()),
                                tol=1e-10,
                                maxiter=1e3,
                                callback=None)

            # testing the difference between DoGIP and FEniCS
            self.assertAlmostEqual(
                0, np.linalg.norm(u_fenics.vector().get_local() - x))
            print('...ok')
Beispiel #22
0
 def _solve_pde(self, diff_coef):
     # Actual PDE solver for any coefficient diff_coef
     u = fe.TrialFunction(self.function_space)
     v = fe.TestFunction(self.function_space)
     a = fe.dot(diff_coef * fe.grad(u), fe.grad(v)) * fe.dx
     L = self.f * v * fe.dx
     bc = fe.DirichletBC(self.function_space, self.bc_function,
                         PoissonSolver.boundary)
     fe.solve(a == L, self.solution, bc)
Beispiel #23
0
    def fenics_p_electric(self, my_d):
        """
        @description:
            Solve poisson equation to get potential and electric field
        @Modify:
            2021/08/31
        """
        if "plugin3D" in self.det_model:
            bc_l = []
            bc_l = self.boundary_definition_3D(my_d, "Possion")
        elif "planar3D" in self.det_model:
            bc_l = self.boundary_definition_2D(my_d, "Possion")

        u = fenics.TrialFunction(self.V)
        v = fenics.TestFunction(self.V)
        if self.det_dic['name'] == "lgad3D":
            if self.det_dic['part'] == 2:
                bond = self.det_dic['bond1']
                doping_avalanche = self.f_value(my_d, self.det_dic['doping1'])
                doping = self.f_value(my_d, self.det_dic['doping2'])
                f = fenics.Expression('x[2] < width ? doping1 : doping2',
                                      degree=1,
                                      width=bond,
                                      doping1=doping_avalanche,
                                      doping2=doping)
            elif self.det_dic['part'] == 3:
                bond1 = self.det_dic['bond1']
                bond2 = self.det_dic['bond2']
                doping1 = self.f_value(my_d, self.det_dic['doping1'])
                doping2 = self.f_value(my_d, self.det_dic['doping2'])
                doping3 = self.f_value(my_d, self.det_dic['doping3'])
                f = fenics.Expression(
                    'x[2] < bonda ? dopinga : x[2] > bondb ? dopingc : dopingb',
                    degree=1,
                    bonda=bond1,
                    bondb=bond2,
                    dopinga=doping1,
                    dopingb=doping2,
                    dopingc=doping3)
            else:
                print("The structure of lgad is wrong.")
        else:
            f = fenics.Constant(self.f_value(my_d))
        a = fenics.dot(fenics.grad(u), fenics.grad(v)) * fenics.dx
        L = f * v * fenics.dx
        # Compute solution
        self.u = fenics.Function(self.V)
        fenics.solve(a == L,
                     self.u,
                     bc_l,
                     solver_parameters=dict(linear_solver='gmres',
                                            preconditioner='ilu'))
        #calculate electric field
        W = fenics.VectorFunctionSpace(self.mesh3D, 'P', 1)
        self.E_field = fenics.project(
            fenics.as_vector((self.u.dx(0), self.u.dx(1), self.u.dx(2))), W)
Beispiel #24
0
 def _solve_cell_problems(self):
     # Solves the cell problems (one for each space dimension)
     w = fe.TrialFunction(self.function_space)
     v = fe.TestFunction(self.function_space)
     a = self.a_y * fe.dot(fe.grad(w), fe.grad(v)) * fe.dx
     for i in range(self.dim):
         L = fe.div(self.a_y * self.e_is[i]) * v * fe.dx
         bc = fe.DirichletBC(self.function_space, self.bc_function,
                             PoissonSolver.boundary)
         fe.solve(a == L, self.cell_solutions[i], bc)
         fe.plot(self.cell_solutions[i])
Beispiel #25
0
    def solve(self, **arguments):

        t_start = time.clock()

        # definig Function space on this mesh using Lagrange
        #polynoimals of degree 1.
        H = FunctionSpace(self.mesh, "CG", 1)

        # Setting up the variational problem
        v = TrialFunction(H)
        w = TestFunction(H)

        coeff_dx2 = Constant(1)
        coeff_v = Constant(1)

        f = Expression("(4*pow(pi,2))*exp(-(1/coeff_v)*t)*sin(2*pi*x[0])",
                       {'coeff_v': coeff_v},
                       degree=2)

        v0 = Expression("sin(2*pi*x[0])", degree=2)

        f.t = 0

        def boundary(x, on_boundary):
            return on_boundary

        bc = DirichletBC(H, v0, boundary)

        v1 = interpolate(v0, H)
        dt = self.steps.time

        a = (dt * inner(grad(v), grad(w)) + dt * coeff_v * inner(v, w)) * dx
        L = (f * dt - coeff_v * v1) * w * dx

        A = assemble(a)
        v = Function(H)

        T = self.domain.time[-1]
        t = dt

        # solving the variational problem.
        while t <= T:
            b = assemble(L, tensor=b)
            vo.t = t
            bc.apply(A, b)

            solve(A, v.vector(), b)
            t += dt

            v1.assign(v)

        self.solution.extend(v.vector().array())

        return [self.solution, time.clock() - t_start]
Beispiel #26
0
def forward(x):
    u = fn.TrialFunction(V)
    w = fn.TestFunction(V)
    sigma = lmbda * tr(sym(grad(u))) * Identity(2) + 2 * G * sym(
        grad(u))  # Stress
    R = simp(x) * inner(sigma, grad(w)) * dx - dot(b, w) * dx
    a, L = ufl.lhs(R), ufl.rhs(R)
    u = fn.Function(V)
    F = L - ufl.action(a, u)
    fn.solve(a == L, u, bcs)
    return u, F, bcs
Beispiel #27
0
def calTrueSol(para):
    nx, ny = para['mesh_N'][0], para['mesh_N'][1]
    mesh = fe.UnitSquareMesh(nx, ny)
    Vu = fe.FunctionSpace(mesh, 'P', para['P'])
    Vc = fe.FunctionSpace(mesh, 'P', para['P'])
    al = fe.Constant(para['alpha'])
    f = fe.Expression(para['f'], degree=5)
    q1 = fe.interpolate(fe.Expression(para['q1'], degree=5), Vc)
    q2 = fe.interpolate(fe.Expression(para['q2'], degree=5), Vc)
    q3 = fe.interpolate(fe.Expression(para['q3'], degree=5), Vc)
    theta = fe.interpolate(fe.Expression(para['q4'], degree=5), Vc)

    class BoundaryX0(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[0], 0.0)

    class BoundaryX1(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[0], 1.0)

    class BoundaryY0(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[1], 0.0)

    class BoundaryY1(fe.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and fe.near(x[1], 1.0)

    boundaries = fe.MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
    boundaries.set_all(0)
    bc0, bc1, bc2, bc3 = BoundaryX0(), BoundaryX1(), BoundaryY0(), BoundaryY1()
    bc0.mark(boundaries, 1)
    bc1.mark(boundaries, 2)
    bc2.mark(boundaries, 3)
    bc3.mark(boundaries, 4)

    domains = fe.MeshFunction("size_t", mesh, mesh.topology().dim())
    domains.set_all(0)

    bcD = fe.DirichletBC(Vu, theta, boundaries, 4)
    dx = fe.Measure('dx', domain=mesh, subdomain_data=domains)
    ds = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

    u_trial, u_test = fe.TrialFunction(Vu), fe.TestFunction(Vu)
    u = fe.Function(Vu)
    left = fe.inner(al * fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * dx
    right = f * u_test * dx + (q1 * u_test * ds(1) + q2 * u_test * ds(2) +
                               q3 * u_test * ds(3))

    left_m, right_m = fe.assemble_system(left, right, bcD)
    fe.solve(left_m, u.vector(), right_m)

    return u
Beispiel #28
0
def dynamic_solver_func(ncells=10,  # количество узлов на заданном итервале
                        init_time=0,  # начальный момент времени
                        end_time=10,  # конечный момент времени
                        dxdphi=1,  # производная от потенциала по х
                        dydphi=1,  # производня от потенциала по у
                        x0=0,  # начальное положение по оси х
                        vx0=1,  # проекция начальной скорости на ось х
                        y0=0,  # начальное положение по оси у
                        vy0=1):  # проекция начальной скорости на ось у
    """ Функция на вход которой подается производная от потенциала
        гравитационного поля, возвращающая координаты смещенных
        материальных точек (частиц).
    """
    # генерация сетки на заданном интервале времени
    mesh = fen.IntervalMesh(ncells, 0, end_time-init_time)

    welm = fen.MixedElement([fen.FiniteElement('Lagrange', fen.interval, 2),
                             fen.FiniteElement('Lagrange', fen.interval, 2),
                             fen.FiniteElement('Lagrange', fen.interval, 2),
                             fen.FiniteElement('Lagrange', fen.interval, 2)])

    # генерация функционального рростаанства
    W = fen.FunctionSpace(mesh, welm)

    # постановка начальных условий задачи
    bcsys = [fen.DirichletBC(W.sub(0), fen.Constant(x0), 'near(x[0], 0)'),
             fen.DirichletBC(W.sub(1), fen.Constant(vx0), 'near(x[0], 0)'),
             fen.DirichletBC(W.sub(2), fen.Constant(y0), 'near(x[0], 0)'),
             fen.DirichletBC(W.sub(3), fen.Constant(vy0), 'near(x[0], 0)')]

    # опееделение тестовых функций для решения задачи
    up = fen.Function(W)
    x_cor, v_x, y_cor, v_y = fen.split(up)
    v1, v2, v3, v4 = fen.split(fen.TestFunction(W))

    # постановка задачи drdt = v; dvdt = - grad(phi) в проекциях на оси системы координат
    weak_form = (x_cor.dx(0) - v_x) * v1 * fen.dx + (v_x.dx(0) + dxdphi) * v2 * fen.dx \
                + (y_cor.dx(0) - v_y) * v3 * fen.dx + (v_y.dx(0) + dydphi) * v4 * fen.dx

    # решние поставленной задачи
    fen.solve(weak_form == 0, up, bcs=bcsys)

    # определение момента времени
    time = fen.Point(end_time - init_time)

    # расчет координат и скоростей
    x_end_time = up(time.x())[0]
    vx_end_time = up(time.x())[1]
    y_end_time = up(time.x())[2]
    vy_end_time = up(time.x())[3]

    return x_end_time, y_end_time, vx_end_time, vy_end_time
Beispiel #29
0
    def solve(self):
        """Evoke FEniCS FEM solver.

        Returns
        -------
        uij : (Ni,) ndarray
            potential at Ni grid points
        nij : (M,Nij) ndarray
            concentrations of M species at Ni grid points
        lamj: (L,) ndarray
            value of L Lagrange multipliers
        """

        # weak form and FEM scheme:

        # in the weak form, u and v are the trial and test functions associated
        # with the Poisson part, p and q the trial and test functions associated
        # with the Nernst-Planck part. lam and mu are trial and test fuctions
        # associated to constraints introduced via Lagrange multipliers.
        # w is the whole set of trial functions [u,p,lam]
        # W is the space all w live in.
        rho = 0
        for i in range(self.M):
            rho += self.z[i] * self.p[i]

        source = -0.5 * rho * self.v * fn.dx

        laplace = fn.dot(fn.grad(self.u), fn.grad(self.v)) * fn.dx

        poisson = laplace + source

        nernst_planck = 0
        for i in range(self.M):
            nernst_planck += fn.dot(
                -fn.grad(self.p[i]) - self.z[i] * self.p[i] * fn.grad(self.u),
                fn.grad(self.q[i])) * fn.dx

        # constraints set up elsewhere
        F = poisson + nernst_planck + self.constraints

        fn.solve(F == 0, self.w, self.boundary_conditions)

        # store results:

        wij = np.array([self.w(x) for x in self.X]).T

        self.uij = wij[0, :]  # potential
        self.nij = wij[1:(self.M + 1), :]  # concentrations
        self.lamj = wij[(self.M + 1):]  # Lagrange multipliers

        return self.uij, self.nij, self.lamj
Beispiel #30
0
def determine_gradient(V_g, u, flux):
    """
    compute flux following http://hplgit.github.io/INF5620/doc/pub/fenics_tutorial1.1/tu2.html#tut-poisson-gradu
    :param mesh
    :param u: solution where gradient is to be determined
    :return:
    """

    w = TrialFunction(V_g)
    v = TestFunction(V_g)

    a = inner(w, v) * dx
    L = inner(grad(u), v) * dx
    solve(a == L, flux)
Beispiel #31
0
def main():
    """Main function. Organizes workflow."""
    fname = str(INPUTS['filename'])
    term = Terminal()
    print(
        term.yellow
        + "Working on file {}.".format(fname)
        + term.normal
    )
    # Load mesh and physical domains from file.
    mesh = fe.Mesh(fname + ".xml")
    if INPUTS['saving']['mesh']:
        fe.File(fname + "_mesh.pvd") << mesh
    if INPUTS['plotting']['mesh']:
        fe.plot(mesh, title='Mesh')
    subdomains = fe.MeshFunction(
        'size_t', mesh, fname + '_physical_region.xml')
    if INPUTS['saving']['subdomains']:
        fe.File(fname + "_subdomains.pvd") << subdomains
    if INPUTS['plotting']['subdomains']:
        fe.plot(subdomains, title='Subdomains')
    # function space for temperature/concentration
    func_space = fe.FunctionSpace(
        mesh,
        INPUTS['element_type'],
        INPUTS['element_degree'],
        constrained_domain=PeriodicDomain()
    )
    # discontinuous function space for visualization
    dis_func_space = fe.FunctionSpace(
        mesh,
        'DG',
        INPUTS['element_degree'],
        constrained_domain=PeriodicDomain()
    )
    if ARGS['--verbose']:
        print('Number of cells:', mesh.num_cells())
        print('Number of faces:', mesh.num_faces())
        print('Number of edges:', mesh.num_edges())
        print('Number of vertices:', mesh.num_vertices())
        print('Number of DOFs:', len(func_space.dofmap().dofs()))
    # temperature/concentration field
    field = fe.TrialFunction(func_space)
    # test function
    test_func = fe.TestFunction(func_space)
    # function, which is equal to 1 everywhere
    unit_function = fe.Function(func_space)
    unit_function.assign(fe.Constant(1.0))
    # assign material properties to each domain
    if INPUTS['mode'] == 'conductivity':
        mat_prop = SubdomainConstant(
            subdomains,
            fe.Constant(INPUTS['conductivity']['gas']),
            fe.Constant(INPUTS['conductivity']['solid']),
            degree=0
        )
    elif INPUTS['mode'] == 'diffusivity':
        mat_prop = SubdomainConstant(
            subdomains,
            fe.Constant(INPUTS['diffusivity']['gas']),
            fe.Constant(INPUTS['diffusivity']['solid']) *
            fe.Constant(INPUTS['solubility'] *
                        gas_constant * INPUTS['temperature']),
            degree=0
        )
    # assign 1 to gas domain, and 0 to solid domain
    gas_content = SubdomainConstant(
        subdomains,
        fe.Constant(1.0),
        fe.Constant(0.0),
        degree=0
    )
    # define structure of foam over whole domain
    structure = fe.project(unit_function * gas_content, dis_func_space)
    # calculate porosity and wall thickness
    porosity = fe.assemble(structure *
                           fe.dx) / ((XMAX - XMIN) * (YMAX - YMIN) * (ZMAX - ZMIN))
    print('Porosity: {0}'.format(porosity))
    dwall = wall_thickness(
        porosity, INPUTS['morphology']['cell_size'],
        INPUTS['morphology']['strut_content'])
    print('Wall thickness: {0} m'.format(dwall))
    # calculate effective conductivity/diffusivity by analytical model
    if INPUTS['mode'] == 'conductivity':
        eff_prop = analytical_conductivity(
            INPUTS['conductivity']['gas'], INPUTS['conductivity']['solid'],
            porosity, INPUTS['morphology']['strut_content'])
        print('Analytical model: {0} W/(mK)'.format(eff_prop))
    elif INPUTS['mode'] == 'diffusivity':
        eff_prop = analytical_diffusivity(
            INPUTS['diffusivity']['solid'] *
            INPUTS['solubility'], INPUTS['solubility'],
            porosity, INPUTS['morphology']['cell_size'], dwall,
            INPUTS['temperature'], INPUTS['morphology']['enhancement_par'])
        print('Analytical model: {0} m^2/s'.format(eff_prop))
    # create system matrix
    system_matrix = -mat_prop * \
        fe.inner(fe.grad(field), fe.grad(test_func)) * fe.dx
    left_side, right_side = fe.lhs(system_matrix), fe.rhs(system_matrix)
    # define boundary conditions
    bcs = [
        fe.DirichletBC(func_space, fe.Constant(
            INPUTS['boundary_conditions']['top']), top_bc),
        fe.DirichletBC(func_space, fe.Constant(
            INPUTS['boundary_conditions']['bottom']), bottom_bc)
    ]
    # compute solution
    field = fe.Function(func_space)
    fe.solve(left_side == right_side, field, bcs)
    # output temperature/concentration at the boundaries
    if ARGS['--verbose']:
        print('Checking periodicity:')
        print('Value at XMIN:', field(XMIN, (YMIN + YMAX) / 3, (ZMIN + ZMAX) / 3))
        print('Value at XMAX:', field(XMAX, (YMIN + YMAX) / 3, (ZMIN + ZMAX) / 3))
        print('Value at YMIN:', field((XMIN + XMAX) / 3, YMIN, (ZMIN + ZMAX) / 3))
        print('Value at YMAX:', field((XMIN + XMAX) / 3, YMAX, (ZMIN + ZMAX) / 3))
        print('Value at ZMIN:', field((XMIN + XMAX) / 3, (YMIN + YMAX) / 3, ZMIN))
        print('Value at ZMAX:', field((XMIN + XMAX) / 3, (YMIN + YMAX) / 3, ZMAX))
    # calculate flux, and effective properties
    vec_func_space = fe.VectorFunctionSpace(
        mesh,
        INPUTS['element_type'],
        INPUTS['element_degree']
    )
    flux = fe.project(-mat_prop * fe.grad(field), vec_func_space)
    divergence = fe.project(-fe.div(mat_prop * fe.grad(field)), func_space)
    flux_x, flux_y, flux_z = flux.split()
    av_flux = fe.assemble(flux_z * fe.dx) / ((XMAX - XMIN) * (YMAX - YMIN))
    eff_prop = av_flux * (ZMAX - ZMIN) / (
        INPUTS['boundary_conditions']['top']
        - INPUTS['boundary_conditions']['bottom']
    )
    if INPUTS['mode'] == 'conductivity':
        print('Numerical model: {0} W/(mK)'.format(eff_prop))
    elif INPUTS['mode'] == 'diffusivity':
        print('Numerical model: {0} m^2/s'.format(eff_prop))
    # projection of concentration has to be in discontinuous function space
    if INPUTS['mode'] == 'diffusivity':
        sol_field = SubdomainConstant(
            subdomains,
            fe.Constant(1.0),
            fe.Constant(INPUTS['solubility'] *
                        gas_constant * INPUTS['temperature']),
            degree=0
        )
        field = fe.project(field * sol_field, dis_func_space)
    # save results
    with open(fname + "_eff_prop.csv", 'w') as textfile:
        textfile.write('eff_prop\n')
        textfile.write('{0}\n'.format(eff_prop))
    fe.File(fname + "_solution.pvd") << field
    fe.File(fname + "_structure.pvd") << structure
    if INPUTS['saving']['flux']:
        fe.File(fname + "_flux.pvd") << flux
    if INPUTS['saving']['flux_divergence']:
        fe.File(fname + "_flux_divergence.pvd") << divergence
    if INPUTS['saving']['flux_components']:
        fe.File(fname + "_flux_x.pvd") << flux_x
        fe.File(fname + "_flux_y.pvd") << flux_y
        fe.File(fname + "_flux_z.pvd") << flux_z
    # plot results
    if INPUTS['plotting']['solution']:
        fe.plot(field, title="Solution")
    if INPUTS['plotting']['flux']:
        fe.plot(flux, title="Flux")
    if INPUTS['plotting']['flux_divergence']:
        fe.plot(divergence, title="Divergence")
    if INPUTS['plotting']['flux_components']:
        fe.plot(flux_x, title='x-component of flux (-kappa*grad(u))')
        fe.plot(flux_y, title='y-component of flux (-kappa*grad(u))')
        fe.plot(flux_z, title='z-component of flux (-kappa*grad(u))')
    if True in INPUTS['plotting'].values():
        fe.interactive()
    print(
        term.yellow
        + "End."
        + term.normal
    )
Beispiel #32
0
    def solve(self):
        # TODO: when FEniCS ported to Python3, this should be exist_ok
        try:
            os.makedirs('results')
        except OSError:
            pass

        z, w = (self.z, self.w)
        u0 = d.Constant(0.0)

        # Define the linear and bilinear forms
        L = u0 * w * dx

        # Define useful functions
        cond = d.Function(self.DV)
        U = d.Function(self.V)

        # Initialize the max_e vector, that will store the cumulative max e values
        max_e = d.Function(self.V)
        max_e.vector()[:] = 0.0
        max_e.rename("max_E", "Maximum energy deposition by location")
        max_e_file = d.File("results/%s-max_e.pvd" % input_mesh)
        max_e_per_step = d.Function(self.V)
        max_e_per_step_file = d.File("results/%s-max_e_per_step.pvd" % input_mesh)

        self.es = {}
        self.max_es = {}
        fi = d.File("results/%s-cond.pvd" % input_mesh)

        potential_file = d.File("results/%s-potential.pvd" % input_mesh)

        # Loop through the voltages and electrode combinations
        for i, (anode, cathode, voltage) in enumerate(v.electrode_triples):
            print("Electrodes %d (%lf) -> %d (0)" % (anode, voltage, cathode))

            cond = d.project(self.sigma_start, V=self.DV)

            # Define the Dirichlet boundary conditions on the active needles
            uV = d.Constant(voltage)
            term1_bc = d.DirichletBC(self.V, uV, self.patches, v.needles[anode])
            term2_bc = d.DirichletBC(self.V, u0, self.patches, v.needles[cathode])

            e = d.Function(self.V)
            e.vector()[:] = max_e.vector()

            # Re-evaluate conductivity
            self.increase_conductivity(cond, e)

            for j in range(v.max_restarts):
                # Update the bilinear form
                a = d.inner(d.nabla_grad(z), cond * d.nabla_grad(w)) * dx

                # Solve again
                print(" [solving...")
                d.solve(a == L, U, bcs=[term1_bc, term2_bc])
                print("  ....solved]")

                # Extract electric field norm
                for k in range(len(U.vector())):
                    if N.isnan(U.vector()[k]):
                        U.vector()[k] = 1e5

                e_new = d.project(d.sqrt(d.dot(d.grad(U), d.grad(U))), self.V)

                # Take the max of the new field and the established electric field
                e.vector()[:] = N.array([max(*X) for X in zip(e.vector(), e_new.vector())])

                # Re-evaluate conductivity
                fi << cond
                self.increase_conductivity(cond, e)

            potential_file << U

            # Save the max e function to a VTU
            max_e_per_step.vector()[:] = e.vector()[:]
            max_e_per_step_file << max_e_per_step

            # Store this electric field norm, for this triple, for later reference
            self.es[i] = e

            # Store the max of this electric field norm and that for all previous triples
            max_e_array = N.array([max(*X) for X in zip(max_e.vector(), e.vector())])
            max_e.vector()[:] = max_e_array

            # Create a new max_e function for storage, or it will be overwritten by the next iteration
            max_e_new = d.Function(self.V)
            max_e_new.vector()[:] = max_e_array

            # Store this max e function for the cumulative coverage curve calculation later
            self.max_es[i] = max_e_new

            # Save the max e function to a VTU
            max_e_file << max_e
            self.max_e_count = i