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)
    def check_conservation_law(self, sol):
        dx = self.dx
        ds = self.ds
        total = []
        out = []
        for s in sol:
            cl = s[0]
            na = s[1]
            k = s[2]

            # integrate interior concentration
            mass_cl = fe.assemble(cl * dx)
            mass_na = fe.assemble(na * dx)
            mass_k = fe.assemble(k * dx)

            # integrate outflux
            n = fe.FacetNormal(self.mesh)
            flow = self.flow
            outflux_cl = fe.assemble(cl * inner(flow, n) * ds)
            outflux_na = fe.assemble(na * inner(flow, n) * ds)
            outflux_k = fe.assemble(k * inner(flow, n) * ds)

            total.append(mass_cl + mass_na + 2 * mass_k)
            out.append(outflux_cl + outflux_na + 2 * outflux_k)

        self.total_mass = total
        self.outflux = out
Пример #3
0
    def build_weak_form_staggered(self):
        self.psi_plus = partial(psi_plus_linear_elasticity_model_A,
                                lamda=self.lamda,
                                mu=self.mu)
        self.psi_minus = partial(psi_minus_linear_elasticity_model_A,
                                 lamda=self.lamda,
                                 mu=self.mu)

        sigma_plus = cauchy_stress_plus(strain(fe.grad(self.x_new)),
                                        self.psi_plus)
        sigma_minus = cauchy_stress_minus(strain(fe.grad(self.x_new)),
                                          self.psi_minus)

        self.G_u = (g_d(self.d_new) * fe.inner(sigma_plus, strain(fe.grad(self.eta))) \
            + fe.inner(sigma_minus, strain(fe.grad(self.eta)))) * fe.dx

        # self.G_d = (self.H_old * self.zeta * g_d_prime(self.d_new, g_d) \
        #     + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx

        self.G_d = (history(self.H_old, self.psi_plus(strain(fe.grad(self.x_new))), self.psi_cr) * self.zeta * g_d_prime(self.d_new, g_d) \
            + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx

        # g_c = 0.01
        # self.G_d = (self.psi_plus(strain(fe.grad(self.x_new))) * self.zeta * g_d_prime(self.d_new, g_d) \
        #     + g_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx

        self.G_d += 1 * (self.d_new - self.d_pre) * self.zeta * fe.dx
Пример #4
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]
Пример #5
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]
Пример #6
0
    def _make_variational_problem(V):
        """
        Formulate the variational problem a(u, v) = L(v).

        Parameters
        ----------
        V: FEniCS.FunctionSpace

        Returns
        -------
        a, L: FEniCS.Expression
            Variational forms.
        """
        # Define trial and test functions
        u = F.TrialFunction(V)
        v = F.TestFunction(V)

        # Collect Neumann conditions
        ds = F.Measure("ds", domain=mesh, subdomain_data=boundary_markers)
        integrals_N = []
        for i in boundary_conditions:
            if isinstance(boundary_conditions[i], dict):
                if "Neumann" in boundary_conditions[i]:
                    if boundary_conditions[i]["Neumann"] != 0:
                        g = boundary_conditions[i]["Neumann"]
                        integrals_N.append(g[0] * v * ds(i))

        # Define variational problem
        a = F.inner(u, v) * F.dx + (DT**2) * (C**2) * F.inner(
            F.grad(u), F.grad(v)) * F.dx
        L = ((DT**2) * f[0] + 2 * u_nm1 -
             u_nm2) * v * F.dx + (DT**2) * (C**2) * sum(integrals_N)
        return a, L
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() 
Пример #8
0
 def geneForwardMatrix(self, q_fun=fe.Constant(0.0), fR=fe.Constant(0.0), \
                       fI=fe.Constant(0.0)):
     if self.haveFunctionSpace == False:
         self.geneFunctionSpace()
         
     xx, yy, dPML, sig0_, p_ = self.domain.xx, self.domain.yy, self.domain.dPML,\
                               self.domain.sig0, self.domain.p
     # define the coefficents induced by PML
     sig1 = fe.Expression('x[0] > x1 && x[0] < x1 + dd ? sig0*pow((x[0]-x1)/dd, p) : (x[0] < 0 && x[0] > -dd ? sig0*pow((-x[0])/dd, p) : 0)', 
                  degree=3, x1=xx, dd=dPML, sig0=sig0_, p=p_)
     sig2 = fe.Expression('x[1] > x2 && x[1] < x2 + dd ? sig0*pow((x[1]-x2)/dd, p) : (x[1] < 0 && x[1] > -dd ? sig0*pow((-x[1])/dd, p) : 0)', 
                  degree=3, x2=yy, dd=dPML, sig0=sig0_, p=p_)
     
     sR = fe.as_matrix([[(1+sig1*sig2)/(1+sig1*sig1), 0.0], [0.0, (1+sig1*sig2)/(1+sig2*sig2)]])
     sI = fe.as_matrix([[(sig2-sig1)/(1+sig1*sig1), 0.0], [0.0, (sig1-sig2)/(1+sig2*sig2)]])
     cR = 1 - sig1*sig2
     cI = sig1 + sig2
     
     # define the coefficients with physical meaning
     angl_fre = self.kappa*np.pi
     angl_fre2 = fe.Constant(angl_fre*angl_fre)
     
     # define equations
     u_ = fe.TestFunction(self.V)
     du = fe.TrialFunction(self.V)
     
     u_R, u_I = fe.split(u_)
     duR, duI = fe.split(du)
     
     def sigR(v):
         return fe.dot(sR, fe.nabla_grad(v))
     def sigI(v):
         return fe.dot(sI, fe.nabla_grad(v))
     
     F1 = - fe.inner(sigR(duR)-sigI(duI), fe.nabla_grad(u_R))*(fe.dx) \
         - fe.inner(sigR(duI)+sigI(duR), fe.nabla_grad(u_I))*(fe.dx) \
         - fR*u_R*(fe.dx) - fI*u_I*(fe.dx)
     
     a2 = fe.inner(angl_fre2*q_fun*(cR*duR-cI*duI), u_R)*(fe.dx) \
          + fe.inner(angl_fre2*q_fun*(cR*duI+cI*duR), u_I)*(fe.dx) \
     
     # define boundary conditions
     def boundary(x, on_boundary):
         return on_boundary
     
     bc = [fe.DirichletBC(self.V.sub(0), fe.Constant(0.0), boundary), \
           fe.DirichletBC(self.V.sub(1), fe.Constant(0.0), boundary)]
     
     a1, L1 = fe.lhs(F1), fe.rhs(F1)
     self.u = fe.Function(self.V)
     self.A1 = fe.assemble(a1)
     self.b1 = fe.assemble(L1)
     self.A2 = fe.assemble(a2)
     bc[0].apply(self.A1, self.b1)
     bc[1].apply(self.A1, self.b1)
     bc[0].apply(self.A2)
     bc[1].apply(self.A2)
     self.A = self.A1 + self.A2
