Ejemplo n.º 1
0
def form_fluid_adjoint(
    displacement_fluid_adjoint,
    velocity_fluid_adjoint,
    xi_fluid,
    eta_fluid,
    fluid: Space,
    param: Parameters,
):

    return (
        param.NU
        * dot(grad(eta_fluid), grad(displacement_fluid_adjoint))
        * fluid.dx
        + dot(param.BETA, grad(eta_fluid))
        * displacement_fluid_adjoint
        * fluid.dx
        + dot(grad(xi_fluid), grad(velocity_fluid_adjoint)) * fluid.dx
        - dot(grad(xi_fluid), fluid.normal_vector)
        * velocity_fluid_adjoint
        * fluid.ds(1)
        - param.NU
        * dot(grad(eta_fluid), fluid.normal_vector)
        * displacement_fluid_adjoint
        * fluid.ds(1)
        + param.GAMMA
        / fluid.cell_size
        * xi_fluid
        * velocity_fluid_adjoint
        * fluid.ds(1)
        + param.GAMMA
        / fluid.cell_size
        * eta_fluid
        * displacement_fluid_adjoint
        * fluid.ds(1)
    )
    def _construct_eigenproblem(self, u: ufl.Argument, v: ufl.Argument) \
            -> Tuple[ufl.algebra.Operator, ufl.algebra.Operator]:
        """Construct left- and right-hand sides of eigenvalue problem.

        Parameters
        ----------
        u : ufl.Argument
            A function belonging to the function space under consideration.
        v : ufl.Argument
            A function belonging to the function space under consideration.

        Returns
        -------
        a : ufl.algebra.Operator
            Left hand side form.
        b : ufl.algebra.Operator
            Right hand side form.

        """
        g = self.metric_tensor
        sqrt_g = fenics.sqrt(fenics.det(g))
        inv_g = fenics.inv(g)

        # $a(u, v) = \int_M \nabla u \cdot g^{-1} \nabla v \, \sqrt{\det(g)} \, d x$.
        a = fenics.dot(fenics.grad(u), inv_g * fenics.grad(v)) * sqrt_g
        # $b(u, v) = \int_M u \, v \, \sqrt{\det(g)} \, d x$.
        b = fenics.dot(u, v) * sqrt_g

        return a, b
Ejemplo n.º 3
0
def functional_fluid_adjoint_initial(
    displacement_fluid_adjoint_old,
    velocity_fluid_adjoint_old,
    displacement_fluid_adjoint_interface,
    velocity_fluid_adjoint_interface,
    displacement_fluid_adjoint_old_interface,
    velocity_fluid_adjoint_old_interface,
    xi_fluid,
    eta_fluid,
    fluid: Space,
    param: Parameters,
    time,
    time_step,
    microtimestep_before: MicroTimeStep,
    microtimestep: MicroTimeStep,
):

    return (
        0.5
        * time_step
        * param.NU
        * dot(grad(eta_fluid), fluid.normal_vector)
        * displacement_fluid_adjoint_interface
        * fluid.ds(1)
        + 2.0 * param.NU
        * characteristic_function_fluid(param)
        * dot(
            goal_functional(
                microtimestep_before, microtimestep, "primal_velocity"
            )[1],
            grad(eta_fluid),
        )
        * fluid.dx
    )
Ejemplo n.º 4
0
def form_fluid(
    displacement_fluid,
    velocity_fluid,
    phi_fluid,
    psi_fluid,
    fluid: Space,
    param: Parameters,
):

    return (
        param.NU * dot(grad(velocity_fluid), grad(phi_fluid)) * fluid.dx
        + dot(param.BETA, grad(velocity_fluid)) * phi_fluid * fluid.dx
        + dot(grad(displacement_fluid), grad(psi_fluid)) * fluid.dx
        - dot(grad(displacement_fluid), fluid.normal_vector)
        * psi_fluid
        * fluid.ds(1)
        - param.NU
        * dot(grad(velocity_fluid), fluid.normal_vector)
        * phi_fluid
        * fluid.ds(1)
        + param.GAMMA
        / fluid.cell_size
        * displacement_fluid
        * psi_fluid
        * fluid.ds(1)
        + param.GAMMA
        / fluid.cell_size
        * velocity_fluid
        * phi_fluid
        * fluid.ds(1)
    )
