示例#1
0
def compute_gradient(u, mesh):
    """Computes the gradient of the value field at the mesh points"""

    W = fen.VectorFunctionSpace(mesh, 'P', 1)
    gradient = fen.project(fen.grad(u), W)

    return gradient
示例#2
0
def setup_vectorspace(mesh):
    """setup"""
    V = fe.VectorFunctionSpace(mesh, "CG", 1, dim=3)
    v = fe.TestFunction(V)
    u = fe.TrialFunction(V)
    m = fe.Function(V)
    Heff = fe.Function(V)
    return m, Heff, u, v, V
示例#3
0
文件: test.py 项目: ZXK666666/FESTIM
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
示例#4
0
文件: pyfenics.py 项目: xshi/raser
    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)
示例#5
0
def test_fenics_to_numpy_mixed_function():
    # Functions in DG0 have nodes at centers of finite element cells
    mesh = fenics.UnitIntervalMesh(10)
    vec_dim = 4
    V = fenics.VectorFunctionSpace(mesh, "DG", 0, dim=vec_dim)
    test_input = fenics.interpolate(
        fenics.Expression(vec_dim * ("x[0]", ), element=V.ufl_element()), V)
    expected = numpy.linspace(0.05, 0.95, num=10)
    expected = numpy.reshape(numpy.tile(expected, (4, 1)).T, V.dim())
    assert numpy.allclose(fenics_to_numpy(test_input), expected)
示例#6
0
文件: mfem.py 项目: tianjuxue/crack
def mfem():
    files = glob.glob('data/pvd/mfem/*')
    for f in files:
        try:
            os.remove(f)
        except Exception as e:
            print('Failed to delete {}, reason: {}' % (f, e))

    plate = mshr.Rectangle(fe.Point(0, 0), fe.Point(100, 100))
    mesh = mshr.generate_mesh(plate, 50)
    # mesh = fe.RectangleMesh(fe.Point(-2, -2), fe.Point(2, 2), 50, 50)

    x_hat = fe.SpatialCoordinate(mesh)

    U = fe.VectorFunctionSpace(mesh, 'CG', 2)
    V = fe.FunctionSpace(mesh, "CG", 1)
    W = fe.FunctionSpace(mesh, "DG", 0)

    # n = 21
    # control_points = np.stack((np.linspace(0, 1, n), np.linspace(0, 1, n)), axis=1)
    # impact_radii = np.linspace(0., 0.5, n)

    rho_default = 25. / np.sqrt(5) * 2
    control_points = np.array([[50., 50.], [62.5, 25.]])
    impact_radii = np.array([rho_default, rho_default])

    mid_point = np.array([75., 0.])
    mid_point1 = np.array([100., 0.])
    mid_point2 = np.array([50., 0.])
    points = [mid_point, mid_point1, mid_point2]
    direct_vec = np.array([1., -2])
    rotated_vec = np.array([2., 1.])

    direct_vec /= np.linalg.norm(direct_vec)
    rotated_vec /= np.linalg.norm(rotated_vec)

    directions = [direct_vec, rotated_vec]
    boundary_info = [points, directions, rho_default]

    # df, xi = distance_function_segments_ufl(x_hat, control_points, impact_radii)
    # d = fe.project(df, V)

    delta_x = map_function_ufl(x_hat, control_points, impact_radii,
                               boundary_info) - x_hat
    u = fe.project(delta_x, U)

    # e = fe.Function(U)
    # int_exp = InterpolateExpression(u, control_points, impact_radii)
    # e = fe.interpolate(int_exp, U)
    # int_exp = InterpolateExpression(e, control_points, impact_radii)
    # e = fe.project(int_exp, U)

    vtkfile_u = fe.File('data/pvd/mfem/u.pvd')
    u.rename("u", "u")
    vtkfile_u << u
def test_1d_velocity():

    mesh = fenics.UnitIntervalMesh(fenics.dolfin.mpi_comm_world(), 5)

    V = fenics.VectorFunctionSpace(mesh, "P", 1)

    u = fenics.Function(V)

    bc = fenics.DirichletBC(V, [10.0], "x[0] < 0.5")

    print(bc.get_boundary_values())
示例#8
0
def test_1d_velocity_unit__ci__():

    mesh = fenics.UnitIntervalMesh(5)

    V = fenics.VectorFunctionSpace(mesh, "P", 1)

    u = fenics.Function(V)

    bc = fenics.DirichletBC(V, [10.0], "x[0] < 0.5")

    print(bc.get_boundary_values())
示例#9
0
def MeshDefinition(Dimensions, NumberElements, Type='Lagrange', PolynomDegree=1):

    # Mesh
    Mesh = fe.BoxMesh(fe.Point(-Dimensions[0]/2, -Dimensions[1]/2, -Dimensions[2]/2), fe.Point(Dimensions[0]/2, Dimensions[1]/2, Dimensions[2]/2), NumberElements, NumberElements, NumberElements)

    # Functions spaces
    V_ele = fe.VectorElement(Type, Mesh.ufl_cell(), PolynomDegree)
    V = fe.VectorFunctionSpace(Mesh, Type, PolynomDegree)

    # Finite element functions
    du = fe.TrialFunction(V)
    v = fe.TestFunction(V)
    u = fe.Function(V)
    
    return [Mesh, V, u, du, v]
示例#10
0
    def __init__(self,
                 mesh: fe.Mesh,
                 density: fe.Expression,
                 constitutive_model: ConstitutiveModelBase,
                 bf: fe.Expression = fe.Expression('0', degree=0)):

        super().__init__(mesh, density, constitutive_model, bf)

        W = fe.VectorFunctionSpace(mesh, "P", 1)

        # Unknowns, values at previous step and test functions
        self.w = fe.Function(W)
        self.u, self.u0 = self.w, fe.Function(W)
        self.v, self.v0 = fe.Function(W), fe.Function(W)
        self.a, self.a0 = fe.Function(W), fe.Function(W)

        # self.a0 = fe.Function(fe.FunctionSpace(mesh, element_v))

        self.ut = fe.TestFunction(W)

        self.F = kin.def_grad(self.u)
        self.F0 = kin.def_grad(self.u0)
示例#11
0
def postprocess(fname, field, cond):
    """Postprocessing of the simulation."""
    func_space = field.function_space()
    mesh = func_space.mesh()
    degree = func_space.ufl_element().degree()
    vec_func_space = fe.VectorFunctionSpace(mesh, INPUTS['element_type'],
                                            degree)
    flux = fe.project(-cond * fe.grad(field), vec_func_space)
    divergence = fe.project(-fe.div(cond * 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))
    keff = av_flux * (ZMAX - ZMIN) / (INPUTS['boundary_conditions']['top'] -
                                      INPUTS['boundary_conditions']['bottom'])
    print('Effective conductivity: {0}'.format(keff))
    with open(fname + "_keff.csv", 'w') as textfile:
        textfile.write('keff\n')
        textfile.write('{0}\n'.format(keff))
    fe.File(fname + "_solution.pvd") << field
    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
    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()
示例#12
0
    def __init__(self,
                 mesh: fe.Mesh,
                 constitutive_model: ConstitutiveModelBase,
                 density: fe.Expression = fe.Expression('0', degree=0),
                 bf: fe.Expression = fe.Expression('0', degree=0),
                 user_output_fn: callable = None):

        W = fe.VectorFunctionSpace(mesh, "P", 1)
        super().__init__(mesh, constitutive_model, W, bf)
        self._density = density

        self.user_output_fn = user_output_fn

        # Unknowns, values at previous step and test functions
        self.w = fe.Function(W)
        self.u, self.u0 = self.w, fe.Function(W)
        self.v, self.v0 = fe.Function(W), fe.Function(W)
        self.a, self.a0 = fe.Function(W), fe.Function(W)

        # self.a0 = fe.Function(fe.FunctionSpace(mesh, element_v))

        self.ut = fe.TestFunction(W)

        self.F = kin.def_grad(self.u)
        self.F0 = kin.def_grad(self.u0)

        self.output_fn_map = {
            Outputs.stress: self.write_stress,
            Outputs.strain: self.write_strain,
            Outputs.displacement: self.write_u
        }

        self.d_LHS = fe.inner(self.F * constitutive_model.stress(self.u),
                              fe.grad(self.ut)) * fe.dx

        self.d_RHS = (fe.inner(fe.Constant((0., 0., 0.)), self.ut) * fe.dx)
示例#13
0
 def get_function_space(self, mesh: fenics.Mesh) -> fenics.FunctionSpace:
     return fenics.VectorFunctionSpace(mesh, self.element_family,
                                       self.degree)