Пример #9
0
    def build_weak_form_staggered(self):
        self.psi = partial(psi_linear_elasticity, lamda=self.lamda, mu=self.mu)
        self.sigma = cauchy_stress(strain(fe.grad(self.x_new)), self.psi)

        self.G_u = g_d(self.d_new) * fe.inner(
            self.sigma, strain(fe.grad(self.eta))) * fe.dx

        self.G_d = (history(self.H_old, self.psi(strain(fe.grad(self.x_new))), self.psi_cr) * self.zeta * g_d_prime(self.d_new, g_d) \
            + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx
Пример #10
0
 def _obj(self, x):
     f = da.Function(self.poisson.V)
     f.vector()[:] = x
     self.poisson.source = f
     u = self.poisson.solve_problem_variational_form()
     L_tape = da.assemble(
         (0.5 * fa.inner(u - self.target_u, u - self.target_u) +
          0.5 * self.alpha * fa.inner(f, f)) * fa.dx)
     L = float(L_tape)
     return L, L_tape, f
Пример #11
0
    def build_weak_form_staggered(self):
        self.psi_plus = partial(psi_plus_Miehe, mu=self.mu, beta=self.beta)
        self.psi_minus = partial(psi_minus_Miehe, mu=self.mu, beta=self.beta)

        PK_plus = first_PK_stress_plus(self.I + fe.grad(self.x_new), self.psi_plus)
        PK_minus = first_PK_stress_plus(self.I + fe.grad(self.x_new), self.psi_minus)
 
        self.G_u = (g_d(self.d_new) * fe.inner(PK_plus, fe.grad(self.eta)) +  fe.inner(PK_minus, fe.grad(self.eta)))* fe.dx
        self.G_d = self.H_old * self.zeta * g_d_prime(self.d_new, g_d) * fe.dx \
            + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new))) * fe.dx  
