def __init__(self, V, u, v, b, kappa, rho, cp, source, dirichlet_bcs=[], neumann_bcs={}, robin_bcs={}, dx=dx, ds=ds ): super(HeatCylindrical, self).__init__() self.dirichlet_bcs = dirichlet_bcs r = Expression('x[0]', degree=1, domain=V.mesh()) self.V = V self.dx_multiplier = 2*pi*r self.F0 = kappa * r * dot(grad(u), grad(v / (rho * cp))) \ * 2*pi * dx #F -= dot(b, grad(u)) * v * 2*pi*r * dx_workpiece(0) if b: self.F0 += (b[0] * u.dx(0) + b[1] * u.dx(1)) * v * 2*pi*r * dx # Joule heat self.F0 -= 1.0 / (rho * cp) * source * v * 2*pi*r * dx # Neumann boundary conditions for k, nGradT in neumann_bcs.iteritems(): self.F0 -= r * kappa * nGradT * v / (rho * cp) \ * 2 * pi * ds(k) # Robin boundary conditions for k, value in robin_bcs.iteritems(): alpha, u0 = value self.F0 -= r * kappa * alpha * (u - u0) * v / (rho * cp) \ * 2 * pi * ds(k) return
def setup_forms(self, old_solver): prob = self.prob if old_solver is not None: self.old_vel = dfn.interpolate(old_solver.old_vel, prob.v_fnc_space) self.cur_vel = dfn.interpolate(old_solver.cur_vel, prob.v_fnc_space) else: self.old_vel = dfn.Function(prob.v_fnc_space) self.cur_vel = dfn.Function(prob.v_fnc_space) # Assemble matrices from variational forms. Ax = Ls self.a = dfn.inner(dfn.grad(prob.v), dfn.grad(prob.vt)) * dfn.dx self.A = dfn.assemble(self.a) if params['bcs'] is 'test': self.bcs = get_test_bcs(prob.v_fnc_space, test_bc) else: self.bcs = get_normal_bcs(prob.v_fnc_space, test_bc) # For the gradient term in the stress update self.l_elastic = self.dt * self.mu * \ dfn.inner(dfn.grad(prob.v), prob.St) * dfn.dx self.L_elastic = dfn.assemble(self.l_elastic)
def les_update(nut_, nut_form, A_mass, At, u_, dt, bc_ksgs, bt, ksgs_sol, KineticEnergySGS, CG1, ksgs, delta, **NS_namespace): p, q = TrialFunction(CG1), TestFunction(CG1) Ck = KineticEnergySGS["Ck"] Ce = KineticEnergySGS["Ce"] Sij = sym(grad(u_)) assemble(dt*inner(dot(u_, 0.5*grad(p)), q)*dx + inner((dt*Ce*sqrt(ksgs)/delta)*0.5*p, q)*dx + inner(dt*Ck*sqrt(ksgs)*delta*grad(0.5*p), grad(q))*dx, tensor=At) assemble(dt*2*Ck*delta*sqrt(ksgs)*inner(Sij,grad(u_))*q*dx, tensor=bt) bt.axpy(1.0, A_mass*ksgs.vector()) bt.axpy(-1.0, At*ksgs.vector()) At.axpy(1.0, A_mass, True) # Solve for ksgs bc_ksgs.apply(At, bt) ksgs_sol.solve(At, ksgs.vector(), bt) ksgs.vector().set_local(ksgs.vector().array().clip(min=1e-7)) ksgs.vector().apply("insert") # Update nut_ nut_()
def get_distance_function(config, domains): V = dolfin.FunctionSpace(config.domain.mesh, "CG", 1) v = dolfin.TestFunction(V) d = dolfin.TrialFunction(V) sol = dolfin.Function(V) s = dolfin.interpolate(Constant(1.0), V) domains_func = dolfin.Function(dolfin.FunctionSpace(config.domain.mesh, "DG", 0)) domains_func.vector().set_local(domains.array().astype(numpy.float)) def boundary(x): eps_x = config.params["turbine_x"] eps_y = config.params["turbine_y"] min_val = 1 for e_x, e_y in [(-eps_x, 0), (eps_x, 0), (0, -eps_y), (0, eps_y)]: try: min_val = min(min_val, domains_func((x[0] + e_x, x[1] + e_y))) except RuntimeError: pass return min_val == 1.0 bc = dolfin.DirichletBC(V, 0.0, boundary) # Solve the diffusion problem with a constant source term log(INFO, "Solving diffusion problem to identify feasible area ...") a = dolfin.inner(dolfin.grad(d), dolfin.grad(v)) * dolfin.dx L = dolfin.inner(s, v) * dolfin.dx dolfin.solve(a == L, sol, bc) return sol
def solve(self, mesh, num=5): """ Solve for num eigenvalues based on the mesh. """ # conforming elements V = FunctionSpace(mesh, "CG", self.degree) u = TrialFunction(V) v = TestFunction(V) # weak formulation a = inner(grad(u), grad(v)) * dx b = u * v * ds A = PETScMatrix() B = PETScMatrix() A = assemble(a, tensor=A) B = assemble(b, tensor=B) # find eigenvalues eigensolver = SLEPcEigenSolver(A, B) eigensolver.parameters["spectral_transform"] = "shift-and-invert" eigensolver.parameters["problem_type"] = "gen_hermitian" eigensolver.parameters["spectrum"] = "smallest real" eigensolver.parameters["spectral_shift"] = 1.0E-10 eigensolver.solve(num + 1) # extract solutions lst = [ eigensolver.get_eigenpair(i) for i in range( 1, eigensolver.get_number_converged())] for k in range(len(lst)): u = Function(V) u.vector()[:] = lst[k][2] lst[k] = (lst[k][0], u) # pair (eigenvalue,eigenfunction) return np.array(lst)
def neumann_poisson_data(): ''' Return: a bilinear form in the neumann poisson problem L linear form in therein V function space, where a, L are defined bc homog. dirichlet conditions for case where we want pos. def problem z list of orthonormal vectors in the nullspace of A that form basis of ker(A) ''' mesh = UnitSquareMesh(40, 40) V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) f = Expression('x[0]+x[1]') a = inner(grad(u), grad(v))*dx L = inner(f, v)*dx bc = DirichletBC(V, Constant(0), DomainBoundary()) z0 = interpolate(Constant(1), V).vector() normalize(z0, 'l2') print '%16E' % z0.norm('l2') assert abs(z0.norm('l2')-1) < 1E-13 return a, L, V, bc, [z0]
def weak_F(t, u_t, u, v): # All time-dependent components be set to t. u0.t = t f.t = f F = - 1.0 / (rho * cp) * kappa * dot(grad(u), grad(v)) * dx \ + 1.0 / (rho * cp) * kappa * (u*u*u*u - u0*u0*u0*u0) * v * ds \ + 1.0 / (rho * cp) * f * v * dx return F
def compute(self, get): u = get("Velocity") p = get("Pressure") mu = get("DynamicViscosity") if isinstance(mu, (float, int)): mu = Constant(mu) expr = mu*(grad(u) + grad(u).T) - p*Identity(len(u)) return self.expr2function(expr, self._function)
def get_system(self, t): kappa.t = t f.t = t n = FacetNormal(self.V.mesh()) u = TrialFunction(self.V) v = TestFunction(self.V) F = inner(kappa * grad(u), grad(v / self.rho_cp)) * dx \ - inner(kappa * grad(u), n) * v / self.rho_cp * ds \ - f * v / self.rho_cp * dx return assemble(lhs(F)), assemble(rhs(F))
def weak_F(t, u_t, u, v): # Define the differential equation. mesh = v.function_space().mesh() n = FacetNormal(mesh) # All time-dependent components be set to t. f.t = t F = - inner(kappa * grad(u), grad(v / (rho * cp))) * dx \ + inner(kappa * grad(u), n) * v / (rho * cp) * ds \ + f * v / (rho * cp) * dx return F
def assembleWmm(self, x): """ Assemble the derivative of the parameter equation with respect to the parameter (Newton method) """ trial = dl.TrialFunction(self.Vh[PARAMETER]) test = dl.TestFunction(self.Vh[PARAMETER]) u = vector2Function(x[STATE], self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = vector2Function(x[ADJOINT], self.Vh[ADJOINT]) varf = dl.inner(dl.grad(p),dl.exp(m)*dl.grad(u))*trial*test*dl.dx return dl.assemble(varf)
def compute_lorentz(Phi, omega, sigma): ''' In a time-harmonic discretization with .. math:: A &= \Re(a \exp(i \omega t)),\\\\ B &= \Re(b \exp(i \omega t)), the time-average of :math:`A\\times B` over one period is .. math:: \overline{A\\times B} = \\frac{1}{2} \Re(a \\times b^*), see <http://www.ece.rutgers.edu/~orfanidi/ewa/ch01.pdf>. Since the Lorentz force generated by the current :math:`J` in the magnetic field :math:`B` is .. math:: F_L = J \\times B, its time average is .. math:: \overline{F_L} = \\frac{1}{2} \Re(j \\times b^*). With .. math:: J &= \exp(i \omega t) j e_{\\theta},\\\\ B &= \exp(i \omega t) \left(-\\frac{d\phi}{dz} e_r + \\frac{1}{r} \\frac{d(r\phi)}{dr} e_z\\right), we have .. math:: \overline{F_L} &= \\frac{1}{2} \Re\left(j \\frac{d\phi}{dz} e_z + \\frac{j}{r} \\frac{d(r\phi)}{dr} e_r\\right)\\\\ &= \\frac{1}{2} \Re\\left(\\frac{j}{r} \\nabla(r\phi^*)\\right)\\\\ &= \\frac{1}{2} \\left(\\frac{\Re(j)}{r} \\nabla(r \Re(\phi)) +\\frac{\Im(j)}{r} \\nabla(r \Im(\phi))\\right) Only create the Lorentz force for the workpiece. This avoids complications with j(r,z) for which we here can assume .. math:: j = -i \sigma \omega \phi (in particular not containing a voltage term). ''' r = Expression('x[0]', degree=1, domain=Phi[0].function_space().mesh()) j_r = + sigma * omega * Phi[1] j_i = - sigma * omega * Phi[0] return 0.5 * (j_r / r * grad(r * Phi[0]) +j_i / r * grad(r * Phi[1]))
def Jt(self, state, turbine_field): """ Computes the cost of the farm. :param state: Current solution state :type state: dolfin.Function :param turbine_field: Turbine friction field :type turbine_field: dolfin.Function """ # Note, this will not work properly for DG elements (need to add dS measures) mesh = turbine_field.function_space().mesh() return inner(grad(turbine_field), grad(turbine_field))*self.farm.site_dx(domain=mesh)
def get_convmats(u0_dolfun=None, u0_vec=None, V=None, invinds=None, dbcvals=None, dbcinds=None, diribcs=None): """returns the matrices related to the linearized convection where u_0 is the linearization point Returns ------- N1 : (N,N) sparse matrix representing :math:`(u_0 \\cdot \\nabla )u` N2 : (N,N) sparse matrix representing :math:`(u \\cdot \\nabla )u_0` fv : (N,1) array representing :math:`(u_0 \\cdot \\nabla )u_0` See Also -------- stokes_navier_utils.get_v_conv_conts : the convection contributions \ reduced to the inner nodes """ if u0_vec is not None: u0, p = expand_vp_dolfunc(vc=u0_vec, V=V, diribcs=diribcs, dbcvals=dbcvals, dbcinds=dbcinds, invinds=invinds) else: u0 = u0_dolfun u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) # Assemble system n1 = inner(grad(u) * u0, v) * dx n2 = inner(grad(u0) * u, v) * dx f3 = inner(grad(u0) * u0, v) * dx n1 = dolfin.assemble(n1) n2 = dolfin.assemble(n2) f3 = dolfin.assemble(f3) # Convert DOLFIN representation to scipy arrays N1 = mat_dolfin2sparse(n1) N1.eliminate_zeros() N2 = mat_dolfin2sparse(n2) N2.eliminate_zeros() fv = f3.get_local() fv = fv.reshape(len(fv), 1) return N1, N2, fv
def assembleC(self, x): """ Assemble the derivative of the forward problem with respect to the parameter """ trial = dl.TrialFunction(self.Vh[PARAMETER]) test = dl.TestFunction(self.Vh[STATE]) u = vector2Function(x[STATE], Vh[STATE]) m = vector2Function(x[PARAMETER], Vh[PARAMETER]) Cvarf = dl.inner(dl.exp(m) * trial * dl.grad(u), dl.grad(test)) * dl.dx C = dl.assemble(Cvarf) # print ( "||m||", x[PARAMETER].norm("l2"), "||u||", x[STATE].norm("l2"), "||C||", C.norm("linf") ) self.bc0.zero(C) return C
def weak_F(t, u_t, u, v): # Define the differential equation. mesh = v.function_space().mesh() n = FacetNormal(mesh) r = Expression('x[0]', degree=1, cell=triangle) # All time-dependent components be set to t. f.t = t b.t = t kappa.t = t F = - inner(b, grad(u)) * v * dx \ - 1.0 / (rho * cp) * dot(r * kappa * grad(u), grad(v / r)) * dx \ + 1.0 / (rho * cp) * dot(r * kappa * grad(u), n) * v / r * ds \ + 1.0 / (rho * cp) * f * v * dx return F
def assembleWmu(self, x): """ Assemble the derivative of the parameter equation with respect to the state """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[PARAMETER]) p = vector2Function(x[ADJOINT], self.Vh[ADJOINT]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) varf = dl.inner(dl.exp(m)*dl.grad(trial),dl.grad(p))*test*dl.dx Wmu = dl.assemble(varf) Wmu_t = Transpose(Wmu) self.bc0.zero(Wmu_t) Wmu = Transpose(Wmu_t) return Wmu
def get_convvec(u0_dolfun=None, V=None, u0_vec=None, femp=None, dbcvals=None, dbcinds=None, diribcs=None, invinds=None): """return the convection vector e.g. for explicit schemes given a dolfin function or the coefficient vector """ if u0_vec is not None: if femp is not None: diribcs = femp['diribcs'] invinds = femp['invinds'] u0, p = expand_vp_dolfunc(vc=u0_vec, V=V, diribcs=diribcs, dbcvals=dbcvals, dbcinds=dbcinds, invinds=invinds) else: u0 = u0_dolfun v = dolfin.TestFunction(V) ConvForm = inner(grad(u0) * u0, v) * dx ConvForm = dolfin.assemble(ConvForm) if invinds is not None: ConvVec = ConvForm.get_local()[invinds] else: ConvVec = ConvForm.get_local() ConvVec = ConvVec.reshape(len(ConvVec), 1) return ConvVec
def __init__(self, N, dt): """Set up PDE problem for NxN mesh and time step dt.""" from dolfin import UnitSquareMesh, FunctionSpace, TrialFunction, TestFunction, Function, dx, dot, grad mesh = UnitSquareMesh(N, N) self.V = V = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(V) v = TestFunction(V) a = u * v * dx + dt * dot(grad(u), grad(v)) * dx self.a = a self.dt = dt self.mesh = mesh self.U = Function(V)
def system0(n): import dolfin as df mesh = df.UnitIntervalMesh(n) V = df.FunctionSpace(mesh, 'CG', 1) u = df.TrialFunction(V) v = df.TestFunction(V) bc = df.DirichletBC(V, df.Constant(0), 'on_boundary') a = df.inner(df.grad(u), df.grad(v))*df.dx m = df.inner(u, v)*df.dx L = df.inner(df.Constant(0), v)*df.dx A, _ = df.assemble_system(a, L, bc) M, _ = df.assemble_system(m, L, bc) return A, M
def __init__(self, nut, u, Space, bcs=[], name=""): Function.__init__(self, Space, name=name) dim = Space.mesh().geometry().dim() test = TestFunction(Space) self.bf = [inner(inner(grad(nut), u.dx(i)), test)*dx for i in range(dim)]
def __init__(self, mesh, num, denom, method="CR"): """ Assemble matrices and cache matrices. """ self.V = FunctionSpace(mesh, method, 1) # save coordinates of DOFs self.dofs = np.reshape(self.V.dofmap().tabulate_all_coordinates(mesh), (-1, 2)) u = TrialFunction(self.V) v = TestFunction(self.V) self.boundary = MeshFunction("size_t", mesh, 1) # assemble matrices a = inner(grad(u), grad(v)) * dx b = u * v * dx self.A = uBLASSparseMatrix() self.A = assemble(a, tensor=self.A) self.A.compress() self.B = uBLASSparseMatrix() self.B = assemble(b, tensor=self.B) self.B.compress() size = mesh.size(2) # cell diameter calculation self.H2 = (num ** 2 + denom ** 2) * 1.0 / size # print "Theoretical cell diameter: ", sqrt(self.H2) # print "FEniCS calculated: ", mesh.hmax() # Matrices have rational entries. We can rescale to get integers # and save as scipy matrices scaleB = 6.0*size/num/denom self.scaleB = scaleB self.B *= scaleB r, c, val = self.B.data() val = np.round(val) self.B = sps.csr_matrix((val, c, r)) # check if B is diagonal assert len(self.B.diagonal()) == self.B.nnz # find B inverse self.Binv = sps.csr_matrix((1.0/val, c, r)) scaleA = 1.0*num*denom/2 self.scaleA = scaleA self.A *= scaleA r, c, val = self.A.data() self.A = sps.csr_matrix((np.round(val), c, r)) self.scale = scaleA/scaleB print 'scaling A by: ', scaleA print 'scaling B by: ', scaleB print 'eigenvalues scale by:', self.scale
def test_conv_asquad(self): import dolfin_navier_scipy as dns from dolfin import dx, grad, inner import scipy.sparse as sps femp, stokesmatsc, rhsd_vfrc, rhsd_stbc, \ data_prfx, ddir, proutdir = \ dns.problem_setups.get_sysmats(problem='drivencavity', N=15, nu=1e-2) invinds = femp['invinds'] V = femp['V'] hmat = dns.dolfin_to_sparrays.\ ass_convmat_asmatquad(W=femp['V'], invindsw=invinds) xexp = '(1-x[0])*x[0]*(1-x[1])*x[1]*x[0]+2' yexp = '(1-x[0])*x[0]*(1-x[1])*x[1]*x[1]+1' # yexp = 'x[0]*x[0]*x[1]*x[1]' f = dolfin.Expression((xexp, yexp)) u = dolfin.interpolate(f, V) uvec = np.atleast_2d(u.vector().array()).T uvec_gamma = uvec.copy() uvec_gamma[invinds] = 0 u_gamma = dolfin.Function(V) u_gamma.vector().set_local(uvec_gamma) uvec_i = 0 * uvec uvec_i[invinds, :] = uvec[invinds] u_i = dolfin.Function(V) u_i.vector().set_local(uvec_i) # Assemble the 'actual' form w = dolfin.TrialFunction(V) wt = dolfin.TestFunction(V) nform = dolfin.assemble(inner(grad(w) * u, wt) * dx) rows, cols, values = nform.data() nmat = sps.csr_matrix((values, cols, rows)) # consider only the 'inner' equations nmatrc = nmat[invinds, :][:, :] # the boundary terms N1, N2, fv = dns.dolfin_to_sparrays.\ get_convmats(u0_dolfun=u_gamma, V=V) # print np.linalg.norm(nmatrc * uvec_i + nmatrc * uvec_gamma) classicalconv = nmatrc * uvec quadconv = (hmat * np.kron(uvec[invinds], uvec[invinds]) + ((N1 + N2) * uvec_i)[invinds, :] + fv[invinds, :]) self.assertTrue(np.allclose(classicalconv, quadconv)) # print 'consistency tests' self.assertTrue((np.linalg.norm(uvec[invinds]) - np.linalg.norm(uvec_i)) < 1e-14) self.assertTrue(np.linalg.norm(uvec - uvec_gamma - uvec_i) < 1e-14)
def before_first_compute(self, get): u = get("Velocity") assert len(u) == 2, "Can only compute stream function for 2D problems" V = u.function_space() spaces = SpacePool(V.mesh()) degree = V.ufl_element().degree() V = spaces.get_space(degree, 0) psi = TrialFunction(V) self.q = TestFunction(V) a = dot(grad(psi), grad(self.q))*dx() self.bc = DirichletBC(V, Constant(0), DomainBoundary()) self.A = assemble(a) self.L = Vector() self.bc.apply(self.A) self.solver = KrylovSolver(self.A, "cg") self.psi = Function(V)
def _momentum_equation(u, v, p, f, rho, mu, my_dx): """Weak form of the momentum equation. """ # rho and my are Constant() functions assert rho.values()[0] > 0.0 assert mu.values()[0] > 0.0 # Skew-symmetric formulation. # Don't include the boundary term # # - mu *inner(r*grad(u2)*n , v2) * 2*pi*ds. # # This effectively means that at all boundaries where no sufficient # Dirichlet-conditions are posed, we assume grad(u)*n to vanish. # # The original term # u2[0]/(r*r) * v2[0] # doesn't explode iff u2[0]~r and v2[0]~r at r=0. Hence, we need to enforce # homogeneous Dirichlet-conditions for n.u at r=0. This corresponds to no # flow in normal direction through the symmetry axis -- makes sense. # When using the 2*pi*r weighting, we can even be a bit lax on the # enforcement on u2[0]. # # For this to be well defined, u[0]/r and u[2]/r must be bounded for r=0, # so u[0]~u[2]~r must hold. This either needs to be enforced in the # boundary conditions (homogeneous Dirichlet for u[0], u[2] at r=0) or must # follow from the dynamics of the system. # # TODO some more explanation for the following lines of code mesh = v.function_space().mesh() r = SpatialCoordinate(mesh)[0] F = ( rho * 0.5 * (dot(grad(u) * u, v) - dot(grad(v) * u, u)) * 2 * pi * r * my_dx + mu * inner(r * grad(u), grad(v)) * 2 * pi * my_dx + mu * u[0] / r * v[0] * 2 * pi * my_dx - dot(f, v) * 2 * pi * r * my_dx ) if p: F += (p.dx(0) * v[0] + p.dx(1) * v[1]) * 2 * pi * r * my_dx if len(u) == 3: F += rho * (-u[2] * u[2] * v[0] + u[0] * u[2] * v[2]) * 2 * pi * my_dx F += mu * u[2] / r * v[2] * 2 * pi * my_dx return F
def neumann_elasticity_data(): ''' Return: a bilinear form in the neumann elasticity problem L linear form in therein V function space, where a, L are defined bc homog. dirichlet conditions for case where we want pos. def problem z list of orthonormal vectors in the nullspace of A that form basis of ker(A) ''' mesh = UnitSquareMesh(40, 40) V = VectorFunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) f = Expression(('sin(pi*x[0])', 'cos(pi*x[1])')) epsilon = lambda u: sym(grad(u)) # Material properties E, nu = 10.0, 0.3 mu, lmbda = Constant(E/(2*(1 + nu))), Constant(E*nu/((1 + nu)*(1 - 2*nu))) sigma = lambda u: 2*mu*epsilon(u) + lmbda*tr(epsilon(u))*Identity(2) a = inner(sigma(u), epsilon(v))*dx L = inner(f, v)*dx # Zero stress bc = DirichletBC(V, Constant((0, 0)), DomainBoundary()) z0 = interpolate(Constant((1, 0)), V).vector() normalize(z0, 'l2') z1 = interpolate(Constant((0, 1)), V).vector() normalize(z1, 'l2') X = mesh.coordinates().reshape((-1, 2)) c0, c1 = np.sum(X, axis=0)/len(X) z2 = interpolate(Expression(('x[1]-c1', '-(x[0]-c0)'), c0=c0, c1=c1), V).vector() normalize(z2, 'l2') z = [z0, z1, z2] # Check that this is orthonormal basis I = np.zeros((3, 3)) for i, zi in enumerate(z): for j, zj in enumerate(z): I[i, j] = zi.inner(zj) print I print la.norm(I-np.eye(3)) assert la.norm(I-np.eye(3)) < 1E-13 return a, L, V, bc, z
def Matrix_creation(mesh,mu_r,k,k0,ref,extinction = None,vector_order = 3,nodal_order = 3): combined_space = function_space(vector_order,nodal_order,mesh) # Define the test and trial functions from the combined space here N_i and N_j are Nedelec # basis functions and L_i and L_j are Lagrange basis functions (N_i,L_i) = df.TestFunctions(combined_space) (N_j,L_j) = df.TrialFunctions(combined_space) e_r_real = epsilon_real(ref) s_tt_ij = 1.0/mu_r*df.inner(df.curl(N_i),df.curl(N_j)) t_tt_ij = e_r_real*df.inner(N_i,N_j) s_zz_ij = (1.0/mu_r) * df.inner(df.grad(L_i),df.grad(L_j)) t_zz_ij = e_r_real*df.inner(L_i,L_j) A_tt_ij = s_tt_ij - k0**2*t_tt_ij B_zz_ij = s_zz_ij - k0**2*t_zz_ij B_tt_ij = 1/mu_r*df.inner(N_i, N_j) B_tz_ij = 1/mu_r*df.inner(N_i, df.grad(L_j)) B_zt_ij = 1/mu_r*df.inner(df.grad(L_i),N_j) #post-multiplication by dx will result in integration over the domain of the mesh at assembly time A_ij = A_tt_ij*df.dx B_ij = (B_tt_ij+B_tz_ij+B_zt_ij+B_zz_ij)*df.dx #assemble the system Matrices. If there is loss in the system then #we create a new set of matrixes and assemble them ####This is to try and introduce the complex part if k !=0: A = df.assemble(A_ij) B = df.assemble(B_ij) e_r_imag = epsilon_imag(extinction) A_ii_complex = e_r_imag*k0**2*df.inner(N_i,N_j)*df.dx B_ii_complex = e_r_imag*k0**2*df.inner(L_i,L_j)*df.dx A_complex = df.assemble(A_ii_complex) B_complex = df.assemble(B_ii_complex) else: A_complex, B_complex = None, None A,B = df.PETScMatrix(),df.PETScMatrix() df.assemble(A_ij, tensor=A) df.assemble(B_ij, tensor=B) return combined_space, A,B, A_complex,B_complex
def amr(mesh, m, DirichletBoundary, g, mesh2d, s0=1, alpha=1): """Function for computing the Anisotropic MagnetoResistance (AMR), using given magnetisation configuration.""" # Scalar and vector function spaces. V = df.FunctionSpace(mesh, "CG", 1) VV = df.VectorFunctionSpace(mesh, 'CG', 1, 3) # Define boundary conditions. bcs = df.DirichletBC(V, g, DirichletBoundary()) # Nonlinear conductivity. def sigma(u): E = -df.grad(u) costheta = df.dot(m, E)/(df.sqrt(df.dot(E, E))*df.sqrt(df.dot(m, m))) return s0/(1 + alpha*costheta**2) # Define variational problem for Picard iteration. u = df.TrialFunction(V) # electric potential v = df.TestFunction(V) u_k = df.interpolate(df.Expression('x[0]'), V) # previous (known) u a = df.inner(sigma(u_k)*df.grad(u), df.grad(v))*df.dx # RHS to mimic linear problem. f = df.Constant(0.0) # set to 0 -> nonlinear Poisson equation. L = f*v*df.dx u = df.Function(V) # new unknown function eps = 1.0 # error measure ||u-u_k|| tol = 1.0e-20 # tolerance iter = 0 # iteration counter maxiter = 50 # maximum number of iterations allowed while eps > tol and iter < maxiter: iter += 1 df.solve(a == L, u, bcs) diff = u.vector().array() - u_k.vector().array() eps = np.linalg.norm(diff, ord=np.Inf) print 'iter=%d: norm=%g' % (iter, eps) u_k.assign(u) # update for next iteration j = df.project(-sigma(u)*df.grad(u), VV) return u, j, compute_flux(j, mesh2d)
def compute(self, get): u = get("Velocity") mu = get("DynamicViscosity") if isinstance(mu, (float, int)): mu = Constant(mu) n = self._n T = -mu*dot((grad(u) + grad(u).T), n) Tn = dot(T, n) Tt = T - Tn*n tau_form = dot(self.v, Tt)*ds() assemble(tau_form, tensor=self.tau.vector()) #self.b[self._keys] = self.tau.vector()[self._values] # FIXME: This is not safe!!! get_set_vector(self.b, self._keys, self.tau.vector(), self._values, self._temp_array) # Ensure proper scaling self.solver.solve(self.tau_boundary.vector(), self.b) return self.tau_boundary
def F(u, p, v, q, f, r, mu, my_dx): mu = Constant(mu) # Momentum equation (without the nonlinear Navier term). F0 = ( mu * inner(r * grad(u), grad(v)) * 2 * pi * my_dx + mu * u[0] / r * v[0] * 2 * pi * my_dx - dot(f, v) * 2 * pi * r * my_dx ) if len(u) == 3: F0 += mu * u[2] / r * v[2] * 2 * pi * my_dx F0 += (p.dx(0) * v[0] + p.dx(1) * v[1]) * 2 * pi * r * my_dx # Incompressibility condition. # div_u = 1/r * div(r*u) F0 += ((r * u[0]).dx(0) + r * u[1].dx(1)) * q * 2 * pi * my_dx # a = mu * inner(r * grad(u), grad(v)) * 2*pi * my_dx \ # - ((r * v[0]).dx(0) + (r * v[1]).dx(1)) * p * 2*pi * my_dx \ # + ((r * u[0]).dx(0) + (r * u[1]).dx(1)) * q * 2*pi * my_dx # # - div(r*v)*p* 2*pi*my_dx \ # # + q*div(r*u)* 2*pi*my_dx return F0
# values[1] = 2.4142 # values[2] = -22.252E-3 # print("counter value",values) # else: # values[0] = 1.0 # values[1] = 1.0 # values[2] = 0.0 # print("counter value 2 ",values) # def value_shape(self): # return (3,) # u.interpolate(InitialConditions(degree=1)) an, ca, psi = split(u) van, vca, vpsi = TestFunctions(ME) Fan = D_an*(-inner(grad(an), grad(van))*dx - Farad / R / Temp * z_an*an*inner(grad(psi), grad(van))*dx) Fca = D_ca*(-inner(grad(ca), grad(vca))*dx - Farad / R / Temp * z_ca*ca*inner(grad(psi), grad(vca))*dx) Fpsi = inner(grad(psi), grad(vpsi))*dx - (Farad/(eps0*epsR))*(z_an*an + z_ca*ca + z_fc*fc_function)*vpsi*dx F = Fpsi + Fan + Fca J = derivative(F, u) problem = NonlinearVariationalProblem(F, u, bcs = bcs, J = J) solver = NonlinearVariationalSolver(problem) #solver = AdaptiveNonlinearVariationalSolver(problem, M) #print(solver.default_parameters().items()) solver.parameters["newton_solver"]["linear_solver"] = "mumps" solver.solve() ######################### Post - Processing #################################
def constructGalerkinWeakFormulation(self): #----------------------------------------------------------------------------------- tDim = self.tDim wr, wi = self.wr, self.wi ur, ui = self.ur, self.ui MS, MT = self.MS, self.MT mOpt = self.materialOpt pmlOpt = self.pmlOpt s = sigmaFun MTR = MT[tDim](mOpt, s, pmlOpt, returnReal=True, degree=self.meshOpt['polynomialOrder']) MTI = MT[tDim](mOpt, s, pmlOpt, returnReal=False, degree=self.meshOpt['polynomialOrder']) MSR = MS[tDim](mOpt, s, pmlOpt, returnReal=True, degree=self.meshOpt['polynomialOrder']) MSI = MS[tDim](mOpt, s, pmlOpt, returnReal=False, degree=self.meshOpt['polynomialOrder']) bFormR = df.inner(df.grad(wr), MTR*df.grad(ur) - MTI*df.grad(ui))*df.dx \ -df.inner(df.grad(wi), MTI*df.grad(ur) + MTR*df.grad(ui))*df.dx \ - ( df.inner(wr, MSR*ur - MSI*ui)*df.dx \ -df.inner(wi, MSI*ur + MSR*ui)*df.dx ) bFormI = df.inner(df.grad(wr), MTI*df.grad(ur) + MTR*df.grad(ui))*df.dx \ +df.inner(df.grad(wi), MTR*df.grad(ur) - MTI*df.grad(ui))*df.dx \ - ( df.inner(wr, MSI*ur + MSR*ui)*df.dx \ +df.inner(wi, MSR*ur - MSI*ui)*df.dx ) self.bForm = bFormR + bFormI return
def __init__(self, Th): mesh = UnitSquareMesh(Th, Th) self.V = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(self.V) v = TestFunction(self.V) self.a = lambda k: k * inner(grad(u), grad(v)) * dx
bc1_t = d.DirichletBC(V, T_0, facets, 4) bc2_t = d.DirichletBC(V, T_0, facets, 5) # circle bc_e = [bc0_e, bc1_e] bc_t = [bc0_t, bc1_t, bc2_t] # Define initial value, which will later be the solution from the previous (n-th) time step T_n = d.Function(V) T_n = d.interpolate(T_ref, V) # Define variational problem for temperature and potential psi = d.TrialFunction(V) # trial for potential T_n1 = d.TrialFunction(V) # trial for temperature v = d.TestFunction(V) # potential a = d.inner(sigma_T(T_n) * d.grad(psi), d.grad(v)) * dx L = f * v * dx # keep in mind: f=0 psi = d.Function(V) # solution for potential # temperature a_1 = (rho * C_p * T_n1 * v * dx + k_iso * dt * d.dot(d.grad(T_n1), d.grad(v)) * dx) L_1 = (rho * C_p * T_n + dt * sigma_T(T_n) * d.dot(d.grad(psi), d.grad(psi))) * v * dx T_n1 = d.Function(V) # solution for T # Time-stepping t = 0 # write initial temperature datafile.write("%f\t%f\n" % (t, T_n(d.Point(0., 0.25)))) datafileHDF5.write(T_n, "/T_0")
def eps(d, u): return 1. / 2 * (grad(u) * inv(F_(d)) + inv(F_(d)).T * grad(u).T)
def F_(U): return Identity(len(U)) + grad(U)
def test_krylov_reuse_pc(): "Test preconditioner re-use with PETScKrylovSolver" # Define problem mesh = UnitSquareMesh(MPI.comm_world, 8, 8) V = FunctionSpace(mesh, 'Lagrange', 1) bc = DirichletBC(V, Constant(0.0), lambda x, on_boundary: on_boundary) u = TrialFunction(V) v = TestFunction(V) # Forms a, L = inner(grad(u), grad(v)) * dx, dot(Constant(1.0), v) * dx A, P = PETScMatrix(), PETScMatrix() b = PETScVector() # Assemble linear algebra objects assemble(a, tensor=A) # noqa assemble(a, tensor=P) # noqa assemble(L, tensor=b) # noqa # Apply boundary conditions bc.apply(A) bc.apply(P) bc.apply(b) # Create Krysolv solver and set operators solver = PETScKrylovSolver("gmres", "bjacobi") solver.set_operators(A, P) # Solve x = PETScVector() num_iter_ref = solver.solve(x, b) # Change preconditioner matrix (bad matrix) and solve (PC will be # updated) a_p = u * v * dx assemble(a_p, tensor=P) # noqa bc.apply(P) x = PETScVector() num_iter_mod = solver.solve(x, b) assert num_iter_mod > num_iter_ref # Change preconditioner matrix (good matrix) and solve (PC will be # updated) a_p = a assemble(a_p, tensor=P) # noqa bc.apply(P) x = PETScVector() num_iter = solver.solve(x, b) assert num_iter == num_iter_ref # Change preconditioner matrix (bad matrix) and solve (PC will not # be updated) solver.set_reuse_preconditioner(True) a_p = u * v * dx assemble(a_p, tensor=P) # noqa bc.apply(P) x = PETScVector() num_iter = solver.solve(x, b) assert num_iter == num_iter_ref # Update preconditioner (bad PC, will increase iteration count) solver.set_reuse_preconditioner(False) x = PETScVector() num_iter = solver.solve(x, b) assert num_iter == num_iter_mod
def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym( grad(v))) * Identity(2)
def dn_mat(s, n): return dot(outer(grad(s) * n, n).T, n) - dot(grad(s).T, n)
def tan_div(s, n): return div(s) - dot(dot(grad(s), n), n)
# Assign a function to each mesh, such that T and lmb are discontinuous at the # interface Gamma T = MultiMeshFunction(V) T.assign_part(0, project(sin(x0[1]), FunctionSpace(meshes[0], "CG", degree))) T.assign_part( 1, project(cos(x1[0]) * x1[1], FunctionSpace(meshes[1], "CG", degree))) lmb = MultiMeshFunction(V) lmb.assign_part( 0, project(cos(x0[1]) * x0[0], FunctionSpace(meshes[0], "CG", degree))) lmb.assign_part( 1, project(x1[0] * sin(x1[1]), FunctionSpace(meshes[1], "CG", degree))) # Create bilinear form and corresponding gradients #---------------------------------------------------------------------------- a1 = inner(grad(T), grad(lmb)) * dX # Classic shape derivative term top mesh da1_top = div(s_top) * inner(grad(T), grad(lmb)) * dX # Term stemming from grad(T) da1_top -= inner(dot(grad(s_top), grad(T)), grad(lmb)) * dX # Term stemming from grad(lmb) da1_top -= inner(grad(T), dot(grad(s_top), grad(lmb))) * dX # Classic shape derivative term bottom mesh da1_bottom = div(s_bottom) * inner(grad(T), grad(lmb)) * dX # Term stemming from grad(T) da1_bottom += inner(grad(dot(s_bottom, grad(T))), grad(lmb)) * dX # Term stemming from grad(lmb) da1_bottom += inner(grad(T), grad(dot(s_bottom, grad(lmb)))) * dX # Material derivative of background T da1_bottom -= inner(dot(nabla_grad(s_bottom), grad(T)), grad(lmb)) * dX # Material derivative of background lmb
def _test_linear_solver_sparse(callback_type): from dolfin import Function from rbnics.backends.dolfin import LinearSolver # Create mesh and define function space mesh = IntervalMesh(132, 0, 2 * pi) V = FunctionSpace(mesh, "Lagrange", 1) # Define Dirichlet boundary (x = 0 or x = 2 * pi) def boundary(x): return x[0] < 0 + DOLFIN_EPS or x[0] > 2 * pi - 10 * DOLFIN_EPS # Define exact solution exact_solution_expression = Expression("x[0] + sin(2 * x[0])", element=V.ufl_element()) exact_solution = project(exact_solution_expression, V) # Define variational problem u = TrialFunction(V) v = TestFunction(V) g = Expression("4 * sin(2 * x[0])", element=V.ufl_element()) a = inner(grad(u), grad(v)) * dx f = g * v * dx x = inner(u, v) * dx # Assemble inner product matrix X = assemble(x) # Define boundary condition bc = [DirichletBC(V, exact_solution_expression, boundary)] # Define callback function depending on callback type assert callback_type in ("form callbacks", "tensor callbacks") if callback_type == "form callbacks": def callback(arg): return arg elif callback_type == "tensor callbacks": def callback(arg): return assemble(arg) # Define problem wrapper class ProblemWrapper(LinearProblemWrapper): # Vector function def vector_eval(self): return callback(f) # Matrix function def matrix_eval(self): return callback(a) # Define boundary condition def bc_eval(self): return bc # Define custom monitor to plot the solution def monitor(self, solution): if matplotlib.get_backend() != "agg": plot(solution, title="u") plt.show(block=False) plt.pause(1) else: print("||u|| = " + str(solution.vector().norm("l2"))) # Solve the linear problem problem_wrapper = ProblemWrapper() solution = Function(V) solver = LinearSolver(problem_wrapper, solution) solver.solve() # Compute the error error = Function(V) error.vector().add_local(+solution.vector().get_local()) error.vector().add_local(-exact_solution.vector().get_local()) error.vector().apply("") error_norm = error.vector().inner(X * error.vector()) print("Sparse error (" + callback_type + "):", error_norm) assert isclose(error_norm, 0., atol=1.e-5) return (error_norm, V, a, f, X, exact_solution)
def sigma_f_u(u, d, mu_f): """ Deviatoric component of the Cauchy stress tensor (fluid problem) """ return mu_f * (grad(u) * inv(F_(d)) + inv(F_(d)).T * grad(u).T)
def form(self, x): #return dl.avg(dl.exp(x[PARAMETER])*dl.dot( dl.grad(x[STATE]), self.n) )*self.dsGamma return dl.exp(x[PARAMETER]) * dl.dot(dl.grad(x[STATE]), self.n) * self.dsGamma
def define_advection_equation(self): """ Setup the advection equation for the colour function This implementation assembles the full LHS and RHS each time they are needed """ sim = self.simulation mesh = sim.data['mesh'] n = dolfin.FacetNormal(mesh) dS, dx = dolfin.dS(mesh), dolfin.dx(mesh) # Trial and test functions Vc = self.Vc c = dolfin.TrialFunction(Vc) d = dolfin.TestFunction(Vc) c1, c2, c3 = self.time_coeffs dt = self.dt u_conv = self.u_conv if not self.colour_is_discontinuous: # Continous Galerkin implementation of the advection equation # FIXME: add stabilization eq = (c1 * c + c2 * self.cp + c3 * self.cpp) / dt * d * dx + div( c * u_conv) * d * dx elif self.velocity_is_trace: # Upstream and downstream normal velocities w_nU = (dot(u_conv, n) + abs(dot(u_conv, n))) / 2 w_nD = (dot(u_conv, n) - abs(dot(u_conv, n))) / 2 if self.beta is not None: # Define the blended flux # The blending factor beta is not DG, so beta('+') == beta('-') b = self.beta('+') flux = (1 - b) * jump(c * w_nU) + b * jump(c * w_nD) else: flux = jump(c * w_nU) # Discontinuous Galerkin implementation of the advection equation eq = (c1 * c + c2 * self.cp + c3 * self.cpp) / dt * d * dx + flux * jump(d) * dS # On each facet either w_nD or w_nU will be 0, the other is multiplied # with the appropriate flux, either the value c going out of the domain # or the Dirichlet value coming into the domain for dbc in self.dirichlet_bcs: eq += w_nD * dbc.func() * d * dbc.ds() eq += w_nU * c * d * dbc.ds() elif self.beta is not None: # Upstream and downstream normal velocities w_nU = (dot(u_conv, n) + abs(dot(u_conv, n))) / 2 w_nD = (dot(u_conv, n) - abs(dot(u_conv, n))) / 2 if self.beta is not None: # Define the blended flux # The blending factor beta is not DG, so beta('+') == beta('-') b = self.beta('+') flux = (1 - b) * jump(c * w_nU) + b * jump(c * w_nD) else: flux = jump(c * w_nU) # Discontinuous Galerkin implementation of the advection equation eq = ((c1 * c + c2 * self.cp + c3 * self.cpp) / dt * d * dx - dot(c * u_conv, grad(d)) * dx + flux * jump(d) * dS) # Enforce Dirichlet BCs weakly for dbc in self.dirichlet_bcs: eq += w_nD * dbc.func() * d * dbc.ds() eq += w_nU * c * d * dbc.ds() else: # Downstream normal velocities w_nD = (dot(u_conv, n) - abs(dot(u_conv, n))) / 2 # Discontinuous Galerkin implementation of the advection equation eq = (c1 * c + c2 * self.cp + c3 * self.cpp) / dt * d * dx # Convection integrated by parts two times to bring back the original # div form (this means we must subtract and add all fluxes) eq += div(c * u_conv) * d * dx # Replace downwind flux with upwind flux on downwind internal facets eq -= jump(w_nD * d) * jump(c) * dS # Replace downwind flux with upwind BC flux on downwind external facets for dbc in self.dirichlet_bcs: # Subtract the "normal" downwind flux eq -= w_nD * c * d * dbc.ds() # Add the boundary value upwind flux eq += w_nD * dbc.func() * d * dbc.ds() # Penalty forcing zones for fz in self.forcing_zones: eq += fz.penalty * fz.beta * (c - fz.target) * d * dx a, L = dolfin.system(eq) self.form_lhs = dolfin.Form(a) self.form_rhs = dolfin.Form(L) self.tensor_lhs = None self.tensor_rhs = None
def eps(d): """ Infinitesimal strain tensor """ return 0.5 * (grad(d) * inv(F_(d)) + inv(F_(d)).T * grad(d).T)
def D_U(d, v): return 1. / 2 * grad(v) * inv(F_(d))
def F_(d): """ Deformation gradient tensor """ return Identity(len(d)) + grad(d)
def A_E(d, v, lamda_s, mu_s, rho_s, delta, psi, phi, dx_s): return inner(Piola1(d, lamda_s, mu_s), grad(psi))*dx_s \ - delta*rho_s*inner(v, phi)*dx_s
# Incident plane wave theta = np.pi / 8 ui = Expression('exp(j*k0*(cos(theta)*x[0] + sin(theta)*x[1]))', k0=k0, theta=theta, degree=deg + 3, domain=mesh.ufl_domain()) # Test and trial function space V = FunctionSpace(mesh, "Lagrange", deg) # Define variational problem u = TrialFunction(V) v = TestFunction(V) g = dot(grad(ui), n) + 1j * k0 * ui a = inner(grad(u), grad(v)) * dx - k0**2 * inner(u, v) * dx + \ 1j * k0 * inner(u, v) * ds L = inner(g, v) * ds # Compute solution u = Function(V) solve(a == L, u, []) # Save solution in XDMF format (to be viewed in Paraview, for example) with XDMFFile(MPI.comm_world, "plane_wave.xdmf", encoding=XDMFFile.Encoding.HDF5) as file: file.write(u) ''' Calculate L2 and H1 errors of FEM solution and best approximation. This demonstrates the error bounds given in Ihlenburg.
def get_poisson_steps_dolfin(pts, cells, tol): from dolfin import ( Constant, DirichletBC, Function, FunctionSpace, KrylovSolver, Mesh, TestFunction, TrialFunction, XDMFFile, assemble, dx, grad, inner, ) # Still can't initialize a mesh from points, cells filename = "mesh.xdmf" if cells.shape[1] == 3: meshio.write_points_cells(filename, pts, {"triangle": cells}) else: assert cells.shape[1] == 4 meshio.write_points_cells(filename, pts, {"tetra": cells}) mesh = Mesh() with XDMFFile(filename) as f: f.read(mesh) os.remove(filename) os.remove("mesh.h5") # build Laplace matrix with Dirichlet boundary using dolfin V = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx u0 = Constant(0.0) bc = DirichletBC(V, u0, "on_boundary") f = Constant(1.0) L = f * v * dx A = assemble(a) b = assemble(L) bc.apply(A, b) # solve(A, x, b, "cg") solver = KrylovSolver("cg", "none") solver.parameters["absolute_tolerance"] = 0.0 solver.parameters["relative_tolerance"] = tol x = Function(V) x_vec = x.vector() num_steps = solver.solve(A, x_vec, b) # # convert to scipy matrix # A = as_backend_type(A).mat() # ai, aj, av = A.getValuesCSR() # A = scipy.sparse.csr_matrix( # (av, aj, ai), shape=(A.getLocalSize()[0], A.getSize()[1]) # ) # # ev = eigvals(A.todense()) # ev_max = scipy.sparse.linalg.eigs(A, k=1, which="LM")[0][0] # assert numpy.abs(ev_max.imag) < 1.0e-15 # ev_max = ev_max.real # ev_min = scipy.sparse.linalg.eigs(A, k=1, which="SM")[0][0] # assert numpy.abs(ev_min.imag) < 1.0e-15 # ev_min = ev_min.real # cond = ev_max / ev_min # solve poisson system, count num steps # b = numpy.ones(A.shape[0]) # out = pykry.gmres(A, b) # num_steps = len(out.resnorms) return num_steps
#defiene external force f = df.Expression(("f_0 + f_1*cos(2*M_PI*t/tau)", "0."), f_0=f0, f_1=f1, t=0., tau=tau, degree=2) #define Crank-Nikolsen and Adams-Basforth for the time-dependent terms and derivative terms u_CN = 0.5 * (u + u_1) u_CN_ = 0.5 * (u_ + u_1) u_AB_ = 1.5 * u_1 - 0.5 * u_2 #variational form of NSE F = (df.dot(u - u_1, v) / dt * df.dx + nu * df.inner(df.grad(u_CN), df.grad(v)) * df.dx - df.div(v) * p * df.dx - df.div(u) * q * df.dx - df.dot(f, v) * df.dx) #additional term if including u*grad*u if enable_inertia: F += df.inner(df.grad(u_CN) * u_AB_, v) * df.dx #for parallelization x0, y0 = x[0, 0], x[0, 1] x0 = comm.bcast(x0, root=0) y0 = comm.bcast(y0, root=0) #pressure boundary conditions bcp = df.DirichletBC(W.sub(1), df.Constant(0.), ("abs(x[0]-({x0})) < DOLFIN_EPS && " "abs(x[1]-({y0})) < DOLFIN_EPS").format(x0=x0, y0=y0),
# g0 and g1 n = FacetNormal(mesh) xy = Expression(('x[0]', 'x[1]')) g1 = assemble(inner(xy, xy) / inner(xy, n) * ds) * 2 * pi / L**2 g0 = assemble(1. / inner(xy, n) * ds) / 2 / pi g = np.sqrt(g0 * g1) print "g0, g1, g: ", g0, g1, g # final solutions print "Final solving ..." sol = solver.solve(mesh, numeig) print "Eigenvalues: " eigs = np.zeros(len(sol[:, 0])) for i in range(len(eigs)): # Rayleigh quotients eigs[i] = assemble(inner(grad(sol[i, 1]), grad(sol[i, 1])) * dx) / assemble(sol[i, 1] * sol[i, 1] * ds) print sol[i, 0], eigs[i] disk = np.cumsum(sorted(range(1, len(eigs)) * 2)) print "sum*L/(2pi)/disk (optimal g): " sums = np.cumsum(eigs) for i in range(len(eigs)): print sums[i] * L / 2 / pi / disk[i] # make pdf from solutions from export import export export(name, mesh, eigs, sums, disk, sol, f, degree, n, k, l, size, L, g0, g1, g, density)
def xtest_mg_solver_stokes(): mesh0 = UnitCubeMesh(2, 2, 2) mesh1 = UnitCubeMesh(4, 4, 4) mesh2 = UnitCubeMesh(8, 8, 8) Ve = VectorElement("CG", mesh0.ufl_cell(), 2) Qe = FiniteElement("CG", mesh0.ufl_cell(), 1) Ze = MixedElement([Ve, Qe]) Z0 = FunctionSpace(mesh0, Ze) Z1 = FunctionSpace(mesh1, Ze) Z2 = FunctionSpace(mesh2, Ze) W = Z2 # Boundaries def right(x, on_boundary): return x[0] > (1.0 - DOLFIN_EPS) def left(x, on_boundary): return x[0] < DOLFIN_EPS def top_bottom(x, on_boundary): return x[1] > 1.0 - DOLFIN_EPS or x[1] < DOLFIN_EPS # No-slip boundary condition for velocity noslip = Constant((0.0, 0.0, 0.0)) bc0 = DirichletBC(W.sub(0), noslip, top_bottom) # Inflow boundary condition for velocity inflow = Expression(("-sin(x[1]*pi)", "0.0", "0.0"), degree=2) bc1 = DirichletBC(W.sub(0), inflow, right) # Collect boundary conditions bcs = [bc0, bc1] # Define variational problem (u, p) = TrialFunctions(W) (v, q) = TestFunctions(W) f = Constant((0.0, 0.0, 0.0)) a = inner(grad(u), grad(v)) * dx + div(v) * p * dx + q * div(u) * dx L = inner(f, v) * dx # Form for use in constructing preconditioner matrix b = inner(grad(u), grad(v)) * dx + p * q * dx # Assemble system A, bb = assemble_system(a, L, bcs) # Assemble preconditioner system P, btmp = assemble_system(b, L, bcs) spaces = [Z0, Z1, Z2] dm_collection = PETScDMCollection(spaces) solver = PETScKrylovSolver() solver.set_operators(A, P) PETScOptions.set("ksp_type", "gcr") PETScOptions.set("pc_type", "mg") PETScOptions.set("pc_mg_levels", 3) PETScOptions.set("pc_mg_galerkin") PETScOptions.set("ksp_monitor_true_residual") PETScOptions.set("ksp_atol", 1.0e-10) PETScOptions.set("ksp_rtol", 1.0e-10) solver.set_from_options() from petsc4py import PETSc ksp = solver.ksp() ksp.setDM(dm_collection.dm()) ksp.setDMActive(False) x = PETScVector() solver.solve(x, bb) # Check multigrid solution against LU solver solver = LUSolver(A) # noqa x_lu = PETScVector() solver.solve(x_lu, bb) assert round((x - x_lu).norm("l2"), 10) == 0 # Clear all PETSc options opts = PETSc.Options() for key in opts.getAll(): opts.delValue(key)
def _test_time_stepping_2_sparse(callback_type, integrator_type): from dolfin import Function from rbnics.backends.dolfin import TimeStepping # Create mesh and define function space mesh = IntervalMesh(132, 0, 2 * pi) V = FunctionSpace(mesh, "Lagrange", 1) # Define Dirichlet boundary (x = 0 or x = 2*pi) def boundary(x): return x[0] < 0 + DOLFIN_EPS or x[0] > 2 * pi - 10 * DOLFIN_EPS # Define time step dt = 0.01 monitor_dt = 0.02 T = 1. # Define exact solution exact_solution_expression = Expression("sin(x[0]+t)", t=0, element=V.ufl_element()) # ... and interpolate it at the final time exact_solution_expression.t = T exact_solution = project(exact_solution_expression, V) # Define exact solution dot exact_solution_dot_expression = Expression("cos(x[0]+t)", t=0, element=V.ufl_element()) # ... and interpolate it at the final time exact_solution_dot_expression.t = T exact_solution_dot = project(exact_solution_dot_expression, V) # Define variational problem du = TrialFunction(V) du_dot = TrialFunction(V) v = TestFunction(V) u = Function(V) u_dot = Function(V) g = Expression("5. / 4. * sin(t + x[0]) - 3. / 4. * sin(3 * (t + x[0])) + cos(t + x[0])", t=0., element=V.ufl_element()) r_u = inner((1 + u**2) * grad(u), grad(v)) * dx j_u = derivative(r_u, u, du) r_u_dot = inner(u_dot, v) * dx j_u_dot = derivative(r_u_dot, u_dot, du_dot) r = r_u_dot + r_u - g * v * dx x = inner(du, v) * dx def bc(t): exact_solution_expression.t = t return [DirichletBC(V, exact_solution_expression, boundary)] # Assemble inner product matrix X = assemble(x) # Define callback function depending on callback type assert callback_type in ("form callbacks", "tensor callbacks") if callback_type == "form callbacks": def callback(arg): return arg elif callback_type == "tensor callbacks": def callback(arg): return assemble(arg) # Define problem wrapper class ProblemWrapper(TimeDependentProblemWrapper): # Residual and jacobian functions def residual_eval(self, t, solution, solution_dot): g.t = t return callback(r) def jacobian_eval(self, t, solution, solution_dot, solution_dot_coefficient): return callback(Constant(solution_dot_coefficient) * j_u_dot + j_u) # Define boundary condition def bc_eval(self, t): return bc(t) # Define initial condition def ic_eval(self): exact_solution_expression.t = 0. return project(exact_solution_expression, V) # Define custom monitor to plot the solution def monitor(self, t, solution, solution_dot): assert isclose(round(t / monitor_dt), t / monitor_dt) if matplotlib.get_backend() != "agg": plt.subplot(1, 2, 1).clear() plot(solution, title="u at t = " + str(t)) plt.subplot(1, 2, 2).clear() plot(solution_dot, title="u_dot at t = " + str(t)) plt.show(block=False) plt.pause(DOLFIN_EPS) else: print("||u|| at t = " + str(t) + ": " + str(solution.vector().norm("l2"))) print("||u_dot|| at t = " + str(t) + ": " + str(solution_dot.vector().norm("l2"))) # Solve the time dependent problem problem_wrapper = ProblemWrapper() (solution, solution_dot) = (u, u_dot) solver = TimeStepping(problem_wrapper, solution, solution_dot) solver.set_parameters({ "initial_time": 0.0, "time_step_size": dt, "monitor": { "time_step_size": monitor_dt, }, "final_time": T, "exact_final_time": "stepover", "integrator_type": integrator_type, "problem_type": "nonlinear", "snes_solver": { "linear_solver": "mumps", "maximum_iterations": 20, "report": True }, "report": True }) solver.solve() # Compute the error at the final time error = Function(V) error.vector().add_local(+ solution.vector().get_local()) error.vector().add_local(- exact_solution.vector().get_local()) error.vector().apply("") error_norm = error.vector().inner(X * error.vector()) error_dot = Function(V) error_dot.vector().add_local(+ solution_dot.vector().get_local()) error_dot.vector().add_local(- exact_solution_dot.vector().get_local()) error_dot.vector().apply("") error_dot_norm = error_dot.vector().inner(X * error_dot.vector()) print("Sparse error (" + callback_type + ", " + integrator_type + "):", error_norm, error_dot_norm) assert isclose(error_norm, 0., atol=1.e-4) assert isclose(error_dot_norm, 0., atol=1.e-4) return ((error_norm, error_dot_norm), V, dt, monitor_dt, T, u, u_dot, g, r, j_u, j_u_dot, X, exact_solution_expression, exact_solution, exact_solution_dot)
def Fbarevol(v, i): dx = geo.dx("molecule") return dolfin.Constant(Moleculeqv) * (-r * lscale * dolfin.grad(v)[i]) * dx
def scalar_laplacians(mesh): """ Calculate the laplacians needed by fiberrule algorithms Arguments --------- mesh : dolfin.Mesh A dolfin mesh with marked boundaries: base = 10, rv = 20, lv = 30, epi = 40 The base is assumed placed at x=0 """ if not isinstance(mesh, d.Mesh): raise TypeError("Expected a dolfin.Mesh as the mesh argument.") # Init connectivities mesh.init(2) facet_markers = d.MeshFunction("size_t", mesh, 2, mesh.domains()) # Boundary markers, solutions and cases markers = dict(base=10, rv=20, lv=30, epi=40, apex=50) # Solver parameters solver_param=dict(solver_parameters=dict( preconditioner="ml_amg" if d.has_krylov_solver_preconditioner("ml_amg") \ else "default", linear_solver="gmres")) cases = ["rv", "lv", "epi"] boundaries = cases + ["base"] # Check that all boundary faces are marked num_boundary_facets = d.BoundaryMesh(mesh, "exterior").num_cells() if num_boundary_facets != sum(np.sum(\ facet_markers.array()==markers[boundary])\ for boundary in boundaries): d.error("Not all boundary faces are marked correctly. Make sure all "\ "boundary facets are marked as: base = 10, rv = 20, lv = 30, "\ "epi = 40.") # Coords and cells coords = mesh.coordinates() cells_info = mesh.cells() # Find apex by solving a laplacian with base solution = 0 # Create Base variational problem V = d.FunctionSpace(mesh, "CG", 1) u = d.TrialFunction(V) v = d.TestFunction(V) a = d.dot(d.grad(u), d.grad(v))*d.dx L = v*d.Constant(1)*d.dx DBC_10 = d.DirichletBC(V, 1, facet_markers, markers["base"], "topological") # Create solutions solutions = dict((what, d.Function(V)) for what in markers if what != "base") d.solve(a==L, solutions["apex"], DBC_10, solver_parameters={"linear_solver": "gmres"}) apex_values = solutions["apex"].vector().array() apex_values[d.dof_to_vertex_map(V)] = solutions["apex"].vector().array() ind_apex_max = apex_values.argmax() apex_coord = coords[ind_apex_max,:] # Update rhs L = v*d.Constant(0)*d.dx d.info(" Apex coord: ({0}, {1}, {2})".format(*apex_coord)) d.info(" Num coords: {0}".format(len(coords))) d.info(" Num cells: {0}".format(len(cells_info))) # Calculate volume volume = 0.0 for cell in d.cells(mesh): volume += cell.volume() d.info(" Volume: {0}".format(volume)) d.info("") # Cases # ===== # # 1) base: 1, apex: 0 # 2) lv: 1, rv, epi: 0 # 3) rv: 1, lv, epi: 0 # 4) epi: 1, rv, lv: 0 class ApexDomain(d.SubDomain): def inside(self, x, on_boundary): return d.near(x[0], apex_coord[0]) and d.near(x[1], apex_coord[1]) and \ d.near(x[2], apex_coord[2]) apex_domain = ApexDomain() # Case 1: Poisson = 1 DBC_11 = d.DirichletBC(V, 0, apex_domain, "pointwise") # Using Poisson if Poisson: d.solve(a==L, solutions["apex"], [DBC_10, DBC_11], solver_parameters={"linear_solver": "gmres"}) # Using Eikonal equation else: Le = v*d.Constant(1)*d.dx d.solve(a==Le, solutions["apex"], DBC_11, solver_parameters={"linear_solver": "gmres"}) # Create Eikonal problem eps = d.Constant(mesh.hmax()/25) y = solutions["apex"] F = d.sqrt(d.inner(d.grad(y), d.grad(y)))*v*d.dx - \ d.Constant(1)*v*d.dx + eps*d.inner(d.grad(y), d.grad(v))*d.dx d.solve(F==0, y, DBC_11, solver_parameters={ "linear_solver": "lu", "newton_solver": {"relative_tolerance":1e-5}}) # Check that solution of the three last cases all sum to 1. sol = solutions["apex"].vector().copy() sol[:] = 0.0 # Iterate over the three different cases for case in cases: # Solve linear system bcs = [d.DirichletBC(V, 1 if what == case else 0, \ facet_markers, markers[what], "topological") \ for what in cases]
def acoustic_main(theta, plot=False, level=0): """ theta is the parameter vector. here we have theta 0 = x1 theta 1 = x2 theta 2 = alpha theta 3 = beta """ x1 = theta[0] x2 = theta[1] alpha = theta[2]**2.0 beta = theta[3]**2.0 ML = 2**level #c=500 Nx = 40 * ML Ny = 40 * ML p0 = dl.Point(0., 0.) p1 = dl.Point(3, 2) rx = [1., 1.5, 2.] ry = [1.99, 1.99, 1.99] Nrx = len(rx) Nry = len(ry) Nr = Nry t0 = time.time() #beta/alpha=c^2=500**2 #beta=5000**2 #alpha=10**2 #defines the source model def source(t, x1, x2): delta = dl.Expression( 'M*exp(-(x[0]-x1)*(x[0]-x1)/(a*a)-(x[1]-x2)*(x[1]-x2)/(a*a))/a*(1-2*pi2*f02*t*t)*exp(-pi2*f02*t*t)', pi2=np.pi**2, a=1E-1, f02=f02, M=1E10, x1=x1, x2=x2, t=t, degree=1) return delta B = dl.Constant(beta) A = dl.Constant(alpha) mesh = dl.RectangleMesh(p0, p1, Nx, Ny) V = dl.FunctionSpace(mesh, "Lagrange", 1) c2 = beta / alpha hmin = mesh.hmin() dt = 0.15 * hmin / (c2**0.5) # Time variables t = 0 T = 0.003 Nt = int(np.ceil(T / dt)) if plot: print('value of Nt is ' + str(Nt)) print('dt is ' + str(dt)) time_ = np.zeros(Nt) U_wave = np.zeros((Nt, Nr)) # Previous and current solution u1 = dl.interpolate(dl.Constant(0.0), V) u0 = dl.interpolate(dl.Constant(0.0), V) # Variational problem at each time u = dl.TrialFunction(V) v = dl.TestFunction(V) M, K = dl.PETScMatrix(), dl.PETScMatrix() # Assembles matrices M = dl.assemble(A * u * v * dl.dx, tensor=M) f02 = 1000**2.0 K = dl.assemble(dl.inner(B * dl.grad(u), dl.grad(v)) * dl.dx, tensor=K) # M=dl.assemble(u*v*dl.dx) # K=dl.assemble(dl.inner(dl.grad(u),dl.grad(v))*dl.dx) delta = source(t, x1, x2) f = dl.interpolate(delta, V) # ABC class ABCdom(dl.SubDomain): def inside(self, x, on_boundary): return on_boundary and (x[1] < 2.0) abc_boundaryparts = dl.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) ABCdom().mark(abc_boundaryparts, 1) #self.ds = Measure("ds")[abc_boundaryparts] ds = dl.Measure('ds', domain=mesh, subdomain_data=abc_boundaryparts) weak_d = dl.inner((A * B)**0.5 * u, v) * ds(1) class_bc_abc = ABCdom() # to make copies # builds the ABS matrix D = dl.assemble(weak_d) #saves if plot: ofile = dl.File('output/ud_.pvd') u = dl.Function(V) ti = 0 while t <= T: fv = dl.assemble(f * v * dl.dx) Kun = K * u1.vector() Dun = D * (u1.vector() - u0.vector()) / dt b = fv - Kun - Dun dl.solve(M, u.vector(), b) # dl.plot(u);plt.show() # import pdb # pdb.set_trace() u.vector( )[:] = dt**2.0 * u.vector()[:] + 2.0 * u1.vector()[:] - u0.vector()[:] #u=dt**2*u+2.0*u1-u0 u0.assign(u1) u1.assign(u) for rec in range(Nr): U_wave[ti, rec] = u([rx[rec], ry[rec]]) time_[ti] = t t += dt ti += 1 delta = source(t, x1, x2) f = dl.interpolate(delta, V) # Reduce the range of the solution so that we can see the waves if plot: ofile << (u, t) #print('Total time '+str(round(time.time()-t0,3))) return U_wave, time_
def transpmult(self, b): '''Action on vector from V0''' raise NotImplementedError # -------------------------------------------------------------------- if __name__ == '__main__': import numpy as np mesh = df.UnitSquareMesh(32, 32) V = df.FunctionSpace(mesh, 'CG', 1) u, v = df.TrialFunction(V), df.TestFunction(V) a = df.inner(u, df.grad(v)[0]) * df.dx A = df.assemble(a) class Foo(FESpaceOperator): def __init__(self, V=V, A=A): self.A = A FESpaceOperator.__init__(self, V1=V) def matvec(self, b): return self.A * b foo = Foo() x = df.interpolate(df.Constant(0), V).vector() x.set_local(np.r_[1, np.zeros(V.dim() - 1)])
def run_with_params(Tb, mu_value, k_s, path): run_time_init = clock() temperature_vals = [27.0 + 273, Tb + 273, 1300.0 + 273, 1305.0 + 273] temp_prof = TemperatureProfile(temperature_vals) mu_a = mu_value # this was taken from the Blankenbach paper, can change Ep = b / temp_prof.delta mu_bot = exp(-Ep * (temp_prof.bottom * temp_prof.delta - 1573.0) + cc) * mu_a Ra = rho_0 * alpha * g * temp_prof.delta * h**3 / (kappa_0 * mu_a) w0 = rho_0 * alpha * g * temp_prof.delta * h**2 / mu_a tau = h / w0 p0 = mu_a * w0 / h log(mu_a, mu_bot, Ra, w0, p0) vslipx = 1.6e-09 / w0 vslip = Constant((vslipx, 0.0)) # Non-dimensional noslip = Constant((0.0, 0.0)) time_step = 3.0E11 / tau / 10.0 dt = Constant(time_step) tEnd = 3.0E15 / tau / 5.0 # Non-dimensionalising times mesh = RectangleMesh(Point(0.0, 0.0), Point(mesh_width, mesh_height), nx, ny) pbc = PeriodicBoundary() W = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc) S = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) WSSS = MixedFunctionSpace([W, S, S, S]) # WSSS -> W u = Function(WSSS) # Instead of TrialFunctions, we use split(u) for our non-linear problem v, p, T, Tf = split(u) v_t, p_t, T_t, Tf_t = TestFunctions(WSSS) T0 = interpolate(temp_prof, S) FluidTemp = Expression('max(T0, 1.031)', T0=T0) muExp = Expression( 'exp(-Ep * (T_val * dTemp - 1573.0) + cc * x[1] / mesh_height)', Ep=Ep, dTemp=temp_prof.delta, cc=cc, mesh_height=mesh_height, T_val=T0) Tf0 = interpolate(temp_prof, S) mu = Function(S) v0 = Function(W) v_theta = (1.0 - theta) * v0 + theta * v T_theta = (1.0 - theta) * T0 + theta * T Tf_theta = (1.0 - theta) * Tf0 + theta * Tf r_v = (inner(sym(grad(v_t)), 2.0 * mu * sym(grad(v))) - div(v_t) * p - T * v_t[1]) * dx r_p = p_t * div(v) * dx heat_transfer = k_s * (Tf_theta - T_theta) * dt r_T = (T_t * ((T - T0) + dt * inner(v_theta, grad(T_theta))) + (dt / Ra) * inner(grad(T_t), grad(T_theta)) - T_t * heat_transfer) * dx # yvec = Constant((0.0, 1.0)) # rhosolid = rho_0 * (1.0 - alpha * (T_theta * temp_prof.delta - 1573.0)) # deltarho = rhosolid - rhomelt # v_f = v_theta - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0 v_melt = Function(W) yvec = Constant((0.0, 1.0)) # TODO: inner -> dot, take out Tf_t r_Tf = (Tf_t * ((Tf - Tf0) + dt * dot(v_melt, grad(Tf_theta))) + Tf_t * heat_transfer) * dx r = r_v + r_p + r_T + r_Tf bcv0 = DirichletBC(WSSS.sub(0), noslip, top) bcv1 = DirichletBC(WSSS.sub(0), vslip, bottom) bcp0 = DirichletBC(WSSS.sub(1), Constant(0.0), bottom) bct0 = DirichletBC(WSSS.sub(2), Constant(temp_prof.surface), top) bct1 = DirichletBC(WSSS.sub(2), Constant(temp_prof.bottom), bottom) bctf1 = DirichletBC(WSSS.sub(3), Constant(temp_prof.bottom), bottom) bcs = [bcv0, bcv1, bcp0, bct0, bct1, bctf1] t = 0 count = 0 files = DefaultDictByKey(partial(create_xdmf, path)) while t < tEnd: mu.interpolate(muExp) rhosolid = rho_0 * (1.0 - alpha * (T0 * temp_prof.delta - 1573.0)) deltarho = rhosolid - rhomelt assign( v_melt, project(v0 - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0, W)) # use nP after to avoid projection? # pdb.set_trace() solve(r == 0, u, bcs) nV, nP, nT, nTf = u.split() if count % output_every == 0: time_left(count, tEnd / time_step, run_time_init) # TODO: Make sure all writes are to the same function for each time step files['T_fluid'].write(nTf) files['p'].write(nP) files['v_solid'].write(nV) files['T_solid'].write(nT) files['mu'].write(mu) files['v_melt'].write(v_melt) files['gradp'].write(project(grad(nP), W)) files['rho'].write(project(rhosolid, S)) files['Tf_grad'].write(project(grad(Tf), W)) files['advect'].write(project(dt * dot(v_melt, grad(nTf)))) files['ht'].write(project(heat_transfer, S)) assign(T0, nT) assign(v0, nV) assign(Tf0, nTf) t += time_step count += 1 log('Case mu=%g, Tb=%g complete. Run time = %g s' % (mu_a, Tb, clock() - run_time_init))