示例#14
0
"""

import fenics as fs
import numpy as np
import matplotlib.pyplot as plt

# scaled variables
T = 10.0                # final time
num_steps = 500         # number of time steps
dt = T / num_steps      # time step size
mu = 1                  # kinematic viscosity
rho = 1                 # density

# Create mesh and define function spaces SEPARATELY for pressure and velocity spaces. 
mesh = fs.UnitSquareMesh(16, 16)
V = fs.VectorFunctionSpace(mesh, 'P', 2)    # velocity space, a vector space
Q = fs.FunctionSpace(mesh, 'P', 1)          # pressure space, a scalar space

# Define trial and test functions
u = fs.TrialFunction(V)     # in velocity space
v = fs.TestFunction(V)
p = fs.TrialFunction(Q)     # in pressure space
q = fs.TestFunction(Q)

# Define functions for solutions at previous and current time steps
u_n = fs.Function(V)    # u^(n)
u_  = fs.Function(V)    # u^(n+1)
p_n = fs.Function(Q)    # p^(n)
p_  = fs.Function(Q)    # p^(n+1)

# Define boundaries
示例#15
0
    def solve(self):
        """
        Solve the Stokes_sim problem based on the mathematical procedure presented by Ximo in this thesis.
        Returns:

        """

        # --------------------------------------------------------------------
        # DEFINE THE INPUTS #
        # --------------------------------------------------------------------
        self.get_mesh()
        self.get_boundaries()
        self.get_subdomains()
        self.get_restrictions()

        # Create a block of restrictions.
        """ This variable will be used by multiphenics when creating function spaces. It will create function spaces
        on the introduced restrictions. 
        """
        block_restrictions = [
            self.restrictions_dict['liquid_rtc'],
            self.restrictions_dict['liquid_rtc'],
            self.restrictions_dict['interface_rtc']
        ]

        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # FUNCTION SPACES #
        # --------------------------------------------------------------------
        V = fn.VectorFunctionSpace(self.mesh, "CG", 2)
        Q = fn.FunctionSpace(self.mesh, "CG", 1)
        L = fn.FunctionSpace(self.mesh, "DGT", 0)  # DGT 0.

        # Create a 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, Q, L] 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 -> liquid_rtc
            - Q -> liquid_rtc
            - L -> interface_rtc
        """
        W = mp.BlockFunctionSpace([V, Q, L], restrict=block_restrictions)
        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # TRIAL/TEST FUNCTIONS #
        # --------------------------------------------------------------------
        """ Trial and test functions are created the multiphenics commands for creating these functions. However, the
        difference wrt the FEniCS functions for this purpose, a trial/test function will be created for each of the
        restrictions (for each function space of the BlockFunctionSpace).
        """
        test = mp.BlockTestFunction(W)
        (v, q, l) = mp.block_split(test)

        trial = mp.BlockTrialFunction(W)
        (u, p, theta) = mp.block_split(trial)

        # Use a value of previous velocity to make the system linear, as explained by Ximo.
        u_prev = fn.Function(V)
        u_prev.assign(fn.Constant((0.1, 0.1)))

        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # 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."

        # --------------------------------------------------------------------
        # DEFINE THE VARIATIONAL PROBLEM #
        # --------------------------------------------------------------------
        r = fn.SpatialCoordinate(self.mesh)[0]
        n = fn.FacetNormal(self.mesh)
        tan_vector = fn.as_vector((n[1], -n[0]))
        e_r = fn.Constant((1., 0.))  # Define unit radial vector
        e_z = fn.Constant((0., 1.))  # Define unit axial vector
        aux_term = (self.eps_r * self.Ca *
                    np.sqrt(self.B)) / (1 + self.Lambda * (self.T_h - 1))

        # Define the term a.
        a = r * aux_term * fn.inner((fn.grad(u) + fn.grad(u).T),
                                    (fn.grad(v) + fn.grad(v).T)) * self.dx(
                                        self.subdomains_ids['Liquid'])
        a += 2 / r * aux_term * fn.dot(u, e_r) * fn.dot(v, e_r) * self.dx(
            self.subdomains_ids['Liquid'])

        # Define the term d.
        del_operation = fn.dot(fn.grad(u), u_prev)
        d = r * self.eps_r**2 * self.We * fn.dot(del_operation, v) * self.dx(
            self.subdomains_ids['Liquid'])

        # Define the term l1.
        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)))

        l1 = -r * evaporated_charge() * l("+") * self.dS

        # Define the term l2.
        l2 = r * self.sigma * fn.dot(self.E_v, tan_vector("-")) * fn.dot(
            v("+"), tan_vector("-")) * self.dS

        # Define the term b.
        def b(vector, scalar):
            radial_term = r * fn.dot(vector, e_r)
            axial_term = r * fn.dot(vector, e_z)
            return -(radial_term.dx(0) + axial_term.dx(1)) * scalar * self.dx(
                self.subdomains_ids['Liquid'])

        # Define the term c.
        c1 = -r * fn.dot(v("+"), n("-")) * theta("+") * self.dS
        c2 = -r * fn.dot(u("+"), n("-")) * l("+") * self.dS

        # Define the tensors to be solved.
        # The following order is used.
        #       u            p           theta       #
        aa = [
            [a + d, b(v, p), c1],  # Test function v
            [b(u, q), 0, 0],  # Test function q
            [c2, 0, 0]
        ]  # Test function l

        bb = [l2, fn.Constant(0.) * q("+") * self.dS, l1]

        # --------------------------------------------------------------------
        # DEFINE THE BOUNDARY CONDITIONS #
        # --------------------------------------------------------------------
        """ When creating Dirichlet boundary conditions with the multiphenics code, a function space from the Block
        must be selected, depending on which subdomain/boundary should it be applied. To do so, the .sub method is used.
        The input is an integer, which depends on the function space in which you want the BC to be applied. For this
        case, inputs of 0, 1 and 2 are accepted, because we have 3 restrictions. The assignments of these ids to the 
        function space is the one done in the block of restrictions.
        """
        bcs_u = []
        bcs_p = []
        for i in self.boundary_conditions:
            if 'Dirichlet' in self.boundary_conditions[i]:
                bc_val = self.boundary_conditions[i]['Dirichlet'][1]
                if self.boundary_conditions[i]['Dirichlet'][0] == 'v':
                    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_u.append(bc)
                elif self.boundary_conditions[i]['Dirichlet'][0] == 'p':
                    bc = mp.DirichletBC(W.sub(1), 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_p.append(bc)

        bcs_block = mp.BlockDirichletBC([bcs_u, bcs_p])

        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # SOLVE #
        # --------------------------------------------------------------------
        # Assemble the system.
        AA = mp.block_assemble(aa)
        BB = mp.block_assemble(bb)

        # Apply the boundary conditions.
        bcs_block.apply(AA)
        bcs_block.apply(BB)

        # Solve.
        uptheta = mp.BlockFunction(W)
        mp.block_solve(AA, uptheta.block_vector(), BB)
        (u, p, theta) = uptheta.block_split()

        self.u = u
        self.p_star = p
        self.theta = theta

        # Compute normal and tangential velocity components.
        u_n = fn.dot(u, n)
        self.u_n = Stokes.block_project(
            u_n,
            self.mesh,
            self.restrictions_dict['interface_rtc'],
            self.boundaries,
            self.boundaries_ids['Interface'],
            space_type='scalar',
            boundary_type='internal',
            sign='-')

        u_t = fn.dot(u, tan_vector)
        self.u_t = Stokes.block_project(
            u_t,
            self.mesh,
            self.restrictions_dict['interface_rtc'],
            self.boundaries,
            self.boundaries_ids['Interface'],
            space_type='scalar',
            boundary_type='internal',
            sign='+')

        # Compute the convection charge transport.
        special = (fn.Identity(self.mesh.topology().dim()) -
                   fn.outer(n, n)) * fn.grad(self.sigma)
        self.j_conv = self.Kc * self.B**(
            3 / 2) * (fn.dot(self.sigma * n, fn.dot(fn.grad(self.u), n)) -
                      fn.dot(self.u, special))
        self.j_conv = Stokes.block_project(
            self.j_conv,
            self.mesh,
            self.restrictions_dict['interface_rtc'],
            self.boundaries,
            self.boundaries_ids['Interface'],
            space_type='scalar',
            boundary_type='internal',
            sign='-')
示例#16
0
    def __init__(self,
                 lagrangian,
                 bcs_list,
                 states,
                 adjoints,
                 boundaries,
                 config,
                 ksp_options,
                 adjoint_ksp_options,
                 shape_scalar_product=None,
                 deformation_space=None):
        """Initializes the ShapeFormHandler object.

		Parameters
		----------
		lagrangian : cashocs._forms.Lagrangian
			The Lagrangian corresponding to the shape optimization problem
		bcs_list : list[list[dolfin.fem.dirichletbc.DirichletBC]]
			list of boundary conditions for the state variables
		states : list[dolfin.function.function.Function]
			list of state variables
		adjoints : list[dolfin.function.function.Function]
			list of adjoint variables
		boundaries : dolfin.cpp.mesh.MeshFunctionSizet
			a MeshFunction for the boundary markers
		config : configparser.ConfigParser
			the configparser object storing the problems config
		ksp_options : list[list[list[str]]]
			The list of command line options for the KSP for the
			state systems.
		adjoint_ksp_options : list[list[list[str]]]
			The list of command line options for the KSP for the
			adjoint systems.
		shape_scalar_product : ufl.form.Form
			The weak form of the scalar product used to determine the
			shape gradient.
		"""

        FormHandler.__init__(self, lagrangian, bcs_list, states, adjoints,
                             config, ksp_options, adjoint_ksp_options)

        self.boundaries = boundaries
        self.shape_scalar_product = shape_scalar_product

        self.degree_estimation = self.config.getboolean('ShapeGradient',
                                                        'degree_estimation',
                                                        fallback=False)
        self.use_pull_back = self.config.getboolean('ShapeGradient',
                                                    'use_pull_back',
                                                    fallback=True)

        if deformation_space is None:
            self.deformation_space = fenics.VectorFunctionSpace(
                self.mesh, 'CG', 1)
        else:
            self.deformation_space = deformation_space

        self.test_vector_field = fenics.TestFunction(self.deformation_space)

        self.regularization = Regularization(self)

        # Calculate the necessary UFL forms
        self.inhomogeneous_mu = False
        self.__compute_shape_derivative()
        self.__compute_shape_gradient_forms()
        self.__setup_mu_computation()

        if self.degree_estimation:
            self.estimated_degree = np.maximum(
                estimate_total_polynomial_degree(self.riesz_scalar_product),
                estimate_total_polynomial_degree(self.shape_derivative))
            self.assembler = fenics.SystemAssembler(self.riesz_scalar_product,
                                                    self.shape_derivative,
                                                    self.bcs_shape,
                                                    form_compiler_parameters={
                                                        'quadrature_degree':
                                                        self.estimated_degree
                                                    })
        else:
            try:
                self.assembler = fenics.SystemAssembler(
                    self.riesz_scalar_product, self.shape_derivative,
                    self.bcs_shape)
            except (AssertionError, ValueError):
                self.estimated_degree = np.maximum(
                    estimate_total_polynomial_degree(
                        self.riesz_scalar_product),
                    estimate_total_polynomial_degree(self.shape_derivative))
                self.assembler = fenics.SystemAssembler(
                    self.riesz_scalar_product,
                    self.shape_derivative,
                    self.bcs_shape,
                    form_compiler_parameters={
                        'quadrature_degree': self.estimated_degree
                    })

        self.assembler.keep_diagonal = True
        self.fe_scalar_product_matrix = fenics.PETScMatrix()
        self.fe_shape_derivative_vector = fenics.PETScVector()

        self.update_scalar_product()

        # test for symmetry
        if not self.scalar_product_matrix.isSymmetric():
            if not self.scalar_product_matrix.isSymmetric(1e-15):
                if not (self.scalar_product_matrix -
                        self.scalar_product_matrix.copy().transpose()
                        ).norm() / self.scalar_product_matrix.norm() < 1e-15:
                    raise InputError(
                        'cashocs._forms.ShapeFormHandler',
                        'shape_scalar_product',
                        'Supplied scalar product form is not symmetric.')

        if self.opt_algo == 'newton' \
          or (self.opt_algo == 'pdas' and self.inner_pdas == 'newton'):
            raise NotImplementedError(
                'Second order methods are not implemented for shape optimization yet'
            )
示例#17
0
def navierStokes(projectId, mesh, faceSets, boundarySets, config):

    log("Navier Stokes Analysis has started")

    # this is the default directory, when user request for download all files in this directory is being compressed and sent to the user
    resultDir = "./Results/"

    if len(config["steps"]) > 1:
        return "more than 1 step is not supported yet"

    # config is a dictionary containing all the user inputs for solver configurations
    t_init = 0.0
    t_final = float(config['steps'][0]["finalTime"])
    t_num = int(config['steps'][0]["iterationNo"])
    dt = ((t_final - t_init) / t_num)
    t = t_init

    #
    #  Viscosity coefficient.
    #
    nu = float(config['materials'][0]["viscosity"])
    rho = float(config['materials'][0]["density"])

    #
    #  Declare Finite Element Spaces
    # do not use triangle directly
    P2 = fn.VectorElement("P", mesh.ufl_cell(), 2)
    P1 = fn.FiniteElement("P", mesh.ufl_cell(), 1)
    TH = fn.MixedElement([P2, P1])
    V = fn.VectorFunctionSpace(mesh, "P", 2)
    Q = fn.FunctionSpace(mesh, "P", 1)
    W = fn.FunctionSpace(mesh, TH)

    #
    #  Declare Finite Element Functions
    #
    (u, p) = fn.TrialFunctions(W)
    (v, q) = fn.TestFunctions(W)
    w = fn.Function(W)
    u0 = fn.Function(V)
    p0 = fn.Function(Q)

    #
    # Macros needed for weak formulation.
    #
    def contract(u, v):
        return fn.inner(fn.nabla_grad(u), fn.nabla_grad(v))

    def b(u, v, w):
        return 0.5 * (fn.inner(fn.dot(u, fn.nabla_grad(v)), w) -
                      fn.inner(fn.dot(u, fn.nabla_grad(w)), v))

    # Define boundaries
    bcs = []
    for BC in config['BCs']:
        if BC["boundaryType"] == "wall":
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(0),
                                   fn.Constant((0.0, 0.0, 0.0)),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))
        if BC["boundaryType"] == "inlet":
            vel = json.loads(BC['value'])
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(0),
                                   fn.Expression(
                                       (str(vel[0]), str(vel[1]), str(vel[2])),
                                       degree=2),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))
        if BC["boundaryType"] == "outlet":
            for edge in json.loads(BC["edges"]):
                bcs.append(
                    fn.DirichletBC(W.sub(1),
                                   fn.Constant(float(BC['value'])),
                                   boundarySets,
                                   int(edge),
                                   method='topological'))

    f = fn.Constant((0.0, 0.0, 0.0))

    #  weak form NSE
    NSE = (1.0/dt)*fn.inner(u, v)*fn.dx + b(u0, u, v)*fn.dx + nu * \
        contract(u, v)*fn.dx - fn.div(v)*p*fn.dx + q*fn.div(u)*fn.dx
    LNSE = fn.inner(f, v) * fn.dx + (1. / dt) * fn.inner(u0, v) * fn.dx

    velocity_file = fn.XDMFFile(resultDir + "/vel.xdmf")
    pressure_file = fn.XDMFFile(resultDir + "/pressure.xdmf")
    velocity_file.parameters["flush_output"] = True
    velocity_file.parameters["functions_share_mesh"] = True
    pressure_file.parameters["flush_output"] = True
    pressure_file.parameters["functions_share_mesh"] = True
    #
    # code for projecting a boundary condition into a file for visualization
    #
    # for bc in bcs:
    #     bc.apply(w.vector())
    # fn.File("para_plotting/bc.pvd") << w.sub(0)

    for jj in range(0, t_num):
        t = t + dt
        # print('t = ' + str(t))
        A, b = fn.assemble_system(NSE, LNSE, bcs)
        fn.solve(A, w.vector(), b)
        # fn.solve(NSE==LNSE,w,bcs)
        fn.assign(u0, w.sub(0))
        fn.assign(p0, w.sub(1))
        # Save Solutions to Paraview File
        if (jj % 20 == 0):
            velocity_file.write(u0, t)
            pressure_file.write(p0, t)
            sendFile(projectId, resultDir + "vel.xdmf")
            sendFile(projectId, resultDir + "vel.h5")
            sendFile(projectId, resultDir + "pressure.xdmf")
            sendFile(projectId, resultDir + "pressure.h5")
            statusUpdate(projectId, "STARTED", {"progress": jj / t_num * 100})