Пример #12
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]
Пример #13
0
    def __init__(self, mesh, constitutive_model):

        W = fe.FunctionSpace(mesh, "DG", 1)
        super().__init__(mesh, constitutive_model, W)

        self.w = fe.Function(W)
        self.p, self.p0 = self.w, fe.Function(W)

        self.g = fe.TestFunction(W)

        self.functional = fe.inner(self.p, self.g) - fe.inner(
            self.constitutive_model)
Пример #14
0
    def build_weak_form_staggered(self):
        self.x_hat = fe.variable(fe.SpatialCoordinate(self.mesh))
        self.x = map_function_ufl(self.x_hat, self.control_points,
                                  self.impact_radii, self.map_type,
                                  self.boundary_info)
        self.grad_gamma = fe.diff(self.x, self.x_hat)

        def mfem_grad_wrapper(grad):
            def mfem_grad(u):
                return fe.dot(grad(u), fe.inv(self.grad_gamma))

            return mfem_grad

        self.mfem_grad = mfem_grad_wrapper(fe.grad)

        # A special note (Tianju): We hope to use Model C, but Newton solver fails without the initial guess by Model A
        if self.i < 2:
            self.psi_plus = partial(psi_plus_linear_elasticity_model_A,
                                    lamda=self.lamda,
                                    mu=self.mu)
            self.psi_minus = partial(psi_minus_linear_elasticity_model_A,
                                     lamda=self.lamda,
                                     mu=self.mu)
        else:
            self.psi_plus = partial(psi_plus_linear_elasticity_model_C,
                                    lamda=self.lamda,
                                    mu=self.mu)
            self.psi_minus = partial(psi_minus_linear_elasticity_model_C,
                                     lamda=self.lamda,
                                     mu=self.mu)
            print("use model C")

        self.psi = partial(psi_linear_elasticity, lamda=self.lamda, mu=self.mu)

        self.sigma_plus = cauchy_stress_plus(
            strain(self.mfem_grad(self.x_new)), self.psi_plus)
        self.sigma_minus = cauchy_stress_minus(
            strain(self.mfem_grad(self.x_new)), self.psi_minus)

        # self.sigma = cauchy_stress_plus(strain(self.mfem_grad(self.x_new)), self.psi)
        # self.sigma_degraded = g_d(self.d_new) * self.sigma_plus + self.sigma_minus

        self.G_u = (g_d(self.d_new) * fe.inner(self.sigma_plus, strain(self.mfem_grad(self.eta))) \
            + fe.inner(self.sigma_minus, strain(self.mfem_grad(self.eta)))) * fe.det(self.grad_gamma) * fe.dx

        if self.solution_scheme == 'explicit':
            self.G_d = (self.H_old * self.zeta * g_d_prime(self.d_new, g_d) \
                    + self.G_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(self.mfem_grad(self.zeta), self.mfem_grad(self.d_new)))) * fe.det(self.grad_gamma) * fe.dx
        else:
            self.G_d = (history(self.H_old, self.psi_plus(strain(self.mfem_grad(self.x_new))), self.psi_cr) * self.zeta * g_d_prime(self.d_new, g_d) \
                    + self.G_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(self.mfem_grad(self.zeta), self.mfem_grad(self.d_new)))) * fe.det(self.grad_gamma) * fe.dx
