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 check_conservation_law(self, sol): dx = self.dx ds = self.ds total = [] out = [] for s in sol: cl = s[0] na = s[1] k = s[2] # integrate interior concentration mass_cl = fe.assemble(cl * dx) mass_na = fe.assemble(na * dx) mass_k = fe.assemble(k * dx) # integrate outflux n = fe.FacetNormal(self.mesh) flow = self.flow outflux_cl = fe.assemble(cl * inner(flow, n) * ds) outflux_na = fe.assemble(na * inner(flow, n) * ds) outflux_k = fe.assemble(k * inner(flow, n) * ds) total.append(mass_cl + mass_na + 2 * mass_k) out.append(outflux_cl + outflux_na + 2 * outflux_k) self.total_mass = total self.outflux = out
def build_weak_form_staggered(self): self.psi_plus = partial(psi_plus_linear_elasticity_model_A, lamda=self.lamda, mu=self.mu) self.psi_minus = partial(psi_minus_linear_elasticity_model_A, lamda=self.lamda, mu=self.mu) sigma_plus = cauchy_stress_plus(strain(fe.grad(self.x_new)), self.psi_plus) sigma_minus = cauchy_stress_minus(strain(fe.grad(self.x_new)), self.psi_minus) self.G_u = (g_d(self.d_new) * fe.inner(sigma_plus, strain(fe.grad(self.eta))) \ + fe.inner(sigma_minus, strain(fe.grad(self.eta)))) * fe.dx # self.G_d = (self.H_old * self.zeta * g_d_prime(self.d_new, g_d) \ # + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx self.G_d = (history(self.H_old, self.psi_plus(strain(fe.grad(self.x_new))), self.psi_cr) * self.zeta * g_d_prime(self.d_new, g_d) \ + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx # g_c = 0.01 # self.G_d = (self.psi_plus(strain(fe.grad(self.x_new))) * self.zeta * g_d_prime(self.d_new, g_d) \ # + g_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx self.G_d += 1 * (self.d_new - self.d_pre) * self.zeta * fe.dx
def solve(self, **arguments): t_start = time.clock() # definig Function space on this mesh using Lagrange #polynoimals of degree 1. H = FunctionSpace(self.mesh, "CG", 1) # Setting up the variational problem v = TrialFunction(H) w = TestFunction(H) epsilon = Constant(arguments[Components().Diffusion]) f = Expression("(1 - epsilon*4*pow(pi,2))*cos(2*pi*x[0])",\ epsilon=epsilon, degree=1) a = (epsilon * inner(grad(v), grad(w)) + inner(v, w)) * dx L = f * w * dx # solving the variational problem. v = Function(H) solve(a == L, v) self.solution.extend(v.vector().array()) return [self.solution, time.clock() - t_start]
def solve(self, **arguments): t_start = time.clock() # definig Function space on this mesh using Lagrange #polynoimals of degree 1. H = FunctionSpace(self.mesh, "CG", 1) # Setting up the variational problem v = TrialFunction(H) w = TestFunction(H) epsilon = Constant(arguments[Components().Diffusion]) f = Constant(0) a = (epsilon * inner(grad(v), grad(w)) + inner(v, w)) * dx #Still have to figure it how to use a Neumann Condition here L = f * w * dx # solving the variational problem. v = Function(H) solve(a == L, v) self.solution.extend(v.vector().array()) return [self.solution, time.clock() - t_start]
def _make_variational_problem(V): """ Formulate the variational problem a(u, v) = L(v). Parameters ---------- V: FEniCS.FunctionSpace Returns ------- a, L: FEniCS.Expression Variational forms. """ # Define trial and test functions u = F.TrialFunction(V) v = F.TestFunction(V) # Collect Neumann conditions ds = F.Measure("ds", domain=mesh, subdomain_data=boundary_markers) integrals_N = [] for i in boundary_conditions: if isinstance(boundary_conditions[i], dict): if "Neumann" in boundary_conditions[i]: if boundary_conditions[i]["Neumann"] != 0: g = boundary_conditions[i]["Neumann"] integrals_N.append(g[0] * v * ds(i)) # Define variational problem a = F.inner(u, v) * F.dx + (DT**2) * (C**2) * F.inner( F.grad(u), F.grad(v)) * F.dx L = ((DT**2) * f[0] + 2 * u_nm1 - u_nm2) * v * F.dx + (DT**2) * (C**2) * sum(integrals_N) return a, L
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 geneForwardMatrix(self, q_fun=fe.Constant(0.0), fR=fe.Constant(0.0), \ fI=fe.Constant(0.0)): if self.haveFunctionSpace == False: self.geneFunctionSpace() xx, yy, dPML, sig0_, p_ = self.domain.xx, self.domain.yy, self.domain.dPML,\ self.domain.sig0, self.domain.p # define the coefficents induced by PML sig1 = fe.Expression('x[0] > x1 && x[0] < x1 + dd ? sig0*pow((x[0]-x1)/dd, p) : (x[0] < 0 && x[0] > -dd ? sig0*pow((-x[0])/dd, p) : 0)', degree=3, x1=xx, dd=dPML, sig0=sig0_, p=p_) sig2 = fe.Expression('x[1] > x2 && x[1] < x2 + dd ? sig0*pow((x[1]-x2)/dd, p) : (x[1] < 0 && x[1] > -dd ? sig0*pow((-x[1])/dd, p) : 0)', degree=3, x2=yy, dd=dPML, sig0=sig0_, p=p_) sR = fe.as_matrix([[(1+sig1*sig2)/(1+sig1*sig1), 0.0], [0.0, (1+sig1*sig2)/(1+sig2*sig2)]]) sI = fe.as_matrix([[(sig2-sig1)/(1+sig1*sig1), 0.0], [0.0, (sig1-sig2)/(1+sig2*sig2)]]) cR = 1 - sig1*sig2 cI = sig1 + sig2 # define the coefficients with physical meaning angl_fre = self.kappa*np.pi angl_fre2 = fe.Constant(angl_fre*angl_fre) # define equations u_ = fe.TestFunction(self.V) du = fe.TrialFunction(self.V) u_R, u_I = fe.split(u_) duR, duI = fe.split(du) def sigR(v): return fe.dot(sR, fe.nabla_grad(v)) def sigI(v): return fe.dot(sI, fe.nabla_grad(v)) F1 = - fe.inner(sigR(duR)-sigI(duI), fe.nabla_grad(u_R))*(fe.dx) \ - fe.inner(sigR(duI)+sigI(duR), fe.nabla_grad(u_I))*(fe.dx) \ - fR*u_R*(fe.dx) - fI*u_I*(fe.dx) a2 = fe.inner(angl_fre2*q_fun*(cR*duR-cI*duI), u_R)*(fe.dx) \ + fe.inner(angl_fre2*q_fun*(cR*duI+cI*duR), u_I)*(fe.dx) \ # define boundary conditions def boundary(x, on_boundary): return on_boundary bc = [fe.DirichletBC(self.V.sub(0), fe.Constant(0.0), boundary), \ fe.DirichletBC(self.V.sub(1), fe.Constant(0.0), boundary)] a1, L1 = fe.lhs(F1), fe.rhs(F1) self.u = fe.Function(self.V) self.A1 = fe.assemble(a1) self.b1 = fe.assemble(L1) self.A2 = fe.assemble(a2) bc[0].apply(self.A1, self.b1) bc[1].apply(self.A1, self.b1) bc[0].apply(self.A2) bc[1].apply(self.A2) self.A = self.A1 + self.A2
def build_weak_form_staggered(self): self.psi = partial(psi_linear_elasticity, lamda=self.lamda, mu=self.mu) self.sigma = cauchy_stress(strain(fe.grad(self.x_new)), self.psi) self.G_u = g_d(self.d_new) * fe.inner( self.sigma, strain(fe.grad(self.eta))) * fe.dx self.G_d = (history(self.H_old, self.psi(strain(fe.grad(self.x_new))), self.psi_cr) * self.zeta * g_d_prime(self.d_new, g_d) \ + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx
def _obj(self, x): f = da.Function(self.poisson.V) f.vector()[:] = x self.poisson.source = f u = self.poisson.solve_problem_variational_form() L_tape = da.assemble( (0.5 * fa.inner(u - self.target_u, u - self.target_u) + 0.5 * self.alpha * fa.inner(f, f)) * fa.dx) L = float(L_tape) return L, L_tape, f
def build_weak_form_staggered(self): self.psi_plus = partial(psi_plus_Miehe, mu=self.mu, beta=self.beta) self.psi_minus = partial(psi_minus_Miehe, mu=self.mu, beta=self.beta) PK_plus = first_PK_stress_plus(self.I + fe.grad(self.x_new), self.psi_plus) PK_minus = first_PK_stress_plus(self.I + fe.grad(self.x_new), self.psi_minus) self.G_u = (g_d(self.d_new) * fe.inner(PK_plus, fe.grad(self.eta)) + fe.inner(PK_minus, fe.grad(self.eta)))* fe.dx self.G_d = self.H_old * self.zeta * g_d_prime(self.d_new, g_d) * fe.dx \ + 2 * self.psi_cr * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new))) * fe.dx
def solve(self, **arguments): t_start = time.clock() # definig Function space on this mesh using Lagrange #polynoimals of degree 1. H = FunctionSpace(self.mesh, "CG", 1) # Setting up the variational problem v = TrialFunction(H) w = TestFunction(H) coeff_dx2 = Constant(1) coeff_v = Constant(1) f = Expression("(4*pow(pi,2))*exp(-(1/coeff_v)*t)*sin(2*pi*x[0])", {'coeff_v': coeff_v}, degree=2) v0 = Expression("sin(2*pi*x[0])", degree=2) f.t = 0 def boundary(x, on_boundary): return on_boundary bc = DirichletBC(H, v0, boundary) v1 = interpolate(v0, H) dt = self.steps.time a = (dt * inner(grad(v), grad(w)) + dt * coeff_v * inner(v, w)) * dx L = (f * dt - coeff_v * v1) * w * dx A = assemble(a) v = Function(H) T = self.domain.time[-1] t = dt # solving the variational problem. while t <= T: b = assemble(L, tensor=b) vo.t = t bc.apply(A, b) solve(A, v.vector(), b) t += dt v1.assign(v) self.solution.extend(v.vector().array()) return [self.solution, time.clock() - t_start]
def __init__(self, mesh, constitutive_model): W = fe.FunctionSpace(mesh, "DG", 1) super().__init__(mesh, constitutive_model, W) self.w = fe.Function(W) self.p, self.p0 = self.w, fe.Function(W) self.g = fe.TestFunction(W) self.functional = fe.inner(self.p, self.g) - fe.inner( self.constitutive_model)
def build_weak_form_staggered(self): self.x_hat = fe.variable(fe.SpatialCoordinate(self.mesh)) self.x = map_function_ufl(self.x_hat, self.control_points, self.impact_radii, self.map_type, self.boundary_info) self.grad_gamma = fe.diff(self.x, self.x_hat) def mfem_grad_wrapper(grad): def mfem_grad(u): return fe.dot(grad(u), fe.inv(self.grad_gamma)) return mfem_grad self.mfem_grad = mfem_grad_wrapper(fe.grad) # A special note (Tianju): We hope to use Model C, but Newton solver fails without the initial guess by Model A if self.i < 2: self.psi_plus = partial(psi_plus_linear_elasticity_model_A, lamda=self.lamda, mu=self.mu) self.psi_minus = partial(psi_minus_linear_elasticity_model_A, lamda=self.lamda, mu=self.mu) else: self.psi_plus = partial(psi_plus_linear_elasticity_model_C, lamda=self.lamda, mu=self.mu) self.psi_minus = partial(psi_minus_linear_elasticity_model_C, lamda=self.lamda, mu=self.mu) print("use model C") self.psi = partial(psi_linear_elasticity, lamda=self.lamda, mu=self.mu) self.sigma_plus = cauchy_stress_plus( strain(self.mfem_grad(self.x_new)), self.psi_plus) self.sigma_minus = cauchy_stress_minus( strain(self.mfem_grad(self.x_new)), self.psi_minus) # self.sigma = cauchy_stress_plus(strain(self.mfem_grad(self.x_new)), self.psi) # self.sigma_degraded = g_d(self.d_new) * self.sigma_plus + self.sigma_minus self.G_u = (g_d(self.d_new) * fe.inner(self.sigma_plus, strain(self.mfem_grad(self.eta))) \ + fe.inner(self.sigma_minus, strain(self.mfem_grad(self.eta)))) * fe.det(self.grad_gamma) * fe.dx if self.solution_scheme == 'explicit': self.G_d = (self.H_old * self.zeta * g_d_prime(self.d_new, g_d) \ + self.G_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(self.mfem_grad(self.zeta), self.mfem_grad(self.d_new)))) * fe.det(self.grad_gamma) * fe.dx else: self.G_d = (history(self.H_old, self.psi_plus(strain(self.mfem_grad(self.x_new))), self.psi_cr) * self.zeta * g_d_prime(self.d_new, g_d) \ + self.G_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(self.mfem_grad(self.zeta), self.mfem_grad(self.d_new)))) * fe.det(self.grad_gamma) * fe.dx
def compute_shape_derivative(self): """Computes the part of the shape derivative that comes from the regularization Returns ------- ufl.form.Form The weak form of the shape derivative coming from the regularization """ V = self.form_handler.test_vector_field if self.has_regularization: x = fenics.SpatialCoordinate(self.form_handler.mesh) n = fenics.FacetNormal(self.form_handler.mesh) I = fenics.Identity(self.form_handler.mesh.geometric_dimension()) self.shape_form = Constant(self.mu_surface)*(self.current_surface - Constant(self.target_surface))*t_div(V, n)*self.ds self.shape_form += Constant(self.mu_curvature)*(inner((I - (t_grad(x, n) + (t_grad(x, n)).T))*t_grad(V, n), t_grad(self.kappa_curvature, n))*self.ds \ + Constant(0.5)*t_div(V, n)*t_div(self.kappa_curvature, n)*self.ds) if not self.measure_hole: self.shape_form += Constant(self.mu_volume)*(self.current_volume - Constant(self.target_volume))*div(V)*self.dx self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\ *(self.current_barycenter_x/self.current_volume*div(V) + 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \ + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\ *(self.current_barycenter_y/self.current_volume*div(V) + 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx if self.form_handler.mesh.geometric_dimension() == 3: self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\ *(self.current_barycenter_z/self.current_volume*div(V) + 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx else: self.shape_form -= Constant(self.mu_volume)*(self.current_volume - Constant(self.target_volume))*div(V)*self.dx self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\ *(self.current_barycenter_x/self.current_volume*div(V) - 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \ + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\ *(self.current_barycenter_y/self.current_volume*div(V) - 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx if self.form_handler.mesh.geometric_dimension() == 3: self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\ *(self.current_barycenter_z/self.current_volume*div(V) - 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx return self.shape_form else: dim = self.form_handler.mesh.geometric_dimension() return inner(fenics.Constant([0]*dim), V)*self.dx
def determine_gradient(V_g, u, flux): """ compute flux following http://hplgit.github.io/INF5620/doc/pub/fenics_tutorial1.1/tu2.html#tut-poisson-gradu :param V_g: Vector function space :param u: solution where gradient is to be determined :param flux: returns calculated flux into this value """ w = TrialFunction(V_g) v = TestFunction(V_g) a = inner(w, v) * dx L = inner(grad(u), v) * dx solve(a == L, flux)
def determine_gradient(V_g, u, flux): """ compute flux following http://hplgit.github.io/INF5620/doc/pub/fenics_tutorial1.1/tu2.html#tut-poisson-gradu :param mesh :param u: solution where gradient is to be determined :return: """ w = TrialFunction(V_g) v = TestFunction(V_g) a = inner(w, v) * dx L = inner(grad(u), v) * dx solve(a == L, flux)
def local_project(v, V, u=None): """Element-wise projection using LocalSolver""" dv = fnc.TrialFunction(V) v_ = fnc.TestFunction(V) a_proj = fnc.inner(dv, v_) * fnc.dx b_proj = fnc.inner(v, v_) * fnc.dx solver = fnc.LocalSolver(a_proj, b_proj) solver.factorize() if u is None: u = fnc.Function(V) solver.solve_local_rhs(u) return u else: solver.solve_local_rhs(u) return
def solve_steady_state_heiser_weissinger(kappa): w = fe.Function(V_up) (u, p) = fe.split(w) p = fe.variable(p) (eta, q) = fe.TestFunctions(V_up) dw = fe.TrialFunction(V_up) kappa = fe.Constant(kappa) bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_up.sub(0), V_up.sub(1), None, boundaries) F = deformation_grad(u) I_1, I_2, J = invariants(F) F_iso = isochronic_deformation_grad(F, J) I_1_iso, I_2_iso = invariants(F)[0:2] W = material_mooney_rivlin(I_1_iso, I_2_iso, c_10, c_01) #+ incompr_relaxation(p, kappa) g = incompr_constr(J) # Lagrange function (without constraint) L = -W # Modified Lagrange function (with constraints) L_mod = L - p * g P = first_piola_stress(L, F) G = incompr_stress(g, F) # = J*fe.inv(F.T) Lp = const_eq(L_mod, p) a_static = weak_div_term(P + p * G, eta) + inner(B, eta) * dx + inner(Lp, q) * dx J_static = fe.derivative(a_static, w, dw) ffc_options = {"optimize": True} problem = fe.NonlinearVariationalProblem( a_static, w, bcs_u + bcs_p, J=J_static, form_compiler_parameters=ffc_options) solver = fe.NonlinearVariationalSolver(problem) solver.solve() return w
def run(self): domain = self._create_domain() mesh = generate_mesh(domain, MESH_PTS) # fe.plot(mesh) # plt.show() self._create_boundary_expression() Omega = fe.FiniteElement("Lagrange", mesh.ufl_cell(), 1) R = fe.FiniteElement("Real", mesh.ufl_cell(), 0) W = fe.FunctionSpace(mesh, Omega*R) Theta, c = fe.TrialFunction(W) v, d = fe.TestFunctions(W) sigma = self.conductivity LHS = (sigma * fe.inner(fe.grad(Theta), fe.grad(v)) + c*v + Theta*d) * fe.dx RHS = self.boundary_exp * v * fe.ds w = fe.Function(W) fe.solve(LHS == RHS, w) Theta, c = w.split() print(c(0, 0)) # fe.plot(Theta, "solution", mode='color', vmin=-3, vmax=3) # plt.show() plot(fe.interpolate(Theta, fe.FunctionSpace(mesh, Omega)), mode='color') plt.show()
def eva(self, num): # construct basis functions, Set num points corresponding to num basis functions basPoints = np.linspace(0, 1, num) dx = basPoints[1] - basPoints[0] aa, bb, cc = -dx, 0.0, dx for x_p in basPoints: self.theta.append( fe.interpolate( fe.Expression( 'x[0] < a || x[0] > c ? 0 : (x[0] >=a && x[0] <= b ? (x[0]-a)/(b-a) : 1-(x[0]-b)/(c-b))', degree=2, a=aa, b=bb, c=cc), self.Vc)) aa, bb, cc = aa + dx, bb + dx, cc + dx u_trial, u_test = fe.TrialFunction(self.Vu), fe.TestFunction(self.Vu) left = fe.inner(self.al * fe.nabla_grad(u_trial), fe.nabla_grad(u_test)) * fe.dx right = self.f * u_test * fe.dx def boundaryD(x, on_boundary): return on_boundary and fe.near(x[1], 1.0) for i in range(num): uH = fe.Function(self.Vu) bcD = fe.DirichletBC(self.Vu, self.theta[i], boundaryD) left_m, right_m = fe.assemble_system(left, right, bcD) fe.solve(left_m, uH.vector(), right_m) self.sol.append(uH)
def compute_objective(self): """Computes the part of the objective value that comes from the regularization Returns ------- float Part of the objective value coming from the regularization """ if self.has_regularization: value = 0.0 if self.mu_volume > 0.0: if not self.measure_hole: volume = fenics.assemble(Constant(1.0)*self.dx) else: volume = self.delta_x*self.delta_y*self.delta_z - fenics.assemble(Constant(1)*self.dx) value += 0.5*self.mu_volume*pow(volume - self.target_volume, 2) if self.mu_surface > 0.0: surface = fenics.assemble(Constant(1.0)*self.ds) # self.current_surface.val = surface value += 0.5*self.mu_surface*pow(surface - self.target_surface, 2) if self.mu_curvature > 0.0: self.compute_curvature() curvature_val = fenics.assemble(fenics.inner(self.kappa_curvature, self.kappa_curvature)*self.ds) value += 0.5*self.mu_curvature*curvature_val if self.mu_barycenter > 0.0: if not self.measure_hole: volume = fenics.assemble(Constant(1)*self.dx) barycenter_x = fenics.assemble(self.spatial_coordinate[0]*self.dx) / volume barycenter_y = fenics.assemble(self.spatial_coordinate[1]*self.dx) / volume if self.form_handler.mesh.geometric_dimension() == 3: barycenter_z = fenics.assemble(self.spatial_coordinate[2]*self.dx) / volume else: barycenter_z = 0.0 else: volume = self.delta_x*self.delta_y*self.delta_z - fenics.assemble(Constant(1)*self.dx) barycenter_x = (0.5*(pow(self.x_end, 2) - pow(self.x_start, 2))*self.delta_y*self.delta_z - fenics.assemble(self.spatial_coordinate[0]*self.dx)) / volume barycenter_y = (0.5*(pow(self.y_end, 2) - pow(self.y_start, 2))*self.delta_x*self.delta_z - fenics.assemble(self.spatial_coordinate[1]*self.dx)) / volume if self.form_handler.mesh.geometric_dimension() == 3: barycenter_z = (0.5*(pow(self.z_end, 2) - pow(self.z_start, 2))*self.delta_x*self.delta_y - fenics.assemble(self.spatial_coordinate[2]*self.dx)) / volume else: barycenter_z = 0.0 value += 0.5*self.mu_barycenter*(pow(barycenter_x - self.target_barycenter_list[0], 2) + pow(barycenter_y - self.target_barycenter_list[1], 2) + pow(barycenter_z - self.target_barycenter_list[2], 2)) return value else: return 0.0
def __call__(self, mesh, V=None, Vc=None): boundaries, boundarymarkers, domainmarkers, dx, ds, V, Vc = SetupUnitMeshHelper( mesh, V, Vc) self._ds_markers = boundarymarkers self._dx_markers = domainmarkers self._dx = dx self._ds = ds self._boundaries = boundaries self._subdomains = self._boundaries u = df.TrialFunction(V) v = df.TestFunction(V) alpha = df.Function(Vc, name='conductivity') alpha.vector()[:] = 1 def set_alpha(x): alpha.vector()[:] = x self._set_alpha = set_alpha a = alpha * df.inner(df.grad(u), df.grad(v)) * dx return a, set_alpha, alpha, V, Vc
def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy): dJdu_copy = dJdu.copy() bcs = self._homogenize_bcs() solver = self.block_helper.adjoint_solver if solver is None: if self.assemble_system: rhs_bcs_form = backend.inner(backend.Function(self.function_space), dFdu_adj_form.arguments()[0]) * backend.dx A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form, bcs) else: A = compat.assemble_adjoint_value(dFdu_adj_form) [bc.apply(A) for bc in bcs] solver = backend.LUSolver(A, self.method) self.block_helper.adjoint_solver = solver solver.parameters.update(self.lu_solver_parameters) [bc.apply(dJdu) for bc in bcs] adj_sol = backend.Function(self.function_space) solver.solve(adj_sol.vector(), dJdu) adj_sol_bdy = None if compute_bdy: adj_sol_bdy = compat.function_from_vector(self.function_space, dJdu_copy - compat.assemble_adjoint_value( backend.action(dFdu_adj_form, adj_sol))) return adj_sol, adj_sol_bdy
def __setup_decrease_computation(self): """Initializes attributes and solver for the frobenius norm check. Returns ------- None """ if not self.angle_change > 0: raise ConfigError('MeshQuality', 'angle_change', 'This parameter has to be positive.') options = [[['ksp_type', 'preonly'], ['pc_type', 'jacobi'], ['pc_jacobi_type', 'diagonal'], ['ksp_rtol', 1e-16], ['ksp_atol', 1e-20], ['ksp_max_it', 1000]]] self.ksp_frobenius = PETSc.KSP().create() _setup_petsc_options([self.ksp_frobenius], options) self.trial_dg0 = fenics.TrialFunction(self.form_handler.DG0) self.test_dg0 = fenics.TestFunction(self.form_handler.DG0) if not (self.angle_change == float('inf')): self.search_direction_container = fenics.Function( self.form_handler.deformation_space) self.a_frobenius = self.trial_dg0 * self.test_dg0 * self.dx self.L_frobenius = fenics.sqrt( fenics.inner(fenics.grad(self.search_direction_container), fenics.grad(self.search_direction_container)) ) * self.test_dg0 * self.dx
def debug(self): v = fa.Function(self.V) v.vector()[4] = 1 u = fa.Function(self.V) u.vector()[4] = 1 # v.vector()[:] = 1 value = np.array(fa.assemble(fa.inner(fa.grad(u), fa.grad(v)) * fa.dx)) print(value)
def problem_mix(T, dt, E, coupling, VV, boundaries, rho_s, lambda_, mu_s, f, bcs, **Solid_namespace): # Temporal parameters t = 0 k = Constant(dt) # Split problem to two 1.order differential equations psi, phi = TestFunctions(VV) # Functions, wd is for holding the solution d_ = {} w_ = {} wd_ = {} for time in ["n", "n-1", "n-2", "n-3"]: #if time == "n" and E not in [None, reference]: # tmp_wd = Function(VV) # wd_[time] = tmp_wd # wd = TrialFunction(VV) # w, d = split(wd) #else: wd = Function(VV) wd_[time] = wd w, d = split(wd) d_[time] = d w_[time] = w # Time derivative if coupling == "center": G = rho_s / (2 * k) * inner(w_["n"] - w_["n-2"], psi) * dx else: G = rho_s / k * inner(w_["n"] - w_["n-1"], psi) * dx # Stress tensor G += inner(Piola2(d_, w_, k, lambda_, mu_s, E_func=E), grad(psi)) * dx # External forces, like gravity G -= rho_s * inner(f, psi) * dx # d-w coupling if coupling == "CN": G += inner(d_["n"] - d_["n-1"] - k * 0.5 * (w_["n"] + w_["n-1"]), phi) * dx elif coupling == "imp": G += inner(d_["n"] - d_["n-1"] - k * w_["n"], phi) * dx elif coupling == "exp": G += inner(d_["n"] - d_["n-1"] - k * w_["n-1"], phi) * dx elif coupling == "center": G += inner(d_["n"] - d_["n-2"] - 2 * k * w_["n-1"], phi) * dx else: print "The coupling %s is not implemented, 'CN', 'imp', and 'exp' are the only valid choices." sys.exit(0) # Solve #if E in [None, reference]: solver_nonlinear(G, d_, w_, wd_, bcs, T, dt, **Solid_namespace)
def avg_condition_number(mesh): """Computes average mesh quality based on the condition number of the reference mapping. This quality criterion uses the condition number (in the Frobenius norm) of the (linear) mapping from the elements of the mesh to the reference element. Computes the average of the condition number over all elements. Parameters ---------- mesh : dolfin.cpp.mesh.Mesh The mesh, whose quality shall be computed. Returns ------- float The average mesh quality based on the condition number. """ DG0 = fenics.FunctionSpace(mesh, 'DG', 0) jac = Jacobian(mesh) inv = JacobianInverse(mesh) options = [ ['ksp_type', 'preonly'], ['pc_type', 'jacobi'], ['pc_jacobi_type', 'diagonal'], ['ksp_rtol', 1e-16], ['ksp_atol', 1e-20], ['ksp_max_it', 1000] ] ksp = PETSc.KSP().create() _setup_petsc_options([ksp], [options]) dx = fenics.Measure('dx', mesh) a = fenics.TrialFunction(DG0)*fenics.TestFunction(DG0)*dx L = fenics.sqrt(fenics.inner(jac, jac))*fenics.sqrt(fenics.inner(inv, inv))*fenics.TestFunction(DG0)*dx cond = fenics.Function(DG0) A, b = _assemble_petsc_system(a, L) _solve_linear_problem(ksp, A, b, cond.vector().vec(), options) cond.vector().apply('') return np.average(np.sqrt(mesh.geometric_dimension()) / cond.vector()[:])
def _assembly(V): """ Assemble the matrices used in the linear system Au = b. Alternative representation of the variational form. Pre-calculate to speed up. """ # Define trial and test functions u = F.TrialFunction(V) v = F.TestFunction(V) # Assemble a_M = F.inner(u, v) * F.dx a_K = F.inner(F.grad(u), F.grad(v)) * F.dx M = F.assemble(a_M) K = F.assemble(a_K) A = M + (DT**2) * (C**2) * K return M, K, A
def build_weak_form_staggered(self): self.psi_plus = partial(psi_plus_linear_elasticity_model_A, lamda=self.lamda, mu=self.mu) self.psi_minus = partial(psi_minus_linear_elasticity_model_A, lamda=self.lamda, mu=self.mu) sigma_plus = cauchy_stress_plus(strain(fe.grad(self.x_new)), self.psi_plus) sigma_minus = cauchy_stress_minus(strain(fe.grad(self.x_new)), self.psi_minus) self.G_u = (g_d(self.d_new) * fe.inner(sigma_plus, strain(fe.grad(self.eta))) \ + fe.inner(sigma_minus, strain(fe.grad(self.eta)))) * fe.dx g_c = 2.7e-6 self.G_d = (self.psi_plus(strain(fe.grad(self.x_new))) * self.zeta * g_d_prime(self.d_new, g_d) \ + g_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(fe.grad(self.zeta), fe.grad(self.d_new)))) * fe.dx
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 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