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
示例#2
0
    def set_target_velocity(self, u=None, v=None, U=None):
        """ 
    Set target velocity.

    Accepts a list of surface velocity data, and generates a dolfin
    expression from these.  Then projects this onto the velocity 
    function space.  The sum square error between this velocity 
    and modelled surface velocity is the objective function.
    
    :param u : Surface velocity
    :param v : Surface velocity perpendicular to :attr:`u`
    :param U : 2-D surface velocity data
    
    """
        model = self.model
        S = model.S
        Q = model.Q

        if u != None and v != None:
            model.u_o = project(u, Q)
            model.v_o = project(v, Q)

        elif U != None:
            Smag = project(sqrt(S.dx(0)**2 + S.dx(1)**2 + 1e-10), Q)
            model.U_o.interpolate(U)
            model.u_o = project(-model.U_o * S.dx(0) / Smag, Q)
            model.v_o = project(-model.U_o * S.dx(1) / Smag, Q)
示例#3
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
def CompressibleOgden(Lambda, Mu, Alpha, C, Ic, J):
    
    # Invariant of Right Cauchy-Green deformation tensor
    def I1(C):
        return fe.tr(C)

    def I2(C):
        c1 = C[0,0]*C[1,1] + C[0,0]*C[2,2] + C[1,1]*C[2,2]
        c2 = C[0,1]*C[0,1] + C[0,2]*C[0,2] + C[1,2]*C[1,2]
        return c1 - c2

    def I3(C):
        return fe.det(C)

    # Define function necessary for eigenvalues computation
    def v_inv(C):
        return (I1(C)/3.)**2 - I2(C)/3.

    def s_inv(C):
        return (I1(C)/3.)**3 - I1(C)*I2(C)/6. + I3(C)/2.

    def phi_inv(C):
        arg = s_inv(C)/v_inv(C)*fe.sqrt(1./v_inv(C))
        # numerical issues if arg~0
        # https://fenicsproject.org/qa/12299
        # /nan-values-when-computing-arccos-1-0-bug/
        arg_cond = fe.conditional( fe.ge(arg, 1-fe.DOLFIN_EPS),
        1-fe.DOLFIN_EPS,fe.conditional( fe.le(arg, -1+fe.DOLFIN_EPS),
        -1+fe.DOLFIN_EPS, arg ))
        return fe.acos(arg_cond)/3.

    # Eigenvalues of the strech tensor C
    Lambda1 = Ic/3. + 2*fe.sqrt(v_inv(C))*fe.cos(phi_inv(C))
    Lambda2 = Ic/3. - 2*fe.sqrt(v_inv(C))*fe.cos(fe.pi/3. + phi_inv(C))
    Lambda3 = Ic/3. - 2*fe.sqrt(v_inv(C))*fe.cos(fe.pi/3. - phi_inv(C))

    D1 = Lambda/2
    
    Lambda1b = J**(-1/3) * Lambda1
    Lambda2b = J**(-1/3) * Lambda2
    Lambda3b = J**(-1/3) * Lambda3
    
    # Constitutive model
    Psi = 2 * Mu * (Lambda1b**(Alpha/2) + Lambda2b**(Alpha/2) + Lambda3b**(Alpha/2) - 3) / Alpha**2 + D1 * (J-1)**2
        
    return Psi
示例#5
0
 def phi_inv(C):
     arg = s_inv(C)/v_inv(C)*fe.sqrt(1./v_inv(C))
     # numerical issues if arg~0
     # https://fenicsproject.org/qa/12299
     # /nan-values-when-computing-arccos-1-0-bug/
     arg_cond = fe.conditional( fe.ge(arg, 1-fe.DOLFIN_EPS),
     1-fe.DOLFIN_EPS,fe.conditional( fe.le(arg, -1+fe.DOLFIN_EPS),
     -1+fe.DOLFIN_EPS, arg ))
     return fe.acos(arg_cond)/3.
def local_refine(mesh, center, r):
    xc, yc = center
    cell_markers = MeshFunction("bool", mesh, mesh.topology().dim())
    for c in cells(mesh):
        mp = c.midpoint()
        cell_markers[c] = sqrt((mp[0] - xc) * (mp[0] - xc) + (mp[1] - yc) *
                               (mp[1] - yc)) < r
    mesh = refine(mesh, cell_markers)
    return mesh
	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()[:])
