def run_fokker_planck(nx, num_steps, t_0 = 0, t_final=10): # define mesh mesh = IntervalMesh(nx, -200, 200) # define function space. V = FunctionSpace(mesh, "Lagrange", 1) # Homogenous Neumann BCs don't have to be defined as they are the default in dolfin # define parameters. dt = (t_final-t_0) / num_steps # set mu and sigma mu = Constant(-1) D = Constant(1) # define initial conditions u_0 u_0 = Expression('x[0]', degree=1) # set U_n to be the interpolant of u_0 over the function space V. Note that # u_n is the value of u at the previous timestep, while u is the current value. u_n = interpolate(u_0, V) # Define variational problem u = TrialFunction(V) v = TestFunction(V) F = u*v*dx + dt*inner(D*grad(u), grad(v))*dx + dt*mu*grad(u)[0]*v*dx - inner(u_n, v)*dx # isolate the bilinear and linear forms. a, L = lhs(F), rhs(F) # initialize function to capture solution. t = 0 u_h = Function(V) plt.figure(figsize=(15, 15)) # time-stepping section for n in range(num_steps): t += dt # compute solution solve(a == L, u_h) u_n.assign(u_h) # Plot solutions intermittently if n % (num_steps // 10) == 0 and num_steps > 0: plot(u_h, label='t = %s' % t) plt.legend() plt.grid() plt.title("Finite Element Solutions to Fokker-Planck Equation with $\mu(x, t) = -(x+1)$ , $D(x, t) = e^t x^2$, $t_n$ = %s" % t_final) plt.ylabel("$u(x, t)$") plt.xlabel("x") plt.savefig("fpe/fokker-planck-solutions-mu.png") plt.clf() # return the approximate solution evaluated on the coordinates, and the actual coordinates. return u_n.compute_vertex_values(), mesh.coordinates()
def plotSol(self, func): (Asol, Qsol) = self.U0.split() if func == "A": fe.plot(Asol) elif func == "Q": fe.plot(Qsol) else: raise ValueError('input can either be "Q" or "A"')
def impl_dyn(w0, dt=1.e-5, t_end=1.e-4, show_plots=False): (u0, p0, v0) = fe.split(w0) bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_upv.sub(0), V_upv.sub(1), V_upv.sub(2), boundaries) # Lagrange function (without constraint) (u1, p1, v1) = fe.TrialFunctions(V_upv) (eta, q, xi) = fe.TestFunctions(V_upv) F = deformation_grad(u1) I_1, I_2, J = invariants(F) F_iso = isochronic_deformation_grad(F, J) #I_1_iso, I_2_iso = invariants(F_iso)[0:2] W = material_mooney_rivlin(I_1, I_2, c_10, c_01) g = incompr_constr(J) L = -W P = first_piola_stress(L, F) G = incompr_stress(g, F) a_dyn_u = inner(u1 - u0, eta) * dx - dt * inner(v1, eta) * dx a_dyn_p = inner(g, q) * dx a_dyn_v = rho * inner(v1 - v0, xi) * dx + dt * (inner( P, grad(xi)) * dx + inner(p1 * G, grad(xi)) * dx - inner(B, xi) * dx) a = a_dyn_u + a_dyn_p + a_dyn_v w1 = fe.Function(V_upv) sol = [] t = 0 while t < t_end: print("progress: %f" % (100. * t / t_end)) fe.solve(a == 0, w1, bcs_u + bcs_p + bcs_v) if fe.norm(w1.vector()) > 1e7: print('ERROR: norm explosion') break # update initial values for next step w0.assign(w1) t += dt if show_plots: # plot result fe.plot(w0.sub(0), mode='displacement') plt.show() # save solutions sol.append(Solution(t=t)) sol[-1].upv.assign(w0) return sol, W, kappa
def drawSolution(self): plt.figure(figsize=(10, 5)) plt.subplot(1, 2, 1) imuR = fe.plot(self.uReal, title='Real part of the solution') plt.colorbar(imuR) plt.subplot(1, 2, 2) imuI = fe.plot(self.uImag, title='Imaginary part of the solution') plt.colorbar(imuI) plt.show()
def plot_diffusion_coef(self, entries='01'): indices = [int(entry) for entry in entries] vector = np.zeros(2) vector[indices] = 1 print(vector) fevec = fe.Constant(vector) val = fe.dot(self.composed_diff_coef, fevec) val = fe.dot(fevec, val) fe.plot(val, mesh=self.mesh) plt.show()
def _solve_cell_problems(self): # Solves the cell problems (one for each space dimension) w = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) a = self.a_y * fe.dot(fe.grad(w), fe.grad(v)) * fe.dx for i in range(self.dim): L = fe.div(self.a_y * self.e_is[i]) * v * fe.dx bc = fe.DirichletBC(self.function_space, self.bc_function, PoissonSolver.boundary) fe.solve(a == L, self.cell_solutions[i], bc) fe.plot(self.cell_solutions[i])
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 solve_poisson_with_fem(lightweight=False): # Create mesh and define function space mesh = fs.UnitSquareMesh(8, 8) V = fs.FunctionSpace(mesh, 'P', 1) # Define boundary condition u_code = 'x[0] + 2*x[1] + 1' u_D = fs.Expression(u_code, degree=2) def boundary(x, on_boundary): return on_boundary bc = fs.DirichletBC(V, u_D, boundary) # Define variational problem u = fs.Function(V) # Note: not TrialFunction! v = fs.TestFunction(V) # f = fs.Expression(f_code, degree=2) f_code = '-10*x[0] - 20*x[1] - 10' f = fs.Expression(f_code, degree=2) F = q(u) * fs.dot(fs.grad(u), fs.grad(v)) * fs.dx - f * v * fs.dx # Compute solution fs.solve(F == 0, u, bc) # Plot solution fs.plot(u) # Compute maximum error at vertices. This computation illustrates # an alternative to using compute_vertex_values as in poisson.py. u_e = fs.interpolate(u_D, V) # Restore numpy object image1d = np.empty((81, ), dtype=np.float) for v in fs.vertices(mesh): image1d[v.index()] = u(*mesh.coordinates()[v.index()]) if not lightweight: error_max = np.abs(u_e.vector().get_local() - u.vector().get_local()).max() print('error_max = ', error_max) fs.plot(u) plt.show() save_contour(image1d, 1.0, 1.0, 'poisson') return image1d
def solve_poisson_eps(h, eps, plot=False): eps = fe.Constant(eps) n = int(1 / h) # Create mesh and define function space mesh = fe.UnitIntervalMesh(n) V = fe.FunctionSpace(mesh, 'P', 1) # Define boundary condition u_D = fe.Constant(0.0) # Find exact solution: u_exact = fe.Expression( "(1./2 - x[0]) * (2 * x[0] + eps/(2*pi) * sin(2*pi*x[0]/eps)) " "+ eps*eps/(2*pi*2*pi) * (1 - cos(2*pi*x[0]/eps)) + x[0]*x[0]", eps=eps, degree=4) def boundary(x, on_boundary): return on_boundary bc = fe.DirichletBC(V, u_D, boundary) # Define variational problem u = fe.TrialFunction(V) v = fe.TestFunction(V) f = fe.Constant(1) A = fe.Expression('1./(2+cos(2*pi*x[0]/eps))', eps=eps, degree=2) a = A * fe.dot(fe.grad(u), fe.grad(v)) * fe.dx L = f * v * fe.dx # Compute solution u = fe.Function(V) fe.solve(a == L, u, bc) if plot: # Plot solution fe.plot(u) fe.plot(u_exact, mesh=mesh) # Hold plot fe.interactive() # # Save solution to file in VTK format # vtkfile = fe.File('poisson/solution.pvd') # vtkfile << u # Compute error err_norm = fe.errornorm(u_exact, u, 'L2') return err_norm
def solve_pde(self): u = fe.Function(self.function_space) v = fe.TestFunction(self.function_space) u_old = fe.project(self.u_0, self.function_space) # Todo: Average right hand side if we choose it non-constant flux = self.dt * fe.dot( self.composed_diff_coef * (fe.grad(u) + self.drift_function(u)), fe.grad(v)) * fe.dx bilin_part = u * v * fe.dx + flux funtional_part = self.rhs * v * self.dt * fe.dx + u_old * v * fe.dx full_form = bilin_part - funtional_part num_steps = int(self.T / self.dt) + 1 bc = fe.DirichletBC(self.function_space, self.u_boundary, MembraneSimulator.full_boundary) for n in range(num_steps): print("Step %d" % n) self.time += self.dt fe.solve(full_form == 0, u, bc) # fe.plot(u) # plt.show() # print(fe.errornorm(u_old, u)) u_old.assign(u) self.file << (u, self.time) f = fe.plot(u) plt.rc('text', usetex=True) plt.colorbar(f, format='%.0e') plt.title(r'Macroscopic density profile of $u(x,t)$ at $t=1$') plt.xlabel(r'$x_1$') plt.ylabel(r'$x_2$') plt.show()
def fplot(f, compare=None, dim=None, xmin=0, xmax=1, npoints=100, axes=None, legend=None, mesh=None): """plot a function f Positional parameter: f: the function to be plotted Keyword parameters: dim=1: dimensionality of the argument of f npoints=100: number points to plot xmin=0, xmax=1: range to plot """ if not dim: if mesh: dim = mesh.geometry().dim() else: dim = 1 if (dim > 1): # # compare ignored in this case # p = fe.plot(f, mesh=mesh, axes=axes) plt.colorbar(p) return p if not axes: axes = plt.gca() xs = np.linspace(xmin, xmax, npoints) if compare: p = axes.plot(xs, [f(x) for x in xs], 'b', xs, [compare(x) for x in xs], 'r') if legend: plt.legend(p, legend) else: p = axes.plot(xs, [f(x) for x in xs], 'b') return p
def test_video_loading(): m = UnitSquareMesh(30, 30) V = FunctionSpace(m, "CG", 4) video = VideoData(element=V.ufl_element()) video.load_video("video_data/ach12.mp4") print(video) plot(video, mesh=m) plt.show() video.set_time(10000.) plot(video, mesh=m) plt.show() assert True
def run(self): domain = self._create_domain() mesh = generate_mesh(domain, MESH_PTS) # fe.plot(mesh) # plt.show() self._create_boundary_expression() Omega = fe.FunctionSpace(mesh, 'CG', 2) sigma = self.conductivity Theta = fe.Function(Omega) v = fe.TestFunction(Omega) LHS = sigma * fe.inner(fe.grad(Theta), fe.grad(v)) * fe.dx - self.boundary_exp * v * fe.ds fe.solve(LHS == 0, Theta, solver_parameters={"newton_solver": {"absolute_tolerance": 1e-4}}) fe.plot(Theta, "solution") plt.show()
def plot(eigenvalues: np.array, eigenfunctions: List[fenics.Function], **kwargs) -> None: """Plot eigenvalues and eigenfunctions. Convenience function for plotting the results of the eigenfunction decomposition. """ num_eigenpairs = len(eigenvalues) assert num_eigenpairs == len(eigenfunctions) import matplotlib.pyplot as plt k = int(np.ceil(np.sqrt(num_eigenpairs - 1))) for i, (ew, ev) in enumerate(zip(eigenvalues[1:], eigenfunctions[1:])): ax = plt.subplot(k, k, i + 1) ax.axis('off') ax.set_title('$\lambda_{{{}}} = {:.2f}$'.format(i + 1, ew)) fenics.plot(ev, **kwargs)
def solve_pde(self, name='pde'): u = fe.Function(self.function_space) v = fe.TestFunction(self.function_space) u_old = fe.project(self.u_0, self.function_space) # Todo: Average right hand side if we choose it non-constant flux = self.dt * fe.dot( self.composed_diff_coef * (fe.grad(u) + self.drift_function(u)), fe.grad(v)) * fe.dx bilin_part = u * v * fe.dx + flux funtional_part = self.rhs * v * self.dt * fe.dx + u_old * v * fe.dx full_form = bilin_part - funtional_part num_steps = int(self.T / self.dt) + 1 bc = fe.DirichletBC(self.function_space, self.u_boundary, MembraneSimulator.full_boundary) for n in range(num_steps): print("Step %d" % n) self.time += self.dt fe.solve(full_form == 0, u, bc) fe.plot(u) plt.savefig('images/plt%d.pdf' % n) plt.show() # print(fe.errornorm(u_old, u)) u_old.assign(u) self.file << (u, self.time) plt.figure() # u=u+1E-9 f = fe.plot(u) # f = fe.plot(u,norm=colors.LogNorm(vmin=1E-9,vmax=2E-4)) plt.rc('text', usetex=True) plt.colorbar(f, format='%.0e') plt.title(r'Macroscopic density $u(x,t=1)$ for $\alpha=%.1f$' % MembraneSimulator.alpha) plt.xlabel(r'$x_1$') plt.ylabel(r'$x_2$') plt.savefig('%s.pdf' % name) plt.show()
def demo_video_complex(): #comm_mpi4py = fe.mpi_comm_world().tompi4py() #rk = comm_mpi4py.Get_rank() #if rk == 0: g = GmshInterface("geo/movie_2.geo", dim=2) g.generate_xml("geo/movie_2.xml",lc=1.,replace=False) #comm_mpi4py.Barrier() d.load_mesh("geo/movie_2.xml") d.boundary_fnc = lambda x: x[0] > -5. and x[1] < 5. fe.plot(d.mesh) plt.show() d.compute_potential_flow() fe.plot(d.flow) plt.show() d.load_video("video_data/ach12.mp4") d.compute_conv_diff_reac_video(video_ref=[0,0],video_size=[99.,69.])
def plot(object, **kwargs): """ Plot the given object based on its type. Parameters ---------- object: The object to be plotted. **kwargs: Same kwargs as the ones defined for fenics.plot(). Check docs to see all available arguments. Returns ------- None. """ kwargs.setdefault('figsize', (12, 7)) # Check if the given object is a mesh or submesh plt.figure(figsize=kwargs.get('figsize')) kwargs.pop('figsize') pp = fn.plot(object, **kwargs) plt.colorbar(pp) plt.show()
def plot_curves(t, soln, opts=defplotopts): min = soln.meshstats['xmin'] max = soln.meshstats['xmax'] nplots = len(opts['subspaces']) names = opts['names'] dim = soln.dim soln.load(t) width = 4.0 * nplots + 2.0 * (nplots - 1) fig = plt.figure(1, figsize=(width, 5)) currplot = 1 fig.clf() params = soln.params(t) try: labelval = params[opts['label']] except KeyError: labelval = t label = '%s = %.4g' % (opts['label'], labelval) for name, subspace in zip(names, opts['subspaces']): ra = fig.add_subplot(1, nplots, currplot) if type(subspace) == int: ssfunc = soln.function.sub(subspace) elif subspace == 'V': ssfunc = Vufl(soln, t) if dim == 1: p = fplot(ssfunc, xmin=min, xmax=max) plt.title("%s\n%s" % (name, label)) elif dim == 2: p = fe.plot(ssfunc, title="%s\n%s" % (name, label)) if opts['colorbar']: try: plt.colorbar(p) except AttributeError: pass else: raise KSDGException("can only plot 1 or 2 dimensions") dofs = np.array(ssfunc.function_space().dofmap().dofs()) fvec = ssfunc.vector()[:] ymin, ymax = np.min(fvec[dofs]), np.max(fvec[dofs]) plt.xlabel('(%7g, %7g)' % (ymin, ymax), axes=ra) currplot += 1 return (fig)
def plot(f): """ This patches `fenics.plot` which is incorrect for functions on refind 1D meshes. See https://bitbucket.org/fenics-project/dolfin/issues/1029/plotting-1d-function-incorrectly-ignores """ if (type(f) == fenics.Function) and ( f.function_space().mesh().topology().dim() == 1): mesh = f.function_space().mesh() C = f.compute_vertex_values(mesh) X = list(mesh.coordinates()[:, 0]) sorted_C = [c for _, c in sorted(zip(X, C))] return matplotlib.pyplot.plot(sorted(X), sorted_C) else: return fenics.plot(f)
def preprocess(fname): """Loads mesh, defines system of equations and prepares system matrix.""" mesh = fe.Mesh(fname + ".xml") if INPUTS['saving']['mesh']: fe.File(fname + "_mesh.pvd") << mesh boundaries = fe.MeshFunction('size_t', mesh, fname + '_facet_region.xml') if INPUTS['saving']['boundaries']: fe.File(fname + "_subdomains.pvd") << boundaries subdomains = fe.MeshFunction('size_t', mesh, fname + '_physical_region.xml') if INPUTS['saving']['subdomains']: fe.File(fname + "_subdomains.pvd") << subdomains if INPUTS['plotting']['mesh']: fe.plot(mesh, title='Mesh') if INPUTS['plotting']['boundaries']: fe.plot(boundaries, title='Boundaries') if INPUTS['plotting']['subdomains']: fe.plot(subdomains, title='Subdomains') fun_space = fe.FunctionSpace(mesh, INPUTS['element_type'], INPUTS['element_degree'], constrained_domain=PeriodicDomain()) if ARGS['--verbose']: dofmap = fun_space.dofmap() print('Number of DOFs:', len(dofmap.dofs())) field = fe.TrialFunction(fun_space) test_func = fe.TestFunction(fun_space) cond = Conductivity(subdomains, fe.Constant(INPUTS['conductivity']['gas']), fe.Constant(INPUTS['conductivity']['solid']), degree=0) system_matrix = -cond * fe.inner(fe.grad(field), fe.grad(test_func)) * fe.dx bctop = fe.Constant(INPUTS['boundary_conditions']['top']) bcbot = fe.Constant(INPUTS['boundary_conditions']['bottom']) bcs = [ fe.DirichletBC(fun_space, bctop, boundaries, 1), fe.DirichletBC(fun_space, bcbot, boundaries, 2) ] field = fe.Function(fun_space) return system_matrix, field, bcs, cond
bc = fex.DirichletBC(V, u_D, boundary) # Define variational problem u = fex.TrialFunction(V) v = fex.TestFunction(V) f = fex.Constant(-6.0) a = fex.dot(fex.grad(u), fex.grad(v)) * fex.dx L = f * v * fex.dx # Compute solution u = fex.Function(V) fex.solve(a == L, u, bc) print(u) # Plot solution and mesh plt.subplot(2, 1, 1) fex.plot(u) #define the boundary conditions plt.subplot(2, 1, 2) fex.plot(mesh) plt.savefig('possion_fex2.png') #define the boundary conditions # Save solution to file in VTK format vtkfile = fex.File('poisson/solution.pvd') vtkfile << u # Compute error in L2 norm error_L2 = fex.errornorm(u_D, u, 'L2') # Compute maximum error at vertices vertex_values_u_D = u_D.compute_vertex_values(mesh) vertex_values_u = u.compute_vertex_values(mesh)
def plot_mesh(self): FEN.plot(self._mesh)
def plot_u(self): FEN.plot(self._u)
hessp=SR1(), tol=1e-7, constraints=volume_constraint, bounds=((0, 1.0),) * A.dim(), options={"verbose": 3, "gtol": 1e-7, "maxiter": 20}, ) q.assign(0.1) res = minimize( min_f, res.x, method="trust-constr", jac=True, hessp=SR1(), tol=1e-7, constraints=volume_constraint, bounds=((0, 1.0),) * A.dim(), options={"verbose": 3, "gtol": 1e-7, "maxiter": 100}, ) rho_opt_final = from_numpy(res.x, fenics.Function(A)) c = fenics.plot(rho_opt_final) plt.colorbar(c) plt.show() rho_opt_file = fenics.XDMFFile( fenics.MPI.comm_world, "output/control_solution_final.xdmf" ) rho_opt_file.write(rho_opt_final)
constraints = [{ "type": "ineq", "fun": volume_inequality_fun, "jac": lambda x: jax.grad(volume_inequality_fun)(x), }] x0 = np.ones(C.dim()) * max_volume / (L * h) res = minimize_ipopt( min_f, x0, jac=True, bounds=((0.0, 1.0), ) * C.dim(), constraints=constraints, options={ "print_level": 5, "max_iter": 100 }, ) rho_opt_final = numpy_to_fenics(res.x, fa.Function(C)) c = fn.plot(rho_opt_final) plt.colorbar(c) plt.show() # Save optimal solution for visualizing with ParaView # with XDMFFile("1_dist_load/control_solution_1.xdmf") as f: # f.write(rho_opt)
# values[0] = sin(3.0*x[0])*sin(3.0*x[1])*sin(3.0*x[2]) # f0 = F0(name="f0", label="My expression", degree=2) class F0(UserExpression): def eval(self, values, x): values[0] = sin(3.0 * x[0]) * sin(3.0 * x[1]) * sin(3.0 * x[2]) class F1(UserExpression): def __init__(self, mesh, *arg, **kwargs): super().__init__(*arg, **kwargs) self.mesh = mesh def eval_cell(self, values, x, cell): c = Cell(self.mesh, cell.index) values[0] = sin(3.0 * x[0]) * sin(3.0 * x[1]) * sin(3.0 * x[2]) e0 = F0(degree=2) e1 = F1(mesh, degree=2) e2 = Expression("sin(3.0*x[0])*sin(3.0*x[1])*sin(3.0*x[2])", degree=2) u0 = interpolate(e0, V) u1 = interpolate(e1, V) u2 = interpolate(e2, V) fp = fe.interpolate(f0, V) fe.plot(fp) plt.show()
def solve_cell_problems(self, method='regularized', plot=False): """ Solve the cell problems for the given PDE by changing the geometry to exclude the zone in the middle :return: """ class PeriodicBoundary(fe.SubDomain): # Left boundary is "target domain" G def inside(self, x, on_boundary): par = MembraneSimulator.w / MembraneSimulator.length tol = 1E-4 return on_boundary and x[1] >= -tol and x[1] <= tol # Map right boundary (H) to left boundary (G) def map(self, x, y): y[1] = x[1] + 2 * self.eta / MembraneSimulator.length y[0] = x[0] mesh_size = 50 # Domain if method == 'circle': self.obstacle_radius = self.eta / MembraneSimulator.length / 2 box_begin_point = fe.Point(-self.w / MembraneSimulator.length, 0) box_end_point = fe.Point(self.w / MembraneSimulator.length, 2 * self.eta / MembraneSimulator.length) box = mshr.Rectangle(box_begin_point, box_end_point) cell = box - mshr.Circle( fe.Point(0, self.eta / MembraneSimulator.length), self.obstacle_radius, mesh_size) self.cell_mesh = mshr.generate_mesh(cell, mesh_size) diff_coef = fe.Constant( ((0, 0), (0, self.D[1, 1]))) # limit for regularisation below. # elif method == 'diff_coef': # print("Haha this is going to crash. Also it is horrible in accuracy") # self.cell_mesh = fe.RectangleMesh(fe.Point(-self.w / MembraneSimulator.length, 0), # fe.Point(self.w / MembraneSimulator.length, # 2 * self.eta / MembraneSimulator.length), mesh_size, mesh_size) # diff_coef = fe.Expression( # (('0', '0'), ('0', 'val * ((x[0] - c_x)*(x[0] - c_x) + (x[1] - c_y)*(x[1] - c_y) > r*r)')), # val=(4 * self.ref_T * MembraneSimulator.d2 / MembraneSimulator.length ** 2), c_x=0, # c_y=(self.eta / MembraneSimulator.length), # r=self.obstacle_radius, degree=2, domain=self.cell_mesh) elif method == 'regularized': box_begin_point = fe.Point(-self.w / MembraneSimulator.length, 0) box_end_point = fe.Point(self.w / MembraneSimulator.length, 2 * self.eta / MembraneSimulator.length) box = mshr.Rectangle(box_begin_point, box_end_point) obstacle_begin_point = fe.Point( -self.w / MembraneSimulator.length * self.obs_length, self.eta / MembraneSimulator.length * (1 - self.obs_height)) obstacle_end_point = fe.Point( self.w / MembraneSimulator.length * self.obs_length, self.eta / MembraneSimulator.length * (1 + self.obs_height)) obstacle = mshr.Rectangle(obstacle_begin_point, obstacle_end_point) cell = box - obstacle self.cell_mesh = mshr.generate_mesh(cell, mesh_size) diff_coef = fe.Constant(((self.obs_ratio * self.D[0, 0], 0), (0, self.D[1, 1]))) # defect matrix. else: raise ValueError("%s not a valid method to solve cell problem" % method) self.cell_fs = fe.FunctionSpace(self.cell_mesh, 'P', 2) self.cell_solutions = [ fe.Function(self.cell_fs), fe.Function(self.cell_fs) ] w = fe.TrialFunction(self.cell_fs) phi = fe.TestFunction(self.cell_fs) scaled_unit_vectors = [ fe.Constant((1. / np.sqrt(self.obs_ratio), 0.)), fe.Constant((0., 1.)) ] for i in range(2): weak_form = fe.dot( diff_coef * (fe.grad(w) + scaled_unit_vectors[i]), fe.grad(phi)) * fe.dx print("Solving cell problem") bc = fe.DirichletBC(self.cell_fs, fe.Constant(0), MembraneSimulator.cell_boundary) if i == 0: # Periodicity is applied automatically bc = None fe.solve( fe.lhs(weak_form) == fe.rhs(weak_form), self.cell_solutions[i], bc) if plot: plt.rc('text', usetex=True) f = fe.plot(self.cell_solutions[i]) plt.colorbar(f) plt.title(r'Solution to cell problem $w_%d$' % (i + 1)) plt.xlabel(r'$Y_1$') plt.ylabel(r'$Y_2$') print("Cell solution") print(np.min(self.cell_solutions[i].vector().get_local()), np.max(self.cell_solutions[i].vector().get_local())) plt.show()
from gmsh_interface import GmshInterface g = GmshInterface("../geo/simple_muscle_3d.geo") g.set_parameter("lc",0.1) g.generate_xml("../geo/test.xml") from fenics import Mesh, plot import matplotlib.pyplot as plt mesh = Mesh("../geo/test.xml") plot(mesh) plt.show()
def main(): """Main function. Organizes workflow.""" fname = str(INPUTS['filename']) term = Terminal() print( term.yellow + "Working on file {}.".format(fname) + term.normal ) # Load mesh and physical domains from file. mesh = fe.Mesh(fname + ".xml") if INPUTS['saving']['mesh']: fe.File(fname + "_mesh.pvd") << mesh if INPUTS['plotting']['mesh']: fe.plot(mesh, title='Mesh') subdomains = fe.MeshFunction( 'size_t', mesh, fname + '_physical_region.xml') if INPUTS['saving']['subdomains']: fe.File(fname + "_subdomains.pvd") << subdomains if INPUTS['plotting']['subdomains']: fe.plot(subdomains, title='Subdomains') # function space for temperature/concentration func_space = fe.FunctionSpace( mesh, INPUTS['element_type'], INPUTS['element_degree'], constrained_domain=PeriodicDomain() ) # discontinuous function space for visualization dis_func_space = fe.FunctionSpace( mesh, 'DG', INPUTS['element_degree'], constrained_domain=PeriodicDomain() ) if ARGS['--verbose']: print('Number of cells:', mesh.num_cells()) print('Number of faces:', mesh.num_faces()) print('Number of edges:', mesh.num_edges()) print('Number of vertices:', mesh.num_vertices()) print('Number of DOFs:', len(func_space.dofmap().dofs())) # temperature/concentration field field = fe.TrialFunction(func_space) # test function test_func = fe.TestFunction(func_space) # function, which is equal to 1 everywhere unit_function = fe.Function(func_space) unit_function.assign(fe.Constant(1.0)) # assign material properties to each domain if INPUTS['mode'] == 'conductivity': mat_prop = SubdomainConstant( subdomains, fe.Constant(INPUTS['conductivity']['gas']), fe.Constant(INPUTS['conductivity']['solid']), degree=0 ) elif INPUTS['mode'] == 'diffusivity': mat_prop = SubdomainConstant( subdomains, fe.Constant(INPUTS['diffusivity']['gas']), fe.Constant(INPUTS['diffusivity']['solid']) * fe.Constant(INPUTS['solubility'] * gas_constant * INPUTS['temperature']), degree=0 ) # assign 1 to gas domain, and 0 to solid domain gas_content = SubdomainConstant( subdomains, fe.Constant(1.0), fe.Constant(0.0), degree=0 ) # define structure of foam over whole domain structure = fe.project(unit_function * gas_content, dis_func_space) # calculate porosity and wall thickness porosity = fe.assemble(structure * fe.dx) / ((XMAX - XMIN) * (YMAX - YMIN) * (ZMAX - ZMIN)) print('Porosity: {0}'.format(porosity)) dwall = wall_thickness( porosity, INPUTS['morphology']['cell_size'], INPUTS['morphology']['strut_content']) print('Wall thickness: {0} m'.format(dwall)) # calculate effective conductivity/diffusivity by analytical model if INPUTS['mode'] == 'conductivity': eff_prop = analytical_conductivity( INPUTS['conductivity']['gas'], INPUTS['conductivity']['solid'], porosity, INPUTS['morphology']['strut_content']) print('Analytical model: {0} W/(mK)'.format(eff_prop)) elif INPUTS['mode'] == 'diffusivity': eff_prop = analytical_diffusivity( INPUTS['diffusivity']['solid'] * INPUTS['solubility'], INPUTS['solubility'], porosity, INPUTS['morphology']['cell_size'], dwall, INPUTS['temperature'], INPUTS['morphology']['enhancement_par']) print('Analytical model: {0} m^2/s'.format(eff_prop)) # create system matrix system_matrix = -mat_prop * \ fe.inner(fe.grad(field), fe.grad(test_func)) * fe.dx left_side, right_side = fe.lhs(system_matrix), fe.rhs(system_matrix) # define boundary conditions bcs = [ fe.DirichletBC(func_space, fe.Constant( INPUTS['boundary_conditions']['top']), top_bc), fe.DirichletBC(func_space, fe.Constant( INPUTS['boundary_conditions']['bottom']), bottom_bc) ] # compute solution field = fe.Function(func_space) fe.solve(left_side == right_side, field, bcs) # output temperature/concentration at the boundaries if ARGS['--verbose']: print('Checking periodicity:') print('Value at XMIN:', field(XMIN, (YMIN + YMAX) / 3, (ZMIN + ZMAX) / 3)) print('Value at XMAX:', field(XMAX, (YMIN + YMAX) / 3, (ZMIN + ZMAX) / 3)) print('Value at YMIN:', field((XMIN + XMAX) / 3, YMIN, (ZMIN + ZMAX) / 3)) print('Value at YMAX:', field((XMIN + XMAX) / 3, YMAX, (ZMIN + ZMAX) / 3)) print('Value at ZMIN:', field((XMIN + XMAX) / 3, (YMIN + YMAX) / 3, ZMIN)) print('Value at ZMAX:', field((XMIN + XMAX) / 3, (YMIN + YMAX) / 3, ZMAX)) # calculate flux, and effective properties vec_func_space = fe.VectorFunctionSpace( mesh, INPUTS['element_type'], INPUTS['element_degree'] ) flux = fe.project(-mat_prop * fe.grad(field), vec_func_space) divergence = fe.project(-fe.div(mat_prop * fe.grad(field)), func_space) flux_x, flux_y, flux_z = flux.split() av_flux = fe.assemble(flux_z * fe.dx) / ((XMAX - XMIN) * (YMAX - YMIN)) eff_prop = av_flux * (ZMAX - ZMIN) / ( INPUTS['boundary_conditions']['top'] - INPUTS['boundary_conditions']['bottom'] ) if INPUTS['mode'] == 'conductivity': print('Numerical model: {0} W/(mK)'.format(eff_prop)) elif INPUTS['mode'] == 'diffusivity': print('Numerical model: {0} m^2/s'.format(eff_prop)) # projection of concentration has to be in discontinuous function space if INPUTS['mode'] == 'diffusivity': sol_field = SubdomainConstant( subdomains, fe.Constant(1.0), fe.Constant(INPUTS['solubility'] * gas_constant * INPUTS['temperature']), degree=0 ) field = fe.project(field * sol_field, dis_func_space) # save results with open(fname + "_eff_prop.csv", 'w') as textfile: textfile.write('eff_prop\n') textfile.write('{0}\n'.format(eff_prop)) fe.File(fname + "_solution.pvd") << field fe.File(fname + "_structure.pvd") << structure if INPUTS['saving']['flux']: fe.File(fname + "_flux.pvd") << flux if INPUTS['saving']['flux_divergence']: fe.File(fname + "_flux_divergence.pvd") << divergence if INPUTS['saving']['flux_components']: fe.File(fname + "_flux_x.pvd") << flux_x fe.File(fname + "_flux_y.pvd") << flux_y fe.File(fname + "_flux_z.pvd") << flux_z # plot results if INPUTS['plotting']['solution']: fe.plot(field, title="Solution") if INPUTS['plotting']['flux']: fe.plot(flux, title="Flux") if INPUTS['plotting']['flux_divergence']: fe.plot(divergence, title="Divergence") if INPUTS['plotting']['flux_components']: fe.plot(flux_x, title='x-component of flux (-kappa*grad(u))') fe.plot(flux_y, title='y-component of flux (-kappa*grad(u))') fe.plot(flux_z, title='z-component of flux (-kappa*grad(u))') if True in INPUTS['plotting'].values(): fe.interactive() print( term.yellow + "End." + term.normal )
def plot(self): # Quickplot of the solution fe.plot(self.diff_coef, mesh=self.mesh) fe.plot(self.solution) fe.interactive()
# Update current time t += dt # Step 1: Tentative velocity step b1 = fs.assemble(L1) [bc.apply(b1) for bc in bcu] fs.solve(A1, u_.vector(), b1) # Step 2: Pressure correction step b2 = fs.assemble(L2) [bc.apply(b2) for bc in bcp] fs.solve(A2, p_.vector(), b2) # Step 3: Velocity correction step b3 = fs.assemble(L3) fs.solve(A3, u_.vector(), b3) # Plot solutions fs.plot(u_) plt.pause(0.1) # Compute error u_e = fs.Expression(('4*x[1]*(1.0 - x[1])', '0'), degree=2) u_e = fs.interpolate(u_e, V) error = np.abs(u_e.vector() - u_.vector()).max() print('t = %.2f: error = %.3g' % (t, error)) print('max u:', u_.vector().max()) # Update previous solution u_n.assign(u_) p_n.assign(p_)