示例#18
0
def fwi_si(gt_data, i_guess, n_receivers, noise_lv, path):
    """
    This is the main function of the project.
    Entries 
        gt_data: string path to the ground truth image data
        i_guess: integer pointing the algorithm initialization guess
        n_shots: integer, number of strikes for the FWI
        n_receivers: integer, number of receivers for the FWI
        noise_lv: float type variable that we use to compute noise level
        path: string type variable, path to local results directory
    """

    # Implementing parallel processing at shots level """
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    n_shots = comm.Get_size()

    seism_vel = [4.12, 1.95]
    image_phi = mpimg.imread(gt_data)
    chi0 = np.int64(image_phi == 0)
    chi1 = 1.0 - chi0
    synth_model = seism_vel[0] * chi1 + seism_vel[1] * chi0
    #scale in meter
    xMin = 0.0
    xMax = 1.0
    zMin = 0.0
    zMax = 0.650
    #scale in seconds
    tMin = 0.0
    tMax = 1.0

    # Damping layer width and damping limits
    damp_layer = 0.1 * xMax
    dmp_xMin = xMin + damp_layer
    dmp_xMax = xMax - damp_layer
    dmp_zMax = zMax - damp_layer

    #    Number of grid points are determined by the loaded image size
    #    Nz, Nx are (#) of grid point
    Nz, Nx = synth_model.shape
    delta_x = xMax / Nx
    delta_z = zMax / Nz
    CFL = 0.4
    delta_t = (CFL * min(delta_x, delta_z)) / max(seism_vel)
    gc_t = np.arange(tMin, tMax, delta_t)
    Nt = len(gc_t)

    # Level set parameters
    MainItMax = 5000
    gamma = 0.8
    gamma2 = 0.8
    stop_coeff = 1.0e-8
    add_weight = True
    ls_max = 3
    ls = 0
    beta0_init = 1.5  # 1.2 #0.8 #0.5 #0.3
    beta0 = beta0_init
    beta = beta0
    stop_decision_limit = 150
    stop_decision = 0
    alpha1 = 0.01
    alpha2 = 0.97

    # wave Parameters
    PlotFields = True
    add_noise = False if noise_lv == 0 else True
    src_Zpos = 5.0
    source_peak_frequency = 5.0  # (kilo hertz)

    # Grid coordinates
    gc_x = np.arange(xMin, xMax, delta_x)
    gc_z = np.arange(zMin, zMax, delta_z)

    # Compute receivers
    id_dmp_xMin = np.where(gc_x == dmp_xMin)[0][0]
    id_dmp_xMax = np.where(gc_x == dmp_xMax)[0][0]
    id_dmp_zMax = np.where(gc_z == dmp_zMax)[0][0]
    rec_index = np.linspace(id_dmp_xMin,
                            id_dmp_xMax,
                            n_receivers + 1,
                            dtype='int')
    try:
        assert (len(rec_index) < id_dmp_xMax - id_dmp_xMin)
    except AssertionError:
        "receivers in different positions"

    # Build the HUGE parameter dictionary
    parameters = {
        "gamma": gamma,
        "gamma2": gamma2,
        "ls_max": ls_max,
        "stop_coeff": stop_coeff,
        "add_noise": add_noise,
        "add_weight": add_weight,
        "beta0_init": beta0_init,
        "stop_decision_limit": stop_decision_limit,
        "alpha1": alpha1,
        "alpha2": alpha2,
        "CFL": CFL,
        "source_peak_frequency": source_peak_frequency,
        "src_Zpos": src_Zpos,
        "i_guess": i_guess,
        "n_shots": n_shots,
        "n_receivers": n_receivers,
        "add_weight": add_weight,
        "nz": Nz,
        "nx": Nx,
        "nt": Nt,
        "gc_t": gc_t,
        "gc_x": gc_x,
        "gc_z": gc_z,
        "xMin": xMin,
        "xMax": xMax,
        "zMin": zMin,
        "zMax": zMax,
        "tMin": tMin,
        "tMax": tMax,
        "hz": delta_z,
        "hx": delta_x,
        "ht": delta_t,
        "dmp_xMin": dmp_xMin,
        "dmp_xMax": dmp_xMax,
        "dmp_zMax": dmp_zMax,
        "dmp_layer": damp_layer,
        "id_dmp_xMin": id_dmp_xMin,
        "id_dmp_xMax": id_dmp_xMax,
        "id_dmp_zMax": id_dmp_zMax,
        "rec": gc_x[rec_index],
        "rec_index": rec_index,
        'noise_lv': noise_lv,
        "path": path,
        "path_misfit": path + 'misfit/',
        "path_phi": path + 'phi/'
    }

    # Compute initial guess matrix
    if rank == 0:
        outputs_and_paths(parameters)
        gnu_data(image_phi, 'ground_truth.dat', parameters)
        mkDirectory(parameters["path_phi"])

    comm.Barrier()
    phi_mat = initial_guess(parameters)
    ind = inside_shape(phi_mat)
    ind_c = np.ones_like(phi_mat) - ind
    vel_field = seism_vel[0] * ind + seism_vel[1] * ind_c

    # Initialization of Fenics-Dolfin functions
    # ----------------------------------------
    # Define mesh for the entire domain Omega
    # ----------------------------------------
    mesh = fc.RectangleMesh(comm, fc.Point(xMin, zMin), fc.Point(xMax, zMax),
                            Nx - 1, Nz - 1)
    # ----------------------------------------
    # Function spaces
    # ----------------------------------------
    V = fc.FunctionSpace(mesh, "Lagrange", 1)
    VF = fc.VectorFunctionSpace(mesh, "Lagrange", 1)
    theta = fc.TrialFunction(VF)
    csi = fc.TestFunction(VF)

    # ----------------------------------------
    # Define boundaries of the domain
    # ----------------------------------------
    tol = fc.DOLFIN_EPS  # tolerance for coordinate comparisons

    class Left(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[0] - xMin) < tol

    class Right(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[0] - xMax) < tol

    class Bottom(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[1] - zMin) < tol

    class Top(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[1] - zMax) < tol

    # --------------------------------------
    # Initialize sub-domain instances
    # --------------------------------------
    left = Left()
    top = Top()
    right = Right()
    bottom = Bottom()
    # ----------------------------------------------
    # Initialize mesh function for boundary domains
    # ----------------------------------------------
    boundaries = fc.MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    domains = fc.MeshFunction("size_t", mesh, mesh.topology().dim())
    left.mark(boundaries, 3)
    top.mark(boundaries, 4)
    right.mark(boundaries, 5)
    bottom.mark(boundaries, 6)
    # ---------------------------------------
    # Define operator for speed vector theta
    # ---------------------------------------
    dtotal = Measure("dx")
    dircond = 1
    # ---------------------------------------
    # setting shape derivative weights
    # re-balancing sensibility to be greater at the bottom
    # ---------------------------------------
    wei_equation = '1.0e8*(pow(x[0] - 0.5, 16) + pow(x[1] - 0.325, 10))+100'
    wei = fc.Expression(str(wei_equation), degree=1)

    # Building the left hand side of the bi-linear system
    # to obtain the descendant direction from shape derivative
    if dircond < 4:
        bcF = [
            fc.DirichletBC(VF, (0, 0), boundaries, 3),
            fc.DirichletBC(VF, (0, 0), boundaries, 4),
            fc.DirichletBC(VF, (0, 0), boundaries, 5),
            fc.DirichletBC(VF, (0, 0), boundaries, 6)
        ]
    if dircond == 1:
        lhs = wei * alpha1 * inner(grad(theta), grad(csi)) * dtotal \
          + wei * alpha2 * inner(theta, csi) * dtotal
    #
    elif dircond == 2:
        lhs = alpha1 * inner(grad(theta), grad(csi)) * \
            dtotal + alpha2 * inner(theta, csi) * dtotal
    elif dircond == 3:
        lhs = inner(grad(theta), grad(csi)) * dtotal
    elif dircond == 5:
        lhs = inner(grad(theta), grad(csi)) * \
            dtotal + inner(theta, csi) * dtotal

    aV = fc.assemble(lhs)
    #
    if dircond < 4:
        for bc in bcF:
            bc.apply(aV)
    #
    # solver_V = fc.LUSolver(aV, "mumps")
    solver_V = fc.LUSolver(aV)
    # ------------------------------
    # Initialize Level set function
    # ------------------------------
    phi = fc.Function(V)
    phivec = phi.vector()
    phivalues = phivec.get_local()  # empty values
    my_first, my_last = V.dofmap().ownership_range()

    tabcoord = V.tabulate_dof_coordinates().reshape((-1, 2))

    unowned = V.dofmap().local_to_global_unowned()
    dofs = list(
        filter(
            lambda dof: V.dofmap().local_to_global_index(dof) not in unowned,
            [i for i in range(my_last - my_first)]))

    tabcoord = tabcoord[dofs]
    phivalues[:] = phi_mat.reshape(Nz * Nx)[dofs]  # assign values
    phivec.set_local(phivalues)
    phivec.apply('insert')

    cont = 0
    boundaries = fc.MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    domains = fc.MeshFunction("size_t", mesh, mesh.topology().dim())
    # -----------------------------
    # Define measures
    # -----------------------------
    dx = Measure('dx')(subdomain_data=domains)

    # -------------------------------
    # Define function Omega1
    # -------------------------------

    class Omega1(fc.SubDomain):
        def __init__(self) -> None:
            super(Omega1, self).__init__()

        def inside(self, x, on_boundary):
            return True if phi(x) <= 0 and x[0] >= xMin and x[0] <= xMax and x[
                1] >= zMin and x[1] <= zMax else False

    # instantiate variables
    eta = dmp(parameters)

    source = Source(parameters)
    FT = source.inject()

    phi_mat_old = np.zeros_like(phi_mat)
    vel_field_new = np.zeros_like(vel_field)
    theta1_mat = np.zeros((Nz * Nx))
    theta2_mat = np.zeros_like(theta1_mat)
    MainItEff = 0
    MainIt = 0
    stop_decision = 0
    st_mem_usage = 0.0
    adj_mem_usage = 0.0
    Jevaltotal = np.zeros((MainItMax))
    norm_theta = np.zeros((MainItMax))

    # path to recording phi function
    # path to recording misfit function
    if rank == 0:
        plot_mat(parameters, 'Damping', 'Damping function', eta)
        mkDirectory(parameters["path_phi"])
        mkDirectory(parameters["path_misfit"])

    comm.Barrier()
    # -------------------------------
    # Seismograms
    # -------------------------------
    wavesolver = WaveSolver(parameters, eta)
    start = time.time()
    d_send = np.empty((Nz, Nx, Nt), np.dtype('float'))
    d = wavesolver.measurements(d_send[0:Nz, 0:Nx, 0:Nt], synth_model,
                                FT[rank, 0:Nz, 0:Nx, 0:Nt], add_noise)
    seismograms = d[0, rec_index, 0:Nt].copy(order='C')
    end = time.time()

    # Plot Seismograms
    if PlotFields:
        print("{:.1f}s to build synthetic seismograms".format(end - start))
        plotMeasurements(parameters, seismograms, rank)
        if rank == 0:
            plot_displacement_field(parameters, d)

    sys.stdout.flush()
    del (d, d_send)
    ###################################################
    # Main Loop
    ###################################################
    gradshape = ShapeDerivative(parameters, csi, V, dtotal, seism_vel)
    while MainIt < MainItMax:
        # ----------------------------------------------
        # Initialize mesh function for boundary domains
        # ----------------------------------------------
        if MainIt > 0:
            vel_field = vel_field_new

        domains.set_all(0)
        omega1 = Omega1()
        omega1.mark(domains, 1)
        dx = Measure('dx')(subdomain_data=domains)

        u = np.empty((Nz, Nx, Nt), np.dtype('float'))
        P = np.empty((Nz, Nx, Nt), np.dtype('float'))

        if MainIt > 0:
            vel_field = vel_field_new
        # ------------------------------------
        # Compute STATE. u stands for displacement field
        # ------------------------------------
        start = time.time()
        u[0:Nz, 0:Nx, 0:Nt] = wavesolver.state(u[0:Nz, 0:Nx, 0:Nt], vel_field,
                                               FT[rank, 0:Nz, 0:Nx, 0:Nt])
        end = time.time()
        # ------------------------------------
        # Compute ADJOINT. P stands for the adjoint variable
        # ------------------------------------
        start1 = time.time()
        tr_u = u[0, rec_index, 0:Nt].copy(order='C')
        misfit = tr_u - seismograms
        P[0:Nz, 0:Nx, 0:Nt] = wavesolver.adjoint(P[0:Nz, 0:Nx, 0:Nt],
                                                 vel_field, misfit)
        end1 = time.time()
        comm.Barrier()
        print(
            '{:.1f}s to compute state and {:.1f}s to compute adjoint with {:d} shots. '
            .format(end - start, end1 - start1, n_shots))

        del (start, end, start1, end1)

        # Plot state/adjoint in 1st-iteration only
        if MainIt == 0 and PlotFields:
            if rank == 0:
                mkDirectory(path + 'initial_state_%03d/' % (n_shots))
                plotadjoint(parameters, P[0:Nz, 0:Nx, 0:Nt])
            folder_name = 'initial_state_%03d/' % (n_shots)
            plotstate(parameters, u[0:Nz, 0:Nx, 0:Nt], folder_name, rank)
            # plot_displacement_field(parameters, u[1, 0:Nz, 0:Nx, 0:Nt])
            st_mem_usage = (u.size * u.itemsize) / 1_073_741_824  # 1GB
            adj_mem_usage = (P.size * P.itemsize) / 1_073_741_824  # 1GB

        # Plotting reconstructions
        if rank == 0 and (MainItEff % 10 == 0
                          or stop_decision == stop_decision_limit - 1):
            plottype1(parameters, synth_model, phi_mat, cont)
            plottype2(parameters, synth_model, phi_mat, cont)
            plottype3(parameters, synth_model, phi_mat, MainIt, cont)
            plotcostfunction(parameters, Jevaltotal, MainItEff)
            plotnormtheta(parameters, norm_theta, MainItEff)
            np.save(path + 'last_phi_mat.npy', phi_mat)
            gnu_data(phi_mat, 'reconstruction.dat', parameters)

        plot_misfit(parameters, 'misfit', 'Misfit', misfit,
                    rank) if (MainItEff % 50 == 0 and PlotFields) else None

        # -------------------------
        # Compute Cost Function
        # -------------------------
        J_omega = np.zeros((1))
        l2_residual = np.sum(np.power(misfit, 2), axis=0)

        if MainIt == 0 and add_weight:
            weights = 1.0e-5

        comm.Reduce(simpson_rule(l2_residual[0:Nt], gc_t), J_omega, op=MPI.SUM)
        Jevaltotal[MainItEff] = 0.5 * (J_omega / weights)
        del (J_omega)
        # -------------------------
        # Evaluate shape derivative
        # -------------------------
        start = time.time()
        shapeder = (1.0 / weights) * gradshape.compute(u[0:Nz, 0:Nx, 0:Nt],
                                                       P[0:Nz, 0:Nx, 0:Nt], dx)
        # Build the rhs of bi-linear system
        shapeder = fc.assemble(shapeder)
        end = time.time()
        print('{}s to compute shape derivative.'.format(end - start))
        del (start, end)
        del (u, P)

        with open(path + "cost_function.txt", "a") as file_costfunction:
            file_costfunction.write('{:d} - {:.4e} \n'.format(
                MainItEff, Jevaltotal[MainItEff]))
        # ====================================
        # ---------- Line search -------------
        # ====================================
        if MainIt > 0 and Jevaltotal[MainItEff] > Jevaltotal[
                MainItEff - 1] and ls < ls_max:
            ls = ls + 1
            beta = beta * gamma
            phi_mat = phi_mat_old
            # ------------------------------------------------------------
            # Update level set function using the descent direction theta
            # ------------------------------------------------------------
            hj_input = [
                theta1_mat, theta2_mat, phi_mat, parameters, beta, MainItEff
            ]
            phi_mat = hamiltonjacobi(*hj_input)
            del (hj_input)
            ind = inside_shape(phi_mat)
            ind_c = np.ones_like(phi_mat) - ind
            vel_field_new = seism_vel[0] * ind + seism_vel[1] * ind_c

            phivec = phi.vector()
            phivalues = phivec.get_local()  # empty values
            my_first, my_last = V.dofmap().ownership_range()

            tabcoord = V.tabulate_dof_coordinates().reshape((-1, 2))
            set_trace()
            unowned = V.dofmap().local_to_global_unowned()
            dofs = list(
                filter(
                    lambda dof: V.dofmap().local_to_global_index(dof) not in
                    unowned, [i for i in range(my_last - my_first)]))

            tabcoord = tabcoord[dofs]
            phivalues[:] = phi_mat.reshape(Nz * Nx)[dofs]  # assign values
            phivec.set_local(phivalues)
            phivec.apply('insert')

        else:
            print("----------------------------------------------")
            print("Record in: {}".format(path))
            print("----------------------------------------------")
            print("ITERATION NUMBER (MainItEff)  : {:d}".format(MainItEff))
            print("ITERATION NUMBER (MainIt)  : {:d}".format(MainIt))
            print("----------------------------------------------")
            print("Grid Size                : {:d} x {:d}".format(Nx, Nz))
            print("State memory usage       : {:.4f} GB".format(st_mem_usage))
            print("Adjoint memory usage     : {:.4f} GB".format(adj_mem_usage))
            print("----------------------------------------------")
            print("Line search  iterations  : {:d}".format(ls))
            print("Step length beta         : {:.4e}".format(beta))
            if ls == ls_max:
                beta0 = max(beta0 * gamma2, 0.1 * beta0_init)
            if ls == 0:
                beta0 = min(beta0 / gamma2, 1.0)
            ls = 0
            MainItEff = MainItEff + 1
            beta = beta0  # /(0.999**MainIt)

            theta = fc.Function(VF)
            solver_V.solve(theta.vector(), -1.0 * shapeder)

            # ------------------------------------
            # Compute norm theta and grad(phi)
            # ------------------------------------
            mpi_comm = theta.function_space().mesh().mpi_comm()
            arraytheta = theta.vector().get_local()
            theta_gathered = mpi_comm.gather(arraytheta, root=0)

            # parei aqui !!!!!
            comm.Barrier()
            if rank == 0:
                set_trace()
                theta_vec = theta.vector()[fc.vertex_to_dof_map(VF)]
                theta1_mat = theta_vec[0:len(theta_vec):2].reshape(Nz, Nx)
                theta2_mat = theta_vec[1:len(theta_vec):2].reshape(Nz, Nx)
            norm_theta[MainItEff - 1] = np.sqrt(
                theta1_mat.reshape(Nz * Nx).dot(theta1_mat.reshape(Nx * Nz)) +
                theta2_mat.reshape(Nz * Nx).dot(theta2_mat.reshape(Nx * Nz)))
            max_gnp = np.sqrt(fc.assemble(dot(grad(phi), grad(phi)) * dtotal))
            print("Norm(grad(phi))          : {:.4e}".format(max_gnp))
            print("L2-norm of theta         : {:.4e}".format(
                norm_theta[MainItEff - 1]))
            print("Cost functional          : {:.4e}".format(
                Jevaltotal[MainItEff - 1]))

            # ------------------------------------------------------------
            # Update level set function using the descent direction theta
            # ------------------------------------------------------------
            phi_mat_old = phi_mat

            hj_input = [
                theta1_mat, theta2_mat, phi_mat, parameters, beta,
                MainItEff - 1
            ]

            phi_mat = hamiltonjacobi(*hj_input)

            del (hj_input)
            phi.vector()[:] = phi_mat.reshape(
                (Nz) * (Nx))[fc.dof_to_vertex_map(V)]
            ind = inside_shape(phi_mat)
            ind_c = np.ones_like(phi_mat) - ind
            vel_field_new = seism_vel[0] * ind + seism_vel[1] * ind_c

            # ----------------
            # Computing error
            # ----------------
            error_area = np.abs(chi1 - ind)
            relative_error = np.sum(error_area) / np.sum(chi0)
            print('relative error           : {:.3f}%'.format(100 *
                                                              relative_error))

            with open(path + "error.txt", "a") as text_file:
                text_file.write(f'{MainIt} {np.round(relative_error,3):>3}\n')

            # Plot actual phi function
            if MainIt % 50 == 0:
                plot_mat3D(parameters, 'phi_3D', phi_mat, MainIt)
                plot_countour(parameters, 'phi_contour', phi_mat, MainIt)
                phi_ind = '%03d_' % (MainIt)
                np.save(parameters["path_phi"] + phi_ind + 'phi.npy', phi_mat)

            # --------------------------------
            # Reinitialize level set function
            # --------------------------------
            if np.mod(MainItEff, 10) == 0:
                phi_mat = reinit(Nz, Nx, phi_mat)

            # ====================================
            # -------- Stopping criterion --------
            # ====================================
            if MainItEff > 5:
                stop0 = stop_coeff * (Jevaltotal[1] - Jevaltotal[2])
                stop1 = Jevaltotal[MainItEff - 2] - Jevaltotal[MainItEff - 1]
                if stop1 < stop0:
                    stop_decision = stop_decision + 1
                if stop_decision == stop_decision_limit:
                    MainIt = MainItMax + 1
                print("stop0                    : {:.4e}".format(stop0))
                print("stop1                    : {:.4e}".format(stop1))
            print("Stopping step            : {:d} of {:d}".format(
                stop_decision, stop_decision_limit))
            print("----------------------------------------------\n")
            cont += 1

        MainIt += 1

    return None