示例#8
0
文件: mfem.py 项目: tianjuxue/crack
def distance_function_line_segement_ufl(P, A=[-1, 0], B=[1, 0]):
    AB = [None, None]
    AB[0] = B[0] - A[0]
    AB[1] = B[1] - A[1]

    BP = [None, None]
    BP[0] = P[0] - B[0]
    BP[1] = P[1] - B[1]

    AP = [None, None]
    AP[0] = P[0] - A[0]
    AP[1] = P[1] - A[1]

    AB_BP = AB[0] * BP[0] + AB[1] * BP[1]
    AB_AP = AB[0] * AP[0] + AB[1] * AP[1]

    y = P[1] - B[1]
    x = P[0] - B[0]
    df1 = fe.sqrt(x**2 + y**2)
    xi1 = 1

    y = P[1] - A[1]
    x = P[0] - A[0]
    df2 = fe.sqrt(x**2 + y**2)
    xi2 = 0

    x1 = AB[0]
    y1 = AB[1]
    x2 = AP[0]
    y2 = AP[1]
    mod = fe.sqrt(x1**2 + y1**2)
    df3 = np.absolute(x1 * y2 - y1 * x2) / mod
    xi3 = fe.conditional(fe.gt(x2**2 + y2**2 - df3**2, 0),
                         fe.sqrt(x2**2 + y2**2 - df3**2) / mod, 0)

    df = fe.conditional(fe.gt(AB_BP, 0), df1,
                        fe.conditional(fe.lt(AB_AP, 0), df2, df3))
    xi = fe.conditional(fe.gt(AB_BP, 0), xi1,
                        fe.conditional(fe.lt(AB_AP, 0), xi2, xi3))

    return df, xi
示例#9
0
def compute_errors(u_approx, u_ref, V, total_error_tol=10**-4):
    error_normalized = (u_ref - u_approx) / u_ref  # compute pointwise L2 error
    error_pointwise = project(abs(error_normalized),
                              V)  # project onto function space
    error_total = sqrt(
        assemble(inner(error_pointwise, error_pointwise) *
                 dx))  # determine L2 norm to estimate total error
    error_pointwise.rename("error", " ")

    assert (error_total < total_error_tol)

    return error_total, error_pointwise
示例#10
0
def psi_minus_linear_elasticity_model_C(epsilon, lamda, mu):
    sqrt_delta = fe.conditional(
        fe.gt(fe.tr(epsilon)**2 - 4 * fe.det(epsilon), 0),
        fe.sqrt(fe.tr(epsilon)**2 - 4 * fe.det(epsilon)), 0)
    eigen_value_1 = (fe.tr(epsilon) + sqrt_delta) / 2
    eigen_value_2 = (fe.tr(epsilon) - sqrt_delta) / 2
    tr_epsilon_minus = fe.conditional(fe.lt(fe.tr(epsilon), 0.),
                                      fe.tr(epsilon), 0.)
    eigen_value_1_minus = fe.conditional(fe.lt(eigen_value_1, 0.),
                                         eigen_value_1, 0.)
    eigen_value_2_minus = fe.conditional(fe.lt(eigen_value_2, 0.),
                                         eigen_value_2, 0.)
    return lamda / 2 * tr_epsilon_minus**2 + mu * (eigen_value_1_minus**2 +
                                                   eigen_value_2_minus**2)
示例#11
0
def _handle_function(
    obj,
    **kwargs,
):
    data = []
    scatter = kwargs.get("scatter", False)
    norm = kwargs.get("norm", False)
    component = kwargs.get("component", None)

    if len(obj.ufl_shape) == 0:
        if scatter:
            surface = _scatter_plot_function(obj, **kwargs)
        else:
            surface = _surface_plot_function(obj, **kwargs)
        data.append(surface)

    elif len(obj.ufl_shape) == 1:
        if norm or component == "magnitude":
            V = obj.function_space().split()[0].collapse()
            magnitude = fe.project(fe.sqrt(fe.inner(obj, obj)), V)
        else:
            magnitude = None

        if component is None:
            if norm:
                surface = _surface_plot_function(magnitude, **kwargs)
                data.append(surface)

            cones = _cone_plot(obj, **kwargs)
            data.append(cones)
        else:
            if component == "magnitude":
                surface = _surface_plot_function(magnitude, **kwargs)
                data.append(surface)
            else:
                for i, comp in enumerate(["x", "y", "z"]):

                    if component not in [comp, comp.upper()]:
                        continue
                    surface = _surface_plot_function(
                        obj.sub(i, deepcopy=True), **kwargs
                    )
                    data.append(surface)

    if kwargs.get("wireframe", True):
        lines = _wireframe_plot_mesh(obj.function_space().mesh())
        data.append(lines)

    return data
示例#12
0
bc_p = fe.DirichletBC(W.sub(1), bc_p, dbc_top)


def Max(a, b):
    return (a + b + abs(a - b)) / 2.


def Min(a, b):
    return (a + b - abs(a - b)) / 2.


