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
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)
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
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
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'))
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])
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')
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)
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
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)
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
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
# 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
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)
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
def rectangle(self, p1, p2, nx, ny): return FEN.RectangleMesh(FEN.Point(p1), FEN.Point(p2), nx, ny)
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)
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)
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
def unit_square(): mesh = fa.RectangleMesh(fa.Point(0, 0), fa.Point(1, 1), 30, 30) return mesh
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)
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
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
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