Ejemplo n.º 5
0
    def defineWeakSystemDomain():
        """Define system of equations of the weak formulation of 
        the second-orderformulation of the PN equations on the domain .
        """
        sMD = importlib.import_module(
            "systemMatricesDomain_d_%d_k_%s_N_%d" %
            (par['spatialDimension'], par['kernelName'], N_PN))
        systemMatricesDomain = sMD.getSystemMatricesDomain(par)

        lhs = 0.0 * v[0] * fe.dx(V)
        for i in range(nEvenMoments):
            for j in range(nEvenMoments):
                if (par['spatialDimension'] == 1):
                    lhs += systemMatricesDomain['Kzz'][i][j] * fe.dot(
                        fe.grad(u[j])[0],
                        fe.grad(v[i])[0]) * fe.dx(V)
                elif (par['spatialDimension'] == 2):
                    lhs += systemMatricesDomain['Kxx'][i][j] * fe.dot(
                        fe.grad(u[j])[0],
                        fe.grad(v[i])[0]) * fe.dx(V)
                    lhs += systemMatricesDomain['Kxy'][i][j] * fe.dot(
                        fe.grad(u[j])[1],
                        fe.grad(v[i])[0]) * fe.dx(V)
                    lhs += systemMatricesDomain['Kyx'][i][j] * fe.dot(
                        fe.grad(u[j])[0],
                        fe.grad(v[i])[1]) * fe.dx(V)
                    lhs += systemMatricesDomain['Kyy'][i][j] * fe.dot(
                        fe.grad(u[j])[1],
                        fe.grad(v[i])[1]) * fe.dx(V)
                else:
                    raise ValueError(
                        'Only spatial dimensions <= 2 implemented!')
                lhs += systemMatricesDomain['S'][i][j] * u[j] * v[i] * fe.dx(V)

        return lhs
Ejemplo n.º 6
0
 def plot_diffusion_coef(self, entries='01'):
     indices = [int(entry) for entry in entries]
     vector = np.zeros(2)
     vector[indices] = 1
     print(vector)
     fevec = fe.Constant(vector)
     val = fe.dot(self.composed_diff_coef, fevec)
     val = fe.dot(fevec, val)
     fe.plot(val, mesh=self.mesh)
     plt.show()
Ejemplo n.º 7
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
Ejemplo n.º 8
0
def goal_functional_solid(
    displacement_solid_array,
    velocity_solid_array,
    solid,
    solid_timeline,
    param,
):

    global_result = 0.0
    macrotimestep = solid_timeline.head
    global_size = solid_timeline.size
    m = 1
    for n in range(global_size):

        microtimestep = macrotimestep.head.after
        local_size = macrotimestep.size - 1
        for k in range(local_size):

            print(f"Current contribution: {m}")
            result = 0.0
            time_step = microtimestep.before.dt
            gauss_1, gauss_2 = gauss(microtimestep)
            result += (
                0.5 * time_step * param.ZETA *
                characteristic_function_solid(param) * dot(
                    grad(
                        linear_extrapolation(displacement_solid_array, m,
                                             gauss_1, microtimestep)),
                    grad(
                        linear_extrapolation(displacement_solid_array, m,
                                             gauss_1, microtimestep)),
                ) * solid.dx)
            result += (
                0.5 * time_step * param.ZETA *
                characteristic_function_solid(param) * dot(
                    grad(
                        linear_extrapolation(displacement_solid_array, m,
                                             gauss_2, microtimestep)),
                    grad(
                        linear_extrapolation(displacement_solid_array, m,
                                             gauss_2, microtimestep)),
                ) * solid.dx)

            m += 1
            microtimestep = microtimestep.after
            global_result += assemble(result)

        macrotimestep = macrotimestep.after

    return global_result
Ejemplo n.º 9
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
Ejemplo n.º 10
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
Ejemplo n.º 11
0
 def construct_variation_problem(self) -> Tuple[Form, Form]:
     p = self.params
     u_t = (p.T - p.T_prev) / p.dt
     f = p.Q_pc + p.Q_sw + p.Q_mm
     F = p.P_s * p.c_s * u_t * p.v * dx + p.k_e * dot(grad(p.T), grad(
         p.v)) * dx - f * p.v * dx
     return lhs(F), rhs(F)