ns_conv = fe.inner(v, fe.grad(u) * u) * fe.dx
ns_press = p * fe.div(v) * fe.dx
#s = fe.grad(u) + fe.grad(u).T
sij = 0.5 * (fe.grad(u) + fe.grad(u).T)
S = fe.sqrt(EPSILON + 2. * fe.inner(0.5 * (fe.grad(u) + fe.grad(u).T), 0.5 *
                                    (fe.grad(u) + fe.grad(u).T)))
lmx = 0.01
nu_tv = lmx**2. * S

#nu_tv = 0.5 * fe.inner(sij, sij) ** 0.5
#nu_tv = lmx * (2 * fe.inner(sij, sij)) ** (0.5)
#ns_tv = fe.inner((nu_tv) * fe.grad(v), fe.grad(u)) * fe.dx
ns_visc = (nu + nu_tv) * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx
#ns_visc = nu * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx
ns_conti = q * fe.div(u) * fe.dx
ns_forcing = fe.dot(v, b) * fe.dx

NS = ns_conv + ns_press + ns_visc - ns_conti + ns_forcing
#NS = ns_conv + ns_press + ns_tv + ns_visc + ns_conti + ns_forcing

N = 5
示例#13
0
文件: rheology.py 项目: knutsvk/fins
 def differentiated_apparent_viscosity(self, II):
     return self.ty / II**1.5 \
             * ((1 + sqrt(II)/self.eps) * exp(-sqrt(II) / self.eps) - 1)
示例#14
0
 def eval(self, values, x):
     values[0] = min(M_max, S_b * (R_el - sqrt(x[0]**2 + x[1]**2)))
f = fs.Constant((0, 0, -rho * g))
T = fs.Constant((0, 0, 0))
a = fs.inner(sigma(u), epsilon(v)) * fs.dx
L = fs.dot(f, v) * fs.dx + fs.dot(T, v) * fs.ds

# Compute solution
u = fs.Function(V)
fs.solve(a == L, u, bc)

# Plot solution
plt.figure()
fs.plot(u, title='Displacement', mode='displacement')

# Plot stress
s = sigma(u) - (1. / 3) * fs.tr(sigma(u)) * fs.Identity(d)  # deviatoric stress
von_Mises = fs.sqrt(3. / 2 * fs.inner(s, s))
V = fs.FunctionSpace(mesh, 'P', 1)
von_Mises = fs.project(von_Mises, V)
plt.figure()
fs.plot(von_Mises, title='Stress intensity')

# Compute magnitude of displacement
u_magnitude = fs.sqrt(fs.dot(u, u))
u_magnitude = fs.project(u_magnitude, V)
plt.figure()
fs.plot(u_magnitude, title='Displacement magnitude')
print('min/max u:', u_magnitude.vector().min(), u_magnitude.vector().max())

