示例#1
0
 def _build_mesh(self):
     args = self.args
     self.width = 0.5
     # mesh = fa.Mesh(args.root_path + '/' + args.solutions_path + '/saved_mesh/mesh_robot.xml')
     mesh = fa.RectangleMesh(fa.Point(0, 0), fa.Point(
         self.width, 10), 2, 20, 'crossed')
     self.mesh = mesh
示例#2
0
def problem(f, nx=8, ny=8, degrees=[1, 2]):
    """
    Plot u along x=const or y=const for Lagrange elements,
    of given degrees, on a nx times ny mesh. f is a SymPy expression.
    """
    f = sym.printing.ccode(f)
    f = fe.Expression(f, degree=2)
    mesh = fe.RectangleMesh(fe.Point(-1, 0), fe.Point(1, 2), 2, 2)
    for degree in degrees:
        if degree == 0:
            # The P0 element is specified like this in FEniCS
            V = fe.FunctionSpace(mesh, 'DG', 0)
        else:
            # The Lagrange Pd family of elements, d=1,2,3,...
            V = fe.FunctionSpace(mesh, 'P', degree)
        u = fe.project(f, V)
        u_error = fe.errornorm(f, u, 'L2')
        print('||u-f||=%g' % u_error, degree)
        comparison_plot2D(u,
                          f,
                          n=50,
                          value=0.4,
                          variation='x',
                          plottitle='Approximation by P%d elements' % degree,
                          filename='approx_fenics_by_P%d' % degree,
                          tol=1E-3)
示例#3
0
def calc_system_variables(*, coords, advect_params, flags, pert_params):
    dx = (coords.we[1] - coords.we[0]) * 1000
    dy = (coords.sn[1] - coords.sn[0]) * 1000  # dx, dy in m not km
    max_horizon = pd.Timedelta(advect_params['max_horizon'])
    ci_crop_shape = np.array([coords.sn_crop.size, coords.we_crop.size],
                             dtype='int')
    U_crop_shape = np.array([coords.sn_crop.size, coords.we_stag_crop.size],
                            dtype='int')
    V_crop_shape = np.array([coords.sn_stag_crop.size, coords.we_crop.size],
                            dtype='int')
    U_crop_size = U_crop_shape[0] * U_crop_shape[1]
    V_crop_size = V_crop_shape[0] * V_crop_shape[1]
    wind_size = U_crop_size + V_crop_size
    num_of_horizons = int((max_horizon / 15).seconds / 60)
    sys_vars = {
        'dx': dx,
        'dy': dy,
        'num_of_horizons': num_of_horizons,
        'max_horizon': max_horizon,
        'ci_crop_shape': ci_crop_shape,
        'U_crop_shape': U_crop_shape,
        'V_crop_shape': V_crop_shape,
        'U_crop_size': U_crop_size,
        'V_crop_size': V_crop_size,
        'wind_size': wind_size
    }
    if flags['div']:
        mesh = fe.RectangleMesh(
            fe.Point(0, 0),
            fe.Point(int(V_crop_shape[1] - 1), int(U_crop_shape[0] - 1)),
            int(V_crop_shape[1] - 1), int(U_crop_shape[0] - 1))
        FunctionSpace_wind = fe.FunctionSpace(mesh, 'P', 1)
        sys_vars['FunctionSpace_wind'] = FunctionSpace_wind
    if flags['perturbation']:
        rf_eig, rf_vectors = eig_2d_covariance(x=coords.we_crop,
                                               y=coords.sn_crop,
                                               Lx=pert_params['Lx'],
                                               Ly=pert_params['Ly'],
                                               tol=pert_params['tol'])
        rf_approx_var = (rf_vectors * rf_eig[None, :] *
                         rf_vectors).sum(-1).mean()
        sys_vars['rf_eig'] = rf_eig
        sys_vars['rf_vectors'] = rf_vectors
        sys_vars['rf_approx_var'] = rf_approx_var
    if flags['perturb_winds']:
        rf_eig, rf_vectors = eig_2d_covariance(coords.we_crop,
                                               coords.sn_crop,
                                               Lx=pert_params['Lx_wind'],
                                               Ly=pert_params['Ly_wind'],
                                               tol=pert_params['tol_wind'])
        rf_approx_var = (rf_vectors * rf_eig[None, :] *
                         rf_vectors).sum(-1).mean()
        rf_eig = rf_eig * pert_params['Lx_wind']**2
        sys_vars['rf_eig_wind'] = rf_eig
        sys_vars['rf_vectors_wind'] = rf_vectors
        sys_vars['rf_approx_var_wind'] = rf_approx_var
    sys_vars = dict2nt(sys_vars, 'sys_vars')
    return sys_vars
示例#4
0
def make_mesh(num_cells: int) -> fenics.Mesh:
    """Generate mesh for FEM solver.

    """
    mesh = fenics.RectangleMesh(fenics.Point(0, 0),
                                fenics.Point(2 * np.pi, np.pi), num_cells,
                                num_cells)
    pbcs = lbe.periodic_boundary_conditions([0, 0], [2 * np.pi, np.pi],
                                            [True, False])

    return mesh, pbcs
示例#5
0
    def xest_second_tutorial(self):
        T = 2.0  # final time
        num_steps = 50  # number of time steps
        dt = T / num_steps  # time step size
        # Create mesh and define function space
        nx = ny = 30
        mesh = fenics.RectangleMesh(fenics.Point(-2, -2), fenics.Point(2, 2),
                                    nx, ny)
        V = fenics.FunctionSpace(mesh, 'P', 1)

        # Define boundary condition
        def boundary(x, on_boundary):
            return on_boundary

        bc = fenics.DirichletBC(V, fenics.Constant(0), boundary)
        # Define initial value
        u_0 = fenics.Expression('exp(-a*pow(x[0], 2) - a*pow(x[1], 2))',
                                degree=2,
                                a=5)
        u_n = fenics.interpolate(u_0, V)
        # Define variational problem
        u = fenics.TrialFunction(V)
        v = fenics.TestFunction(V)
        f = fenics.Constant(0)
        F = u * v * fenics.dx + dt * fenics.dot(fenics.grad(u), fenics.grad(
            v)) * fenics.dx - (u_n + dt * f) * v * fenics.dx
        a, L = fenics.lhs(F), fenics.rhs(F)
        # Create VTK file for saving solution
        vtkfile = fenics.File(
            os.path.join(os.path.dirname(__file__), 'output', 'heat_gaussian',
                         'solution.pvd'))
        # Time-stepping
        u = fenics.Function(V)
        t = 0
        not_initialised = True
        for n in range(num_steps):
            # Update current time
            t += dt
            # Compute solution
            fenics.solve(a == L, u, bc)
            # Save to file and plot solution
            vtkfile << (u, t)
            # Here we'll need to call tripcolor ourselves to get access to the color range
            fenics.plot(u)
            animation_camera.snap()
            u_n.assign(u)
        animation = animation_camera.animate()
        animation.save(
            os.path.join(os.path.dirname(__file__), 'output',
                         'heat_gaussian.mp4'))
