def form_fluid_adjoint( displacement_fluid_adjoint, velocity_fluid_adjoint, xi_fluid, eta_fluid, fluid: Space, param: Parameters, ): return ( param.NU * dot(grad(eta_fluid), grad(displacement_fluid_adjoint)) * fluid.dx + dot(param.BETA, grad(eta_fluid)) * displacement_fluid_adjoint * fluid.dx + dot(grad(xi_fluid), grad(velocity_fluid_adjoint)) * fluid.dx - dot(grad(xi_fluid), fluid.normal_vector) * velocity_fluid_adjoint * fluid.ds(1) - param.NU * dot(grad(eta_fluid), fluid.normal_vector) * displacement_fluid_adjoint * fluid.ds(1) + param.GAMMA / fluid.cell_size * xi_fluid * velocity_fluid_adjoint * fluid.ds(1) + param.GAMMA / fluid.cell_size * eta_fluid * displacement_fluid_adjoint * fluid.ds(1) )
def _construct_eigenproblem(self, u: ufl.Argument, v: ufl.Argument) \ -> Tuple[ufl.algebra.Operator, ufl.algebra.Operator]: """Construct left- and right-hand sides of eigenvalue problem. Parameters ---------- u : ufl.Argument A function belonging to the function space under consideration. v : ufl.Argument A function belonging to the function space under consideration. Returns ------- a : ufl.algebra.Operator Left hand side form. b : ufl.algebra.Operator Right hand side form. """ g = self.metric_tensor sqrt_g = fenics.sqrt(fenics.det(g)) inv_g = fenics.inv(g) # $a(u, v) = \int_M \nabla u \cdot g^{-1} \nabla v \, \sqrt{\det(g)} \, d x$. a = fenics.dot(fenics.grad(u), inv_g * fenics.grad(v)) * sqrt_g # $b(u, v) = \int_M u \, v \, \sqrt{\det(g)} \, d x$. b = fenics.dot(u, v) * sqrt_g return a, b
def functional_fluid_adjoint_initial( displacement_fluid_adjoint_old, velocity_fluid_adjoint_old, displacement_fluid_adjoint_interface, velocity_fluid_adjoint_interface, displacement_fluid_adjoint_old_interface, velocity_fluid_adjoint_old_interface, xi_fluid, eta_fluid, fluid: Space, param: Parameters, time, time_step, microtimestep_before: MicroTimeStep, microtimestep: MicroTimeStep, ): return ( 0.5 * time_step * param.NU * dot(grad(eta_fluid), fluid.normal_vector) * displacement_fluid_adjoint_interface * fluid.ds(1) + 2.0 * param.NU * characteristic_function_fluid(param) * dot( goal_functional( microtimestep_before, microtimestep, "primal_velocity" )[1], grad(eta_fluid), ) * fluid.dx )
def form_fluid( displacement_fluid, velocity_fluid, phi_fluid, psi_fluid, fluid: Space, param: Parameters, ): return ( param.NU * dot(grad(velocity_fluid), grad(phi_fluid)) * fluid.dx + dot(param.BETA, grad(velocity_fluid)) * phi_fluid * fluid.dx + dot(grad(displacement_fluid), grad(psi_fluid)) * fluid.dx - dot(grad(displacement_fluid), fluid.normal_vector) * psi_fluid * fluid.ds(1) - param.NU * dot(grad(velocity_fluid), fluid.normal_vector) * phi_fluid * fluid.ds(1) + param.GAMMA / fluid.cell_size * displacement_fluid * psi_fluid * fluid.ds(1) + param.GAMMA / fluid.cell_size * velocity_fluid * phi_fluid * fluid.ds(1) )
def defineWeakSystemDomain(): """Define system of equations of the weak formulation of the second-orderformulation of the PN equations on the domain . """ sMD = importlib.import_module( "systemMatricesDomain_d_%d_k_%s_N_%d" % (par['spatialDimension'], par['kernelName'], N_PN)) systemMatricesDomain = sMD.getSystemMatricesDomain(par) lhs = 0.0 * v[0] * fe.dx(V) for i in range(nEvenMoments): for j in range(nEvenMoments): if (par['spatialDimension'] == 1): lhs += systemMatricesDomain['Kzz'][i][j] * fe.dot( fe.grad(u[j])[0], fe.grad(v[i])[0]) * fe.dx(V) elif (par['spatialDimension'] == 2): lhs += systemMatricesDomain['Kxx'][i][j] * fe.dot( fe.grad(u[j])[0], fe.grad(v[i])[0]) * fe.dx(V) lhs += systemMatricesDomain['Kxy'][i][j] * fe.dot( fe.grad(u[j])[1], fe.grad(v[i])[0]) * fe.dx(V) lhs += systemMatricesDomain['Kyx'][i][j] * fe.dot( fe.grad(u[j])[0], fe.grad(v[i])[1]) * fe.dx(V) lhs += systemMatricesDomain['Kyy'][i][j] * fe.dot( fe.grad(u[j])[1], fe.grad(v[i])[1]) * fe.dx(V) else: raise ValueError( 'Only spatial dimensions <= 2 implemented!') lhs += systemMatricesDomain['S'][i][j] * u[j] * v[i] * fe.dx(V) return lhs
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(self): """Evoke FEniCS FEM solver. Returns ------- uij : (Ni,) ndarray potential at Ni grid points nij : (M,Nij) ndarray concentrations of M species at Ni grid points lamj: (L,) ndarray value of L Lagrange multipliers """ # weak form and FEM scheme: # in the weak form, u and v are the trial and test functions associated # with the Poisson part, p and q the trial and test functions associated # with the Nernst-Planck part. lam and mu are trial and test fuctions # associated to constraints introduced via Lagrange multipliers. # w is the whole set of trial functions [u,p,lam] # W is the space all w live in. rho = 0 for i in range(self.M): rho += self.z[i] * self.p[i] source = -0.5 * rho * self.v * fn.dx laplace = fn.dot(fn.grad(self.u), fn.grad(self.v)) * fn.dx poisson = laplace + source nernst_planck = 0 for i in range(self.M): nernst_planck += fn.dot( -fn.grad(self.p[i]) - self.z[i] * self.p[i] * fn.grad(self.u), fn.grad(self.q[i])) * fn.dx # constraints set up elsewhere F = poisson + nernst_planck + self.constraints fn.solve(F == 0, self.w, self.boundary_conditions) # store results: wij = np.array([self.w(x) for x in self.X]).T self.uij = wij[0, :] # potential self.nij = wij[1:(self.M + 1), :] # concentrations self.lamj = wij[(self.M + 1):] # Lagrange multipliers return self.uij, self.nij, self.lamj
def goal_functional_solid( displacement_solid_array, velocity_solid_array, solid, solid_timeline, param, ): global_result = 0.0 macrotimestep = solid_timeline.head global_size = solid_timeline.size m = 1 for n in range(global_size): microtimestep = macrotimestep.head.after local_size = macrotimestep.size - 1 for k in range(local_size): print(f"Current contribution: {m}") result = 0.0 time_step = microtimestep.before.dt gauss_1, gauss_2 = gauss(microtimestep) result += ( 0.5 * time_step * param.ZETA * characteristic_function_solid(param) * dot( grad( linear_extrapolation(displacement_solid_array, m, gauss_1, microtimestep)), grad( linear_extrapolation(displacement_solid_array, m, gauss_1, microtimestep)), ) * solid.dx) result += ( 0.5 * time_step * param.ZETA * characteristic_function_solid(param) * dot( grad( linear_extrapolation(displacement_solid_array, m, gauss_2, microtimestep)), grad( linear_extrapolation(displacement_solid_array, m, gauss_2, microtimestep)), ) * solid.dx) m += 1 microtimestep = microtimestep.after global_result += assemble(result) macrotimestep = macrotimestep.after return global_result
def project_gradient_neumann( f0, degree=None, mesh=None, solver_type='gmres', preconditioner_type='default' ): """Find an approximation to f0 that has the same gradient The resulting function also satisfies homogeneous Neumann boundary conditions. Parameters: f0: the function to approximate mesh=None: the mesh on which to approximate it If not provided, the mesh is extracted from f0. degree=None: degree of the polynomial approximation. extracted from f0 if not provided. solver_type='gmres': The linear solver type to use. preconditioner_type='default': Preconditioner type to use """ if not mesh: mesh = f0.function_space().mesh() element = f0.ufl_element() if not degree: degree = element.degree() CE = FiniteElement('CG', mesh.ufl_cell(), degree) CS = FunctionSpace(mesh, CE) DE = FiniteElement('DG', mesh.ufl_cell(), degree) DS = FunctionSpace(mesh, DE) CVE = VectorElement('CG', mesh.ufl_cell(), degree - 1) CV = FunctionSpace(mesh, CVE) RE = FiniteElement('R', mesh.ufl_cell(), 0) R = FunctionSpace(mesh, RE) CRE = MixedElement([CE, RE]) CR = FunctionSpace(mesh, CRE) f = fe.project(f0, CS, solver_type=solver_type, preconditioner_type=preconditioner_type) g = fe.project(fe.grad(f), CV, solver_type=solver_type, preconditioner_type=preconditioner_type) lf = fe.project(fe.nabla_div(g), CS, solver_type=solver_type, preconditioner_type=preconditioner_type) tf, tc = TrialFunction(CR) wf, wc = TestFunctions(CR) dx = Measure('dx', domain=mesh, metadata={'quadrature_degree': min(degree, 10)}) a = (fe.dot(fe.grad(tf), fe.grad(wf)) + tc * wf + tf * wc) * dx L = (f * wc - lf * wf) * dx igc = Function(CR) fe.solve(a == L, igc, solver_parameters={'linear_solver': solver_type, 'preconditioner': preconditioner_type} ) ig, c = igc.sub(0), igc.sub(1) igd = fe.project(ig, DS, solver_type=solver_type, preconditioner_type=preconditioner_type) return igd
def solver(f, u_D, bc_funs, ndim, length, nx, ny, nz=None, degree=1): """Fenics 求解器 Args: f (Expression): [description] u_D (Expression): [description] bc_funs (List[Callable]): [description] ndim (int): [description] length (float): [description] nx (int): [description] ny (int): [description] nz (int, optional): [description]. Defaults to None. degree (int, optional): [description]. Defaults to 1. Returns: Function: 解 u """ mesh = get_mesh(length, nx, ny, nz) V = fs.FunctionSpace(mesh, "P", degree) bcs = [fs.DirichletBC(V, u_D, bc) for bc in bc_funs] u = fs.TrialFunction(V) v = fs.TestFunction(V) FF = fs.dot(fs.grad(u), fs.grad(v)) * fs.dx - f * v * fs.dx a = fs.lhs(FF) L = fs.rhs(FF) u = fs.Function(V) fs.solve(a == L, u, bcs) return u
def construct_variation_problem(self) -> Tuple[Form, Form]: p = self.params u_t = (p.T - p.T_prev) / p.dt f = p.Q_pc + p.Q_sw + p.Q_mm F = p.P_s * p.c_s * u_t * p.v * dx + p.k_e * dot(grad(p.T), grad( p.v)) * dx - f * p.v * dx return lhs(F), rhs(F)
def __call__(self, u_test, return_sol=False, return_permeability=False): # Variables x, y = sym.symbols('x[0], x[1]', real=True, positive=True) # Diffusivities diff_1 = np.exp(u_test[0]) diff_2 = np.exp(u_test[1]) # Interfaces ix = u_test[2] iy = u_test[3] # Diffusivity diff = sym.Piecewise((sym.Piecewise( (diff_1, y <= iy), (diff_2, True)), x <= ix), (diff_2, True)) # if return_permeability: # return sym.lambdify((x, y), diff) ccode_coeff = sym.ccode(diff) diff = fen.Expression(ccode_coeff, degree=2) if return_permeability: return diff # Define bilinear form in variational problem a_bil = diff * fen.dot(fen.grad(self.trial_f), fen.grad( self.test_f)) * fen.dx # Compute solution sol = fen.Function(self.f_space) fen.solve(a_bil == self.lin_func, sol, self.bound_cond) evaluations = [sol(xi, yi) for xi, yi in zip(self.x_obs, self.y_obs)] return sol if return_sol else np.array(evaluations)
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 effective_field(m, volume=None): w_Zeeman = - mu0 * Ms * fe.dot(m, H) w_exchange = A * fe.inner(fe.grad(m), fe.grad(m)) w_DMI = D * fe.inner(m, fe.curl(m)) w_ani = - K * fe.inner(m, ea)**2 w = w_Zeeman + w_exchange + w_DMI + w_ani return -1/(mu0*Ms) * fe.derivative(w*fe.dx, m)
def form_solid( displacement_solid, velocity_solid, phi_solid, psi_solid, solid: Space, param: Parameters, ): return ( param.ZETA * dot(grad(displacement_solid), grad(phi_solid)) * solid.dx + param.DELTA * dot(grad(velocity_solid), grad(phi_solid)) * solid.dx - velocity_solid * psi_solid * solid.dx - param.DELTA * dot(grad(velocity_solid), solid.normal_vector) * phi_solid * solid.ds(1) )
def test_formulation_1_extrap_1_material(): ''' Test function formulation() with 1 extrinsic trap and 1 material ''' dt = 1 traps = [{ "energy": 1, "materials": [1], "type": "extrinsic" }] materials = [{ "alpha": 1, "beta": 2, "density": 3, "borders": [0, 1], "E_diff": 4, "D_0": 5, "id": 1 }] mesh = fenics.UnitIntervalMesh(10) V = fenics.VectorFunctionSpace(mesh, 'P', 1, 2) W = fenics.FunctionSpace(mesh, 'P', 1) u = fenics.Function(V) u_n = fenics.Function(V) v = fenics.TestFunction(V) n = fenics.interpolate(fenics.Expression('1', degree=0), W) solutions = list(fenics.split(u)) previous_solutions = list(fenics.split(u_n)) testfunctions = list(fenics.split(v)) extrinsic_traps = [n] mf = fenics.MeshFunction('size_t', mesh, 1, 1) dx = fenics.dx(subdomain_data=mf) temp = fenics.Expression("300", degree=0) flux_ = fenics.Expression("10000", degree=0) F, expressions = FESTIM.formulation( traps, extrinsic_traps, solutions, testfunctions, previous_solutions, dt, dx, materials, temp, flux_) expected_form = ((solutions[0] - previous_solutions[0]) / dt) * \ testfunctions[0]*dx expected_form += 5 * fenics.exp(-4/8.6e-5/temp) * \ fenics.dot( fenics.grad(solutions[0]), fenics.grad(testfunctions[0]))*dx(1) expected_form += -flux_*testfunctions[0]*dx + \ ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[1]*dx expected_form += - 5 * fenics.exp(-4/8.6e-5/temp)/1/1/2 * \ solutions[0] * (extrinsic_traps[0] - solutions[1]) * \ testfunctions[1]*dx(1) expected_form += 1e13*fenics.exp(-1/8.6e-5/temp)*solutions[1] * \ testfunctions[1]*dx(1) expected_form += ((solutions[1] - previous_solutions[1]) / dt) * \ testfunctions[0]*dx assert expected_form.equals(F) is True
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 _solve_pde(self, diff_coef): # Actual PDE solver for any coefficient diff_coef u = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) a = fe.dot(diff_coef * fe.grad(u), fe.grad(v)) * fe.dx L = self.f * v * fe.dx bc = fe.DirichletBC(self.function_space, self.bc_function, PoissonSolver.boundary) fe.solve(a == L, self.solution, bc)
def fenics_p_electric(self, my_d): """ @description: Solve poisson equation to get potential and electric field @Modify: 2021/08/31 """ if "plugin3D" in self.det_model: bc_l = [] bc_l = self.boundary_definition_3D(my_d, "Possion") elif "planar3D" in self.det_model: bc_l = self.boundary_definition_2D(my_d, "Possion") u = fenics.TrialFunction(self.V) v = fenics.TestFunction(self.V) if self.det_dic['name'] == "lgad3D": if self.det_dic['part'] == 2: bond = self.det_dic['bond1'] doping_avalanche = self.f_value(my_d, self.det_dic['doping1']) doping = self.f_value(my_d, self.det_dic['doping2']) f = fenics.Expression('x[2] < width ? doping1 : doping2', degree=1, width=bond, doping1=doping_avalanche, doping2=doping) elif self.det_dic['part'] == 3: bond1 = self.det_dic['bond1'] bond2 = self.det_dic['bond2'] doping1 = self.f_value(my_d, self.det_dic['doping1']) doping2 = self.f_value(my_d, self.det_dic['doping2']) doping3 = self.f_value(my_d, self.det_dic['doping3']) f = fenics.Expression( 'x[2] < bonda ? dopinga : x[2] > bondb ? dopingc : dopingb', degree=1, bonda=bond1, bondb=bond2, dopinga=doping1, dopingb=doping2, dopingc=doping3) else: print("The structure of lgad is wrong.") else: f = fenics.Constant(self.f_value(my_d)) a = fenics.dot(fenics.grad(u), fenics.grad(v)) * fenics.dx L = f * v * fenics.dx # Compute solution self.u = fenics.Function(self.V) fenics.solve(a == L, self.u, bc_l, solver_parameters=dict(linear_solver='gmres', preconditioner='ilu')) #calculate electric field W = fenics.VectorFunctionSpace(self.mesh3D, 'P', 1) self.E_field = fenics.project( fenics.as_vector((self.u.dx(0), self.u.dx(1), self.u.dx(2))), W)
def construct_variation_problem(self) -> Tuple[Form, Form]: p = self.params ds = self.make_ds(p.mesh) u_t = (p.u - p.P_prev) / p.dt term = p.alpha_th * p.u * p.P_d * (p.my_v + p.my_d)**2 / ( (p.P_prev + p.P_d) * p.my_v * p.my_d) / p.T_s * grad(p.T_s) F = p.theta_a * u_t * p.v * dx + p.theta_a * p.D_e * dot( grad(p.u) - term, grad( p.v)) * dx - p.M_mm * p.v * dx + p.q_h * p.v * ds(1) return lhs(F), rhs(F)
def _compute_effective_diffusion(self): # Uses the solutions of the cell problems to compute the harmonic average of the diffusivity for i, j in np.ndindex((self.dim, self.dim)): integrand_ij = fe.project( self.a_y * fe.dot(self.e_is[i] + fe.grad(self.cell_solutions[i]), self.e_is[j] + fe.grad(self.cell_solutions[j])), self.function_space) self.eff_diff[i, j] = fe.assemble(integrand_ij * fe.dx) return fe.Constant(self.eff_diff)
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 __compute_shape_derivative(self): """Computes the shape derivative. Returns ------- None Notes ----- This only works properly if differential operators only act on state and adjoint variables, else the results are incorrect. A corresponding warning whenever this could be the case is issued. """ # Shape derivative of Lagrangian w/o regularization and pull-backs self.shape_derivative = fenics.derivative( self.lagrangian.lagrangian_form, fenics.SpatialCoordinate(self.mesh), self.test_vector_field) # Add pull-backs if self.use_pull_back: self.state_adjoint_ids = [coeff.id() for coeff in self.states] + [ coeff.id() for coeff in self.adjoints ] self.material_derivative_coeffs = [] for coeff in self.lagrangian.lagrangian_form.coefficients(): if coeff.id() in self.state_adjoint_ids: pass else: if not (coeff.ufl_element().family() == 'Real'): self.material_derivative_coeffs.append(coeff) if len(self.material_derivative_coeffs) > 0: warning( 'Shape derivative might be wrong, if differential operators act on variables other than states and adjoints. \n' 'You can check for correctness of the shape derivative with cashocs.verification.shape_gradient_test\n' ) for coeff in self.material_derivative_coeffs: # temp_space = fenics.FunctionSpace(self.mesh, coeff.ufl_element()) # placeholder = fenics.Function(temp_space) # temp_form = fenics.derivative(self.lagrangian.lagrangian_form, coeff, placeholder) # material_derivative = replace(temp_form, {placeholder : fenics.dot(fenics.grad(coeff), self.test_vector_field)}) material_derivative = fenics.derivative( self.lagrangian.lagrangian_form, coeff, fenics.dot(fenics.grad(coeff), self.test_vector_field)) material_derivative = expand_derivatives(material_derivative) self.shape_derivative += material_derivative # Add regularization self.shape_derivative += self.regularization.compute_shape_derivative()
def create_bilinear_form_and_rhs(self): # Define variational problem u = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) self.bilinear_form = (1 + self.lam * self.dt) *\ (u * v * fe.dx) + self.dt * self.diffusion_coefficient *\ (fe.dot(fe.grad(u), fe.grad(v)) * fe.dx) self.rhs = (self.u_n + self.dt * self.rhs_fun * self.u_n) * v * fe.dx
def functional_solid( displacement_solid_old, velocity_solid_old, displacement_solid_interface, velocity_solid_interface, displacement_solid_old_interface, velocity_solid_old_interface, phi_solid, psi_solid, solid: Space, param: Parameters, time, time_step, ): return ( velocity_solid_old * phi_solid * solid.dx + displacement_solid_old * psi_solid * solid.dx - 0.5 * time_step * form_solid( displacement_solid_old, velocity_solid_old, phi_solid, psi_solid, solid, param, ) - 0.5 * time_step * param.NU * dot(grad(velocity_solid_interface), solid.normal_vector) * phi_solid * solid.ds(1) - 0.5 * time_step * param.NU * dot(grad(velocity_solid_old_interface), solid.normal_vector) * phi_solid * solid.ds(1) )
def create_bilinear_form_and_rhs(self): # Define variational problem u = fe.TrialFunction(self.function_space) v = fe.TestFunction(self.function_space) if self.dimension == 1: diffusion_tensor = self.diffusion_matrix self.bilinear_form = (1 + self.lam * self.dt) * (u * v * fe.dx) +\ self.dt * (fe.dot(\ diffusion_tensor * fe.grad(u),\ fe.grad(v)) * fe.dx) if self.dimension == 2: diffusion_tensor = fe.as_matrix(self.diffusion_matrix) self.bilinear_form = (1 + self.lam * self.dt) * (u * v * fe.dx) +\ self.dt * (fe.dot(\ fe.dot(diffusion_tensor, fe.grad(u)),\ fe.grad(v)) * fe.dx) self.rhs = (self.u_n + self.dt * self.rhs_fun) * v * fe.dx
def get_tangential_component(self, t, E): E_t = fn.dot(E, t) E_t = Poisson.block_project(E_t, self.mesh, self.restrictions_dict['interface_rtc'], self.boundaries, self.boundaries_ids['Interface'], space_type='scalar', boundary_type='internal', sign=t.side(), restricted=True) return E_t
def solve_wave_equation(u0, u1, u_boundary, f, domain, mesh, degree): """Solving the wave equation using CG-CG method. Args: u0: Initial data. u1: Initial velocity. u_boundary: Dirichlet boundary condition. f: Right-hand side. domain: Space-time domain. mesh: Computational mesh. degree: CG(degree) will be used as the finite element. Outputs: uh: Numerical solution. """ # Element V = FunctionSpace(mesh, "CG", degree) # Measures on the initial and terminal slice mask = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0) domain.get_initial_slice().mark(mask, 1) ends = ds(subdomain_data=mask) # Form g = Constant(((-1.0, 0.0), (0.0, 1.0))) u = TrialFunction(V) v = TestFunction(V) a = dot(grad(v), dot(g, grad(u))) * dx L = f * v * dx + u1 * v * ends(1) # Assembled matrices A = assemble(a, keep_diagonal=True) b = assemble(L, keep_diagonal=True) # Spatial boundary condition bc = DirichletBC(V, u_boundary, domain.get_spatial_boundary()) bc.apply(A, b) # Temporal boundary conditions (by hand) (A, b) = apply_time_boundary_conditions(domain, V, u0, A, b) # Solve solver = LUSolver() solver.set_operator(A) uh = Function(V) solver.solve(uh.vector(), b) return uh
def compute_dmdt(m): """Convenience function that does all in one go""" # Assemble RHS b = fe.assemble(Heff_form) # Project onto Heff LU.solve(Heff.vector(), b) LLG = -gamma/(1+alpha*alpha)*fe.cross(m, Heff) - alpha*gamma/(1+alpha*alpha)*fe.cross(m, fe.cross(m, Heff)) result = fe.assemble(fe.dot(LLG, v)*fe.dP) return result.array()
def form_solid_adjoint( displacement_solid_adjoint, velocity_solid_adjoint, xi_solid, eta_solid, solid: Space, param: Parameters, ): return ( param.ZETA * dot(grad(xi_solid), grad(displacement_solid_adjoint)) * solid.dx + param.DELTA * dot(grad(eta_solid), grad(displacement_solid_adjoint)) * solid.dx - eta_solid * velocity_solid_adjoint * solid.dx - param.DELTA * dot(grad(eta_solid), solid.normal_vector) * displacement_solid_adjoint * solid.ds(1) )
def solve(self): # TODO: when FEniCS ported to Python3, this should be exist_ok try: os.makedirs('results') except OSError: pass z, w = (self.z, self.w) u0 = d.Constant(0.0) # Define the linear and bilinear forms L = u0 * w * dx # Define useful functions cond = d.Function(self.DV) U = d.Function(self.V) # Initialize the max_e vector, that will store the cumulative max e values max_e = d.Function(self.V) max_e.vector()[:] = 0.0 max_e.rename("max_E", "Maximum energy deposition by location") max_e_file = d.File("results/%s-max_e.pvd" % input_mesh) max_e_per_step = d.Function(self.V) max_e_per_step_file = d.File("results/%s-max_e_per_step.pvd" % input_mesh) self.es = {} self.max_es = {} fi = d.File("results/%s-cond.pvd" % input_mesh) potential_file = d.File("results/%s-potential.pvd" % input_mesh) # Loop through the voltages and electrode combinations for i, (anode, cathode, voltage) in enumerate(v.electrode_triples): print("Electrodes %d (%lf) -> %d (0)" % (anode, voltage, cathode)) cond = d.project(self.sigma_start, V=self.DV) # Define the Dirichlet boundary conditions on the active needles uV = d.Constant(voltage) term1_bc = d.DirichletBC(self.V, uV, self.patches, v.needles[anode]) term2_bc = d.DirichletBC(self.V, u0, self.patches, v.needles[cathode]) e = d.Function(self.V) e.vector()[:] = max_e.vector() # Re-evaluate conductivity self.increase_conductivity(cond, e) for j in range(v.max_restarts): # Update the bilinear form a = d.inner(d.nabla_grad(z), cond * d.nabla_grad(w)) * dx # Solve again print(" [solving...") d.solve(a == L, U, bcs=[term1_bc, term2_bc]) print(" ....solved]") # Extract electric field norm for k in range(len(U.vector())): if N.isnan(U.vector()[k]): U.vector()[k] = 1e5 e_new = d.project(d.sqrt(d.dot(d.grad(U), d.grad(U))), self.V) # Take the max of the new field and the established electric field e.vector()[:] = N.array([max(*X) for X in zip(e.vector(), e_new.vector())]) # Re-evaluate conductivity fi << cond self.increase_conductivity(cond, e) potential_file << U # Save the max e function to a VTU max_e_per_step.vector()[:] = e.vector()[:] max_e_per_step_file << max_e_per_step # Store this electric field norm, for this triple, for later reference self.es[i] = e # Store the max of this electric field norm and that for all previous triples max_e_array = N.array([max(*X) for X in zip(max_e.vector(), e.vector())]) max_e.vector()[:] = max_e_array # Create a new max_e function for storage, or it will be overwritten by the next iteration max_e_new = d.Function(self.V) max_e_new.vector()[:] = max_e_array # Store this max e function for the cumulative coverage curve calculation later self.max_es[i] = max_e_new # Save the max e function to a VTU max_e_file << max_e self.max_e_count = i