# Save solution to file in VTK format
fs.File('results/displacement.pvd') << u
fs.File('results/von_mises.pvd') << von_Mises
示例#16
0
    def solve(self, **kwargs):
        """
        Solves the variational form of the electrostatics as defined in the
        End of Master thesis from Ximo Gallud Cidoncha:
            A comprehensive numerical procedure for solving the Taylor-Melcher
            leaky dielectric model with charge evaporation.
        Parameters
        ----------
        **kwargs : dict
            Accepted kwargs are:
                - electrostatics_solver_settings: The user may define its own solver parameters. They must be defined
                as follows:
                solver_parameters = {"snes_solver": {"linear_solver": "mumps",
                                      "maximum_iterations": 50,
                                      "report": True,
                                      "error_on_nonconvergence": True,
                                      'line_search': 'bt',
                                      'relative_tolerance': 1e-4}}
                where:
                    - snes_solver is the type of solver to be used. In this
                    case, it is compulsory to use snes, since it's the solver
                    accepted by multiphenics. However, one may try other
                    options if only FEniCS is used. These are: krylov_solver
                    and lu_solver.
                    - linear_solver is the type of linear solver to be used.
                    - maximum_iterations is the maximum number of iterations
                    the solver will try to solve the problem. In case no
                    convergence is achieved, the variable
                    error_on_nonconvergence will raise an error in case this
                    is True. If the user preferes not to raise an error when
                    no convergence, the script will continue with the last
                    results obtained in the iteration process.
                    - line_search is the type of line search technique to be
                    used for solving the problem. It is stronly recommended to
                    use the backtracking (bt) method, since it has been proven
                    to be the most robust one, specially in cases where sqrt
                    are defined, where NaNs may appear due to a bad initial
                    guess or a bad step in the iteration process.
                    - relative_tolerance will tell the solver the parameter to
                    consider convergence on the solution.
                All this options, as well as all the other options available
                can be consulted by calling the method
                Poisson.check_solver_options().
                - initial_potential: Dolfin/FEniCS function which will be used as an initial guess on the iterative
                    process. This must be introduced along with kwarg initial_surface_charge_density. Optional.
                - initial_surface_charge_density: Dolfin/FEniCS function which will be used as an initial guess on the
                    iterative process. This must be introduced along with kwarg initial_potential. Optional.
        Raises
        ------
        TypeError
            This error will raise when the convection charge has not one of the
            following types:
                - Dolfin Function.
                - FEniCS UserExpression.
                - FEniCS Constant.
                - Integer or float number, which will be converted to a FEniCS
                Constant.
        Returns
        -------
        phi : dolfin.function.function.Function
            Dolfin function containing the potential solution.
        surface_charge_density : dolfin.function.function.Function
            Dolfin function conataining the surface charge density solution.
        """

        # --------------------------------------------------------------------
        # EXTRACT THE INPUTS #
        # --------------------------------------------------------------------

        # Check if the type of j_conv is the proper one.
        if not isinstance(self.j_conv, (int, float)) \
            and not Poisson.isDolfinFunction(self.j_conv) \
            and not Poisson.isfenicsexpression(self.j_conv) \
                and not Poisson.isfenicsconstant(self.j_conv):
            conv_type = type(self.j_conv)
            raise TypeError(
                f'Convection charge must be an integer, float, Dolfin function, FEniCS UserExpression or FEniCS constant, not {conv_type}.'
            )
        else:
            if isinstance(self.j_conv, (int, float)):
                self.j_conv = fn.Constant(float(self.j_conv))

        # Extract the solver parameters.
        solver_parameters = kwargs.get('electrostatics_solver_settings')

        # --------------------------------------------------------------------
        # FUNCTION SPACES #
        # --------------------------------------------------------------------
        # Extract the restrictions to create the function spaces.
        """ This variable will be used by multiphenics when creating function spaces. It will create function spaces
            on the introduced restrictions. 
        """
        restrictions_block = [
            self.restrictions_dict['domain_rtc'],
            self.restrictions_dict['interface_rtc']
        ]

        # Base Function Space.
        V = fn.FunctionSpace(self.mesh, 'Lagrange', 2)

        # Block Function Space.
        """ Block Function Spaces are similar to FEniCS function spaces. However, since we are creating function spaces
        based on the block of restrictions, we need to create a 'block of function spaces' for each of the restrictions.
        That block of functions is the list [V, V] from the line of code below this comment. They are assigned in the
        same order in which the block of restrictions has been created, that is:
            - V -> domain_rtc
            - V -> interface_rtc
        """
        W = mp.BlockFunctionSpace([V, V], restrict=restrictions_block)

        # Check the dimensions of the created block function spaces.
        for ix, _ in enumerate(restrictions_block):
            assert W.extract_block_sub_space(
                (ix, )).dim() > 0., f'Subdomain {ix} has dimension 0.'

        # --------------------------------------------------------------------
        # TRIAL/TEST FUNCTIONS #
        # --------------------------------------------------------------------
        # Trial Functions.
        dphisigma = mp.BlockTrialFunction(W)

        # Test functions.
        vl = mp.BlockTestFunction(W)
        (v, l) = mp.block_split(vl)

        phisigma = mp.BlockFunction(W)
        (phi, sigma) = mp.block_split(phisigma)

        # --------------------------------------------------------------------
        # MEASURES #
        # --------------------------------------------------------------------
        self.get_measures()
        self.dS = self.dS(
            self.boundaries_ids['Interface'])  # Restrict to the interface.

        # Check proper marking of the interface.
        assert fn.assemble(
            1 * self.dS(domain=self.mesh)
        ) > 0., "The length of the interface is zero, wrong marking. Check the files in Paraview."

        # --------------------------------------------------------------------
        # DEFINE THE F TERM #
        # --------------------------------------------------------------------
        n = fn.FacetNormal(self.mesh)
        t = fn.as_vector((n[1], -n[0]))

        # Define auxiliary terms.
        r = fn.SpatialCoordinate(self.mesh)[0]
        K = 1 + self.Lambda * (self.T_h - 1)

        E_v_n_aux = fn.dot(-fn.grad(phi("-")), n("-"))

        def expFun():
            sqrterm = E_v_n_aux
            expterm = (self.Phi /
                       self.T_h) * (1 - pow(self.B, 0.25) * fn.sqrt(sqrterm))
            return fn.exp(expterm)

        def sigma_fun():
            num = K * E_v_n_aux + self.eps_r * self.j_conv
            den = K + (self.T_h / self.Chi) * expFun()
            return r * num / den

        # Define the relative permittivity.

        class relative_perm(fn.UserExpression):
            def __init__(self, markers, subdomain_ids, relative, **kwargs):
                super().__init__(**kwargs)
                self.markers = markers
                self.subdomain_ids = subdomain_ids
                self.relative = relative

            def eval_cell(self, values, x, cell):
                if self.markers[cell.index] == self.subdomain_ids['Vacuum']:
                    values[0] = 1.
                else:
                    values[0] = self.relative

        rel_perm = relative_perm(self.subdomains,
                                 self.subdomains_ids,
                                 relative=self.eps_r,
                                 degree=0)

        # Define the variational form.
        # vacuum_int = r*fn.inner(fn.grad(phi), fn.grad(v))*self.dx(self.subdomains_ids['Vacuum'])
        # liquid_int = self.eps_r*r*fn.inner(fn.grad(phi), fn.grad(v))*self.dx(self.subdomains_ids['Liquid'])

        F = [
            r * rel_perm * fn.inner(fn.grad(phi), fn.grad(v)) * self.dx -
            r * sigma("-") * v("-") * self.dS,
            r * sigma_fun() * l("-") * self.dS -
            r * sigma("-") * l("-") * self.dS
        ]

        J = mp.block_derivative(F, phisigma, dphisigma)

        # --------------------------------------------------------------------
        # BOUNDARY CONDITIONS #
        # --------------------------------------------------------------------
        bcs_block = []
        for i in self.boundary_conditions:
            if 'Dirichlet' in self.boundary_conditions[i]:
                bc_val = self.boundary_conditions[i]['Dirichlet'][0]
                bc = mp.DirichletBC(W.sub(0), bc_val, self.boundaries,
                                    self.boundaries_ids[i])
                # Check the created boundary condition.
                assert len(bc.get_boundary_values()
                           ) > 0., f'Wrongly defined boundary {i}'
                bcs_block.append(bc)

        bcs_block = mp.BlockDirichletBC([bcs_block])

        # --------------------------------------------------------------------
        # SOLVE #
        # --------------------------------------------------------------------
        # Define and assign the initial guesses.
        if kwargs.get('initial_potential') is None:
            """
            Check if the user is introducing a potential from a previous
            iteration.
            """
            phiv, phil, sigma_init = self.solve_initial_problem()
            # phi_init = self.solve_initial_problem_v2()
            phi.assign(phiv)
            sigma.assign(sigma_init)
        else:
            phi.assign(kwargs.get('initial_potential'))
            sigma.assign(kwargs.get('initial_surface_charge_density'))

        # Apply the initial guesses to the main function.
        phisigma.apply('from subfunctions')

        # Solve the problem with the solver options (either default or user).
        problem = mp.BlockNonlinearProblem(F, phisigma, bcs_block, J)
        solver = mp.BlockPETScSNESSolver(problem)
        solver_type = [i for i in solver_parameters.keys()][0]
        solver.parameters.update(solver_parameters[solver_type])
        solver.solve()

        # Extract the solutions.
        (phi, _) = phisigma.block_split()
        self.phi = phi
        # --------------------------------------------------------------------

        # Compute the electric field at vacuum and correct the surface charge density.
        self.E_v = self.get_electric_field('Vacuum')
        self.E_v_n = self.get_normal_field(n("-"), self.E_v)
        self.E_t = self.get_tangential_component(t("+"), self.E_v)
        C = self.Phi / self.T_h * (1 - self.B**0.25 * fn.sqrt(self.E_v_n))
        self.sigma = (K * self.E_v_n) / (K + self.T_h / self.Chi * fn.exp(-C))