示例#6
0
def get_mesh(length, nx, ny, nz=None):
    """获得 mesh

    """
    if nz is None:
        mesh = fs.RectangleMesh(fs.Point(0.0, 0.0), fs.Point(length, length),
                                nx, ny)
    else:
        mesh = fs.BoxMesh(
            fs.Point(0.0, 0.0, 0.0),
            fs.Point(length, length, length),
            nx,
            ny,
            nz,
        )
    return mesh
    def setup_coarse_mesh(self):
        """ This creates the rectangular mesh, or rectangular prism in 3D. """
        if len(self.mesh_size) == 2:

            self.mesh = fenics.RectangleMesh(
                fenics.mpi_comm_world(), fenics.Point(self.xmin, self.ymin),
                fenics.Point(self.xmax, self.ymax), self.mesh_size[0],
                self.mesh_size[1], "crossed")

        elif len(self.mesh_size) == 3:

            self.mesh = fenics.BoxMesh(
                fenics.mpi_comm_world(),
                fenics.Point(self.xmin, self.ymin, self.zmin),
                fenics.Point(self.xmax, self.ymax, self.zmax),
                self.mesh_size[0], self.mesh_size[1], self.mesh_size[2])
示例#8
0
    def __init__(self):
        self.h = .4

        # Cell properties
        self.obs_length = 0.9
        self.obs_height = 0.001
        self.obs_ratio = self.obs_height / self.obs_length

        if self.h < self.eta:
            raise ValueError("Eta must be smaller than h")
        self.ref_T = 0.1

        self.eps = 2 * self.eta / MembraneSimulator.length
        self.mesh = fe.RectangleMesh(
            fe.Point(-1, 0),
            fe.Point(1, 2 * self.h / MembraneSimulator.length), 50, 50)
        self.cell_mesh = None
        self.D = np.matrix(((4 * self.ref_T * MembraneSimulator.d1 /
                             MembraneSimulator.length**2, -0.05),
                            (+0.05, 4 * self.ref_T * MembraneSimulator.d2 /
                             MembraneSimulator.length**2)))
        # Dirichlet boundary conditions
        self.u_l = 6E-5
        self.u_r = 0
        self.u_boundary = fe.Expression(
            '(u_l*(x[0] < - par) + u_r*(x[0] >= par))',
            u_l=self.u_l,
            u_r=self.u_r,
            par=MembraneSimulator.w / MembraneSimulator.length,
            degree=2)
        self.u_0 = self.u_boundary / 2

        # self.rhs = fe.Expression('(x[1]>par)*u',u=self.u_l*4,par=MembraneSimulator.eta/MembraneSimulator.length, degree=2)
        self.rhs = fe.Constant(0)
        self.time = 0
        self.T = 1
        self.dt = 0.01
        self.tol = 1E-4

        self.function_space = fe.FunctionSpace(self.mesh, 'P', 2)
        self.solution = fe.Function(self.function_space)
        self.cell_solutions = self.cell_fs = None
        self.unit_vectors = [fe.Constant((1., 0.)), fe.Constant((0., 1.))]
        self.eff_diff = np.zeros((2, 2))
        self.file = fe.File('results/solution.pvd')
示例#9
0
 def __init__(self, d, h, ell=1., degree=1, nu=0.3, E=1.0):
     self.d = d
     self.ell = ell
     self.degree = degree
     mesh = fenics.RectangleMesh(fenics.Point(0., -0.5 * d),
                                 fenics.Point(ell, 0.5 * d), int(ell / h),
                                 int(d / h))
     self.left = dolfin.CompiledSubDomain('on_boundary && x[0] <= atol',
                                          atol=1e-5 * h)
     self.right = dolfin.CompiledSubDomain(
         'on_boundary && x[0] >= ell-atol', ell=ell, atol=1e-5 * h)
     element = dolfin.VectorElement('P',
                                    cell=mesh.ufl_cell(),
                                    degree=degree,
                                    dim=DIM)
     self.V = dolfin.FunctionSpace(mesh, element)
     self.lambda_ = dolfin.Constant(E * nu / (1. + nu) / (1. - 2. * nu))
     self.mu = dolfin.Constant(E / 2. / (1. + nu))
import fenics as fn
fn.parameters["form_compiler"]["representation"] = "uflacs"
fn.parameters["form_compiler"]["cpp_optimize"] = True

# create mesh
mesh_size = mesh_width, mesh_height = 6.0, 6.0
mesh = fn.RectangleMesh(fn.Point(-mesh_width/2, 0.0),
                        fn.Point( mesh_width/2, mesh_height),
                        25, 25)  # square elements

# time-related variables
t = 0.0
dt = 0.3
TFinal = 600.0
frequency = 10

# normals
nn = fn.FacetNormal(mesh)

# element spaces
Vh = fn.VectorElement("CG", mesh.ufl_cell(), 2)
Zh = fn.FiniteElement("CG", mesh.ufl_cell(), 1)
Qh = fn.FiniteElement("CG", mesh.ufl_cell(), 2)
Mh = fn.FiniteElement("CG", mesh.ufl_cell(), 1)
Wh = fn.TensorElement("CG", mesh.ufl_cell(), 1)

