def Newton_manual(F, vd, bcs, J, atol, rtol, max_it, lmbda\ , vd_res): #Reset counters Iter = 0 residual = 1 rel_res = residual while rel_res > rtol and residual > atol and Iter < max_it: A = assemble(J, keep_diagonal = True) A.ident_zeros() b = assemble(-F) [bc.apply(A, b, vd.vector()) for bc in bcs] #solve(A, vd_res.vector(), b, "superlu_dist") #solve(A, vd_res.vector(), b, "mumps") solve(A, vd_res.vector(), b) vd.vector().axpy(1., vd_res.vector()) [bc.apply(vd.vector()) for bc in bcs] rel_res = norm(vd_res, 'l2') residual = b.norm('l2') if MPI.rank(mpi_comm_world()) == 0: print "Newton iteration %d: r (atol) = %.3e (tol = %.3e), r (rel) = %.3e (tol = %.3e) " \ % (Iter, residual, atol, rel_res, rtol) Iter += 1 #Reset residual = 1 rel_res = residual Iter = 0 return vd
def Newton_manual(F, udp, bcs, atol, rtol, max_it, lmbda, udp_res, VVQ): #Reset counters Iter = 0 residual = 1 rel_res = residual dw = TrialFunction(VVQ) Jac = derivative(F, udp, dw) # Jacobi while rel_res > rtol and residual > atol and Iter < max_it: A = assemble(Jac) A.ident_zeros() b = assemble(-F) [bc.apply(A, b, udp.vector()) for bc in bcs] #solve(A, udp_res.vector(), b, "superlu_dist") solve(A, udp_res.vector(), b) #, "mumps") udp.vector()[:] = udp.vector()[:] + lmbda * udp_res.vector()[:] #udp.vector().axpy(1., udp_res.vector()) [bc.apply(udp.vector()) for bc in bcs] rel_res = norm(udp_res, 'l2') residual = b.norm('l2') if MPI.rank(mpi_comm_world()) == 0: print "Newton iteration %d: r (atol) = %.3e (tol = %.3e), r (rel) = %.3e (tol = %.3e) " \ % (Iter, residual, atol, rel_res, rtol) Iter += 1 return udp
def _assemble(self) -> Tuple[fenics.PETScMatrix, fenics.PETScMatrix]: """Construct matrices for generalized eigenvalue problem. Assemble the left and the right hand side of the eigenfunction equation into the corresponding matrices. Returns ------- A : fenics.PETScMatrix Matrix corresponding to the form $a(u, v)$. B : fenics.PETScMatrix Matrix corresponding to the form $b(u, v)$. """ V = self.vector_space u = fenics.TrialFunction(V) v = fenics.TestFunction(V) a, b = self._construct_eigenproblem(u, v) A = fenics.PETScMatrix() B = fenics.PETScMatrix() fenics.assemble(a * fenics.dx, tensor=A) fenics.assemble(b * fenics.dx, tensor=B) return A, B
def assemble_as_scipy(form): K = PETScMatrix() assemble(form, tensor=K) ki, kj, kv = K.mat().getValuesCSR() import scipy import scipy.sparse Ksp = scipy.sparse.csr_matrix((kv, kj, ki)) return Ksp
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 vjp_solve_eval_impl( g: np.array, fenics_solution: fenics.Function, fenics_residual: ufl.Form, fenics_inputs: List[FenicsVariable], bcs: List[fenics.DirichletBC], ) -> Tuple[np.array]: """Computes the gradients of the output with respect to the inputs.""" # Convert tangent covector (adjoint) to a FEniCS variable adj_value = numpy_to_fenics(g, fenics_solution) adj_value = adj_value.vector() F = fenics_residual u = fenics_solution V = u.function_space() dFdu = fenics.derivative(F, u) adFdu = ufl.adjoint( dFdu, reordered_arguments=ufl.algorithms.extract_arguments(dFdu) ) u_adj = fenics.Function(V) adj_F = ufl.action(adFdu, u_adj) adj_F = ufl.replace(adj_F, {u_adj: fenics.TrialFunction(V)}) adj_F_assembled = fenics.assemble(adj_F) if len(bcs) != 0: for bc in bcs: bc.homogenize() hbcs = bcs for bc in hbcs: bc.apply(adj_F_assembled) bc.apply(adj_value) fenics.solve(adj_F_assembled, u_adj.vector(), adj_value) fenics_grads = [] for fenics_input in fenics_inputs: if isinstance(fenics_input, fenics.Function): V = fenics_input.function_space() dFdm = fenics.derivative(F, fenics_input, fenics.TrialFunction(V)) adFdm = fenics.adjoint(dFdm) result = fenics.assemble(-adFdm * u_adj) if isinstance(fenics_input, fenics.Constant): fenics_grad = fenics.Constant(result.sum()) else: # fenics.Function fenics_grad = fenics.Function(V, result) fenics_grads.append(fenics_grad) # Convert FEniCS gradients to jax array representation jax_grads = ( None if fg is None else np.asarray(fenics_to_numpy(fg)) for fg in fenics_grads ) jax_grad_tuple = tuple(jax_grads) return jax_grad_tuple
def test_DoGIP_vs_FEniCS(self): print( '\n== testing DoGIP vs. FEniCS for problem of weighted projection ====' ) for dim, pol_order in itertools.product([2, 3], [1, 2]): print('dim={}; pol_order={}'.format(dim, pol_order)) N = 2 # creating MESH, defining MATERIAL and SOURCE if dim == 2: mesh = UnitSquareMesh(N, N) m = Expression("1+10*16*x[0]*(1-x[0])*x[1]*(1-x[1])", degree=3) # material coefficients f = Expression("x[0]*x[0]*x[1]", degree=2) elif dim == 3: mesh = UnitCubeMesh(N, N, N) m = Expression("1+100*x[0]*(1-x[0])*x[1]*x[2]", degree=2) # material coefficients f = Expression("(1-x[0])*x[1]*x[2]", degree=2) mesh.coordinates()[:] += 0.1 * np.random.random( mesh.coordinates().shape) # mesh perturbation ## standard approach with FEniCS ############################################# V = FunctionSpace(mesh, "CG", pol_order) # original FEM space u, v = TrialFunction(V), TestFunction(V) u_fenics = Function(V) solve(m * u * v * dx == m * f * v * dx, u_fenics) ## DoGIP - double-grid integration with interpolation-projection ############# W = FunctionSpace(mesh, "CG", 2 * pol_order) # double-grid space w = TestFunction(W) A_dogip = assemble( m * w * dx).get_local() # diagonal matrix of material coefficients b = assemble(m * f * v * dx) # vector of right-hand side # assembling interpolation-projection matrix B B = get_B(V, W, problem=0) # # linear solver on double grid, standard Afun = lambda x: B.T.dot(A_dogip * B.dot(x)) Alinoper = linalg.LinearOperator((V.dim(), V.dim()), matvec=Afun, dtype=np.float) x, info = linalg.cg(Alinoper, b.get_local(), x0=np.zeros(V.dim()), tol=1e-10, maxiter=1e3, callback=None) # testing the difference between DoGIP and FEniCS self.assertAlmostEqual( 0, np.linalg.norm(u_fenics.vector().get_local() - x)) print('...ok')
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 refine_mesh(self, tolerance: float) -> Optional[bool]: """Generate refined mesh. This method locates cells of the mesh where the error of the eigenfunction is above a certain threshold and generates a new mesh with finer resolution on the problematic regions. For a given eigenfunction $u$ with corresponding eigenvalue $\lambda$, it must be true that $a(u, v) = \lambda b(u, v)$ for all functions $v$. We make $v$ go through all the basis functions on the mesh and locate the cells where the previous identity fails to hold. Parameters ---------- tolerance : float Criterion to determine whether a cell needs to be refined or not. Returns ------- refined_mesh : Optional[fenics.Mesh] A new mesh derived from `mesh` with higher level of granularity on certain regions. If no refinements are needed, None is returned. """ ew, ev = self.eigenvalues[1:], self.eigenfunctions[1:] dofs_needing_refinement = set() # Find all the degrees of freedom needing refinement. for k, (l, u) in enumerate(zip(ew, ev)): v = fenics.TrialFunction(self.vector_space) a, b = self._construct_eigenproblem(u, v) A = fenics.assemble(a * fenics.dx) B = fenics.assemble(b * fenics.dx) error = np.abs((A - l * B).sum()) indices = np.flatnonzero(error > tolerance) dofs_needing_refinement.update(indices) if not dofs_needing_refinement: return # Refine the cells corresponding to the degrees of freedom needing # refinement. dofmap = self.vector_space.dofmap() cell_markers = fenics.MeshFunction('bool', self.mesh, self.mesh.topology().dim()) cell_markers.set_all(False) for cell in fenics.cells(self.mesh): cell_dofs = set(dofmap.cell_dofs(cell.index())) if cell_dofs.intersection(dofs_needing_refinement): cell_markers[cell] = True return fenics.refine(self.mesh, cell_markers)
def test_empty_measure(): mesh, _, _, dx, ds, dS = cashocs.regular_mesh(5) V = fenics.FunctionSpace(mesh, 'CG', 1) dm = cashocs.utils.EmptyMeasure(dx) trial = fenics.TrialFunction(V) test = fenics.TestFunction(V) assert fenics.assemble(1 * dm) == 0.0 assert (fenics.assemble(test * dm).norm('linf')) == 0.0 assert (fenics.assemble(trial * test * dm).norm('linf')) == 0.0
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 integrateFluidStress(p, u): eps = 0.5*(grad(u) + grad(u).T) sig = -p*Identity(2) + 2.0*mu_f*eps sig1 = J_(u)*sig*inv(F_(u)).T traction = dot(sig1, -n) forceX = traction[0]*ds(5) + traction[0]*ds(6) forceY = traction[1]*ds(5) + traction[1]*ds(6) fX = assemble(forceX) fY = assemble(forceY) return fX, fY
def update_map(self): d_clipped = fe.conditional(fe.gt(self.d_new, 0.5), self.d_new, 0.) d_int_full = fe.assemble(self.d_new * fe.det(self.grad_gamma) * fe.dx) d_int = fe.assemble(d_clipped * fe.det(self.grad_gamma) * fe.dx) print("d_int_clipped {}".format(float(d_int))) print("d_int_full {}".format(float(d_int_full))) update_flag = False if d_int - self.d_integrals[-1] > self.d_integral_interval: update_flag = True if update_flag and not self.finish_flag: print('\n') print( '=================================================================================' ) print('>> Updating map...') print( '=================================================================================' ) new_tip_point = self.identify_crack_tip() if self.inside_domain(new_tip_point): if len(self.control_points) > 1: v1 = self.control_points[-1] - self.control_points[-2] v2 = new_tip_point - self.control_points[-1] v1 = v1 / np.linalg.norm(v1) v2 = v2 / np.linalg.norm(v2) print("new_tip_point is {}".format(new_tip_point)) print("v1 is {}".format(v1)) print("v2 is {}".format(v2)) print("control points are \n{}".format( self.control_points)) print("impact_radii are {}".format(self.impact_radii)) assert np.dot( v1, v2 ) > np.sqrt(2) / 2, "Crack propogration angle not good" self.compute_impact_radii(new_tip_point) self.interpolate_H() self.d_integrals.append(d_int) print( '=================================================================================' ) else: self.finish_flag = True self.update_weak_form = True else: print("Do not modify map") print("d_integrals {}".format(self.d_integrals))
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 write_results_table_row(self, table_filepath): with open(table_filepath, "a") as table_file: table_file.write( str(self.pressure_penalty_factor.__float__()) + "," \ + str(self.solid_viscosity.__float__()) + "," \ + str(self.temperature_rayleigh_number.__float__()) + "," \ + str(self.concentration_rayleigh_number.__float__()) + ", " \ + str(self.prandtl_number.__float__()) + ", " \ + str(self.stefan_number.__float__()) + ", " \ + str(self.schmidt_number.__float__()) + ", " \ + str(self.liquidus_slope.__float__()) + ", " \ + str(self.pure_liquidus_temperature.__float__()) + ", " \ + str(self.regularization_central_temperature_offset.__float__()) + ", " \ + str(self.regularization_smoothing_parameter.__float__()) + ", " \ + str(1./float(self.uniform_gridsize)) + ", " \ + str(self.timestep_size.__float__()) + ", " \ + str(self.time_order) + ", " \ + str(self.time) + ", ") solid_area = fenics.assemble(self.solid_area_integrand()) area_above_critical_phi = fenics.assemble( self.area_above_critical_phi_integrand()) solute_mass = fenics.assemble(self.solute_mass_integrand()) p, u, T, C = self.solution.leaf_node().split(deepcopy=True) phi = fenics.project(self.semi_phasefield(T=T, C=C), mesh=self.mesh.leaf_node()) Cbar = fenics.project(C * (1. - phi), mesh=self.mesh.leaf_node()) table_file.write( str(solid_area) + ", " \ + str(area_above_critical_phi) + ", " \ + str(solute_mass) + ", " \ + str(p.vector().min()) + ", " \ + str(p.vector().max()) + ", " \ + str(fenics.norm(u.vector(), "linf")) + ", " \ + str(T.vector().min()) + ", " \ + str(T.vector().max()) + ", " \ + str(Cbar.vector().min()) + ", " \ + str(Cbar.vector().max()) + ", " \ + str(phi.vector().min()) + ", " \ + str(phi.vector().max())) table_file.write("\n")
def solve_problem_matrix_approach(self): u = fa.TrialFunction(self.V) v = fa.TestFunction(self.V) a = fa.inner(fa.grad(u), fa.grad(v)) * fa.dx L = self.source * v * fa.dx # equivalent to solve(a == L, U, b) A = fa.assemble(a) b = fa.assemble(L) [bc.apply(A, b) for bc in self.bcs] u = fa.Function(self.V) U = u.vector() fa.solve(A, U, b) return u
def test__deepcopy__ci__(): tolerance = 1.e-6 sim = CavityMeltingSimulationWithoutConcentration() sim.assign_initial_values() for it in range(3): sim.solve(goal_tolerance=4.e-5) sim.advance() sim2 = sim.deepcopy() assert (all(sim.solution.vector() == sim2.solution.vector())) for it in range(2): sim.solve(goal_tolerance=4.e-5) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) assert (abs(solid_area - expected_solid_area) < tolerance) assert (not (sim.solution.vector() == sim2.solution.vector())) for it in range(2): sim2.solve(goal_tolerance=4.e-5) sim2.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim2.solution) phi = sim2.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) assert (abs(solid_area - expected_solid_area) < tolerance) assert (all(sim.solution.vector() == sim2.solution.vector()))
def compute_operators(self): u = fa.TrialFunction(self.V) v = fa.TestFunction(self.V) form_a = fa.inner(fa.grad(u), fa.grad(v)) * fa.dx form_b = u * v * fa.dx A = fa.assemble(form_a) B = fa.assemble(form_b) A_np = np.array(A.array()) B_np = np.array(B.array()) [bc.apply(A) for bc in self.bcs] A_np_modified = np.array(A.array()) return A_np, B_np, A_np_modified
def mean_value(u, xmin, xmax, V): uu = fenics.Expression( f"((x[0] >= {xmin}) " f"&& (x[0] < {xmax}))" f"? 1 : 0;", element=V.ufl_element() ) one = fenics.Function(V) one.vector()[:] = 1.0 denom = fenics.assemble(uu * one * fenics.dx) if denom == 0: out = np.nan else: out = fenics.assemble(uu * u * fenics.dx) / denom return out
def compute_steady_state(self): names = {'Cl', 'Na', 'K'} P1 = FiniteElement('P', fe.triangle, 1) element = MixedElement([P1, P1, P1]) V = FunctionSpace(self.mesh, element) self.V_conc = V (u_cl, u_na, u_k) = TrialFunction(V) (v_cl, v_na, v_k) = TestFunction(V) assert (self.flow is not None) n = fe.FacetNormal(self.mesh) # F = ( self.F_diff_conv(u_cl, v_cl, n, grad(self.phi), 1. ,1., 0.) # + self.F_diff_conv(u_na, v_na, n, grad(self.phi), 1. ,1., 0.) # + self.F_diff_conv(u_k , v_k , n, grad(self.phi), 1. ,1., 0.) ) dx, ds = self.dx, self.ds flow = self.flow F = inner(grad(u_cl), grad(v_cl)) * dx \ + inner(flow, grad(u_cl)) * v_cl * dx \ + inner(grad(u_na), grad(v_na)) * dx \ + inner(flow, grad(u_na)) * v_na * dx \ + inner(grad(u_k), grad(v_k)) * dx \ + inner(flow, grad(u_k)) * v_k * dx a, L = fe.lhs(F), fe.rhs(F) a_mat = fe.assemble(a) L_vec = fe.assemble(L) # solve u = Function(V) fe.solve(a_mat, u.vector(), L_vec) u_cl, u_na, u_k = u.split() output1 = fe.File('/tmp/steady_state_cl.pvd') output1 << u_cl output2 = fe.File('/tmp/steady_state_na.pvd') output2 << u_na output3 = fe.File('/tmp/steady_state_k.pvd') output3 << u_k self.u_cl = u_cl self.u_na = u_na self.u_k = u_k
def __init__(me, V, max_smooth_vectors=50): R = fenics.FunctionSpace(V.mesh(), 'R', 0) u_trial = fenics.TrialFunction(V) v_test = fenics.TestFunction(V) c_trial = fenics.TrialFunction(R) d_test = fenics.TestFunction(R) a11 = fenics.inner(fenics.grad(u_trial), fenics.grad(v_test)) * fenics.dx a12 = c_trial * v_test * fenics.dx a21 = u_trial * d_test * fenics.dx A11 = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(a11)) A12 = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(a12)) A21 = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(a21)) me.A = sps.bmat([[A11, A12], [A21, None]]).tocsc() solve_A = spla.factorized(me.A) m = u_trial * v_test * fenics.dx me.M = convert_fenics_csr_matrix_to_scipy_csr_matrix( fenics.assemble(m)).tocsc() solve_M = spla.factorized(me.M) def solve_neumann(f_vec): fe_vec = np.concatenate([f_vec, np.array([0])]) ue_vec = solve_A(fe_vec) u_vec = ue_vec[:-1] return u_vec me.solve_neumann_linop = spla.LinearOperator((V.dim(), V.dim()), matvec=solve_neumann) me.solve_M_linop = spla.LinearOperator((V.dim(), V.dim()), matvec=solve_M) ee, UU = spla.eigsh(me.solve_neumann_linop, k=max_smooth_vectors - 1, M=me.solve_M_linop, which='LM') me.U_smooth = np.zeros((V.dim(), max_smooth_vectors)) const_fct = np.ones(V.dim()) me.U_smooth[:, 0] = const_fct / np.sqrt( np.dot(const_fct, me.M * const_fct)) me.U_smooth[:, 1:] = solve_M(UU[:, ::-1]) me.k = 0
def test__cavity_freezing_simulation__ci__(): sim = phaseflow.cavity_freezing_simulation.CavityFreezingSimulation( uniform_gridsize=16, time_order=2) sim.cold_wall_temperature_before_freezing.assign(0.25) sim.cold_wall_temperature_during_freezing.assign(-1.25) sim.temperature_rayleigh_number.assign(3.e5) sim.concentration_rayleigh_number.assign(-3.e4) sim.schmidt_number.assign(1.) sim.liquidus_slope.assign(-0.1) sim.regularization_smoothing_parameter.assign(1. / 16.) sim.output_dir = tempfile.mkdtemp() + "/test__cavity_freezing_simulation/" sim.timestep_size.assign(1.) endtime = 3. sim.run(endtime=endtime, checkpoint_times=( 0., endtime, )) A_S = fenics.assemble(sim.solid_area_integrand()) assert (abs(A_S - 0.177) < 1.e-3)
def vjp_assemble_impl( g: np.array, fenics_output_form: ufl.Form, fenics_inputs: List[FenicsVariable], ) -> Tuple[np.array]: """Computes the gradients of the output with respect to the inputs.""" # Compute derivative form for the output with respect to each input fenics_grads_forms = [] for fenics_input in fenics_inputs: # Need to construct direction (test function) first if isinstance(fenics_input, fenics.Function): V = fenics_input.function_space() elif isinstance(fenics_input, fenics.Constant): mesh = fenics_output_form.ufl_domain().ufl_cargo() V = fenics.FunctionSpace(mesh, "Real", 0) else: raise NotImplementedError dv = fenics.TestFunction(V) fenics_grad_form = fenics.derivative(fenics_output_form, fenics_input, dv) fenics_grads_forms.append(fenics_grad_form) # Assemble the derivative forms fenics_grads = [fenics.assemble(form) for form in fenics_grads_forms] # Convert FEniCS gradients to jax array representation jax_grads = (None if fg is None else np.asarray(g * fenics_to_numpy(fg)) for fg in fenics_grads) jax_grad_tuple = tuple(jax_grads) return jax_grad_tuple
def jvp_assemble_eval( fenics_function: Callable, fenics_templates: Iterable[FenicsVariable], primals: Tuple[np.array], tangents: Tuple[np.array], ) -> Tuple[np.array]: """Computes the jacobian-vector product for fenics.assemble """ numpy_output_primal, output_primal_form, fenics_primals = assemble_eval( fenics_function, fenics_templates, *primals) # Now tangent evaluation! fenics_tangents = convert_all_to_fenics(fenics_primals, *tangents) output_tangent_form = 0.0 for fp, ft in zip(fenics_primals, fenics_tangents): output_tangent_form += fenics.derivative(output_primal_form, fp, ft) if not isinstance(output_tangent_form, float): output_tangent_form = ufl.algorithms.expand_derivatives( output_tangent_form) output_tangent = fenics.assemble(output_tangent_form) jax_output_tangent = output_tangent return numpy_output_primal, jax_output_tangent
def test_create_measure(): meas = cashocs.utils.generate_measure([1, 2, 3], ds) test = ds(1) + ds(2) + ds(3) assert abs(fenics.assemble(1 * meas) - 3) < 1e-14 for i in range(3): assert meas._measures[i] == test._measures[i]
def energy_norm(self, u): psi_plus = self.psi_plus(strain(self.mfem_grad(u))) psi_minus = self.psi_minus(strain(self.mfem_grad(u))) return np.sqrt( float( fe.assemble((g_d(self.d_exact) * psi_plus + psi_minus) * fe.det(self.grad_gamma) * fe.dx)))
def test__compositional_convection_coupled_melting_benchmark__amr__regression__ci__( ): sim = phaseflow.cavity_melting_simulation.CavityMeltingSimulation() sim.output_dir = tempfile.mkdtemp() + \ "/test__compositional_convection_coupled_melting/" phaseflow.helpers.mkdir_p(sim.output_dir) sim.assign_initial_values() sim.timestep_size.assign(10.) for it, epsilon_M in zip(range(4), (0.5e-3, 0.25e-3, 0.125e-3, 0.0625e-3)): if it == 1: sim.regularization_sequence = None sim.solve_with_auto_regularization(goal_tolerance=epsilon_M) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) expected_solid_area = 0.7405 solid_area = fenics.assemble(phi * fenics.dx) tolerance = 1.e-4 assert (abs(solid_area - expected_solid_area) < tolerance)
def test__coarsen__ci__(): sim = CavityMeltingSimulationWithoutConcentration() sim.assign_initial_values() for it in range(3): sim.solve(goal_tolerance=4.e-5) sim.advance() sim.coarsen(absolute_tolerances=(1., 1., 1.e-3, 1., 1.)) for it in range(2): sim.solve(goal_tolerance=4.e-5) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) tolerance = 1.e-3 assert (abs(solid_area - expected_solid_area) < tolerance)
def test__checkpoint__ci__(): sim = CavityMeltingSimulationWithoutConcentration() sim.assign_initial_values() for it in range(2): sim.solve(goal_tolerance=4.e-5) sim.advance() checkpoint_filepath = tempfile.mkdtemp() + "/checkpoint.h5" sim.write_checkpoint(checkpoint_filepath) sim2 = CavityMeltingSimulationWithoutConcentration() sim2.read_checkpoint(checkpoint_filepath) for it in range(3): sim.solve(goal_tolerance=4.e-5) sim.advance() p_fine, u_fine, T_fine, C_fine = fenics.split(sim.solution) phi = sim.semi_phasefield(T=T_fine, C=C_fine) solid_area = fenics.assemble(phi * fenics.dx) assert (abs(solid_area - expected_solid_area) < 1.e-6)
def test__stefan_problem_with_bdf2__regression__ci__(): expected_melted_length = 0.094662 sim = StefanProblemBenchmarkSimulation(time_order=2) sim.output_dir = tempfile.mkdtemp() + "/test__stefan_problem_with_bdf2/" phaseflow.helpers.mkdir_p(sim.output_dir) sim.assign_initial_values() end_time = 0.1 timestep_count = 25 sim.timestep_size.assign(end_time / float(timestep_count)) sim.regularization_smoothing_parameter.assign(0.005) for it in range(timestep_count): if it == 1: sim.regularization_sequence = None sim.solve_with_auto_regularization(goal_tolerance=1.e-7) sim.advance() melted_length = fenics.assemble(sim.melted_length_integrand()) tolerance = 1.e-4 assert (abs(melted_length - expected_melted_length) < tolerance)
def get_tumour_volume(self): # Perhaps there is a prettier way, but integrate a unit function over the tumour tets one = d.Function(self.V) one.vector()[:] = 1 return sum(d.assemble(one * self.dxs(i)) for i in v.tissues["tumour"]["indices"])
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 )