示例#19
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)
示例#20
0
文件: test.py 项目: ZXK666666/FESTIM
def test_formulation_2_traps_1_material():
    '''
    Test function formulation() with 2 intrinsic traps
    and 1 material
    '''    
    # Set parameters
    dt = 1
    traps = [{
        "energy": 1,
        "density": 2,
        "materials": [1]
        },
        {
        "energy": 1,
        "density": 2,
        "materials": [1]
        }]
    materials = [{
            "alpha": 1,
            "beta": 2,
            "density": 3,
            "borders": [0, 1],
            "E_diff": 4,
            "D_0": 5,
            "id": 1
            }]
    extrinsic_traps = []

    # Prepare
    mesh = fenics.UnitIntervalMesh(10)
    V = fenics.VectorFunctionSpace(mesh, 'P', 1, len(traps)+1)
    u = fenics.Function(V)
    u_n = fenics.Function(V)
    v = fenics.TestFunction(V)

    solutions = list(fenics.split(u))
    previous_solutions = list(fenics.split(u_n))
    testfunctions = list(fenics.split(v))

    mf = fenics.MeshFunction('size_t', mesh, 1, 1)
    dx = fenics.dx(subdomain_data=mf)
    temp = fenics.Expression("300", degree=0)
    flux_ = fenics.Expression("1", degree=0)

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

    # Transient trap 2
    expected_form += ((solutions[2] - previous_solutions[2]) / dt) * \
        testfunctions[2]*dx
    # Trapping trap 2
    expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \
        solutions[0] * (2 - solutions[2]) * \
        testfunctions[2]*dx(1)
    # Detrapping trap 2
    expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[2] * \
        testfunctions[2]*dx(1)
    # Source detrapping 2 sol
    expected_form += ((solutions[2] - previous_solutions[2]) / dt) * \
        testfunctions[0]*dx

    assert expected_form.equals(F) is True
