def check_ass_penaro(bcsd=None, bcssfuns=None, V=None, plot=False): mesh = V.mesh() bcone = bcsd[1] contshfunone = bcssfuns[1] Gammaone = bcone() bparts = dolfin.MeshFunction('size_t', mesh, mesh.topology().dim() - 1) Gammaone.mark(bparts, 0) u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) # Robin boundary form arob = dolfin.inner(u, v) * dolfin.ds(0) brob = dolfin.inner(v, contshfunone) * dolfin.ds(0) amatrob = dolfin.assemble(arob, exterior_facet_domains=bparts) bmatrob = dolfin.assemble(brob, exterior_facet_domains=bparts) amatrob = dts.mat_dolfin2sparse(amatrob) amatrob.eliminate_zeros() print 'Number of nonzeros in amatrob:', amatrob.nnz bmatrob = bmatrob.array() # [ININDS] if plot: plt.figure(2) plt.spy(amatrob) if plot: plt.figure(1) for x in contshfunone.xs: plt.plot(x[0], x[1], 'bo') plt.show()
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 __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, config, feasible_area, attraction_center): ''' Generates the inequality constraints to enforce the turbines in the feasible area. If the turbine is outside the domain, the constraints is equal to the distance between the turbine and the attraction center. ''' self.config = config self.feasible_area = feasible_area # Compute the gradient of the feasible area fs = dolfin.FunctionSpace(feasible_area.function_space().mesh(), "DG", feasible_area.function_space().ufl_element().degree() - 1) feasible_area_grad = (dolfin.Function(fs), dolfin.Function(fs)) t = dolfin.TestFunction(fs) log(INFO, "Solving for gradient of feasible area") for i in range(2): form = dolfin.inner(feasible_area_grad[i], t) * dolfin.dx - dolfin.inner(feasible_area.dx(i), t) * dolfin.dx if dolfin.NonlinearVariationalSolver.default_parameters().has_parameter("linear_solver"): dolfin.solve(form == 0, feasible_area_grad[i], solver_parameters={"linear_solver": "cg", "preconditioner": "amg"}) else: dolfin.solve(form == 0, feasible_area_grad[i], solver_parameters={"newton_solver": {"linear_solver": "cg", "preconditioner": "amg"}}) self.feasible_area_grad = feasible_area_grad self.attraction_center = attraction_center
def M_inv_diag(self, domain = "all"): """ Returns the inverse lumped mass matrix for the vector function space. The result ist cached. .. note:: This method requires the PETSc Backend to be enabled. *Returns* :class:`dolfin.Matrix` the matrix """ if not self._M_inv_diag.has_key(domain): v = TestFunction(self.VectorFunctionSpace()) u = TrialFunction(self.VectorFunctionSpace()) mass_form = inner(v, u) * self.dx(domain) mass_action_form = action(mass_form, Constant((1.0, 1.0, 1.0))) diag = assemble(mass_action_form) as_backend_type(diag).vec().reciprocal() result = assemble(inner(v, u) * dP) result.zero() result.set_diagonal(diag) self._M_inv_diag[domain] = result return self._M_inv_diag[domain]
def __init__(self, form, Space, bcs=[], name="x", matvec=[None, None], method="default", solver_type="cg", preconditioner_type="default"): Function.__init__(self, Space, name=name) self.form = form self.method = method self.bcs = bcs self.matvec = matvec self.trial = trial = TrialFunction(Space) self.test = test = TestFunction(Space) Mass = inner(trial, test) * dx() self.bf = inner(form, test) * dx() self.rhs = Vector(self.vector()) if method.lower() == "default": self.A = A_cache[(Mass, tuple(bcs))] self.sol = Solver_cache[(Mass, tuple( bcs), solver_type, preconditioner_type)] elif method.lower() == "lumping": assert Space.ufl_element().degree() < 2 self.A = A_cache[(Mass, tuple(bcs))] ones = Function(Space) ones.vector()[:] = 1. self.ML = self.A * ones.vector() self.ML.set_local(1. / self.ML.array())
def readV(self, functionspaces_V): # Solutions: self.V = functionspaces_V['V'] self.test = TestFunction(self.V) self.trial = TrialFunction(self.V) self.u0 = Function(self.V) # u(t-Dt) self.u1 = Function(self.V) # u(t) self.u2 = Function(self.V) # u(t+Dt) self.rhs = Function(self.V) self.sol = Function(self.V) # Parameters: self.Vl = functionspaces_V['Vl'] self.lam = Function(self.Vl) self.Vr = functionspaces_V['Vr'] self.rho = Function(self.Vr) if functionspaces_V.has_key('Vm'): self.Vm = functionspaces_V['Vm'] self.mu = Function(self.Vm) self.elastic = True assert(False) else: self.elastic = False self.weak_k = inner(self.lam*nabla_grad(self.trial), \ nabla_grad(self.test))*dx self.weak_m = inner(self.rho*self.trial,self.test)*dx
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 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 computeVelocityField(mesh): Xh = dl.VectorFunctionSpace(mesh,'Lagrange', 2) Wh = dl.FunctionSpace(mesh, 'Lagrange', 1) if dlversion() <= (1,6,0): XW = dl.MixedFunctionSpace([Xh, Wh]) else: mixed_element = dl.MixedElement([Xh.ufl_element(), Wh.ufl_element()]) XW = dl.FunctionSpace(mesh, mixed_element) Re = 1e2 g = dl.Expression(('0.0','(x[0] < 1e-14) - (x[0] > 1 - 1e-14)'), element=Xh.ufl_element()) bc1 = dl.DirichletBC(XW.sub(0), g, v_boundary) bc2 = dl.DirichletBC(XW.sub(1), dl.Constant(0), q_boundary, 'pointwise') bcs = [bc1, bc2] vq = dl.Function(XW) (v,q) = dl.split(vq) (v_test, q_test) = dl.TestFunctions (XW) def strain(v): return dl.sym(dl.nabla_grad(v)) F = ( (2./Re)*dl.inner(strain(v),strain(v_test))+ dl.inner (dl.nabla_grad(v)*v, v_test) - (q * dl.div(v_test)) + ( dl.div(v) * q_test) ) * dl.dx dl.solve(F == 0, vq, bcs, solver_parameters={"newton_solver": {"relative_tolerance":1e-4, "maximum_iterations":100, "linear_solver":"default"}}) return v
def __init__(self, form, Space, bcs=[], name="x", matvec=[None, None], method="default", solver_type="cg", preconditioner_type="default"): Function.__init__(self, Space, name=name) self.form = form self.method = method self.bcs = bcs self.matvec = matvec self.trial = trial = TrialFunction(Space) self.test = test = TestFunction(Space) Mass = inner(trial, test)*dx() self.bf = inner(form, test)*dx() self.rhs = Vector(self.vector()) if method.lower() == "default": self.A = A_cache[(Mass, tuple(bcs))] self.sol = KrylovSolver(solver_type, preconditioner_type) self.sol.parameters["preconditioner"]["structure"] = "same" self.sol.parameters["error_on_nonconvergence"] = False self.sol.parameters["monitor_convergence"] = False self.sol.parameters["report"] = False elif method.lower() == "lumping": assert Space.ufl_element().degree() < 2 self.A = A_cache[(Mass, tuple(bcs))] ones = Function(Space) ones.vector()[:] = 1. self.ML = self.A * ones.vector() self.ML.set_local(1. / self.ML.array())
def setget_rhs(V, Q, fv, fp, t=None): if t is not None: fv.t = t fp.t = t elif hasattr(fv, 't') or hasattr(fp, 't'): Warning('No value for t specified') v = dolfin.TestFunction(V) q = dolfin.TestFunction(Q) fv = inner(fv, v) * dx fp = inner(fp, q) * dx fv = dolfin.assemble(fv) fp = dolfin.assemble(fp) fv = fv.get_local() fv = fv.reshape(len(fv), 1) fp = fp.get_local() fp = fp.reshape(len(fp), 1) rhsvecs = {'fv': fv, 'fp': fp} return rhsvecs
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 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 get_conv_diff(u, v, epsilon, wind, stabilize=True): a = ( epsilon*inner(nabla_grad(u), nabla_grad(v))*dx + inner(nabla_grad(u), wind)*v*dx ) L = f*v*dx if stabilize: a += delta*inner(wind, nabla_grad(u))*inner(wind, nabla_grad(v))*dx L += delta*f*inner(wind, nabla_grad(v))*dx return a, L
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 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 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 weighted_H1_norm(w, vec, piecewise=False): if piecewise: DG = FunctionSpace(vec.basis.mesh, "DG", 0) s = TestFunction(DG) ae = assemble(w * inner(nabla_grad(vec._fefunc), nabla_grad(vec._fefunc)) * s * dx) norm_vec = np.array([sqrt(e) for e in ae]) # map DG dofs to cell indices dofs = [DG.dofmap().cell_dofs(c.index())[0] for c in cells(vec.basis.mesh)] norm_vec = norm_vec[dofs] else: ae = assemble(w * inner(nabla_grad(vec._fefunc), nabla_grad(vec._fefunc)) * dx) norm_vec = sqrt(ae) return norm_vec
def get_inp_opa(cdcoo=None, NU=8, V=None, xcomp=0): """dolfin.assemble the 'B' matrix the findim array representation of the input operator Parameters ---------- cdcoo : dictionary with xmin, xmax, ymin, ymax of the control domain NU : dimension of the input space V : FEM space of the velocity xcomp : spatial component that is preserved, the other is averaged out """ cdom = ContDomain(cdcoo) v = dolfin.TestFunction(V) v_one = dolfin.Expression(('1', '1'), element=V.ufl_element()) v_one = dolfin.interpolate(v_one, V) BX, BY = [], [] for nbf in range(NU): ubf = L2abLinBas(nbf, NU) bux = Cast1Dto2D(ubf, cdom, vcomp=0, xcomp=xcomp) buy = Cast1Dto2D(ubf, cdom, vcomp=1, xcomp=xcomp) bx = inner(v, bux) * dx by = inner(v, buy) * dx Bx = dolfin.assemble(bx) By = dolfin.assemble(by) Bx = Bx.array() By = By.array() Bx = Bx.reshape(len(Bx), 1) By = By.reshape(len(By), 1) BX.append(sps.csc_matrix(By)) BY.append(sps.csc_matrix(Bx)) Mu = ubf.massmat() try: return ( sps.hstack([sps.hstack(BX), sps.hstack(BY)], format='csc'), sps.block_diag([Mu, Mu])) except AttributeError: # e.g. in scipy <= 0.9 return ( sps.hstack([sps.hstack(BX), sps.hstack(BY)], format='csc'), sps.hstack([sps.vstack([Mu, sps.csc_matrix((NU, NU))]), sps.vstack([sps.csc_matrix((NU, NU)), Mu])]))
def poisson_bilinear_form(coeff_func, V): """Assemble the discrete problem (i.e. the stiffness matrix).""" # setup problem, assemble and apply boundary conditions u = TrialFunction(V) v = TestFunction(V) a = inner(coeff_func * nabla_grad(u), nabla_grad(v)) * dx return a
def before_first_compute(self, get): u = get("Velocity") V = u.function_space() spaces = SpacePool(V.mesh()) degree = V.ufl_element().degree() if degree <= 1: Q = spaces.get_grad_space(V, shape=(spaces.d,)) else: if degree > 2: cbc_warning("Unable to handle higher order WSS space. Using CG1.") Q = spaces.get_space(1,1) Q_boundary = spaces.get_space(Q.ufl_element().degree(), 1, boundary=True) self.v = TestFunction(Q) self.tau = Function(Q, name="WSS_full") self.tau_boundary = Function(Q_boundary, name="WSS") local_dofmapping = mesh_to_boundarymesh_dofmap(spaces.BoundaryMesh, Q, Q_boundary) self._keys = np.array(local_dofmapping.keys(), dtype=np.intc) self._values = np.array(local_dofmapping.values(), dtype=np.intc) self._temp_array = np.zeros(len(self._keys), dtype=np.float_) Mb = assemble(inner(TestFunction(Q_boundary), TrialFunction(Q_boundary))*dx) self.solver = create_solver("gmres", "jacobi") self.solver.set_operator(Mb) self.b = Function(Q_boundary).vector() self._n = FacetNormal(V.mesh())
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 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 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 _assemble(self): self.V = self.parameters['V'] self.diff = Function(self.V) self.diffv = self.diff.vector() self.trial = TrialFunction(self.V) self.test = TestFunction(self.V) self.W = assemble(inner(self.trial, self.test)*dx)
def get_mass_form(self): """Get 'mass'/identity matrix form""" u = self.trial_function v = self.test_function eps_r = self.material_functions['eps_r'] m = eps_r*inner(v, u)*dx return m
def __init__(self, Vh, dX, bcs, form = None): """ Constructor: :code:`Vh`: the finite element space for the state variable. :code:`dX`: the integrator on subdomain `X` where observation are presents. \ E.g. :code:`dX = dl.dx` means observation on all :math:`\Omega` and :code:`dX = dl.ds` means observations on all :math:`\partial \Omega`. :code:`bcs`: If the forward problem imposes Dirichlet boundary conditions :math:`u = u_D \mbox{ on } \Gamma_D`; \ :code:`bcs` is a list of :code:`dolfin.DirichletBC` object that prescribes homogeneuos Dirichlet conditions :math:`u = 0 \mbox{ on } \Gamma_D`. :code:`form`: if :code:`form = None` we compute the :math:`L^2(X)` misfit: :math:`\int_X (u - u_d)^2 dX,` \ otherwise the integrand specified in the given form will be used. """ if form is None: u, v = dl.TrialFunction(Vh), dl.TestFunction(Vh) self.W = dl.assemble(dl.inner(u,v)*dX) else: self.W = dl.assemble( form ) if bcs is None: bcs = [] if isinstance(bcs, dl.DirichletBC): bcs = [bcs] if len(bcs): Wt = Transpose(self.W) [bc.zero(Wt) for bc in bcs] self.W = Transpose(Wt) [bc.zero(self.W) for bc in bcs] self.d = dl.Vector(self.W.mpi_comm()) self.W.init_vector(self.d,1) self.noise_variance = None
def __init__(self, cparams, dtype_u, dtype_f): """ Initialization routine Args: cparams: custom parameters for the example dtype_u: particle data type (will be passed parent class) dtype_f: acceleration data type (will be passed parent class) """ # define the Dirichlet boundary def Boundary(x, on_boundary): return on_boundary # these parameters will be used later, so assert their existence assert 'c_nvars' in cparams assert 'nu' in cparams assert 't0' in cparams assert 'family' in cparams assert 'order' in cparams assert 'refinements' in cparams # add parameters as attributes for further reference for k,v in cparams.items(): setattr(self,k,v) df.set_log_level(df.WARNING) df.parameters["form_compiler"]["optimize"] = True df.parameters["form_compiler"]["cpp_optimize"] = True # set mesh and refinement (for multilevel) mesh = df.UnitIntervalMesh(self.c_nvars) # mesh = df.UnitSquareMesh(self.c_nvars[0],self.c_nvars[1]) for i in range(self.refinements): mesh = df.refine(mesh) # self.mesh = mesh # define function space for future reference self.V = df.FunctionSpace(mesh, self.family, self.order) tmp = df.Function(self.V) print('DoFs on this level:',len(tmp.vector().array())) # invoke super init, passing number of dofs, dtype_u and dtype_f super(fenics_heat,self).__init__(self.V,dtype_u,dtype_f) self.g = df.Expression('-sin(a*x[0]) * (sin(t) - b*a*a*cos(t))',a=np.pi,b=self.nu,t=self.t0,degree=self.order) # rhs in weak form self.w = df.Function(self.V) v = df.TestFunction(self.V) self.a_K = -self.nu*df.inner(df.nabla_grad(self.w), df.nabla_grad(v))*df.dx + self.g*v*df.dx # mass matrix u = df.TrialFunction(self.V) a_M = u*v*df.dx self.M = df.assemble(a_M) self.bc = df.DirichletBC(self.V, df.Constant(0.0), Boundary)
def assemble_matrix(x, y, nx, ny): diffusion.user_parameters['lower0'] = x/nx diffusion.user_parameters['lower1'] = y/ny diffusion.user_parameters['upper0'] = (x + 1)/nx diffusion.user_parameters['upper1'] = (y + 1)/ny diffusion.user_parameters['open0'] = (x + 1 == nx) diffusion.user_parameters['open1'] = (y + 1 == ny) return df.assemble(df.inner(diffusion * df.nabla_grad(u), df.nabla_grad(v)) * df.dx)
def __init__(self, V, sigma=1.25, s=0.0625, mean=None, rel_tol=1e-10, max_iter=100, **kwargs): self.V = V self.dim = V.dim() self.dof_coords = get_dof_coords(V) self.sigma = sigma self.s = s self.mean = mean # self.mpi_comm=kwargs['mpi_comm'] if 'mpi_comm' in kwargs else df.mpi_comm_world() self.mpi_comm = kwargs.pop('mpi_comm', df.mpi_comm_world()) # mass matrix and its inverse M_form = df.inner(df.TrialFunction(V), df.TestFunction(V)) * df.dx self.M = df.PETScMatrix() df.assemble(M_form, tensor=self.M) self.Msolver = df.PETScKrylovSolver("cg", "jacobi") self.Msolver.set_operator(self.M) self.Msolver.parameters["maximum_iterations"] = max_iter self.Msolver.parameters["relative_tolerance"] = rel_tol self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False # square root of mass matrix self.rtM = self._get_rtmass() # kernel matrix and its square root self.K = self._get_ker() self.rtK = _get_sqrtm(self.K, 'K') # set solvers for op in ['K']: operator = getattr(self, op) solver = self._set_solver(operator, op) setattr(self, op + 'solver', solver) if mean is None: self.mean = df.Vector() self.init_vector(self.mean, 0)
def solve_timestep(u_, p_, r_, u_1, p_1, r_1, tau_SUPG, D, L1, a1, L2, A2, L3, A3, L4, a4, bcu, bcp, bcr): # Step 1: Tentative velocity step A1 = assemble(a1) # needs to be reassembled because density changed! [bc.apply(A1) for bc in bcu] b1 = assemble(L1) [bc.apply(b1) for bc in bcu] solve(A1, u_.vector(), b1, 'bicgstab', 'hypre_amg') # Step 2: Pressure correction step b2 = assemble(L2) [bc.apply(b2) for bc in bcp] solve(A2, p_.vector(), b2, 'bicgstab', 'hypre_amg') # Step 3: Velocity correction step b3 = assemble(L3) solve(A3, u_.vector(), b3, 'cg', 'sor') # Step 4: Transport of rho / Convection-diffusion and SUPG # wont work for DG if D > 0.0: mesh = tau_SUPG.function_space().mesh() magnitude = project((sqrt(inner(u_, u_))), mesh=mesh).vector().vec().array h = project(CellDiameter(mesh), mesh=mesh).vector().vec().array Pe = magnitude * h / (2.0 * D) tau_np = np.zeros_like(Pe) ll = Pe > 0. tau_np[ll] = h[ll] / (2.0 * magnitude[ll]) * (1.0 / np.tanh(Pe[ll]) - 1.0 / Pe[ll]) tau_SUPG.vector().vec().array = tau_np A4 = assemble(a4) b4 = assemble(L4) [bc.apply(A4) for bc in bcr] [bc.apply(b4) for bc in bcr] solve(A4, r_.vector(), b4, 'bicgstab', 'hypre_amg') # F = (div(D*grad(rho_1)) - div(u_*rho_1))*dt + rho_1 # rho_ = project(F, mesh=mesh) # Update previous solution u_1.assign(u_) p_1.assign(p_) r_1.assign(r_) return u_1, p_1, r_1
def updateControl(self): """ The optimal continuous control in this example depends on the gradient. """ x, y = SpatialCoordinate(self.mesh) # res1 = inner((self.a1 - self.a2), grad(grad(self.u))) - (self.f1 - self.f2) # Dxx = grad(grad(self.u)) if hasattr(self, 'H'): print('Use FE Hessian') Dxxu = self.H else: print('Use piecewise Hessian') Dxxu = grad(grad(self.u)) # Dxx = self.H # Dxx = grad(grad(self.u)) res1 = inner((self.a1 - self.a2), Dxxu) - (self.f1 - self.f2) self.gamma[0] = conditional(res1 > 0, 0.0, 1.0)
def solveAdj(self, adj, x, adj_rhs, tol): """ Solve the linear adjoint problem: Given :math:`m, u`; find :math:`p` such that .. math:: \\delta_u F(u, m, p;\\hat{u}) = 0, \\quad \\forall \\hat{u}. """ if self.solver is None: self.solver = self._createLUSolver() u = vector2Function(x[STATE], self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.Function(self.Vh[ADJOINT]) du = dl.TestFunction(self.Vh[STATE]) dp = dl.TrialFunction(self.Vh[ADJOINT]) varf = self.varf_handler(u, m, p) adj_form = dl.derivative( dl.derivative(varf, u, du), p, dp ) Aadj, dummy = dl.assemble_system(adj_form, dl.inner(u,du)*dl.dx, self.bc0) self.solver.set_operator(Aadj) self.solver.solve(adj, adj_rhs)
def __init__(self, domain): rho, mu, dt = domain.rho, domain.mu, domain.dt u, u_1, vu = domain.u, domain.u_1, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) u_mid = (u + u_1) / 2.0 F1 = rho * dot((u - u_1) / dt, vu) * dx \ + rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx \ + inner(sigma(u_mid, p_1, mu), epsilon(vu)) * dx \ + dot(p_1 * n, vu) * ds - dot(mu * nabla_grad(u_mid) * n, vu) * ds a1 = lhs(F1) L1 = rhs(F1) A1 = assemble(a1) [bc.apply(A1) for bc in domain.bcu] self.a1, self.L1, self.A1 = a1, L1, A1 self.domain = domain return
def set_forms(self, unknown, geom_ord=[0]): """ Set up weak forms of elliptic PDE. """ if any(s >= 0 for s in geom_ord): ## forms for forward equation ## # 4. Define variational problem # functions if not hasattr(self, 'states_fwd'): self.states_fwd = df.Function(self.W) # u, l = df.split(self.states_fwd) u, l = df.TrialFunctions(self.W) v, m = df.TestFunctions(self.W) f = _source_term(degree=2) # variational forms if 'true' in str(type(unknown)): unknown = df.interpolate(unknown, self.V) self.F = df.exp(unknown) * df.inner( df.grad(u), df.grad(v)) * df.dx + ( u * m + v * l) * self.ds - f * v * df.dx + self.nugg * l * m * df.dx # self.dFdstates = df.derivative(self.F, self.states_fwd) # Jacobian # self.a = unknown*df.inner(df.grad(u), df.grad(v))*df.dx + (u*m + v*l)*self.ds + self.nugg*l*m*df.dx # self.L = f*v*df.dx if any(s >= 1 for s in geom_ord): ## forms for adjoint equation ## # Set up the objective functional J # u,_,_ = df.split(self.states_fwd) # J_form = obj.form(u) # Compute adjoint of forward operator F2 = df.action(self.F, self.states_fwd) self.dFdstates = df.derivative( F2, self.states_fwd) # linearized forward operator args = ufl.algorithms.extract_arguments( self.dFdstates) # arguments for bookkeeping self.adj_dFdstates = df.adjoint( self.dFdstates, reordered_arguments=args ) # adjoint linearized forward operator # self.dJdstates = df.derivative(J_form, self.states_fwd, df.TestFunction(self.W)) # derivative of functional with respect to solution # self.dirac_1 = obj.ptsrc(u,1) # dirac_1 cannot be initialized here because it involves evaluation ## forms for gradient ## self.dFdunknown = df.derivative(F2, unknown) self.adj_dFdunknown = df.adjoint(self.dFdunknown)
def harmonic_interpolation_simple(mesh, points, values): # Laplace equation V = dolfin.FunctionSpace(mesh, "CG", 1) u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) a = dolfin.inner(dolfin.grad(u), dolfin.grad(v)) * dolfin.dx L = dolfin.Constant(0.) * v * dolfin.dx(domain=mesh) # Point-wise boundary condition bc = PointBC(V, points, values) # Assemble, apply bc and solve A, b = dolfin.assemble_system(a, L) bc.apply(A) bc.apply(b) u = dolfin.Function(V) dolfin.solve(A, u.vector(), b, "cg", "hypre_amg") return u
def __eval_fimpl(self, u, t): """ Helper routine to evaluate the implicit part of the RHS Args: u (dtype_u): current values t (float): current time (not used here) Returns: implicit part of RHS """ tmp = self.dtype_u(self.V) tmp.values.vector()[:] = df.assemble( -self.params.nu * df.inner(df.grad(u.values), df.grad(self.v)) * df.dx) fimpl = self.__invert_mass_matrix(tmp) return fimpl
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 __init__(self, t_end = None, func = None, para_stiff = None, adjoint = False): Problem_Basic.__init__(self, t_end = t_end, func = func, para_stiff = para_stiff) self.k = dol.Constant(self.k) self.u0_expr = dol.Constant(self.u0) # initial value mesh = dol.UnitIntervalMesh(1) R_elem = dol.FiniteElement("R", mesh.ufl_cell(), 0) V_elem = dol.MixedElement([R_elem, R_elem]) self.V = dol.FunctionSpace(mesh, V_elem) if adjoint: self.z0_expr = dol.Constant(np.array([0., 0.])) # initial value adj Problem_FE.__init__(self, adjoint) (self.v1 , self.v2) = dol.split(self.v) (self.u1trial, self.u2trial) = dol.split(self.utrial) (self.u1old , self.u2old) = dol.split(self.uold) (self.u1low , self.u2low) = dol.split(self.ulow) ## Crank nicolson weak formulation F = (dol.inner(self.v1, self.u1trial - self.u1old + self.dt * (0.5 * (self.u1old + self.u1trial) - 0.5 * (self.u2old + self.u2trial)))*dol.dx + dol.inner(self.v2, self.u2trial - self.u2old - self.k * self.dt * 0.5 * (self.u2old + self.u2trial))*dol.dx) prob = dol.LinearVariationalProblem(dol.lhs(F), dol.rhs(F), self.unew) self.solver = dol.LinearVariationalSolver(prob) ## Implicit Euler weak formulation for error estimation Flow = (dol.inner(self.v1, self.u1trial - self.u1old + self.dt * (self.u1trial - self.u2trial))*dol.dx + dol.inner(self.v2, self.u2trial - self.u2old - self.k * self.dt * self.u2trial)*dol.dx) problow = dol.LinearVariationalProblem(dol.lhs(Flow), dol.rhs(Flow), self.ulow) self.solver_low = dol.LinearVariationalSolver(problow) if adjoint: (self.z1old , self.z2old) = dol.split(self.zold) (self.z1trial, self.z2trial) = dol.split(self.ztrial) if self.func not in [1, 2]: raise ValueError('DWR not (yet) implemented for this functional') adj_src = dol.Function(self.V) if self.func == 1: adj_src.interpolate(dol.Constant((1, 0))) elif self.func == 2: adj_src.interpolate(dol.Constant((0, 1))) src1, src2 = dol.split(adj_src) Fadj = (dol.inner(self.z1trial - self.z1old + 0.5 * self.dt * (-self.z1trial - self.z1old + 2*src1), self.v1)*dol.dx + dol.inner(self.z2trial - self.z2old + 0.5 * self.dt * ( self.z1trial + self.z1old + self.k*(self.z2trial + self.z2old) + 2*src2), self.v2)*dol.dx) prob_adj = dol.LinearVariationalProblem(dol.lhs(Fadj), dol.rhs(Fadj), self.znew) self.solver_adj = dol.LinearVariationalSolver(prob_adj)
def weak_residual_form(self, sol): # cast params as constant functions so that, if they are set to 0, FEniCS still understand # what is being integrated mu, M = Constant(self.physics.mu), Constant(self.physics.M) lam = Constant(self.physics.lam) mn, mf = Constant(self.mn), Constant(self.mf) D = self.physics.D v = d.TestFunction(self.fem.S) # r^(D-1) rD = Expression('pow(x[0],D-1)', D=D, degree=self.fem.func_degree) # define the weak residual form F = - inner( grad(sol), grad(v)) * rD * dx + (mu/mn)**2*sol * v * rD * dx \ - lam*(mf/mn)**2*sol**3 * v * rD * dx - mn**(D-2.) / M**2 * self.source.rho * sol * v * rD * dx return F
def setup(self, S3, m, Ms0, unit_length=1.0): self.S3 = S3 self.m = m self.Ms0 = Ms0 self.unit_length = unit_length self.mu0 = mu0 self.exchange_factor = 2.0 / (self.mu0 * Ms0 * self.unit_length**2) u3 = df.TrialFunction(S3) v3 = df.TestFunction(S3) self.K = df.PETScMatrix() df.assemble(self.C * df.inner(df.grad(u3), df.grad(v3)) * df.dx, tensor=self.K) self.H = df.PETScVector() self.vol = df.assemble(df.dot(v3, df.Constant([1, 1, 1])) * df.dx).array() self.coeff = -self.exchange_factor / (self.vol * self.me**2)
def delta_cg(mesh, expr): V = df.FunctionSpace(mesh, "CG", 1) Vv = df.VectorFunctionSpace(mesh, "CG", 1) u = df.interpolate(expr, Vv) u1 = df.TrialFunction(Vv) v1 = df.TestFunction(Vv) K = df.assemble(df.inner(df.grad(u1), df.grad(v1)) * df.dx).array() L = df.assemble(df.dot(v1, df.Constant([1, 1, 1])) * df.dx).array() h = -np.dot(K, u.vector().array()) / L fun = df.Function(Vv) fun.vector().set_local(h) res = [] for x in xs: res.append(fun(x, 5, 0.5)[0]) df.plot(fun) return res
def __init__(self, V, **kwargs): # Call parent ParametrizedProblem.__init__(self, os.path.join("test_eim_approximation_15_tempdir", expression_type, basis_generation, "mock_problem")) # Minimal subset of a ParametrizedDifferentialProblem self.V = V self._solution = Function(V) self.components = ["u", "s", "p"] # Parametrized function to be interpolated x = SpatialCoordinate(V.mesh()) mu = SymbolicParameters(self, V, (-1., -1.)) self.f00 = 1./sqrt(pow(x[0]-mu[0], 2) + pow(x[1]-mu[1], 2) + 0.01) self.f01 = 1./sqrt(pow(x[0]-mu[0], 4) + pow(x[1]-mu[1], 4) + 0.01) # Inner product f = TrialFunction(self.V) g = TestFunction(self.V) self.inner_product = assemble(inner(f, g)*dx) # Collapsed vector and space self.V0 = V.sub(0).collapse() self.V00 = V.sub(0).sub(0).collapse() self.V1 = V.sub(1).collapse()
def updateCoefficients(self): x, y = SpatialCoordinate(self.mesh) # Init coefficient matrix # self.a = as_matrix([[1., Constant(0.)], [Constant(0.), 1.]]) self.a = as_matrix([[self.gamma[0] * x**2 + 1, Constant(0.)], [Constant(0.), 1.]]) # self.a_0 = as_matrix([[1., Constant(0.)], [Constant(0.), 1.]]) # Set up explicit solution r = sqrt(x**2 + y**2) phi = ufl.atan_2(x, y) self.u_0 = r**self.alpha * sin(2. * phi) * (1 - x) * (1 - y) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_0))) + self.gamma[0]**2 # Set boundary conditions to exact solution self.g = Constant(0.0)
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
def _vertex_transfer(f, embedding): '''Use interpolation of archlength''' g = transfer_mesh_function(f, embedding) g = to_P1_function(g) if f.mesh().geometry().dim() == 2: g0 = df.interpolate(df.Expression('std::max(x[0], x[1])', degree=1), g.function_space()) marks = embedding.edge_coloring marks.array()[marks.array() > 0] = 1 dS = df.Measure('dS', domain=embedding.embedding_mesh, subdomain_data=marks) assert df.sqrt(abs(df.assemble(df.inner(df.avg(g0 - g), df.avg(g0 - g))*dS(1)))) < 1E-13 else: # We're on line x=y=z g0 = df.interpolate(df.Expression('x[0]', degree=1), g.function_space()) # And we'd like to do a line integral marks = embedding.edge_coloring edges, = np.where(marks.array() > 0) # The embedded ones f = lambda x: (g(x) - g0(x))**2 x = embedding.embedding_mesh.coordinates() embedding.embedding_mesh.init(1, 0) e2v = embedding.embedding_mesh.topology()(1, 0) result = 0. for edge in edges: x0, x1 = x[e2v(edge)] # Get quarature points for degree 2 xq0 = 0.5*x0*(1-(-1./df.sqrt(3))) + 0.5*x1*(1+(-1./df.sqrt(3))) xq1 = 0.5*x0*(1-(1./df.sqrt(3))) + 0.5*x1*(1+(1./df.sqrt(3))) # Same reference weights equal to 1. So we just rescale wq = np.linalg.norm(x1 - x0) result += f(xq0)*wq + f(xq1)*wq result = df.sqrt(abs(result)) assert result < 1E-13 return True
def big_error_norms(self, u, overlap_subdomain): V = FunctionSpace(self.mesh, "Lagrange", self.p) uu = Function(V) uu.vector()[:] = u.vector() # uu.vector()[:] = u.vector() overlap_marker = MeshFunction('size_t', self.mesh, self.mesh.topology().dim()) overlap_subdomain.mark(overlap_marker, 1) dxo = Measure('dx', subdomain_data=overlap_marker) error = (uu**2) * dxo semi_error = inner(grad(uu), grad(uu)) * dxo L2 = assemble(error) H1 = L2 + assemble(semi_error) SH = H1 - L2 return L2, H1, SH
def compute_object_potentials(objects, E, inv_cap_matrix, mesh, bnd): """ Calculates the image charges for all the objects, and then computes the potential for each object by summing over the difference between the collected and image charges multiplied by the inverse of capacitance matrix. """ ds = df.Measure("ds", domain=mesh, subdomain_data=bnd) normal = df.FacetNormal(mesh) image_charge = [None] * len(objects) for i, o in enumerate(objects): flux = df.inner(E, -1 * normal) * ds(o.id) image_charge[i] = df.assemble(flux) for i, o in enumerate(objects): object_potential = 0.0 for j, p in enumerate(objects): object_potential += (p.charge - image_charge[j]) * inv_cap_matrix[i, j] o.set_potential(df.Constant(object_potential))
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) mu = Constant(parameters["viscosity [Pa*s]"]) dt = Constant(parameters["dt [s]"]) u, u_1, vu = domain.u, domain.u_1, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) u_mid = (u + u_1) / 2.0 F1 = rho*dot((u - u_1) / dt, vu)*dx \ + rho*dot(dot(u_1, nabla_grad(u_1)), vu)*dx \ + inner(sigma(u_mid, p_1, mu), epsilon(vu))*dx \ + dot(p_1*n, vu)*ds - dot(mu*nabla_grad(u_mid)*n, vu)*ds a1 = lhs(F1) L1 = rhs(F1) A1 = assemble(a1) [bc.apply(A1) for bc in domain.bcu] self.a1, self.L1, self.A1 = a1, L1, A1 self.domain = domain return
def weak_residual(self, x, x_test, sigma, m, x0, xl): """ The weak residual """ u, p, k, e = dl.split(x) u0, p0, k0, e0 = dl.split(x0) ul, pl, kl, el = dl.split(xl) u_test, p_test, k_test, e_test = dl.split(x_test) hbinv = hinv_u(self.metric, self.tg) res_u = dl.Constant(2.)*(self.nu+self.nu_t(k,e,m))*dl.inner( self.strain(u), self.strain(u_test))*dl.dx \ + dl.inner(dl.grad(u)*u, u_test)*dl.dx \ - p*dl.div(u_test)*dl.dx \ + self.Cd*(self.nu+self.nu_t(k,e,m))*hbinv*dl.dot(u - self.u_ff, self.tg)*dl.dot(u_test, self.tg)*self.ds_ff \ - dl.dot( self.sigma_n(self.nu+self.nu_t(k,e,m), u), self.tg) * dl.dot(u_test, self.tg)*self.ds_ff \ - dl.dot( self.sigma_n(self.nu+self.nu_t(k,e,m), u_test), self.tg ) * dl.dot(u - self.u_ff, self.tg)*self.ds_ff #- self._chi_inflow(ul)*dl.Constant(.5)*dl.inner( dl.dot(u,u)*self.n + dl.dot(self.n,u)*u, u_test )*self.ds_ff \ res_p = dl.div(u) * p_test * dl.dx res_k = dl.dot(u, dl.grad(k))*k_test*dl.dx \ + (self.nu + self.nu_t(k,e,m)/self.sigma_k)*dl.inner( dl.grad(k), dl.grad(k_test))*dl.dx \ + e*k_test*dl.dx \ - self.nu_t(kl,el,m)*self.production(ul)*k_test*dl.dx \ - self._chi_inflow(ul)*(self.nu + self.nu_t(k,e,m)/self.sigma_k)*dl.dot(dl.grad(k), self.n)*k_test*self.ds_ff \ - self._chi_inflow(ul)*(self.nu + self.nu_t(k,e,m)/self.sigma_k)*dl.dot(dl.grad(k_test), self.n)*(k-self.k_ff)*self.ds_ff \ + self._chi_inflow(ul)*self.Cd*(self.nu + self.nu_t(k,e,m)/self.sigma_k)*hbinv*(k-self.k_ff)*k_test*self.ds_ff res_e = dl.dot(u, dl.grad(e))*e_test*dl.dx \ + (self.nu + self.nu_t(k,e,m)/self.sigma_e)*dl.inner( dl.grad(e), dl.grad(e_test))*dl.dx \ + self.C_e2*e*self._theta(k,e)*e_test*dl.dx \ - self.C_e1*dl.exp(m)*self.C_mu*kl*self.production(ul)*e_test*dl.dx \ - self._chi_inflow(ul)*(self.nu + self.nu_t(k,e,m)/self.sigma_e)*dl.dot(dl.grad(e), self.n)*k_test*self.ds_ff \ - self._chi_inflow(ul)*(self.nu + self.nu_t(k,e,m)/self.sigma_e)*dl.dot(dl.grad(e_test), self.n)*(e-self.e_ff)*self.ds_ff \ + self._chi_inflow(ul)*self.Cd*(self.nu + self.nu_t(k,e,m)/self.sigma_e)*hbinv*(e-self.e_ff)*e_test*self.ds_ff time_derivative = sigma * (dl.inner(u - u0, u_test) + dl.inner( k - k0, k_test) + dl.inner(e - e0, e_test)) * dl.dx return time_derivative + res_u + res_p + res_k + res_e
def _rhs(self, x, y, z): base_conductivity = self.base_conductivity(x, y, z) self._setup_expression(self._base_potential_expression, base_conductivity, x, y, z) self._setup_expression( self._base_potential_gradient_normal_expression, base_conductivity, x, y, z) return ( -sum((inner( (Constant(c - base_conductivity) * grad(self._base_potential_expression)), grad(self._v)) * self._dx(x) for x, c in self.CONDUCTIVITY if c != base_conductivity)) # # Eq. 18 at Piastra et al 2018 - sum( Constant(c) # * inner(self._facet_normal, # grad(self._base_potential_expression)) * self._base_potential_gradient_normal_expression * self._v * self._ds(s) for s, c in self.BOUNDARY_CONDUCTIVITY))
def solve_thermal(self): """ Solve the thermal diffusion problem. """ # thermal diffusivity in log coordinates alphalog_i = dolfin.project( dolfin.Expression('astar*exp(-2.*x[0])', degree=1, astar=self.astar_i), self.ice_V) # Set up the variational form for the current mesh location F_i = (self.u_i - self.u0_i) * self.v_i * dolfin.dx + self.dt * dolfin.inner( dolfin.grad(self.u_i), dolfin.grad( alphalog_i * self.v_i)) * dolfin.dx a_i = dolfin.lhs(F_i) L_i = dolfin.rhs(F_i) # Solve ice temperature dolfin.solve(a_i == L_i, self.T_i, [self.bc_inf, self.bc_iWall]) # Update previous profile to current self.u0_i.assign(self.T_i)
def _assemble_and_solve_adj_eq(self, dFdu_form, dJdu): dJdu_copy = dJdu.copy() bcs = self._homogenize_bcs() solver = self.block_helper.adjoint_solver if solver is None: adj_sol = df.Function(self.function_space) adjoint_problem = pf.BlockProblem(dFdu_form, dJdu, adj_sol, bcs=bcs) for key, value in self.block_field.items(): adjoint_problem.field(key, value[1], solver=value[2]) for key, value in self.block_split.items(): adjoint_problem.split(key, value[0], solver=value[1]) solver = pf.LinearBlockSolver(adjoint_problem) self.block_helper.adjoint_solver = solver ############ ## Assemble ## rhs_bcs_form = df.inner(df.Function(self.function_space), dFdu_form.arguments()[0]) * df.dx A_, _ = df.assemble_system(dFdu_form, rhs_bcs_form, bcs) A = df.as_backend_type(A_) solver.linear_solver.set_operators(A, A) solver.linear_solver.init_solver_options() [bc.apply(dJdu) for bc in bcs] b = df.as_backend_type(dJdu) ## Actual solve ## its = solver.linear_solver.solve(adj_sol.vector(), b) ########### adj_sol_bdy = dfa.compat.function_from_vector( self.function_space, dJdu_copy - dfa.compat.assemble_adjoint_value(df.action(dFdu_form, adj_sol))) return adj_sol, adj_sol_bdy
def structure_setup(d_, v_, phi, psi, n, rho_s, \ dx, mu_s, lamda_s, k, mesh_file, theta, **semimp_namespace): delta = 1E10 F_solid_linear = rho_s/k*inner(v_["n"] - v_["n-1"], psi)*dx \ + delta*(1.0/k)*inner(d_["n"] - d_["n-1"], phi)*dx \ - delta*inner(Constant(theta)*v_["n"] + Constant(1 - theta)*v_["n-1"], phi)*dx gravity = Constant((0, -2 * rho_s)) F_solid_linear -= inner(gravity, psi) * dx F_solid_nonlinear = Constant(theta)*inner(Piola1(d_["n"], lamda_s, mu_s), grad(psi))*dx +\ Constant(1 - theta)*inner(Piola1(d_["n-1"], lamda_s, mu_s), grad(psi))*dx return dict(F_solid_linear=F_solid_linear, F_solid_nonlinear=F_solid_nonlinear)
def apply_stabilization(self): df.dS = self.dS #Important <---- h_msh = df.CellDiameter(self.mesh) h_avg = (h_msh("+") + h_msh("-")) / 2.0 #Output local_stab = 0.0 if self.stab_type == 'cip': if self.moment_order == 3 or self.moment_order == 'ns': local_stab += self.DELTA_T * h_avg**self.ht * df.jump(df.grad(self.u[0]),self.nv)\ * df.jump(df.grad(self.v[0]),self.nv) * df.dS #cip for temp if self.moment_order == 6: local_stab += self.DELTA_P * h_avg**self.hp * df.jump(df.grad(self.u[0]),self.nv)\ * df.jump(df.grad(self.v[0]),self.nv) * df.dS #cip for pressure local_stab += self.DELTA_U * h_avg**self.hu * df.jump(df.grad(self.u[1]),self.nv)\ * df.jump(df.grad(self.v[1]),self.nv) * df.dS #cip for velocity_x local_stab += self.DELTA_U * h_avg**self.hu * df.jump(df.grad(self.u[2]),self.nv)\ * df.jump(df.grad(self.v[2]),self.nv) * df.dS #cip for velocity_y if self.moment_order == 13: local_stab += self.DELTA_T * h_avg**self.ht * df.jump(df.grad(self.u[3]),self.nv)\ * df.jump(df.grad(self.v[3]),self.nv) * df.dS #cip for temp local_stab += self.DELTA_P * h_avg**self.hp * df.jump(df.grad(self.u[0]),self.nv)\ * df.jump(df.grad(self.v[0]),self.nv) * df.dS #cip for pressure local_stab += self.DELTA_U * h_avg**self.hu * df.jump(df.grad(self.u[1]),self.nv)\ * df.jump(df.grad(self.v[1]),self.nv) * df.dS #cip for velocity_x local_stab += self.DELTA_U * h_avg**self.hu * df.jump(df.grad(self.u[2]),self.nv)\ * df.jump(df.grad(self.v[2]),self.nv) * df.dS #cip for velocity_y if self.moment_order == 'grad13': local_stab += self.DELTA_T * h_avg**self.ht * df.jump(df.grad(self.u[3]),self.nv)\ * df.jump(df.grad(self.v[6]),self.nv) * df.dS #cip for temp local_stab += self.DELTA_P * h_avg**self.hp * df.jump(df.grad(self.u[0]),self.nv)\ * df.jump(df.grad(self.v[0]),self.nv) * df.dS #cip for pressure local_stab += self.DELTA_U * h_avg**self.hu * df.jump(df.grad(self.u[1]),self.nv)\ * df.jump(df.grad(self.v[1]),self.nv) * df.dS #cip for velocity_x local_stab += self.DELTA_U * h_avg**self.hu * df.jump(df.grad(self.u[2]),self.nv)\ * df.jump(df.grad(self.v[2]),self.nv) * df.dS #cip for velocity_y elif self.stab_type == 'gls': local_stab = (0.0001* h_msh * df.inner(self.SA_x * df.Dx(self.u,0)\ + self.SA_y * df.Dx(self.u,1) + self.SP_Coeff * self.u, self.SA_x * df.Dx(self.v,0)\ + self.SA_y * df.Dx(self.v,1) + self.SP_Coeff * self.v ) * df.dx) return local_stab
def les_setup(u_, mesh, Smagorinsky, CG1Function, nut_krylov_solver, bcs, **NS_namespace): """ Set up for solving Smagorinsky-Lilly LES model. """ DG = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) # Compute cell size and put in delta dim = mesh.geometry().dim() delta = Function(DG) delta.vector().zero() delta.vector().set_local(assemble(TestFunction(DG) * dx).array()**(1. / dim)) delta.vector().apply('insert') # Set up Smagorinsky form Sij = sym(grad(u_)) magS = sqrt(2 * inner(Sij, Sij)) nut_form = Smagorinsky['Cs']**2 * delta**2 * magS bcs_nut = derived_bcs(CG1, bcs['u0'], u_) nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver, bcs=bcs_nut, bounded=True, name="nut") return dict(Sij=Sij, nut_=nut_, delta=delta, bcs_nut=bcs_nut)
def les_setup(u_, mesh, Wale, bcs, CG1Function, nut_krylov_solver, **NS_namespace): """Set up for solving Wale LES model """ DG = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) # Compute cell size and put in delta delta = Function(DG) delta.vector().zero() delta.vector().axpy(1.0, assemble(TestFunction(DG)*dx)) # Set up Wale form Gij = grad(u_) Sij = sym(Gij) Skk = tr(Sij) dim = mesh.geometry().dim() Sd = sym(Gij*Gij) - 1./3.*Identity(mesh.geometry().dim())*Skk*Skk nut_form = Wale['Cw']**2 * pow(delta, 2./dim) * pow(inner(Sd, Sd), 1.5) / (Max(pow(inner(Sij, Sij), 2.5) + pow(inner(Sd, Sd), 1.25), 1e-6)) ff = FacetFunction("size_t", mesh, 0) bcs_nut = derived_bcs(CG1, bcs['u0'], u_) nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver, bcs=bcs_nut, name='nut', bounded=True) return dict(Sij=Sij, Sd=Sd, Skk=Skk, nut_=nut_, delta=delta, bcs_nut=bcs_nut)
def fenics_nonlinear_operator_factory(): import dolfin as df from pymor.bindings.fenics import FenicsVectorSpace, FenicsOperator, FenicsMatrixOperator class DirichletBoundary(df.SubDomain): def inside(self, x, on_boundary): return abs(x[0] - 1.0) < df.DOLFIN_EPS and on_boundary mesh = df.UnitSquareMesh(10, 10) V = df.FunctionSpace(mesh, "CG", 2) g = df.Constant(1.) c = df.Constant(1.) db = DirichletBoundary() bc = df.DirichletBC(V, g, db) u = df.TrialFunction(V) v = df.TestFunction(V) w = df.Function(V) f = df.Expression("x[0]*sin(x[1])", degree=2) F = df.inner( (1 + c * w**2) * df.grad(w), df.grad(v)) * df.dx - f * v * df.dx space = FenicsVectorSpace(V) op = FenicsOperator( F, space, space, w, (bc, ), parameter_setter=lambda mu: c.assign(mu['c'].item()), parameters={'c': 1}, solver_options={'inverse': { 'type': 'newton', 'rtol': 1e-6 }}) prod = FenicsMatrixOperator(df.assemble(u * v * df.dx), V, V) return op, op.parameters.parse( 42), op.source.random(), op.range.random(), prod, prod
def updateCoefficients(self): x, y = SpatialCoordinate(self.mesh) # Init coefficient matrix self.a = as_matrix( [[pow(abs(sin(4 * pi * (x - 0.5))), 1.0 / 5), cos(2 * pi * x * y)], [ cos(2 * pi * x * y), pow(abs(sin(4 * pi * (y - 0.5))), 1.0 / 5) + 1. ]]) # Init exact solution self.u_ = x * y * sin(2 * pi * x) * sin( 3 * pi * y) / (pow(x, 2) + pow(y, 2) + 1) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_))) # Set boundary conditions to exact solution self.g = self.u_