Ejemplo n.º 12
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)
Ejemplo n.º 13
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()
 def effective_field(m, volume=None):
     w_Zeeman = - mu0 * Ms * fe.dot(m, H)
     w_exchange = A  * fe.inner(fe.grad(m), fe.grad(m))
     w_DMI = D * fe.inner(m, fe.curl(m))
     w_ani = - K * fe.inner(m, ea)**2
     w = w_Zeeman + w_exchange + w_DMI + w_ani
     return -1/(mu0*Ms) * fe.derivative(w*fe.dx, m)
Ejemplo n.º 15
0
def form_solid(
    displacement_solid,
    velocity_solid,
    phi_solid,
    psi_solid,
    solid: Space,
    param: Parameters,
):

    return (
        param.ZETA * dot(grad(displacement_solid), grad(phi_solid)) * solid.dx
        + param.DELTA * dot(grad(velocity_solid), grad(phi_solid)) * solid.dx
        - velocity_solid * psi_solid * solid.dx
        - param.DELTA
        * dot(grad(velocity_solid), solid.normal_vector)
        * phi_solid
        * solid.ds(1)
    )
Ejemplo n.º 16
0
def test_formulation_1_extrap_1_material():
    '''
    Test function formulation() with 1 extrinsic trap
    and 1 material
    '''
    dt = 1
    traps = [{
        "energy": 1,
        "materials": [1],
        "type": "extrinsic"
        }]
    materials = [{
            "alpha": 1,
            "beta": 2,
            "density": 3,
            "borders": [0, 1],
            "E_diff": 4,
            "D_0": 5,
            "id": 1
            }]
    
    mesh = fenics.UnitIntervalMesh(10)
    V = fenics.VectorFunctionSpace(mesh, 'P', 1, 2)
    W = fenics.FunctionSpace(mesh, 'P', 1)
    u = fenics.Function(V)
    u_n = fenics.Function(V)
    v = fenics.TestFunction(V)
    n = fenics.interpolate(fenics.Expression('1', degree=0), W)
    solutions = list(fenics.split(u))
    previous_solutions = list(fenics.split(u_n))
    testfunctions = list(fenics.split(v))
    extrinsic_traps = [n]
    mf = fenics.MeshFunction('size_t', mesh, 1, 1)
    dx = fenics.dx(subdomain_data=mf)
    temp = fenics.Expression("300", degree=0)
    flux_ = fenics.Expression("10000", degree=0)

    F, expressions = FESTIM.formulation(
        traps, extrinsic_traps, solutions, testfunctions,
        previous_solutions, dt, dx, materials, temp, flux_)
    expected_form = ((solutions[0] - previous_solutions[0]) / dt) * \
        testfunctions[0]*dx
    expected_form += 5 * fenics.exp(-4/8.6e-5/temp) * \
        fenics.dot(
            fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(1)
    expected_form += -flux_*testfunctions[0]*dx + \
        ((solutions[1] - previous_solutions[1]) / dt) * \
        testfunctions[1]*dx
    expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \
        solutions[0] * (extrinsic_traps[0] - solutions[1]) * \
        testfunctions[1]*dx(1)
    expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \
        testfunctions[1]*dx(1)
    expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \
        testfunctions[0]*dx

    assert expected_form.equals(F) is True
Ejemplo n.º 17
0
 def get_F(u, v, dt):
     dx = fenics.dx
     F = (u * v * dx
          + dt * (sigma**2 / 2)
             * fenics.dot(fenics.grad(u**2), fenics.grad(v)) * dx
          - (1 / theta) * dt * u * (1 - u) * v * dx
          - u_n * v * dx
     )
     return F
Ejemplo n.º 18
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)
Ejemplo n.º 19
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)
Ejemplo n.º 20
0
 def construct_variation_problem(self) -> Tuple[Form, Form]:
     p = self.params
     ds = self.make_ds(p.mesh)
     u_t = (p.u - p.P_prev) / p.dt
     term = p.alpha_th * p.u * p.P_d * (p.my_v + p.my_d)**2 / (
         (p.P_prev + p.P_d) * p.my_v * p.my_d) / p.T_s * grad(p.T_s)
     F = p.theta_a * u_t * p.v * dx + p.theta_a * p.D_e * dot(
         grad(p.u) - term, grad(
             p.v)) * dx - p.M_mm * p.v * dx + p.q_h * p.v * ds(1)
     return lhs(F), rhs(F)