示例#21
0
文件: pde.py 项目: tianjuxue/crack
    def staggered_solve(self):
        self.U = fe.VectorFunctionSpace(self.mesh, 'CG', 1)
        self.W = fe.FunctionSpace(self.mesh, 'CG', 1)

        self.WW = fe.FunctionSpace(self.mesh, 'DG', 0)
        self.EE = fe.TensorFunctionSpace(self.mesh, 'DG', 0)
        self.MM = fe.VectorFunctionSpace(self.mesh, 'CG', 1)

        self.eta = fe.TestFunction(self.U)
        self.zeta = fe.TestFunction(self.W)
        q = fe.TestFunction(self.WW)

        del_x = fe.TrialFunction(self.U)
        del_d = fe.TrialFunction(self.W)
        p = fe.TrialFunction(self.WW)

        self.x_new = fe.Function(self.U, name="u")
        self.d_new = fe.Function(self.W, name="d")
        self.d_pre = fe.Function(self.W)
        self.x_pre = fe.Function(self.U)

        x_old = fe.Function(self.U)
        d_old = fe.Function(self.W)

        self.H_old = fe.Function(self.WW)

        self.map_plot = fe.Function(self.MM, name="m")
        e = fe.Function(self.EE, name="e")

        self.create_custom_xdmf_files()

        self.file_results = fe.XDMFFile('data/xdmf/{}/u.xdmf'.format(
            self.case_name))
        self.file_results.parameters["functions_share_mesh"] = True

        vtkfile_e = fe.File('data/pvd/simulation/{}/e.pvd'.format(
            self.case_name))
        vtkfile_u = fe.File('data/pvd/simulation/{}/u.pvd'.format(
            self.case_name))
        vtkfile_d = fe.File('data/pvd/simulation/{}/d.pvd'.format(
            self.case_name))

        for i, (disp, rp) in enumerate(
                zip(self.displacements, self.relaxation_parameters)):
            print('\n')
            print(
                '================================================================================='
            )
            print('>> Step {}, disp boundary condition = {} [mm]'.format(
                i, disp))
            print(
                '================================================================================='
            )
            self.i = i
            self.update_weak_form_due_to_Model_C_bug()

            if self.update_weak_form:
                self.set_bcs_staggered()
                print("Update weak form...")
                self.build_weak_form_staggered()

                print("Taking derivatives of weak form...")
                J_u = fe.derivative(self.G_u, self.x_new, del_x)
                J_d = fe.derivative(self.G_d, self.d_new, del_d)
                print("Define nonlinear problems...")
                p_u = fe.NonlinearVariationalProblem(self.G_u, self.x_new,
                                                     self.BC_u, J_u)
                p_d = fe.NonlinearVariationalProblem(self.G_d, self.d_new,
                                                     self.BC_d, J_d)
                print("Define solvers...")
                solver_u = fe.NonlinearVariationalSolver(p_u)
                solver_d = fe.NonlinearVariationalSolver(p_d)
                self.update_weak_form = False

                print("Update history weak form")
                a = p * q * fe.dx
                L = history(self.H_old, self.update_history(),
                            self.psi_cr) * q * fe.dx

                if self.map_flag:
                    self.interpolate_map()
                    # delta_x = self.x - self.x_hat
                    # self.map_plot.assign(fe.project(delta_x, self.MM))

            self.presLoad.t = disp

            newton_prm = solver_u.parameters['newton_solver']
            newton_prm['maximum_iterations'] = 100
            # newton_prm['absolute_tolerance'] = 1e-8
            newton_prm['relaxation_parameter'] = rp

            newton_prm = solver_d.parameters['newton_solver']
            newton_prm['maximum_iterations'] = 100
            # newton_prm['absolute_tolerance'] = 1e-8
            newton_prm['relaxation_parameter'] = rp

            vtkfile_e_staggered = fe.File(
                'data/pvd/simulation/{}/step{}/e.pvd'.format(
                    self.case_name, i))
            vtkfile_u_staggered = fe.File(
                'data/pvd/simulation/{}/step{}/u.pvd'.format(
                    self.case_name, i))
            vtkfile_d_staggered = fe.File(
                'data/pvd/simulation/{}/step{}/d.pvd'.format(
                    self.case_name, i))
            iteration = 0
            err = 1.
            while err > self.staggered_tol:
                iteration += 1

                solver_d.solve()

                solver_u.solve()

                if self.solution_scheme == 'explicit':
                    break

                # # Remarks(Tianju): self.x_new.vector() does not behave as expected: producing nan values
                # The following lines of codes cause issues
                # We use an error measure similar in https://doi.org/10.1007/s10704-019-00372-y
                # np_x_new = np.asarray(self.x_new.vector())
                # np_d_new = np.asarray(self.d_new.vector())
                # np_x_old = np.asarray(x_old.vector())
                # np_d_old = np.asarray(d_old.vector())
                # err_x = np.linalg.norm(np_x_new - np_x_old) / np.sqrt(len(np_x_new))
                # err_d = np.linalg.norm(np_d_new - np_d_old) / np.sqrt(len(np_d_new))
                # err = max(err_x, err_d)

                # # Remarks(Tianju): dolfin (2019.1.0) errornorm function has severe bugs not behave as expected
                # The bug seems to be fixed in later versions
                # The following sometimes produces nonzero results in dolfin (2019.1.0)
                # print(fe.errornorm(self.d_new, self.d_new, norm_type='l2'))

                err_x = fe.errornorm(self.x_new, x_old, norm_type='l2')
                err_d = fe.errornorm(self.d_new, d_old, norm_type='l2')
                err = max(err_x, err_d)

                x_old.assign(self.x_new)
                d_old.assign(self.d_new)
                e.assign(
                    fe.project(strain(self.mfem_grad(self.x_new)), self.EE))

                print(
                    '---------------------------------------------------------------------------------'
                )
                print(
                    '>> iteration. {}, err_u = {:.5}, err_d = {:.5}, error = {:.5}'
                    .format(iteration, err_x, err_d, err))
                print(
                    '---------------------------------------------------------------------------------'
                )

                # vtkfile_e_staggered << e
                # vtkfile_u_staggered << self.x_new
                # vtkfile_d_staggered << self.d_new

                if err < self.staggered_tol or iteration >= self.staggered_maxiter:
                    print(
                        '================================================================================='
                    )
                    print('\n')
                    break

            print("L2 projection to update the history function...")
            fe.solve(a == L, self.H_old, [])

            # self.d_pre.assign(self.d_new)
            # self.H_old.assign(fe.project(history(self.H_old, self.update_history(), self.psi_cr), self.WW))

            if self.map_flag and not self.finish_flag:
                self.update_map()

            if self.compute_and_save_intermediate_results:
                print("Save files...")
                self.file_results.write(e, i)
                self.file_results.write(self.x_new, i)
                self.file_results.write(self.d_new, i)
                self.file_results.write(self.map_plot, i)

                vtkfile_e << e
                vtkfile_u << self.x_new
                vtkfile_d << self.d_new

                # Assume boundary is not affected by the map.
                # There's no need to use the mfem_grad wrapper so that fe.grad is used for speed-up
                print("Define forces...")
                sigma = cauchy_stress_plus(strain(fe.grad(self.x_new)),
                                           self.psi)
                sigma_minus = cauchy_stress_minus(strain(fe.grad(self.x_new)),
                                                  self.psi_minus)
                sigma_plus = cauchy_stress_plus(strain(fe.grad(self.x_new)),
                                                self.psi_plus)
                sigma_degraded = g_d(self.d_new) * sigma_plus + sigma_minus

                print("Compute forces...")
                if self.case_name == 'pure_shear':
                    f_full = float(fe.assemble(sigma[0, 1] * self.ds(1)))
                    f_degraded = float(
                        fe.assemble(sigma_degraded[0, 1] * self.ds(1)))
                else:
                    f_full = float(fe.assemble(sigma[1, 1] * self.ds(1)))
                    f_degraded = float(
                        fe.assemble(sigma_degraded[1, 1] * self.ds(1)))

                print("Force full is {}".format(f_full))
                print("Force degraded is {}".format(f_degraded))
                self.delta_u_recorded.append(disp)
                self.force_full.append(f_full)
                self.force_degraded.append(f_degraded)

                # if force_upper < 0.5 and i > 10:
                #     break

                if self.display_intermediate_results and i % 10 == 0:
                    self.show_force_displacement()

                self.save_data_in_loop()

        if self.display_intermediate_results:
            plt.ioff()
            plt.show()