示例#17
0
bc_p = fe.DirichletBC(W.sub(1), bc_p, dbc_top)


def Max(a, b):
    return (a + b + abs(a - b)) / 2.


def Min(a, b):
    return (a + b - abs(a - b)) / 2.


ns_conv = fe.inner(v, fe.grad(u) * u) * fe.dx
ns_press = p * fe.div(v) * fe.dx
#s = fe.grad(u) + fe.grad(u).T
sij = 0.5 * (fe.grad(u) + fe.grad(u).T)
S = fe.sqrt(EPSILON + 2. * fe.inner(0.5 * (fe.grad(u) + fe.grad(u).T), 0.5 *
                                    (fe.grad(u) + fe.grad(u).T)))
lmx = 0.3
nu_tv = lmx**2. * S

#nu_tv = 0.5 * fe.inner(sij, sij) ** 0.5
#nu_tv = lmx * (2 * fe.inner(sij, sij)) ** (0.5)
#ns_tv = fe.inner((nu_tv) * fe.grad(v), fe.grad(u)) * fe.dx
ns_visc = (nu + nu_tv) * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx
#ns_visc = nu * fe.inner(fe.grad(v), fe.grad(u)) * fe.dx
ns_conti = q * fe.div(u) * fe.dx
ns_forcing = fe.dot(v, b) * fe.dx

NS = ns_conv + ns_press + ns_visc + ns_conti + ns_forcing
#NS = ns_conv + ns_press + ns_tv + ns_visc + ns_conti + ns_forcing