Пример #15
0
	def compute_shape_derivative(self):
		"""Computes the part of the shape derivative that comes from the regularization

		Returns
		-------
		ufl.form.Form
			The weak form of the shape derivative coming from the regularization

		"""

		V = self.form_handler.test_vector_field
		if self.has_regularization:
			
			x = fenics.SpatialCoordinate(self.form_handler.mesh)
			n = fenics.FacetNormal(self.form_handler.mesh)
			I = fenics.Identity(self.form_handler.mesh.geometric_dimension())

			self.shape_form = Constant(self.mu_surface)*(self.current_surface - Constant(self.target_surface))*t_div(V, n)*self.ds
			
			self.shape_form += Constant(self.mu_curvature)*(inner((I - (t_grad(x, n) + (t_grad(x, n)).T))*t_grad(V, n), t_grad(self.kappa_curvature, n))*self.ds \
						+ Constant(0.5)*t_div(V, n)*t_div(self.kappa_curvature, n)*self.ds)
			
			if not self.measure_hole:
				self.shape_form += Constant(self.mu_volume)*(self.current_volume - Constant(self.target_volume))*div(V)*self.dx
				self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\
								   		*(self.current_barycenter_x/self.current_volume*div(V) + 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \
								   + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\
								   		*(self.current_barycenter_y/self.current_volume*div(V) + 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx

				if self.form_handler.mesh.geometric_dimension() == 3:
					self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\
									   *(self.current_barycenter_z/self.current_volume*div(V) + 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx


			else:
				self.shape_form -= Constant(self.mu_volume)*(self.current_volume - Constant(self.target_volume))*div(V)*self.dx
				self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\
								   		*(self.current_barycenter_x/self.current_volume*div(V) - 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \
								   + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\
								   		*(self.current_barycenter_y/self.current_volume*div(V) - 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx

				if self.form_handler.mesh.geometric_dimension() == 3:
					self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\
									   		*(self.current_barycenter_z/self.current_volume*div(V) - 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx


			return self.shape_form

		else:
			dim = self.form_handler.mesh.geometric_dimension()
			return inner(fenics.Constant([0]*dim), V)*self.dx
Пример #16
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 V_g: Vector function space
    :param u: solution where gradient is to be determined
    :param flux: returns calculated flux into this value
    """

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

    a = inner(w, v) * dx
    L = inner(grad(u), v) * dx
    solve(a == L, flux)
Пример #17
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)
Пример #18
0
def local_project(v, V, u=None):
    """Element-wise projection using LocalSolver"""
    dv = fnc.TrialFunction(V)
    v_ = fnc.TestFunction(V)
    a_proj = fnc.inner(dv, v_) * fnc.dx
    b_proj = fnc.inner(v, v_) * fnc.dx
    solver = fnc.LocalSolver(a_proj, b_proj)
    solver.factorize()
    if u is None:
        u = fnc.Function(V)
        solver.solve_local_rhs(u)
        return u
    else:
        solver.solve_local_rhs(u)
        return
Пример #19
0
def solve_steady_state_heiser_weissinger(kappa):

    w = fe.Function(V_up)
    (u, p) = fe.split(w)
    p = fe.variable(p)
    (eta, q) = fe.TestFunctions(V_up)
    dw = fe.TrialFunction(V_up)

    kappa = fe.Constant(kappa)

    bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_up.sub(0), V_up.sub(1), None,
                                            boundaries)

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

    W = material_mooney_rivlin(I_1_iso, I_2_iso, c_10,
                               c_01)  #+ incompr_relaxation(p, kappa)
    g = incompr_constr(J)

    # Lagrange function (without constraint)
    L = -W

    # Modified Lagrange function (with constraints)
    L_mod = L - p * g
    P = first_piola_stress(L, F)
    G = incompr_stress(g, F)  # = J*fe.inv(F.T)

    Lp = const_eq(L_mod, p)

    a_static = weak_div_term(P + p * G,
                             eta) + inner(B, eta) * dx + inner(Lp, q) * dx

    J_static = fe.derivative(a_static, w, dw)
    ffc_options = {"optimize": True}
    problem = fe.NonlinearVariationalProblem(
        a_static,
        w,
        bcs_u + bcs_p,
        J=J_static,
        form_compiler_parameters=ffc_options)
    solver = fe.NonlinearVariationalSolver(problem)

    solver.solve()

    return w
Пример #20
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()
Пример #21
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)
Пример #22
0
	def compute_objective(self):
		"""Computes the part of the objective value that comes from the regularization

		Returns
		-------
		float
			Part of the objective value coming from the regularization

		"""

		if self.has_regularization:

			value = 0.0

			if self.mu_volume > 0.0:
				if not self.measure_hole:
					volume = fenics.assemble(Constant(1.0)*self.dx)
				else:
					volume = self.delta_x*self.delta_y*self.delta_z - fenics.assemble(Constant(1)*self.dx)

				value += 0.5*self.mu_volume*pow(volume - self.target_volume, 2)

			if self.mu_surface > 0.0:
				surface = fenics.assemble(Constant(1.0)*self.ds)
				# self.current_surface.val = surface
				value += 0.5*self.mu_surface*pow(surface - self.target_surface, 2)
			
			if self.mu_curvature > 0.0:
				self.compute_curvature()
				curvature_val = fenics.assemble(fenics.inner(self.kappa_curvature, self.kappa_curvature)*self.ds)
				value += 0.5*self.mu_curvature*curvature_val
			
			if self.mu_barycenter > 0.0:
				if not self.measure_hole:
					volume = fenics.assemble(Constant(1)*self.dx)

					barycenter_x = fenics.assemble(self.spatial_coordinate[0]*self.dx) / volume
					barycenter_y = fenics.assemble(self.spatial_coordinate[1]*self.dx) / volume
					if self.form_handler.mesh.geometric_dimension() == 3:
						barycenter_z = fenics.assemble(self.spatial_coordinate[2]*self.dx) / volume
					else:
						barycenter_z = 0.0

				else:
					volume = self.delta_x*self.delta_y*self.delta_z - fenics.assemble(Constant(1)*self.dx)

					barycenter_x = (0.5*(pow(self.x_end, 2) - pow(self.x_start, 2))*self.delta_y*self.delta_z - fenics.assemble(self.spatial_coordinate[0]*self.dx)) / volume
					barycenter_y = (0.5*(pow(self.y_end, 2) - pow(self.y_start, 2))*self.delta_x*self.delta_z - fenics.assemble(self.spatial_coordinate[1]*self.dx)) / volume
					if self.form_handler.mesh.geometric_dimension() == 3:
						barycenter_z = (0.5*(pow(self.z_end, 2) - pow(self.z_start, 2))*self.delta_x*self.delta_y - fenics.assemble(self.spatial_coordinate[2]*self.dx)) / volume
					else:
						barycenter_z = 0.0

				value += 0.5*self.mu_barycenter*(pow(barycenter_x - self.target_barycenter_list[0], 2) + pow(barycenter_y - self.target_barycenter_list[1], 2)
												 + pow(barycenter_z - self.target_barycenter_list[2], 2))

			return value

		else:
			return 0.0
Пример #23
0
    def __call__(self, mesh, V=None, Vc=None):

        boundaries, boundarymarkers, domainmarkers, dx, ds, V, Vc = SetupUnitMeshHelper(
            mesh, V, Vc)

        self._ds_markers = boundarymarkers
        self._dx_markers = domainmarkers

        self._dx = dx
        self._ds = ds
        self._boundaries = boundaries
        self._subdomains = self._boundaries

        u = df.TrialFunction(V)
        v = df.TestFunction(V)
        alpha = df.Function(Vc, name='conductivity')
        alpha.vector()[:] = 1

        def set_alpha(x):
            alpha.vector()[:] = x

        self._set_alpha = set_alpha
        a = alpha * df.inner(df.grad(u), df.grad(v)) * dx

        return a, set_alpha, alpha, V, Vc
Пример #24
0
    def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()

        solver = self.block_helper.adjoint_solver
        if solver is None:
            if self.assemble_system:
                rhs_bcs_form = backend.inner(backend.Function(self.function_space),
                                             dFdu_adj_form.arguments()[0]) * backend.dx
                A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form, bcs)
            else:
                A = compat.assemble_adjoint_value(dFdu_adj_form)
                [bc.apply(A) for bc in bcs]

            solver = backend.LUSolver(A, self.method)
            self.block_helper.adjoint_solver = solver

        solver.parameters.update(self.lu_solver_parameters)
        [bc.apply(dJdu) for bc in bcs]

        adj_sol = backend.Function(self.function_space)
        solver.solve(adj_sol.vector(), dJdu)

        adj_sol_bdy = None
        if compute_bdy:
            adj_sol_bdy = compat.function_from_vector(self.function_space, dJdu_copy - compat.assemble_adjoint_value(
                backend.action(dFdu_adj_form, adj_sol)))

        return adj_sol, adj_sol_bdy
Пример #25
0
    def __setup_decrease_computation(self):
        """Initializes attributes and solver for the frobenius norm check.

		Returns
		-------
		None
		"""

        if not self.angle_change > 0:
            raise ConfigError('MeshQuality', 'angle_change',
                              'This parameter has to be positive.')

        options = [[['ksp_type', 'preonly'], ['pc_type', 'jacobi'],
                    ['pc_jacobi_type', 'diagonal'], ['ksp_rtol', 1e-16],
                    ['ksp_atol', 1e-20], ['ksp_max_it', 1000]]]
        self.ksp_frobenius = PETSc.KSP().create()
        _setup_petsc_options([self.ksp_frobenius], options)

        self.trial_dg0 = fenics.TrialFunction(self.form_handler.DG0)
        self.test_dg0 = fenics.TestFunction(self.form_handler.DG0)

        if not (self.angle_change == float('inf')):
            self.search_direction_container = fenics.Function(
                self.form_handler.deformation_space)

            self.a_frobenius = self.trial_dg0 * self.test_dg0 * self.dx
            self.L_frobenius = fenics.sqrt(
                fenics.inner(fenics.grad(self.search_direction_container),
                             fenics.grad(self.search_direction_container))
            ) * self.test_dg0 * self.dx
Пример #26
0
 def debug(self):
     v = fa.Function(self.V)
     v.vector()[4] = 1
     u = fa.Function(self.V)
     u.vector()[4] = 1
     # v.vector()[:] = 1
     value = np.array(fa.assemble(fa.inner(fa.grad(u), fa.grad(v)) * fa.dx))
     print(value)
Пример #27
0
def problem_mix(T, dt, E, coupling, VV, boundaries, rho_s, lambda_, mu_s, f,
                bcs, **Solid_namespace):
    # Temporal parameters
    t = 0
    k = Constant(dt)

    # Split problem to two 1.order differential equations
    psi, phi = TestFunctions(VV)

    # Functions, wd is for holding the solution
    d_ = {}
    w_ = {}
    wd_ = {}
    for time in ["n", "n-1", "n-2", "n-3"]:
        #if time == "n" and E not in [None, reference]:
        #    tmp_wd = Function(VV)
        #    wd_[time] = tmp_wd
        #    wd = TrialFunction(VV)
        #    w, d = split(wd)
        #else:
        wd = Function(VV)
        wd_[time] = wd
        w, d = split(wd)

        d_[time] = d
        w_[time] = w

    # Time derivative
    if coupling == "center":
        G = rho_s / (2 * k) * inner(w_["n"] - w_["n-2"], psi) * dx
    else:
        G = rho_s / k * inner(w_["n"] - w_["n-1"], psi) * dx

    # Stress tensor
    G += inner(Piola2(d_, w_, k, lambda_, mu_s, E_func=E), grad(psi)) * dx

    # External forces, like gravity
    G -= rho_s * inner(f, psi) * dx

    # d-w coupling
    if coupling == "CN":
        G += inner(d_["n"] - d_["n-1"] - k * 0.5 *
                   (w_["n"] + w_["n-1"]), phi) * dx
    elif coupling == "imp":
        G += inner(d_["n"] - d_["n-1"] - k * w_["n"], phi) * dx
    elif coupling == "exp":
        G += inner(d_["n"] - d_["n-1"] - k * w_["n-1"], phi) * dx
    elif coupling == "center":
        G += inner(d_["n"] - d_["n-2"] - 2 * k * w_["n-1"], phi) * dx
    else:
        print "The coupling %s is not implemented, 'CN', 'imp', and 'exp' are the only valid choices."
        sys.exit(0)

    # Solve
    #if E in [None, reference]:
    solver_nonlinear(G, d_, w_, wd_, bcs, T, dt, **Solid_namespace)
Пример #28
0
	def avg_condition_number(mesh):
		"""Computes average mesh quality based on the condition number of the reference mapping.

		This quality criterion uses the condition number (in the Frobenius norm) of the
		(linear) mapping from the elements of the mesh to the reference element. Computes
		the average of the condition number over all elements.

		Parameters
		----------
		mesh : dolfin.cpp.mesh.Mesh
			The mesh, whose quality shall be computed.

		Returns
		-------
		float
			The average mesh quality based on the condition number.
		"""

		DG0 = fenics.FunctionSpace(mesh, 'DG', 0)
		jac = Jacobian(mesh)
		inv = JacobianInverse(mesh)

		options = [
				['ksp_type', 'preonly'],
				['pc_type', 'jacobi'],
				['pc_jacobi_type', 'diagonal'],
				['ksp_rtol', 1e-16],
				['ksp_atol', 1e-20],
				['ksp_max_it', 1000]
			]
		ksp = PETSc.KSP().create()
		_setup_petsc_options([ksp], [options])

		dx = fenics.Measure('dx', mesh)
		a = fenics.TrialFunction(DG0)*fenics.TestFunction(DG0)*dx
		L = fenics.sqrt(fenics.inner(jac, jac))*fenics.sqrt(fenics.inner(inv, inv))*fenics.TestFunction(DG0)*dx

		cond = fenics.Function(DG0)

		A, b = _assemble_petsc_system(a, L)
		_solve_linear_problem(ksp, A, b, cond.vector().vec(), options)
		cond.vector().apply('')

		return np.average(np.sqrt(mesh.geometric_dimension()) / cond.vector()[:])
Пример #29
0
    def _assembly(V):
        """
        Assemble the matrices used in the linear system Au = b.
        Alternative representation of the variational form.
        Pre-calculate to speed up.
        """
        # Define trial and test functions
        u = F.TrialFunction(V)
        v = F.TestFunction(V)

        # Assemble
        a_M = F.inner(u, v) * F.dx
        a_K = F.inner(F.grad(u), F.grad(v)) * F.dx

        M = F.assemble(a_M)
        K = F.assemble(a_K)

        A = M + (DT**2) * (C**2) * K
        return M, K, A
Пример #30
0
    def build_weak_form_staggered(self):
        self.psi_plus = partial(psi_plus_linear_elasticity_model_A,
                                lamda=self.lamda,
                                mu=self.mu)
        self.psi_minus = partial(psi_minus_linear_elasticity_model_A,
                                 lamda=self.lamda,
                                 mu=self.mu)

        sigma_plus = cauchy_stress_plus(strain(fe.grad(self.x_new)),
                                        self.psi_plus)
        sigma_minus = cauchy_stress_minus(strain(fe.grad(self.x_new)),
                                          self.psi_minus)

        self.G_u = (g_d(self.d_new) * fe.inner(sigma_plus, strain(fe.grad(self.eta))) \
            + fe.inner(sigma_minus, strain(fe.grad(self.eta)))) * fe.dx

        g_c = 2.7e-6
        self.G_d = (self.psi_plus(strain(fe.grad(self.x_new))) * self.zeta * g_d_prime(self.d_new, g_d) \
            + g_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx
Пример #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
    )
Пример #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