示例#22
0
def sigma(u):
    return (lmbda * fn.tr(eps(u)) * fn.Identity(2) + 2 * mu * eps(u))


# Geometry Specification/Mesh Generation

L = 10.0
H = 2.0

bar = ms.Rectangle(fn.Point(0, 0), fn.Point(L, H))
hole = ms.Circle(fn.Point(L / 2, H / 2), H / 3)
domain = bar - hole
mesh = ms.generate_mesh(domain, 30)

VFS = fn.VectorFunctionSpace(mesh, 'P', 2)

tol = 10**-14

# Boundary conditions


def left(x, on_boundary):
    return on_boundary and x[0] < tol


bc = fn.DirichletBC(VFS, fn.Constant((0, 0)), left)
fext = fn.Expression(('0', '-0.1'), degree=1)

# Weak formulation and solving it
示例#23
0
    def staggered_solve(self):
        self.U = fe.VectorFunctionSpace(self.mesh, 'CG', 1)
        self.W = fe.FunctionSpace(self.mesh, 'CG', 1)
        self.WW = fe.FunctionSpace(self.mesh, 'DG', 0)

        self.eta = fe.TestFunction(self.U)
        self.zeta = fe.TestFunction(self.W)

        del_x = fe.TrialFunction(self.U)
        del_d = fe.TrialFunction(self.W)

        self.x_new = fe.Function(self.U)
        self.d_new = fe.Function(self.W)

        x_old = fe.Function(self.U)
        d_old = fe.Function(self.W)

        self.H_old = fe.Function(self.WW)

        self.build_weak_form_staggered()
        J_u = fe.derivative(self.G_u, self.x_new, del_x)
        J_d = fe.derivative(self.G_d, self.d_new, del_d)

        self.set_bcs_staggered()
        p_u = fe.NonlinearVariationalProblem(self.G_u, self.x_new, self.BC_u,
                                             J_u)
        p_d = fe.NonlinearVariationalProblem(self.G_d, self.d_new, self.BC_d,
                                             J_d)
        solver_u = fe.NonlinearVariationalSolver(p_u)
        solver_d = fe.NonlinearVariationalSolver(p_d)

        vtkfile_u = fe.File('data/pvd/{}/u.pvd'.format(self.case_name))
        vtkfile_d = fe.File('data/pvd/{}/d.pvd'.format(self.case_name))

        for i, (disp, rp) in enumerate(
                zip(self.displacements, self.relaxation_parameters)):

            print('\n')
            print(
                '================================================================================='
            )
            print('>> Step {}, disp boundary condition = {} [mm]'.format(
                i, disp))
            print(
                '================================================================================='
            )

            self.H_old.assign(
                fe.project(
                    history(self.H_old, self.psi(strain(fe.grad(self.x_new))),
                            self.psi_cr), self.WW))

            self.presLoad.t = disp

            newton_prm = solver_u.parameters['newton_solver']
            newton_prm['maximum_iterations'] = 100
            newton_prm['absolute_tolerance'] = 1e-4
            newton_prm['relaxation_parameter'] = rp

            iteration = 0
            err = 1.

            while err > self.staggered_tol:
                iteration += 1

                solver_d.solve()

                solver_u.solve()

                err_u = fe.errornorm(self.x_new,
                                     x_old,
                                     norm_type='l2',
                                     mesh=None)
                err_d = fe.errornorm(self.d_new,
                                     d_old,
                                     norm_type='l2',
                                     mesh=None)
                err = max(err_u, err_d)

                x_old.assign(self.x_new)
                d_old.assign(self.d_new)

                print(
                    '---------------------------------------------------------------------------------'
                )
                print('>> iteration. {}, error = {:.5}'.format(iteration, err))
                print(
                    '---------------------------------------------------------------------------------'
                )

                if err < self.staggered_tol or iteration >= self.staggered_maxiter:
                    print(
                        '================================================================================='
                    )
                    print('\n')

                    self.x_new.rename("u", "u")
                    self.d_new.rename("d", "d")
                    vtkfile_u << self.x_new
                    vtkfile_d << self.d_new
                    break

            force_upper = float(fe.assemble(self.sigma[1, 1] * self.ds(1)))
            print("Force upper {}".format(force_upper))
            self.delta_u_recorded.append(disp)
            self.sigma_recorded.append(force_upper)
    def compute_static_deformation(self):

        assert self.mesh is not None

        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, 3)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, 2)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        # define function spaces
        V = fe.VectorFunctionSpace(self.mesh, "Lagrange", 1)
        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        d = self.mesh.geometry().dim()

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, d)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, d - 1)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        c_zero = fe.Constant((0, 0, 0))

        # define boundary conditions
        bc_bottom = fe.DirichletBC(V, c_zero, bottom)
        bc_top = fe.DirichletBC(V, c_zero, top)

        bcs = [bc_bottom]  # , bc_top]

        # define functions
        du = TrialFunction(V)
        v = TestFunction(V)
        u = Function(V)
        B = fe.Constant((0., 2.0, 0.))
        T = fe.Constant((0.0, 0.0, 0.0))

        d = u.geometric_dimension()
        I = fe.Identity(d)
        F = I + grad(u)
        C = F.T * F

        I_1 = tr(C)
        J = det(F)

        E, mu = 10., 0.3
        mu, lmbda = fe.Constant(E / (2 * (1 + mu))), fe.Constant(
            E * mu / ((1 + mu) * (1 - 2 * mu)))

        # stored energy (comp. neo-hookean model)
        psi = (mu / 2.) * (I_1 - 3) - mu * fe.ln(J) + (lmbda /
                                                       2.) * (fe.ln(J))**2

        dx = self.dx
        ds = self.ds

        Pi = psi * fe.dx - dot(B, u) * fe.dx - dot(T, u) * fe.ds

        F = fe.derivative(Pi, u, v)
        J = fe.derivative(F, u, du)

        fe.solve(F == 0, u, bcs, J=J)

        # save results
        self.u = u

        # write to disk
        output = fe.File("/tmp/static.pvd")
        output << u