N = 5
示例#18
0
 def evaporated_charge():
     return (self.sigma * self.T_h) / (self.eps_r * self.Chi) * fn.exp(
         -self.Phi / self.T_h *
         (1 - self.B**0.25 * fn.sqrt(self.E_v_n)))
示例#19
0
 def sqrt(self, f):
     return FEN.sqrt(f)
示例#20
0
文件: mfem.py 项目: tianjuxue/crack
def distance_function_point_ufl(P, A=[0, 0]):
    x = P[0] - A[0]
    y = P[1] - A[1]
    return fe.sqrt(x * x + y * y)
示例#21
0
    prm['newton_solver']['preconditioner'] = 'ilu'

# Invoke the solver
#cprint("\nSOLUTION OF THE NONLINEAR PROBLEM", 'blue', attrs=['bold'])
#cprint("The solution of the nonlinear system is in progress...", 'red')
solver.solve()

############################# POST-PROCESSING ################################
#cprint("\nSOLUTION POST-PROCESSING", 'blue', attrs=['bold'])
# Save solution to file in VTK format
#cprint("Saving displacement solution to file...", 'green')
uViewer = fe.File('paraview/displacement.pvd')
uViewer << u

# Maximum and minimum displacement
u_magnitude = fe.sqrt(fe.dot(u, u))
u_magnitude = fe.project(u_magnitude, W)
print('Min/Max displacement:',
      u_magnitude.vector().array().min(),
      u_magnitude.vector().array().max())

# Computation of the large deformation strains
#cprint("Computing the deformation tensor and saving to file...", 'green')
epsilon_u = largeKinematics(u)
epsilon_u_project = fe.project(epsilon_u, Z)
epsilonViewer = fe.File('paraview/strain.pvd')
epsilonViewer << epsilon_u_project

# Computation of the stresses
#cprint("Stress derivation and saving to file...", 'green')
S = fe.diff(psi, E)
示例#22
0
文件: mfem.py 项目: tianjuxue/crack
def map_function_ufl(x_hat,
                     control_points,
                     impact_radii,
                     map_type,
                     boundary_info=None):
    if len(control_points) == 0:
        return x_hat
    x_hat = fe.variable(x_hat)
    df, rho = distance_function_segments_ufl(x_hat, control_points,
                                             impact_radii)
    grad_x_hat = fe.diff(df, x_hat)
    delta_x_hat = fe.conditional(
        fe.gt(df, rho), fe.Constant((0., 0.)),
        grad_x_hat * (rho * ratio_function_ufl(df / rho, map_type) - df))
    if boundary_info is None:
        return delta_x_hat + x_hat
    else:
        last_control_point = control_points[-1]
        points, directions, rho_default = boundary_info
        mid_point, mid_point1, mid_point2 = points
        direct_vec, rotated_vec = directions
        aux_control_point1 = last_control_point + rho_default * rotated_vec
        aux_control_point2 = last_control_point - rho_default * rotated_vec

        w1 = np.linalg.norm(mid_point1 - aux_control_point1)
        w2 = np.linalg.norm(mid_point2 - aux_control_point2)
        w0 = np.linalg.norm(mid_point - last_control_point)

        assert np.absolute(2 * w0 - w1 - w2) < 1e-5

        AB = mid_point - last_control_point
        AP = x_hat - last_control_point

        x1 = AB[0]
        y1 = AB[1]
        x2 = AP[0]
        y2 = AP[1]

        mod = fe.sqrt(x1**2 + y1**2)
        df_to_direct = (x1 * y2 - y1 * x2) / mod  # AB x AP
        df_to_rotated = (x1 * x2 + y1 * y2) / mod

        k1 = rho_default * (w1 + w2) / (rho_default *
                                        (w1 + w2) + df_to_direct * (w1 - w2))

        new_df_to_direct = rho_default * ratio_function_ufl(
            df_to_direct / rho_default, map_type)

        k2 = rho_default * (w1 + w2) / (rho_default *
                                        (w1 + w2) + new_df_to_direct *
                                        (w1 - w2))

        new_df_to_rotated = df_to_rotated * k1 / k2

        x = fe.as_vector(last_control_point + direct_vec * new_df_to_rotated +
                         rotated_vec * new_df_to_direct)

        return fe.conditional(
            fe.gt(df_to_rotated, 0),
            fe.conditional(fe.gt(np.absolute(df_to_direct), rho), x_hat, x),
            delta_x_hat + x_hat)
    def extract_all_info(self, general_inputs, liquid_properties):
        """
        Extract all the important data generated from the electrostatics simulation.
        Args:
            general_inputs: Object containing the SimulationGeneralParameters class.
            liquid_properties: Object obtained from the Liquid_Parameters class, which is located at Liquids.py

        Returns:

        """
        self.potential = self.class_caller.phi
        self.vacuum_electric_field = self.class_caller.E_v  # Vacuum electric field.
        self.normal_component_vacuum = self.class_caller.E_v_n  # Normal component of the electric field @interface
        self.tangential_component = self.class_caller.E_t  # @interface
        self.surface_charge_density = self.class_caller.sigma  # Surface charge density at interface.

        # Get coordinates of the nodes and midpoints.
        r_nodes, z_nodes = general_inputs.get_nodepoints(self.mesh, self.boundaries, self.boundaries_ids['Interface'])
        self.coords_nodes = [r_nodes, z_nodes]
        r_mids, z_mids = general_inputs.get_midpoints(self.boundaries, self.boundaries_ids['Interface'])
        self.coords_mids = [r_mids, z_mids]

        # Split the electric field into radial and axial components.
        self.radial_component_vacuum, self.axial_component_vacuum = \
            PostProcessing.extract_from_function(self.vacuum_electric_field, self.coords_nodes)

        # E_v_n_array = PostProcessing.extract_from_function(Electrostatics.normal_component_vacuum, coords_mids)
        E_t_array = PostProcessing.extract_from_function(self.tangential_component, self.coords_mids)

        # Define an auxiliary term for the computations.
        K = 1 + general_inputs.Lambda * (general_inputs.T_h - 1)

        self.normal_component_liquid = (self.normal_component_vacuum - self.surface_charge_density) / \
                                       liquid_properties.eps_r
        E_l_n_array = PostProcessing.extract_from_function(self.normal_component_liquid, self.coords_mids)

        # Get components of the liquid field.
        self.radial_component_liquid, self.axial_component_liquid = \
            Poisson.get_liquid_electric_field(mesh=self.mesh, subdomain_data=self.boundaries,
                                              boundary_id=self.boundaries_ids['Interface'], normal_liquid=E_l_n_array,
                                              tangential_liquid=E_t_array)
        self.radial_component_liquid.append(self.radial_component_liquid[-1])
        self.axial_component_liquid.append(self.axial_component_liquid[-1])

        # Calculate the non-dimensional evaporated charge and current.
        self.evaporated_charge = (self.surface_charge_density * general_inputs.T_h) / (liquid_properties.eps_r *
                                                                                       general_inputs.Chi) \
                                 * fn.exp(-general_inputs.Phi / general_inputs.T_h * (1 - pow(general_inputs.B, 1 / 4) *
                                                                                      fn.sqrt(
                                                                                          self.normal_component_vacuum))
                                          )
        self.conducted_charge = K * self.normal_component_liquid

        # Calculate the emitted current through the interface.
        self.emitted_current = self.class_caller.get_nd_current(self.evaporated_charge)

        # Compute the normal component of the electric stress at the meniscus (electric pressure).
        self.normal_electric_stress = (self.normal_component_vacuum ** 2 - liquid_properties.eps_r *
                                       self.normal_component_liquid ** 2) + \
                                      (liquid_properties.eps_r - 1) * self.tangential_component ** 2