# function spaces
Vhf = fn.FunctionSpace(mesh, Vh)
Zhf = fn.FunctionSpace(mesh, Zh)
Qhf = fn.FunctionSpace(mesh, Qh)
Mhf = fn.FunctionSpace(mesh, Mh)
示例#11
0
def regular_mesh(n=10, L_x=1.0, L_y=1.0, L_z=None):
    r"""Creates a mesh corresponding to a rectangle or cube.

	This function creates a uniform mesh of either a rectangle
	or a cube, starting at the origin and having length specified
	in ``L_x``, ``L_y``, and ``L_z``. The resulting mesh uses ``n`` elements along the
	shortest direction and accordingly many along the longer ones.
	The resulting domain is

	.. math::
		\begin{alignedat}{2}
		&[0, L_x] \times [0, L_y] \quad &&\text{ in } 2D, \\
		&[0, L_x] \times [0, L_y] \times [0, L_z] \quad &&\text{ in } 3D.
		\end{alignedat}

	The boundary markers are ordered as follows:

	  - 1 corresponds to :math:`x=0`.

	  - 2 corresponds to :math:`x=L_x`.

	  - 3 corresponds to :math:`y=0`.

	  - 4 corresponds to :math:`y=L_y`.

	  - 5 corresponds to :math:`z=0` (only in 3D).

	  - 6 corresponds to :math:`z=L_z` (only in 3D).

	Parameters
	----------
	n : int
		Number of elements in the shortest coordinate direction.
	L_x : float
		Length in x-direction.
	L_y : float
		Length in y-direction.
	L_z : float or None, optional
		Length in z-direction, if this is ``None``, then the geometry
		will be two-dimensional (default is ``None``).

	Returns
	-------
	mesh : dolfin.cpp.mesh.Mesh
		The computational mesh.
	subdomains : dolfin.cpp.mesh.MeshFunctionSizet
		A :py:class:`fenics.MeshFunction` object containing the subdomains.
	boundaries : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the boundaries.
	dx : ufl.measure.Measure
		The volume measure of the mesh corresponding to subdomains.
	ds : ufl.measure.Measure
		The surface measure of the mesh corresponding to boundaries.
	dS : ufl.measure.Measure
		The interior facet measure of the mesh corresponding to boundaries.
	"""
    if not n > 0:
        raise InputError('cashocs.geometry.regular_mesh', 'n',
                         'This needs to be positive.')
    if not L_x > 0.0:
        raise InputError('cashocs.geometry.regular_mesh', 'L_x',
                         'L_x needs to be positive')
    if not L_y > 0.0:
        raise InputError('cashocs.geometry.regular_mesh', 'L_y',
                         'L_y needs to be positive')
    if not (L_z is None or L_z > 0.0):
        raise InputError('cashocs.geometry.regular_mesh', 'L_z',
                         'L_z needs to be positive or None (for 2D mesh)')

    n = int(n)

    if L_z is None:
        sizes = [L_x, L_y]
        dim = 2
    else:
        sizes = [L_x, L_y, L_z]
        dim = 3

    size_min = np.min(sizes)
    num_points = [int(np.round(length / size_min * n)) for length in sizes]

    if L_z is None:
        mesh = fenics.RectangleMesh(fenics.Point(0, 0), fenics.Point(sizes),
                                    num_points[0], num_points[1])
    else:
        mesh = fenics.BoxMesh(fenics.Point(0, 0, 0), fenics.Point(sizes),
                              num_points[0], num_points[1], num_points[2])

    subdomains = fenics.MeshFunction('size_t', mesh, dim=dim)
    boundaries = fenics.MeshFunction('size_t', mesh, dim=dim - 1)

    x_min = fenics.CompiledSubDomain('on_boundary && near(x[0], 0, tol)',
                                     tol=fenics.DOLFIN_EPS)
    x_max = fenics.CompiledSubDomain('on_boundary && near(x[0], length, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     length=sizes[0])
    x_min.mark(boundaries, 1)
    x_max.mark(boundaries, 2)

    y_min = fenics.CompiledSubDomain('on_boundary && near(x[1], 0, tol)',
                                     tol=fenics.DOLFIN_EPS)
    y_max = fenics.CompiledSubDomain('on_boundary && near(x[1], length, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     length=sizes[1])
    y_min.mark(boundaries, 3)
    y_max.mark(boundaries, 4)

    if L_z is not None:
        z_min = fenics.CompiledSubDomain('on_boundary && near(x[2], 0, tol)',
                                         tol=fenics.DOLFIN_EPS)
        z_max = fenics.CompiledSubDomain(
            'on_boundary && near(x[2], length, tol)',
            tol=fenics.DOLFIN_EPS,
            length=sizes[2])
        z_min.mark(boundaries, 5)
        z_max.mark(boundaries, 6)

    dx = fenics.Measure('dx', mesh, subdomain_data=subdomains)
    ds = fenics.Measure('ds', mesh, subdomain_data=boundaries)
    dS = fenics.Measure('dS', mesh)

    return mesh, subdomains, boundaries, dx, ds, dS
示例#12
0
    def init_V(self):
        '''
        This function sets up various parameters for the calculation of
        the chemical potential profile using fenics.
        It is generally assumed that during the simulation of a 'sample'
        the following are unchanged:
        - dopant positions
        - electrode positions/number
        Note: only 2D support for now
        '''
        # Turn off log messages
        fn.set_log_level(logging.WARNING)

        # Put electrode positions and values in a dict
        self.fn_electrodes = {}
        for i in range(self.P):
            self.fn_electrodes[f'e{i}_x'] = self.electrodes[i, 0]
            if(self.dim > 1):
                self.fn_electrodes[f'e{i}_y'] = self.electrodes[i, 1]
            self.fn_electrodes[f'e{i}'] = self.electrodes[i, 3]
        for i in range(self.static_electrodes.shape[0]):
            self.fn_electrodes[f'es{i}_x'] = self.static_electrodes[i, 0]
            if(self.dim > 1):
                self.fn_electrodes[f'es{i}_y'] = self.static_electrodes[i, 1]
            self.fn_electrodes[f'es{i}'] = self.static_electrodes[i, 3]


        # Define boundary expression string
        self.fn_expression = ''
        if(self.dim == 1):
            for i in range(self.P):
                self.fn_expression += (f'x[0] == e{i}_x ? e{i} : ')
            for i in range(self.static_electrodes.shape[0]):
                self.fn_expression += (f'x[0] == es{i}_x ? es{i} : ')

        if(self.dim == 2):
            surplus = self.xdim/10  # Electrode modelled as point +/- surplus
            #TODO: Make this not hardcoded
            for i in range(self.P):
                if(self.electrodes[i, 0] == 0 or self.electrodes[i, 0] == self.xdim):
                    self.fn_expression += (f'x[0] == e{i}_x && '
                                           f'x[1] >= e{i}_y - {surplus} && '
                                           f'x[1] <= e{i}_y + {surplus} ? e{i} : ')
                else:
                    self.fn_expression += (f'x[0] >= e{i}_x - {surplus} && '
                                           f'x[0] <= e{i}_x + {surplus} && '
                                           f'x[1] == e{i}_y ? e{i} : ')
            for i in range(self.static_electrodes.shape[0]):
                if(self.static_electrodes[i, 0] == 0 or self.static_electrodes[i, 0] == self.xdim):
                    self.fn_expression += (f'x[0] == es{i}_x && '
                                           f'x[1] >= es{i}_y - {surplus} && '
                                           f'x[1] <= es{i}_y + {surplus} ? es{i} : ')
                else:
                    self.fn_expression += (f'x[0] >= es{i}_x - {surplus} && '
                                           f'x[0] <= es{i}_x + {surplus} && '
                                           f'x[1] == es{i}_y ? es{i} : ')

        self.fn_expression += f'{self.mu}'  # Add constant chemical potential

        # Define boundary expression
        self.fn_boundary = fn.Expression(self.fn_expression,
                                         degree = 1,
                                         **self.fn_electrodes)

        # Define FEM mesh (res should be small enough, otherwise solver may break)
        if(self.dim == 1):
            self.fn_mesh = fn.IntervalMesh(int(self.xdim//self.res), 0, self.xdim)
        if(self.dim == 2):
            self.fn_mesh = fn.RectangleMesh(fn.Point(0, 0),
                                            fn.Point(self.xdim, self.ydim),
                                            int(self.xdim//self.res),
                                            int(self.ydim//self.res))

        # Define function space
        self.fn_functionspace = fn.FunctionSpace(self.fn_mesh, 'P', 1)

        # Define fenics boundary condition
        self.fn_bc = fn.DirichletBC(self.fn_functionspace,
                                    self.fn_boundary,
                                    self.fn_onboundary)

        # Write problem as fn_a == fn_L
        self.V = fn.TrialFunction(self.fn_functionspace)
        self.fn_v = fn.TestFunction(self.fn_functionspace)
        self.fn_a = fn.dot(fn.grad(self.V), fn.grad(self.fn_v)) * fn.dx
        self.fn_f = fn.Constant(0)
        self.fn_L = self.fn_f*self.fn_v*fn.dx

        # Solve V
        self.V = fn.Function(self.fn_functionspace)
        fn.solve(self.fn_a == self.fn_L, self.V, self.fn_bc)
示例#13
0
import fenics as fn
fn.parameters["form_compiler"]["representation"] = "uflacs"
fn.parameters["form_compiler"]["cpp_optimize"] = True

# Create mesh and define function space
size = width, height = 1.0, 0.75

mesh = fn.RectangleMesh(fn.Point(-width / 2, 0.0), fn.Point(width / 2, height),
                        52, 39)  # 52 * 0.75 = 39, elements are square
nn = fn.FacetNormal(mesh)

# Defintion of function spaces
Vh = fn.VectorElement("CG", mesh.ufl_cell(), 2)
Zh = fn.FiniteElement("CG", mesh.ufl_cell(), 1)
Qh = fn.FiniteElement("CG", mesh.ufl_cell(), 2)

# spaces for displacement and total pressure should be compatible
# whereas the space for fluid pressure can be "anything". In particular the one for total pressure

Hh = fn.FunctionSpace(mesh, fn.MixedElement([Vh, Zh, Qh]))

(u, phi, p) = fn.TrialFunctions(Hh)
(v, psi, q) = fn.TestFunctions(Hh)

fileU = fn.File(mesh.mpi_comm(), "Output/2_5_1_Footing_wall_removed/u.pvd")
filePHI = fn.File(mesh.mpi_comm(), "Output/2_5_1_Footing_wall_removed/phi.pvd")
fileP = fn.File(mesh.mpi_comm(), "Output/2_5_1_Footing_wall_removed/p.pvd")

# ******** Model constants ********** #
E = 3.0e4
nu = 0.4995
示例#14
0
def map():
    '''
    Try to reproduce https://doi.org/10.1016/j.cma.2014.11.016
    '''
    files = glob.glob('data/pvd/map/*')
    for f in files:
        try:
            os.remove(f)
        except Exception as e:
            print('Failed to delete {}, reason: {}' % (f, e))

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

    V = fe.FunctionSpace(mesh, "CG", 1)
    d = fe.interpolate(FractureExpression(), V)

    u = fe.TrialFunction(V)
    v = fe.TestFunction(V)

    u_k = fe.interpolate(LevelSetExpression(), V)

    # u_k = fe.project(1 - d, V)

    class CenterPoint(fe.SubDomain):
        def inside(self, x, on_boundary):
            return x[0] > -1 and x[0] < 1 and x[1] > -0.05 and x[1] < 0.05

    BC_u = fe.DirichletBC(V,
                          fe.Constant(0.0),
                          CenterPoint(),
                          method='pointwise')
    # BC = [BC_u]
    BC = []

    a = fe.inner(fe.grad(u), fe.grad(v)) * fe.dx
    a += 100 * u * v * d * fe.dx
    L = fe.inner(fe.grad(u_k), fe.grad(v)) * (1 - d3(fe.grad(u_k))) * fe.dx
    # L += -100*d * v * fe.dx

    # E = 0.5*(fe.sqrt(fe.inner(fe.grad(u), fe.grad(u))) - 1)**2 * fe.dx
    # dE = fe.derivative(E, u, v)
    # jacE = fe.derivative(dE, u, du)
    # fe.solve(dE == 0, u, [], J=jacE, solver_parameters={'newton_solver': {'relaxation_parameter': 0.1, 'maximum_iterations':1000}})

    u = fe.Function(V)
    eps = 1.0  # error measure ||u-u_k||
    tol = 1e-5  # tolerance
    iteration = 0  # iteration counter
    maxiter = 25  # max no of iterations allowed
    while eps > tol and iteration < maxiter:
        iteration += 1
        fe.solve(a == L, u, BC)
        diff = np.array(u.vector()) - np.array(u_k.vector())
        eps = np.linalg.norm(diff, ord=np.Inf)
        # eps = fe.errornorm(u, u_k, norm_type='l2', mesh=None)
        print('iteration={}: norm={}'.format(iteration, eps))
        u_k.assign(u)  # update for next iteration

    vtkfile_u = fe.File('data/pvd/map/u.pvd')
    u.rename("phi", "phi")
    vtkfile_u << u

    vtkfile_d = fe.File('data/pvd/map/d.pvd')
    d.rename("d", "d")
    vtkfile_d << d
示例#15
0
# Source frequency in Hz
f0 = 10.
# Sources definition
possou = np.array([[0.5], [0.98]])
# Receivers definition
posrec = np.array([[0.2, 0.4, 0.6, 0.8], [0.98, 0.98, 0.98, 0.98]])
########## End Data Input ##########

# Element number in absorbing layer
npmlx = int(np.max([1, mt.floor(nx*pml/Lx)])) # Element number in x
npmly = int(np.max([1, mt.floor(ny*pml/Ly)])) # Element number in y
print("Absorbing Layer - nelex:", npmlx, "and neley:", npmly)
# Create mesh
nelx = nx + 2*npmlx
nely = ny + 2*npmly
mesh = fn.RectangleMesh(fn.Point(0.0, 0.0), fn.Point(Lx + 2*pml, Ly  + 2*pml), nelx, nely)
# Normal vector
n = fn.FacetNormal(mesh)
# Minimum lenght of element
lmin = np.min([Lx/nx, Ly/ny])

# Solver parameters
forward_max_it = 10
forward_tol = 1e-12#fn.DOLFIN_EPS
relativ_tol = 1e-12#fn.DOLFIN_EPS

# Propagation speed
class vel_c(fn.UserExpression):
    """
    Mapping of propagation speed for domain with two different materials
示例#16
0
    def xest_implement_2d_myosin(self):
        #Parameters
        total_time = 1.0
        number_of_time_steps = 100
        delta_t = total_time / number_of_time_steps
        nx = ny = 100
        domain_size = 1.0
        lambda_ = 5.0
        mu = 2.0
        gamma = 1.0
        eta_b = 0.0
        eta_s = 1.0
        k_b = 1.0
        k_u = 1.0
        #         zeta_1 = -0.5
        zeta_1 = 0.0
        zeta_2 = 1.0
        mu_a = 1.0
        K_0 = 1.0
        K_1 = 0.0
        K_2 = 0.0
        K_3 = 0.0
        D = 0.25
        alpha = 3
        c = 0.1

        # Sub domain for Periodic boundary condition
        class PeriodicBoundary(fenics.SubDomain):
            # Left boundary is "target domain" G
            def inside(self, x, on_boundary):
                # return True if on left or bottom boundary AND NOT on one of the two corners (0, 1) and (1, 0)
                return bool(
                    (fenics.near(x[0], 0) or fenics.near(x[1], 0)) and
                    (not ((fenics.near(x[0], 0) and fenics.near(x[1], 1)) or
                          (fenics.near(x[0], 1) and fenics.near(x[1], 0))))
                    and on_boundary)

            def map(self, x, y):
                if fenics.near(x[0], 1) and fenics.near(x[1], 1):
                    y[0] = x[0] - 1.
                    y[1] = x[1] - 1.
                elif fenics.near(x[0], 1):
                    y[0] = x[0] - 1.
                    y[1] = x[1]
                else:  # near(x[1], 1)
                    y[0] = x[0]
                    y[1] = x[1] - 1.

        periodic_boundary_condition = PeriodicBoundary()

        #Set up finite elements
        mesh = fenics.RectangleMesh(fenics.Point(0, 0),
                                    fenics.Point(domain_size, domain_size), nx,
                                    ny)
        vector_element = fenics.VectorElement('P', fenics.triangle, 2, dim=2)
        single_element = fenics.FiniteElement('P', fenics.triangle, 2)
        mixed_element = fenics.MixedElement(vector_element, single_element)
        V = fenics.FunctionSpace(
            mesh,
            mixed_element,
            constrained_domain=periodic_boundary_condition)
        v, r = fenics.TestFunctions(V)
        full_trial_function = fenics.Function(V)
        u, rho = fenics.split(full_trial_function)
        full_trial_function_n = fenics.Function(V)
        u_n, rho_n = fenics.split(full_trial_function_n)

        #Define non-linear weak formulation
        def epsilon(u):
            return 0.5 * (fenics.nabla_grad(u) + fenics.nabla_grad(u).T
                          )  #return sym(nabla_grad(u))

        def sigma_e(u):
            return lambda_ * ufl.nabla_div(u) * fenics.Identity(
                2) + 2 * mu * epsilon(u)

        def sigma_d(u):
            return eta_b * ufl.nabla_div(u) * fenics.Identity(
                2) + 2 * eta_s * epsilon(u)
#         def sigma_a(u,rho):
#             return ( -zeta_1*rho/(1+zeta_2*rho)*mu_a*fenics.Identity(2)*(K_0+K_1*ufl.nabla_div(u)+
#                                                                          K_2*ufl.nabla_div(u)*ufl.nabla_div(u)+K_3*ufl.nabla_div(u)*ufl.nabla_div(u)*ufl.nabla_div(u)))

        def sigma_a(u, rho):
            return -zeta_1 * rho / (
                1 + zeta_2 * rho) * mu_a * fenics.Identity(2) * (K_0)

        F = (gamma * fenics.dot(u, v) * fenics.dx -
             gamma * fenics.dot(u_n, v) * fenics.dx +
             fenics.inner(sigma_d(u), fenics.nabla_grad(v)) * fenics.dx -
             fenics.inner(sigma_d(u_n), fenics.nabla_grad(v)) * fenics.dx -
             delta_t *
             fenics.inner(sigma_e(u) + sigma_a(u, rho), fenics.nabla_grad(v)) *
             fenics.dx + rho * r * fenics.dx - rho_n * r * fenics.dx +
             ufl.nabla_div(rho * u) * r * fenics.dx -
             ufl.nabla_div(rho * u_n) * r * fenics.dx - D * delta_t *
             fenics.dot(fenics.nabla_grad(rho), fenics.nabla_grad(r)) *
             fenics.dx + delta_t *
             (-k_u * rho * fenics.exp(alpha * ufl.nabla_div(u)) + k_b *
              (1 - c * ufl.nabla_div(u))) * r * fenics.dx)

        #         F = ( gamma*fenics.dot(u,v)*fenics.dx - gamma*fenics.dot(u_n,v)*fenics.dx + fenics.inner(sigma_d(u),fenics.nabla_grad(v))*fenics.dx -
        #               fenics.inner(sigma_d(u_n),fenics.nabla_grad(v))*fenics.dx - delta_t*fenics.inner(sigma_e(u)+sigma_a(u,rho),fenics.nabla_grad(v))*fenics.dx
        #               +rho*r*fenics.dx-rho_n*r*fenics.dx + ufl.nabla_div(rho*u)*r*fenics.dx - ufl.nabla_div(rho*u_n)*r*fenics.dx -
        #               D*delta_t*fenics.dot(fenics.nabla_grad(rho),fenics.nabla_grad(r))*fenics.dx +delta_t*(-k_u*rho*fenics.exp(alpha*ufl.nabla_div(u))+k_b*(1-c*ufl.nabla_div(u))))

        vtkfile_rho = fenics.File(
            os.path.join(os.path.dirname(__file__), 'output', 'myosin_2d',
                         'solution_rho.pvd'))
        vtkfile_u = fenics.File(
            os.path.join(os.path.dirname(__file__), 'output', 'myosin_2d',
                         'solution_u.pvd'))

        #         rho_0 = fenics.Expression(((('0.0'),('0.0'),('0.0')),('sin(x[0])')), degree=1 )
        #         full_trial_function_n = fenics.project(rho_0, V)
        time = 0.0
        for time_index in range(number_of_time_steps):
            # Update current time
            time += delta_t
            # Compute solution
            fenics.solve(F == 0, full_trial_function)
            # Save to file and plot solution
            vis_u, vis_rho = full_trial_function.split()
            vtkfile_rho << (vis_rho, time)
            vtkfile_u << (vis_u, time)
            full_trial_function_n.assign(full_trial_function)
示例#17
0
 def geneMesh(self):
     dPML, xx, yy, Nx, Ny = self.dPML, self.xx, self.yy, self.nx, self.ny
     self.mesh = fe.RectangleMesh(fe.Point(-dPML, -dPML), fe.Point(xx+dPML, yy+dPML), Nx, Ny)
     self.haveMesh = True
示例#18
0
 def rectangle(self, p1, p2, nx, ny):
     return FEN.RectangleMesh(FEN.Point(p1), FEN.Point(p2), nx, ny)
示例#19
0
                            Chosen to be zero. Dirichlet boundary.
    u  = u_0                at t = 0 (initial condition).
                            Chosen to be a Gaussian hill. exp(-a*x**2 - a*y**2)

"""

import fenics as fs
import matplotlib.pyplot as plt

T = 2.0            # final time
num_steps = 50     # number of time steps
dt = T / num_steps # time step size

# create mesh and define function space
nx = ny = 30
mesh = fs.RectangleMesh(fs.Point(-2,-2), fs.Point(2,2), nx, ny)
V = fs.FunctionSpace(mesh, 'P', 1)

# Define boundary condition
u_D = fs.Constant(0)

def boundary(x, on_boundary):
    return on_boundary

bc = fs.DirichletBC(V, u_D, boundary)

# Define initial value
u_0 = fs.Expression('exp(-a * pow(x[0], 2) - a * pow(x[1], 2))', degree=2, a=5)
u_n = fs.interpolate(u_0, V)

# Define variational problem
def test_variable_viscosity__nightly():

    lid = "near(x[1],  1.)"

    ymin = -0.25
    
    fixed_walls = "near(x[0],  0.) | near(x[0],  1.) | near(x[1],  '+str(ymin)+')"

    left_middle = "near(x[0], 0.) && near(x[1], 0.5)"
    
    output_dir = "output/test_variable_viscosity"
    
    mesh = fenics.RectangleMesh(fenics.Point(0., ymin), fenics.Point(1., 1.), 20, 25, 'crossed')
    
    
    # Refine the initial PCI.
    initial_pci_refinement_cycles = 4
    
    class PCI(fenics.SubDomain):
        
        def inside(self, x, on_boundary):
        
            return fenics.near(x[1], 0.)

            
    pci = PCI()
    
    for i in range(initial_pci_refinement_cycles):
        
        edge_markers = fenics.EdgeFunction("bool", mesh)
        
        pci.mark(edge_markers, True)

        fenics.adapt(mesh, edge_markers)
        
        mesh = mesh.child()
    
    
    # Run the simulation.
    w, mesh = phaseflow.run(
        mesh = mesh,
        end_time = 20.,
        time_step_size = 1.,
        stop_when_steady = True,
        steady_relative_tolerance = 1.e-4,
        thermal_conductivity = 0.,
        liquid_viscosity = 0.01,
        solid_viscosity = 1.e6,
        temperature_of_fusion = -0.01,
        regularization_smoothing_factor = 0.01,
        gravity = (0., 0.),
        stefan_number = 1.e16,
        adaptive = True,
        output_dir = output_dir,
        initial_values_expression = (lid, "0.", "0.", "1. - 2.*(x[1] <= 0.)"),
        boundary_conditions = [
            {'subspace': 0, 'value_expression': ("1.", "0."), 'degree': 3, 'location_expression': lid, 'method': 'topological'},
            {'subspace': 0, 'value_expression': ("0.", "0."), 'degree': 3, 'location_expression': fixed_walls, 'method': 'topological'},
            {'subspace': 1, 'value_expression': "0.", 'degree': 2, 'location_expression': left_middle, 'method': 'pointwise'}])
    
    
    # Verify against the known solution.
    verify_against_ghia1982(w, mesh)
示例#21
0
import fenics as fn
fn.parameters["form_compiler"]["representation"] = "uflacs"
fn.parameters["form_compiler"]["cpp_optimize"] = True

# Create mesh and define function space
L = 50.0

mesh = fn.RectangleMesh(fn.Point(-50, 0), fn.Point(50, 75), 50, 30)
nn = fn.FacetNormal(mesh)

# Defintion of function spaces
Vh = fn.VectorElement("CG", mesh.ufl_cell(), 2)
Zh = fn.FiniteElement("CG", mesh.ufl_cell(), 1)
Qh = fn.FiniteElement("CG", mesh.ufl_cell(), 2)

# spaces for displacement and total pressure should be compatible
# whereas the space for fluid pressure can be "anything".
# In particular the one for total pressure
Hh = fn.FunctionSpace(mesh, fn.MixedElement([Vh, Zh, Qh]))

# trial and test functions
u, phi, p = fn.TrialFunctions(Hh)
v, psi, q = fn.TestFunctions(Hh)

fileU = fn.File(mesh.mpi_comm(), "Output/2_4_Footing_initial/u.pvd")
filePHI = fn.File(mesh.mpi_comm(), "Output/2_4_Footing_initial/phi.pvd")
fileP = fn.File(mesh.mpi_comm(), "Output/2_4_Footing_initial/p.pvd")

# model constants
E = fn.Constant(3.0e4)
nu = fn.Constant(0.4995)
ax.plot(ref_dat_x, ref_dat_concentration[:,0], ref_dat_x, ref_dat_concentration[:,1])
ax.set_ylabel(r'concentration $c\, (\mathrm{mM})$')
ax.set_xlabel(r'location $x\, (\mathrm{m})$')
fig.tight_layout()

# %% [markdown]
# ## minimalistic 

# %%
# define mesh and define function space
X    = 500  #x-limit
Y    = ref_domain_size / 2  #y-limit
NX   = 50  #x-steps
NY   = 50  #y-steps

mesh = fn.RectangleMesh(fn.Point(-X, -Y), fn.Point(X, Y), NX, NY)

Poly    = fn.FiniteElement('Lagrange', mesh.ufl_cell(),2)
Real    = fn.FiniteElement('Real', mesh.ufl_cell(), 0)
Elem    = [Poly,Poly,Poly,Real,Real] 
Mixed   = fn.MixedElement(Elem)
V       = fn.FunctionSpace(mesh, Mixed)

# %%
Elem

# %%
# define potentials and concentrations
u_GND  = fn.Constant(ref_potential_difference/2) #fn.Expression('0', degree=2)
u_DD   = fn.Constant(-ref_potential_difference/2) #fn.Expression('0.025', degree=2)
示例#23
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
示例#24
0
def unit_square():
    mesh = fa.RectangleMesh(fa.Point(0, 0), fa.Point(1, 1), 30, 30)
    return mesh
示例#25
0
def slender_rod():
    mesh = fa.RectangleMesh(fa.Point(0, 0), fa.Point(1, 10), 2, 20)
    return mesh
)  # q value that controls difficulty/discrete-valuedness of solution


def alpha(rho):
    """Inverse permeability as a function of rho"""
    return alphabar + (alphaunderbar - alphabar) * rho * (1 + q) / (rho + q)


N = 20
delta = 1.5  # The aspect ratio of the domain, 1 high and \delta wide
V = (
    fenics_adjoint.Constant(1.0 / 3) * delta
)  # want the fluid to occupy 1/3 of the domain

mesh = fenics_adjoint.Mesh(
    fenics.RectangleMesh(fenics.Point(0.0, 0.0), fenics.Point(delta, 1.0), N, N)
)
A = fenics.FunctionSpace(mesh, "CG", 1)  # control function space

U_h = fenics.VectorElement("CG", mesh.ufl_cell(), 2)
P_h = fenics.FiniteElement("CG", mesh.ufl_cell(), 1)
W = fenics.FunctionSpace(mesh, U_h * P_h)  # mixed Taylor-Hood function space

# Define the boundary condition on velocity
(x, y) = ufl.SpatialCoordinate(mesh)
l = 1.0 / 6.0  # noqa: E741
gbar = 1.0
cond1 = ufl.And(ufl.gt(y, (1.0 / 4 - l / 2)), ufl.lt(y, (1.0 / 4 + l / 2)))
val1 = gbar * (1 - (2 * (y - 0.25) / l) ** 2)
cond2 = ufl.And(ufl.gt(y, (3.0 / 4 - l / 2)), ufl.lt(y, (3.0 / 4 + l / 2)))
val2 = gbar * (1 - (2 * (y - 0.75) / l) ** 2)
示例#27
0
import fenics as fn
import time
# fenics parameters
fn.parameters["form_compiler"]["representation"] = "uflacs"
fn.parameters["form_compiler"]["cpp_optimize"] = True

# file outputs
fileE = fn.File("Output/1_4_Karma/E.pvd")
filen = fn.File("Output/1_4_Karma/n.pvd")
t = 0.0; dt = 0.3; Tfinal = 600.0; frequency = 100;

# mesh
L = 6.72; nps = 64;
mesh = fn.RectangleMesh(fn.Point(0, 0), fn.Point(L, L),
			            nps, nps, "crossed")

# element and function spaces
Mhe = fn.FiniteElement("CG", mesh.ufl_cell(), 1)
Mh  = fn.FunctionSpace(mesh, Mhe)
Nh  = fn.FunctionSpace(mesh, fn.MixedElement([Mhe,Mhe]))

# trial and test functions
v, n   = fn.TrialFunctions(Nh)
w, m   = fn.TestFunctions(Nh)

# solution
Ksol   = fn.Function(Nh)

# model constants
diffScale = fn.Constant(1e-3)
D0 = 1.1 * diffScale
示例#28
0
def regular_box_mesh(n=10,
                     S_x=0.0,
                     S_y=0.0,
                     S_z=None,
                     E_x=1.0,
                     E_y=1.0,
                     E_z=None):
    r"""Creates a mesh corresponding to a rectangle or cube.

	This function creates a uniform mesh of either a rectangle
	or a cube, with specified start (``S_``) and end points (``E_``).
	The resulting mesh uses ``n`` elements along the shortest direction
	and accordingly many along the longer ones. The resulting domain is

	.. math::
		\begin{alignedat}{2}
			&[S_x, E_x] \times [S_y, E_y] \quad &&\text{ in } 2D, \\
			&[S_x, E_x] \times [S_y, E_y] \times [S_z, E_z] \quad &&\text{ in } 3D.
		\end{alignedat}

	The boundary markers are ordered as follows:

	  - 1 corresponds to :math:`x=S_x`.

	  - 2 corresponds to :math:`x=E_x`.

	  - 3 corresponds to :math:`y=S_y`.

	  - 4 corresponds to :math:`y=E_y`.

	  - 5 corresponds to :math:`z=S_z` (only in 3D).

	  - 6 corresponds to :math:`z=E_z` (only in 3D).

	Parameters
	----------
	n : int
		Number of elements in the shortest coordinate direction.
	S_x : float
		Start of the x-interval.
	S_y : float
		Start of the y-interval.
	S_z : float or None, optional
		Start of the z-interval, mesh is 2D if this is ``None``
		(default is ``None``).
	E_x : float
		End of the x-interval.
	E_y : float
		End of the y-interval.
	E_z : float or None, optional
		End of the z-interval, mesh is 2D if this is ``None``
		(default is ``None``).

	Returns
	-------
	mesh : dolfin.cpp.mesh.Mesh
		The computational mesh.
	subdomains : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the subdomains.
	boundaries : dolfin.cpp.mesh.MeshFunctionSizet
		A MeshFunction object containing the boundaries.
	dx : ufl.measure.Measure
		The volume measure of the mesh corresponding to subdomains.
	ds : ufl.measure.Measure
		The surface measure of the mesh corresponding to boundaries.
	dS : ufl.measure.Measure
		The interior facet measure of the mesh corresponding to boundaries.
	"""

    n = int(n)

    if not n > 0:
        raise InputError('cashocs.geometry.regular_box_mesh', 'n',
                         'This needs to be positive.')

    if not S_x < E_x:
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_x',
            'Incorrect input for the x-coordinate. S_x has to be smaller than E_x.'
        )
    if not S_y < E_y:
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_y',
            'Incorrect input for the y-coordinate. S_y has to be smaller than E_y.'
        )
    if not ((S_z is None and E_z is None) or (S_z < E_z)):
        raise InputError(
            'cashocs.geometry.regular_box_mesh', 'S_z',
            'Incorrect input for the z-coordinate. S_z has to be smaller than E_z, or only one of them is specified.'
        )

    if S_z is None:
        lx = E_x - S_x
        ly = E_y - S_y
        sizes = [lx, ly]
        dim = 2
    else:
        lx = E_x - S_x
        ly = E_y - S_y
        lz = E_z - S_z
        sizes = [lx, ly, lz]
        dim = 3

    size_min = np.min(sizes)
    num_points = [int(np.round(length / size_min * n)) for length in sizes]

    if S_z is None:
        mesh = fenics.RectangleMesh(fenics.Point(S_x, S_y),
                                    fenics.Point(E_x, E_y), num_points[0],
                                    num_points[1])
    else:
        mesh = fenics.BoxMesh(fenics.Point(S_x, S_y, S_z),
                              fenics.Point(E_x, E_y, E_z), num_points[0],
                              num_points[1], num_points[2])

    subdomains = fenics.MeshFunction('size_t', mesh, dim=dim)
    boundaries = fenics.MeshFunction('size_t', mesh, dim=dim - 1)

    x_min = fenics.CompiledSubDomain('on_boundary && near(x[0], sx, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     sx=S_x)
    x_max = fenics.CompiledSubDomain('on_boundary && near(x[0], ex, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     ex=E_x)
    x_min.mark(boundaries, 1)
    x_max.mark(boundaries, 2)

    y_min = fenics.CompiledSubDomain('on_boundary && near(x[1], sy, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     sy=S_y)
    y_max = fenics.CompiledSubDomain('on_boundary && near(x[1], ey, tol)',
                                     tol=fenics.DOLFIN_EPS,
                                     ey=E_y)
    y_min.mark(boundaries, 3)
    y_max.mark(boundaries, 4)

    if S_z is not None:
        z_min = fenics.CompiledSubDomain('on_boundary && near(x[2], sz, tol)',
                                         tol=fenics.DOLFIN_EPS,
                                         sz=S_z)
        z_max = fenics.CompiledSubDomain('on_boundary && near(x[2], ez, tol)',
                                         tol=fenics.DOLFIN_EPS,
                                         ez=E_z)
        z_min.mark(boundaries, 5)
        z_max.mark(boundaries, 6)

    dx = fenics.Measure('dx', mesh, subdomain_data=subdomains)
    ds = fenics.Measure('ds', mesh, subdomain_data=boundaries)
    dS = fenics.Measure('dS', mesh)

    return mesh, subdomains, boundaries, dx, ds, dS
示例#29
0
def pme(ts, output_times, x_bins, sigma, fenics_nx=101, fenics_ny=2, fenics_dt=0.05):
    '''
    Here "output_times" are in real, forwards-time units.
    '''
    width = ts.metadata['SLiM']['user_metadata']['WIDTH'][0]
    height = ts.metadata['SLiM']['user_metadata']['HEIGHT'][0]
    K = ts.metadata['SLiM']['user_metadata']['K'][0]
    theta = ts.metadata['SLiM']['user_metadata']['THETA'][0]
    slim_dt = ts.metadata['SLiM']['user_metadata']['DT'][0]

    step_ago = ts.metadata['SLiM']['generation'] - np.min(output_times) / slim_dt - 1
    init_xy = np.array([
        ts.individual(i).location[:2]
        for i in ts.individuals_alive_at(step_ago)
    ])

    # Create mesh and define function space
    mesh = fenics.RectangleMesh(
        p0=fenics.Point(0, 0),
        p1=fenics.Point(width, height),
        nx=fenics_nx,
        ny=fenics_ny,
    )
    V = fenics.FunctionSpace(mesh, 'P', 1)

    # Define initial value
    # Note that since out simulation is 1D, but the analytic solution is 2D,
    # to convert from the simulations' density-per-unit-x-area
    # to fenic's density-per-unit-xy-area we need to multiply the simulation
    # by 'height', which corresponds to placing height/K mass at each point.
    u_n = project_locations(init_xy, V, K/height)

    # Define variational problem
    u = fenics.Function(V)
    v = fenics.TestFunction(V)
    def get_F(u, v, dt):
        dx = fenics.dx
        F = (u * v * dx
             + dt * (sigma**2 / 2)
                * fenics.dot(fenics.grad(u**2), fenics.grad(v)) * dx
             - (1 / theta) * dt * u * (1 - u) * v * dx
             - u_n * v * dx
        )
        return F

    def observed(u, x_bins):
        """
        Note this is in units of (average per unit xy-area).
        """
        out = np.zeros(len(x_bins) - 1)
        for j in range(len(x_bins) - 1):
            out[j] = mean_value(u, x_bins[j], x_bins[j+1], V)
        return out

    # too much output!!!
    fenics.set_log_active(False)

    output = np.empty((len(x_bins) - 1, len(output_times)))
    # Time-stepping
    t = np.min(output_times)
    for j, next_t in enumerate(output_times):
        t_diff = next_t - t
        if t_diff > 0:
            num_dt = int(np.ceil(t_diff / fenics_dt))
            dt = t_diff / num_dt
            F = get_F(u, v, dt=dt)
            for _ in range(num_dt):
                # Compute solution
                fenics.solve(F == 0, u)
                # Update previous solution
                u_n.assign(u)
        output[:, j] = observed(u_n, x_bins)
        t = next_t

    return output