示例#25
0
    def block_project(u, mesh, restriction, subdomain_data, project_id,
                      **kwargs):
        """
        Implement the FEniCS' project function for multiphenics. This method
        allows to extract and project the solution of implicit FEniCS functions
        into user-friendly functions, and then extract the solution of a
        specific subdomain (up to know subdomains of dimensions 1 or 2 are
        accepted). Applications of this method may be to extract the gradient
        of a function (when using FEniCS grad function) and get the solution
        in/on a desired subdomain, or do the same with the dot product when
        using FEniCS dot (or inner) function.
        The implemented method is the same one used when obtaining the weak
        form of a PDE. That is, we impose: f = u, where u is the function
        containing the desired data and f is the trial function. Then, we
        multiply by a test function and integrate. In that way, we are
        projecting the solution into a function that can be easily used for
        post-processing.
        Parameters
        ----------
        u: ufl.tensor...
            Tensor containing the desired solution.
        mesh: cpp.mesh.Mesh
            Mesh object.
        restriction: mesh.mesh_restriction.MeshRestriction
            Subdomain restriction.
        subdomain_data: cpp.mesh.MeshFunctionSizet
            Contains the all information of the subdomain.
        project_id: int
            Indentifier of the place (in the subdomain_data) where the
            solution is desired.
        **kwargs:
            Accepted kwargs are space_type, boundary_type sign and restricted.
            The space_type identifies the type of Function Space in which we
            want to project the solution into. It can be scalar (for scalar
            fields) or vectorial (for vectorial fields).
            The boundary_type is only required when subdomains of dimension 1
            are introduced, and it is used to specify the type of facets (they
            can be internal or external).
            The sign is only required when subdomains of dimension 1
            (boundaries) are introduced. It is used to specify the sign to
            evaluate the line integral For example, let us consider two
            subdomains whose ids are 0 and 1, respectively. To indicate that we
            are integrating quantities on subdomain 0, we should introduce '-'
            as sign, because it is the the subdomain with the lower id. Thus,
            for subdomain 1, we should introduce '+' as sign, which is the
            default one.
            The restricted kwarg indicates if the function to be projected is
            already restricted. This should be taken into account because
            UFL cannot restrict an expression twice.
        Raises
        ------
        TypeError
            This error will rise when the specified type of function space is
            unknown.
        NotImplementedError
            This error will raise when the dimension of the introduced
            subdomain is greater than 2.
        Returns
        -------
        sol: dolfin.function.function.Function
            Dolfin Function which can be easily used for post-processing tasks.
        """
        if 'space_type' not in kwargs:
            print(
                "** WARNING: No Function Space type was specified. Assuming scalar space.",
                flush=True)
        if subdomain_data.dim() == 1 and 'boundary_type' not in kwargs:
            print(
                "** WARNING: No boundary type specified. Assuming internal type.",
                flush=True)
        kwargs.setdefault('space_type', 'scalar')
        kwargs.setdefault('boundary_type', 'internal')
        kwargs.setdefault('sign', "+")
        kwargs.setdefault('restricted', False)
        kwargs.setdefault('function_space_degree', 2)
        # Create a Block Function Space.
        function_space_degree = kwargs.get('function_space_degree')

        if kwargs['space_type'] == 'scalar':
            aux_space = mp.BlockFunctionSpace(
                [fn.FunctionSpace(mesh, 'CG', function_space_degree)],
                restrict=[restriction])
        elif kwargs['space_type'] == 'vectorial':
            aux_space = mp.BlockFunctionSpace(
                [fn.VectorFunctionSpace(mesh, 'CG', function_space_degree)],
                restrict=[restriction])
        else:
            raise TypeError(
                f"Unknown type of Function Space: {kwargs['space_type']}")

        # Define the trial and test functions.
        trial, = mp.BlockTrialFunction(aux_space)
        test, = mp.BlockTestFunction(aux_space)

        # Define the measure of the subdomain and the variational problem.
        if subdomain_data.dim() == 2:
            dom_measure = fn.Measure('dx')(subdomain_data=subdomain_data)
            lhs = [[fn.inner(trial, test) * dom_measure(project_id)]]
            rhs = [fn.inner(u, test) * dom_measure(project_id)]
        elif subdomain_data.dim() == 1:
            if kwargs['boundary_type'] == 'internal':
                dom_measure = fn.Measure('dS')(subdomain_data=subdomain_data)
            elif kwargs['boundary_type'] == 'external':
                dom_measure = fn.Measure('ds')(subdomain_data=subdomain_data)
            # Check if the interface exists.
            assert fn.assemble(
                1 * dom_measure(domain=mesh)
            ) > 0., "The length of the interface is zero, wrong marking."
            lhs = [[
                fn.inner(trial, test)(kwargs['sign']) * dom_measure(project_id)
            ]]
            if not kwargs.get('restricted'):
                rhs = [
                    fn.inner(u, test)(kwargs['sign']) * dom_measure(project_id)
                ]
            else:
                rhs = [
                    fn.inner(u, test(kwargs['sign'])) * dom_measure(project_id)
                ]
        else:
            raise NotImplementedError(
                f"Domains of dimension {subdomain_data.dim()} are not supported."
            )

        # Define the variational form and solve.
        LHS = mp.block_assemble(lhs)
        RHS = mp.block_assemble(rhs)
        sol = mp.BlockFunction(aux_space)
        mp.block_solve(LHS, sol.block_vector(), RHS)

        return sol[0]