示例#24
0
K = 1+Lambda*(T_h - 1)

E_l_n = (Electrostatics.E_v_n-Electrostatics.sigma)/LiquidInps.eps_r
E_l_n_array = PostProcessing.extract_from_function(E_l_n, coords_mids)
sigma_arr = PostProcessing.extract_from_function(Electrostatics.sigma, coords_mids)

# Get components of the liquid field.
E_l_r, E_l_z = Poisson.get_liquid_electric_field(mesh=mesh, subdomain_data=boundaries,
                                                 boundary_id=boundaries_ids['Interface'], normal_liquid=E_l_n_array,
                                                 tangential_liquid=E_t_array)
E_l_r.append(E_l_r[-1])
E_l_z.append(E_l_z[-1])

# Calculate the non-dimensional evaporated charge and current.
j_ev = (Electrostatics.sigma*T_h)/(LiquidInps.eps_r*Chi) * fn.exp(-Phi/T_h * (
        1-pow(B, 1/4)*fn.sqrt(Electrostatics.E_v_n)))
j_cond = K*E_l_n

I_h = Electrostatics.get_nd_current(j_ev)

j_ev_arr = PostProcessing.extract_from_function(j_ev, coords_mids)
j_cond_arr = PostProcessing.extract_from_function(j_cond, coords_mids)

# Compute the normal component of the electric stress at the meniscus (electric pressure).
n_taue_n = (Electrostatics.E_v_n**2-LiquidInps.eps_r*E_l_n**2) + (LiquidInps.eps_r-1)*Electrostatics.E_t**2
n_taue_n_arr = PostProcessing.extract_from_function(n_taue_n, coords_mids)