Ejemplo n.º 21
0
 def _compute_effective_diffusion(self):
     # Uses the solutions of the cell problems to compute the harmonic average of the diffusivity
     for i, j in np.ndindex((self.dim, self.dim)):
         integrand_ij = fe.project(
             self.a_y *
             fe.dot(self.e_is[i] + fe.grad(self.cell_solutions[i]),
                    self.e_is[j] + fe.grad(self.cell_solutions[j])),
             self.function_space)
         self.eff_diff[i, j] = fe.assemble(integrand_ij * fe.dx)
     return fe.Constant(self.eff_diff)
Ejemplo n.º 22
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])
Ejemplo n.º 23
0
    def __compute_shape_derivative(self):
        """Computes the shape derivative.

		Returns
		-------
		None

		Notes
		-----
		This only works properly if differential operators only
		act on state and adjoint variables, else the results are incorrect.
		A corresponding warning whenever this could be the case is issued.
		"""

        # Shape derivative of Lagrangian w/o regularization and pull-backs
        self.shape_derivative = fenics.derivative(
            self.lagrangian.lagrangian_form,
            fenics.SpatialCoordinate(self.mesh), self.test_vector_field)

        # Add pull-backs
        if self.use_pull_back:
            self.state_adjoint_ids = [coeff.id() for coeff in self.states] + [
                coeff.id() for coeff in self.adjoints
            ]

            self.material_derivative_coeffs = []
            for coeff in self.lagrangian.lagrangian_form.coefficients():
                if coeff.id() in self.state_adjoint_ids:
                    pass
                else:
                    if not (coeff.ufl_element().family() == 'Real'):
                        self.material_derivative_coeffs.append(coeff)

            if len(self.material_derivative_coeffs) > 0:
                warning(
                    'Shape derivative might be wrong, if differential operators act on variables other than states and adjoints. \n'
                    'You can check for correctness of the shape derivative with cashocs.verification.shape_gradient_test\n'
                )

            for coeff in self.material_derivative_coeffs:
                # temp_space = fenics.FunctionSpace(self.mesh, coeff.ufl_element())
                # placeholder = fenics.Function(temp_space)
                # temp_form = fenics.derivative(self.lagrangian.lagrangian_form, coeff, placeholder)
                # material_derivative = replace(temp_form, {placeholder : fenics.dot(fenics.grad(coeff), self.test_vector_field)})

                material_derivative = fenics.derivative(
                    self.lagrangian.lagrangian_form, coeff,
                    fenics.dot(fenics.grad(coeff), self.test_vector_field))
                material_derivative = expand_derivatives(material_derivative)

                self.shape_derivative += material_derivative

        # Add regularization
        self.shape_derivative += self.regularization.compute_shape_derivative()
Ejemplo n.º 24
0
    def create_bilinear_form_and_rhs(self):

        # Define variational problem
        u = fe.TrialFunction(self.function_space)
        v = fe.TestFunction(self.function_space)

        self.bilinear_form = (1 + self.lam * self.dt) *\
                (u * v * fe.dx) + self.dt * self.diffusion_coefficient *\
                (fe.dot(fe.grad(u), fe.grad(v)) * fe.dx)

        self.rhs = (self.u_n + self.dt * self.rhs_fun * self.u_n) * v * fe.dx
Ejemplo n.º 25
0
def functional_solid(
    displacement_solid_old,
    velocity_solid_old,
    displacement_solid_interface,
    velocity_solid_interface,
    displacement_solid_old_interface,
    velocity_solid_old_interface,
    phi_solid,
    psi_solid,
    solid: Space,
    param: Parameters,
    time,
    time_step,
):

    return (
        velocity_solid_old * phi_solid * solid.dx
        + displacement_solid_old * psi_solid * solid.dx
        - 0.5
        * time_step
        * form_solid(
            displacement_solid_old,
            velocity_solid_old,
            phi_solid,
            psi_solid,
            solid,
            param,
        )
        - 0.5
        * time_step
        * param.NU
        * dot(grad(velocity_solid_interface), solid.normal_vector)
        * phi_solid
        * solid.ds(1)
        - 0.5
        * time_step
        * param.NU
        * dot(grad(velocity_solid_old_interface), solid.normal_vector)
        * phi_solid
        * solid.ds(1)
    )