示例#26
0
def simp(x):
    return eps + (1 - eps) * x**p


max_volume = 0.4 * L * h  # Volume constraint
p = 4  # Exponent
eps = fa.Constant(1.0e-6)  # Epsilon for SIMP

# Mesh, Control and Solution Spaces
nelx = 192
nely = 64
mesh = fa.RectangleMesh.create(
    [fn.Point(0.0, 0.0), fn.Point(L, h)], [nelx, nely],
    fn.CellType.Type.triangle)

V = fn.VectorFunctionSpace(mesh, "CG", 1)  # Displacements
C = fn.FunctionSpace(mesh, "CG", 1)  # Control

# Volumetric Load
q = -10.0 / t
b = fa.Constant((0.0, q))


def Left_boundary(x, on_boundary):
    return on_boundary and abs(x[0]) < fn.DOLFIN_EPS


u_L = fa.Constant((0.0, 0.0))
bcs = [fa.DirichletBC(V, u_L, Left_boundary)]

    def __init__(self, mesh: fe.Mesh, family="P", order=1):

        self.V = fe.VectorFunctionSpace(mesh, family, order)
示例#28
0
vFile = fe.File('Vorticity.pvd')
#wFile = fe.File('W.pvd')
T = fe.FunctionSpace(mesh, 'CG', 1)
solver.solve()
u1, p1 = W0.split()
We.assign(W0)
uFile << u1
pFile << p1
u, p = W0.split()

#-------------------------------------------------
# Save this solution to a file for post-processing
#-------------------------------------------------
T = fe.TensorFunctionSpace(mesh, 'CG', 1)
wFile = fe.File('Sij.pvd')
wFile << fe.project(sij, T)
T = fe.FunctionSpace(mesh, 'CG', 1)
#wFile = fe.File('S.pvd')
#File << fe.project(lmx**2.*S, T)
T = fe.VectorFunctionSpace(mesh, 'CG', 1)
vtkFile = fe.File('CFL.pvd')
vtkFile << fe.project(u * dt / h, T)

T = fe.TensorFunctionSpace(mesh, 'CG', 1)
vtkFile = fe.File('tau.pvd')
vtkFile << fe.project(nu * (fe.grad(u) + fe.grad(u).T), T)

T = fe.FunctionSpace(mesh, 'CG', 1)
wFile = fe.File('S.pvd')
wFile << fe.project(lmx**2. * S, T)
示例#29
0
subprocess.check_output('dolfin-convert ./gmsh/beam.msh mesh/beam.xml',
                        shell=True)
#cprint("Importing mesh in FEniCS...", 'green')
mesh = fe.Mesh('mesh/beam.xml')
#cprint("Generating boundaries and subdomains...", 'green')
subdomains = fe.MeshFunction("size_t", mesh, "mesh/beam_physical_region.xml")
boundaries = fe.MeshFunction("size_t", mesh, "mesh/beam_facet_region.xml")

# Redefine the integration measures
dxp = fe.Measure('dx', domain=mesh, subdomain_data=subdomains)
dsp = fe.Measure('ds', domain=mesh, subdomain_data=boundaries)

##################### FINITE ELEMENT SPACES ##################################
# Finite element spaces
W = fe.FunctionSpace(mesh, 'P', 1)
V = fe.VectorFunctionSpace(mesh, 'P', 1)
Z = fe.TensorFunctionSpace(mesh, 'P', 1)

# Finite element functions
du = fe.TrialFunction(V)
v = fe.TestFunction(V)
u = fe.Function(V)

######################### PROBLEM PARAMS ######################################
# Material properties
materials = {
    1: [210e9, 0.33],
}

# Load multipliers
p = 500000.
示例#30
0
文件: test.py 项目: ZXK666666/FESTIM
def test_formulation_1_trap_2_materials():
    '''
    Test function formulation() with 1 intrinsic trap
    and 2 materials
    '''
    def create_subdomains(x1, x2):
        class domain(FESTIM.SubDomain):
            def inside(self, x, on_boundary):
                return x[0] >= x1 and x[0] <= x2
        domain = domain()
        return domain
    dt = 1
    traps = [{
        "energy": 1,
        "density": 2,
        "materials": [1, 2]
        }]
    materials = [{
            "alpha": 1,
            "beta": 2,
            "density": 3,
            "borders": [0, 0.5],
            "E_diff": 4,
            "D_0": 5,
            "id": 1
            },
            {
            "alpha": 2,
            "beta": 3,
            "density": 4,
            "borders": [0.5, 1],
            "E_diff": 5,
            "D_0": 6,
            "id": 2
            }]
    extrinsic_traps = []
    mesh = fenics.UnitIntervalMesh(10)
    mf = fenics.MeshFunction("size_t", mesh, 1, 1)
    mat1 = create_subdomains(0, 0.5)
    mat2 = create_subdomains(0.5, 1)
    mat1.mark(mf, 1)
    mat2.mark(mf, 2)
    V = fenics.VectorFunctionSpace(mesh, 'P', 1, 2)
    u = fenics.Function(V)
    u_n = fenics.Function(V)
    v = fenics.TestFunction(V)

    solutions = list(fenics.split(u))
    previous_solutions = list(fenics.split(u_n))
    testfunctions = list(fenics.split(v))

    mf = fenics.MeshFunction('size_t', mesh, 1, 1)
    dx = fenics.dx(subdomain_data=mf)
    temp = fenics.Expression("300", degree=0)
    flux_ = fenics.Expression("1", degree=0)

    F, expressions = FESTIM.formulation(
        traps, extrinsic_traps, solutions, testfunctions,
        previous_solutions, dt, dx, materials, temp, flux_)

    # Transient sol
    expected_form = ((solutions[0] - previous_solutions[0]) / dt) * \
        testfunctions[0]*dx
    # Diffusion sol mat 1
    expected_form += 5 * fenics.exp(-4/8.6e-5/temp) * \
        fenics.dot(
            fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(1)
    # Diffusion sol mat 2
    expected_form += 6 * fenics.exp(-5/8.6e-5/temp) * \
        fenics.dot(
            fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(2)
    # Source sol
    expected_form += -flux_*testfunctions[0]*dx
    # Transient trap 1
    expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \
        testfunctions[1]*dx
    # Trapping trap 1 mat 1
    expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \
        solutions[0] * (2 - solutions[1]) * \
        testfunctions[1]*dx(1)
    # Trapping trap 1 mat 2
    expected_form += - 6 * fenics.exp(-5/8.6e-5/temp)/2/2/3 * \
        solutions[0] * (2 - solutions[1]) * \
        testfunctions[1]*dx(2)
    # Detrapping trap 1 mat 1
    expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \
        testfunctions[1]*dx(1)
    # Detrapping trap 1 mat 2
    expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \
        testfunctions[1]*dx(2)
    # Source detrapping sol
    expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \
        testfunctions[0]*dx

    assert expected_form.equals(F) is True