# %% DATA POSTPROCESSING.
# Check charge conservation.
charge_check = abs(j_ev_arr-j_cond_arr)/j_ev_arr
print(f'Maximum relative difference between evaporated and conducted charge is {max(charge_check)}')
示例#25
0
文件: rheology.py 项目: knutsvk/fins
 def differentiated_apparent_viscosity(self, II):
     return self.ty / (pi * II) \
             * (self.eps / (self.eps**2 + II) - atan(sqrt(II) / self.eps) / sqrt(II))
示例#26
0
    #d2 = fe.Expression('1 - x[0]', degree=1)
    #d3 = fe.Expression('1 - x[1]', degree=1)
    d4 = fe.Expression('x[1] - 0', degree=1)

    d = fe.Constant(10)
    #d = Min(d1, d4)

    xi = nu_trial / nu
    fv1 = fe.elem_pow(xi, 3) / (fe.elem_pow(xi, 3) + Cv1 * Cv1 * Cv1)
    #fv2 = fe.Constant(1)
    fv2 = 1 - xi / (1 + xi * fv1)
    #ft2 = fe.Constant(1)
    ft2 = Ct3 * fe.exp(-Ct4 * xi * xi)
    Omega = fe.Constant(0.5) * (fe.grad(u) - fe.grad(u).T)
    #S = fe.Constant(2) * fe.inner(Omega, Omega)
    S = fe.sqrt(fe.Constant(2) * fe.inner(Omega, Omega))
    #Stilde = fe.Constant(1)
    #Stilde = nu_trial /(kappa * kappa * d * d) * fv2
    #Stilde = nu_trial * fe.Constant(1000)
    Stilde = S + nu_trial / (kappa * kappa * d * d) * fv2
    ft2 = Ct3 * fe.exp(fe.Constant(-1) * Ct4 * xi * xi)
    #ft2 = fe.Constant(0)
    #r =fe.Constant(1)
    #r = nu_trial / (Stilde * kappa * kappa * d * d)
    r = Max(Min(nu_trial / (Stilde * kappa * kappa * d * d), fe.Constant(10)),
            -10)
    #r = fe.Constant(0.1)
    #g = fe.Constant(0.01)
    g = r + Cw2 * (r * r * r * r * r * r - r)
    #fw =  g * ((1 + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3) / (g * g * g * g * g * g + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3))
    fw = fe.elem_pow(
示例#27
0
文件: rheology.py 项目: knutsvk/fins
 def apparent_viscosity(self, II):
     return 2 * self.mu + 2 * self.ty / sqrt(II) * (
         1 - exp(-sqrt(II) / self.eps))
示例#28
0
 def expFun():
     sqrterm = E_v_n_aux
     expterm = (self.Phi /
                self.T_h) * (1 - pow(self.B, 0.25) * fn.sqrt(sqrterm))
     return fn.exp(expterm)
示例#29
0
    d1 = fe.Expression('x[0] - 0', degree=1)
    #d2 = fe.Expression('1 - x[0]', degree=1)
    #d3 = fe.Expression('1 - x[1]', degree=1)
    d = fe.Expression('x[1] - 0', degree=1)

    #d = fe.Constant(10)
    #d = Min(d1, d4)

    xi = nu_trial / nu
    fv1 = xi**3 / (xi**3 + Cv1 * Cv1 * Cv1)
    #fv1 = fe.elem_pow(xi, 3) / (fe.elem_pow(xi, 3) + Cv1 * Cv1 * Cv1)
    fv2 = 1 - xi / (1 + xi * fv1)
    ft2 = Ct3 * fe.exp(-Ct4 * xi * xi)
    Omega = fe.Constant(0.5) * (fe.grad(u) - fe.grad(u).T)
    S = fe.sqrt(EPSILON + fe.Constant(2) * fe.inner(Omega, Omega))
    Stilde = S + nu_trial / (kappa * kappa * d * d) * fv2
    ft2 = Ct3 * fe.exp(fe.Constant(-1) * Ct4 * xi * xi)
    r = Min(nu_trial / (Stilde * kappa * kappa * d * d), 10)
    g = r + Cw2 * (r * r * r * r * r * r - r)
    fw = fe.elem_pow(
        EPSILON +
        abs(g * ((1 + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3) /
                 (g * g * g * g * g * g + Cw3 * Cw3 * Cw3 * Cw3 * Cw3 * Cw3))),
        fe.Constant(1. / 6.))

ns_conv = fe.inner(v, fe.grad(u) * u) * fe.dx
ns_press = p * fe.div(v) * fe.dx
s = fe.grad(u) + fe.grad(u).T
if MODEL:
    ns_tv = fe.inner((fv1 * nu_trial) * fe.grad(v), fe.grad(u)) * fe.dx
示例#30
0
文件: rheology.py 项目: knutsvk/fins
 def apparent_viscosity(self, II):
     return 2 * self.mu + 2 * self.ty / (pi * sqrt(II)) * atan(
         sqrt(II) / self.eps)
示例#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