Ejemplo n.º 26
0
    def create_bilinear_form_and_rhs(self):

        # Define variational problem
        u = fe.TrialFunction(self.function_space)
        v = fe.TestFunction(self.function_space)

        if self.dimension == 1:
            diffusion_tensor = self.diffusion_matrix
            self.bilinear_form = (1 + self.lam * self.dt) * (u * v * fe.dx) +\
                    self.dt * (fe.dot(\
                    diffusion_tensor * fe.grad(u),\
                    fe.grad(v)) * fe.dx)

        if self.dimension == 2:
            diffusion_tensor = fe.as_matrix(self.diffusion_matrix)
            self.bilinear_form = (1 + self.lam * self.dt) * (u * v * fe.dx) +\
                    self.dt * (fe.dot(\
                    fe.dot(diffusion_tensor, fe.grad(u)),\
                    fe.grad(v)) * fe.dx)

        self.rhs = (self.u_n + self.dt * self.rhs_fun) * v * fe.dx
Ejemplo n.º 27
0
 def get_tangential_component(self, t, E):
     E_t = fn.dot(E, t)
     E_t = Poisson.block_project(E_t,
                                 self.mesh,
                                 self.restrictions_dict['interface_rtc'],
                                 self.boundaries,
                                 self.boundaries_ids['Interface'],
                                 space_type='scalar',
                                 boundary_type='internal',
                                 sign=t.side(),
                                 restricted=True)
     return E_t
Ejemplo n.º 28
0
def solve_wave_equation(u0, u1, u_boundary, f, domain, mesh, degree):
    """Solving the wave equation using CG-CG method.

    Args:
        u0: Initial data.
        u1: Initial velocity.
        u_boundary: Dirichlet boundary condition.
        f: Right-hand side.
        domain: Space-time domain.
        mesh: Computational mesh.
        degree: CG(degree) will be used as the finite element.
    Outputs:
        uh: Numerical solution.
    """
    # Element
    V = FunctionSpace(mesh, "CG", degree)
    # Measures on the initial and terminal slice
    mask = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)
    domain.get_initial_slice().mark(mask, 1)
    ends = ds(subdomain_data=mask)
    # Form
    g = Constant(((-1.0, 0.0), (0.0, 1.0)))
    u = TrialFunction(V)
    v = TestFunction(V)
    a = dot(grad(v), dot(g, grad(u))) * dx
    L = f * v * dx + u1 * v * ends(1)
    # Assembled matrices
    A = assemble(a, keep_diagonal=True)
    b = assemble(L, keep_diagonal=True)
    # Spatial boundary condition
    bc = DirichletBC(V, u_boundary, domain.get_spatial_boundary())
    bc.apply(A, b)
    # Temporal boundary conditions (by hand)
    (A, b) = apply_time_boundary_conditions(domain, V, u0, A, b)
    # Solve
    solver = LUSolver()
    solver.set_operator(A)
    uh = Function(V)
    solver.solve(uh.vector(), b)
    return uh
    def compute_dmdt(m):
        """Convenience function that does all in one go"""

        # Assemble RHS
        b = fe.assemble(Heff_form)

        # Project onto Heff
        LU.solve(Heff.vector(), b)

        LLG = -gamma/(1+alpha*alpha)*fe.cross(m, Heff) - alpha*gamma/(1+alpha*alpha)*fe.cross(m, fe.cross(m, Heff))

        result = fe.assemble(fe.dot(LLG, v)*fe.dP)
        return result.array()
Ejemplo n.º 30
0
def form_solid_adjoint(
    displacement_solid_adjoint,
    velocity_solid_adjoint,
    xi_solid,
    eta_solid,
    solid: Space,
    param: Parameters,
):

    return (
        param.ZETA
        * dot(grad(xi_solid), grad(displacement_solid_adjoint))
        * solid.dx
        + param.DELTA
        * dot(grad(eta_solid), grad(displacement_solid_adjoint))
        * solid.dx
        - eta_solid * velocity_solid_adjoint * solid.dx
        - param.DELTA
        * dot(grad(eta_solid), solid.normal_vector)
        * displacement_solid_adjoint
        * solid.ds(1)
    )
Ejemplo n.º 31
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