def set_default_values(self): self._alpha_mult = df.Function(self.S1) self._alpha_mult.assign(df.Constant(1.0)) self._beta_mult = df.Function(self.S1) self._beta_mult.assign(df.Constant(1.0)) self.alpha = 0.5 # alpha for solve: alpha * _alpha_mult self.beta=0 self.t = 0.0 # s self.do_precession = True u3 = df.TrialFunction(self.S3) v3 = df.TestFunction(self.S3) self.K = df.PETScMatrix() df.assemble(1.0/self.unit_length**2*df.inner(df.grad(u3),df.grad(v3))*df.dx, tensor=self.K) self.H_laplace = df.PETScVector() self.H_eff_vec = df.PETScVector(len(self.M)) self.vol = df.assemble(df.dot(df.TestFunction(self.S3), df.Constant([1, 1, 1])) * df.dx).array() self.gamma = consts.gamma #source for gamma: OOMMF manual, and in Werner Scholz thesis, #after (3.7), llg_gamma_G = m/(As). self.c = 1e11 # 1/s numerical scaling correction \ # 0.1e12 1/s is the value used by default in nmag 0.2 self.M0 = 8.6e5 # A/m saturation magnetisation self.t = 0.0 # s self._pins=np.zeros(self.S1.mesh().num_vertices(),dtype="int") self._pre_rhs_callables=[] self._post_rhs_callables=[] self.interactions = []
def set_parameters(self, J_profile=(1e10, 0, 0), P=0.5, D=2.5e-4, lambda_sf=5e-9, lambda_J=1e-9, speedup=1): self._J = helpers.vector_valued_function(J_profile, self.S3) self.J = self._J.vector().array() self.compute_gradient_matrix() self.H_gradm = df.PETScVector() self.P = P self.D = D / speedup self.lambda_sf = lambda_sf self.lambda_J = lambda_J self.tau_sf = lambda_sf**2 / D * speedup self.tau_sd = lambda_J**2 / D * speedup self.compute_laplace_matrix() self.H_laplace = df.PETScVector() self.nodal_volume_S3 = nodal_volume(self.S3)
def setup(self, DG3, m, Ms, unit_length=1.0): self.DG3 = DG3 self.m = m self.Ms = Ms self.unit_length = unit_length mesh = DG3.mesh() self.mesh = mesh DG = df.FunctionSpace(mesh, "DG", 0) BDM = df.FunctionSpace(mesh, "BDM", 1) #deal with three components simultaneously, each represents a vector W1 = df.MixedFunctionSpace([BDM, BDM, BDM]) (sigma0, sigma1, sigma2) = df.TrialFunctions(W1) (tau0, tau1, tau2) = df.TestFunctions(W1) W2 = df.MixedFunctionSpace([DG, DG, DG]) (u0, u1, u2) = df.TrialFunctions(W2) (v0, v1, v2) = df.TestFunction(W2) # what we need is A x = K1 m a0 = (df.dot(sigma0, tau0) + df.dot(sigma1, tau1) + df.dot(sigma2, tau2)) * df.dx self.A = df.assemble(a0) a1 = -(df.div(tau0) * u0 + df.div(tau1) * u1 + df.div(tau2) * u2) * df.dx self.K1 = df.assemble(a1) def boundary(x, on_boundary): return on_boundary # actually, we need to apply the Neumann boundary conditions. # we need a tensor here zero = df.Constant((0, 0, 0, 0, 0, 0, 0, 0, 0)) self.bc = df.DirichletBC(W1, zero, boundary) self.bc.apply(self.A) a2 = (df.div(sigma0) * v0 + df.div(sigma1) * v1 + df.div(sigma2) * v2) * df.dx self.K2 = df.assemble(a2) self.L = df.assemble((v0 + v1 + v2) * df.dx).array() self.mu0 = mu0 self.exchange_factor = 2.0 * self.C / (self.mu0 * Ms * self.unit_length**2) self.coeff = self.exchange_factor / self.L # b = K m self.b = df.PETScVector() # the vector in BDM space self.sigma_v = df.PETScVector(self.K2.size(1)) # to store the exchange fields self.H = df.PETScVector()
def use_zhangli(self, J_profile=(1e10, 0, 0), P=0.5, beta=0.01, using_u0=False, with_time_update=None): self.zhangli_stt = True self.fun_zhangli_time_update = with_time_update self.P = P self.beta = beta self._J = helpers.vector_valued_function(J_profile, self.S3) self.J = self._J.vector().array() self.compute_gradient_matrix() self.H_gradm = df.PETScVector() self.integrator = native_llb.StochasticLLGIntegratorSTT( self.m, self.m_pred, self._Ms, self._T, self.real_volumes, self._alpha, self.P, self.beta, self.stochastic_update_field, self.method) # seems that in the presence of current, the time step have to very # small self.dt = 1e-14
def is_elastic(self): Ealpha = assemble(self.Ealpha) vec = dolfin.PETScVector(MPI.comm_self) Ealpha.gather(vec, np.array(range(self.Z.sub(1).dim()), "intc")) return np.all(vec[:] > 0)
def use_zhangli(self, J_profile=(1e10, 0, 0), P=0.5, beta=0.01, using_u0=False, with_time_update=None): """ if using_u0 = True, the factor of 1/(1+beta^2) will be dropped. With with_time_update should be a function like: def f(t): return (0, 0, J*g(t)) We do not use a position dependent function for performance reasons. """ self.do_zhangli = True self.fun_zhangli_time_update = with_time_update self._J = helpers.vector_valued_function(J_profile, self.S3) self.J = self._J.vector().array() self.compute_gradient_matrix() self.H_gradm = df.PETScVector() const_e = 1.602176565e-19 # elementary charge in As mu_B = 9.27400968e-24 # Bohr magneton self.P = P self.beta = beta u0 = P * mu_B / const_e # P g mu_B/(2 e Ms) and g=2 for electrons if using_u0: self.u0 = u0 else: self.u0 = u0 / (1 + beta ** 2)
def soln_adj2(self, obj): """ Solve the 2nd order adjoint equation. < adj_dFdstates, states_adj2 > = < d2Jdstates, states_fwd2 > """ self.states_adj2 = df.Function(self.W) # 2nd forward states # Solve 2nd adjoint PDE < adj_dFdstates, states_adj2 > = < d2Jdstates, states_fwd2 > # df.solve(self.adj_dFdstates == df.action(self.d2Jdstates, self.states_fwd2), self.states_adj2, self.adj_bcs) # A,b = df.assemble_system(self.adj_dFdstates, df.action(self.d2Jdstates, self.states_fwd2), self.adj_bcs) # df.solve(A, self.states_adj2.vector(), b) # rhs_adj2 = df.PETScVector() # df.assemble(df.action(self.d2Jdstates, self.states_fwd2), tensor=rhs_adj2) u_fwd2, _ = df.split(self.states_fwd2) if not df.has_petsc4py(): warnings.warn('Configure dolfin with petsc4py to run faster!') self.dirac_2 = obj.ptsrc(u_fwd2, ord=2) rhs_adj2 = df.Vector(self.mpi_comm, self.W.dim()) [delta.apply(rhs_adj2) for delta in self.dirac_2] else: rhs_adj2 = df.PETScVector(self.mpi_comm, self.W.dim()) val_dirac_2, idx_dirac_2 = obj.dirac(u_fwd2, ord=2) rhs_adj2.vec()[idx_dirac_2] = val_dirac_2 # np.allclose(rhs_adj2.array(),rhs_adj12.vec()) [bc.apply(rhs_adj2) for bc in self.adj_bcs] df.solve(self.adj_dFdstates_assemb, self.states_adj2.vector(), rhs_adj2) self.soln_count[3] += 1 u_adj2, l_adj2 = df.split(self.states_adj2) return u_adj2, l_adj2
def soln_adj(self, obj): """ Solve the adjoint equation. < adj_dFdstates, states_adj > = dJdstates """ self.states_adj = df.Function(self.W) # adjoint states # Solve adjoint PDE < adj_dFdstates, states_adj > = dJdstates # df.solve(self.adj_dFdstates == self.dJdstates , self.states_adj, self.adj_bcs) # A,b = df.assemble_system(self.adj_dFdstates, self.dJdstates, self.adj_bcs) # df.solve(A, self.states_adj.vector(), b) # error: assemble (solve) point integral (J) has supported underlying FunctionSpace no more than CG1; have to use PointSource? Yuk! u_fwd, _ = df.split(self.states_fwd) if not df.has_petsc4py(): warnings.warn('Configure dolfin with petsc4py to run faster!') self.dirac_1 = obj.ptsrc(u_fwd, ord=1) rhs_adj = df.Vector(self.mpi_comm, self.W.dim()) [delta.apply(rhs_adj) for delta in self.dirac_1] else: rhs_adj = df.PETScVector(self.mpi_comm, self.W.dim()) val_dirac_1, idx_dirac_1 = obj.dirac(u_fwd, ord=1) rhs_adj.vec()[idx_dirac_1] = val_dirac_1 # np.allclose(rhs_adj.array(),rhs_adj1.vec()) [bc.apply(self.adj_dFdstates_assemb, rhs_adj) for bc in self.adj_bcs] df.solve(self.adj_dFdstates_assemb, self.states_adj.vector(), rhs_adj) self.soln_count[1] += 1 u_adj, l_adj = df.split(self.states_adj) return u_adj, l_adj
def __init__(self, solver, u_=None): self.solver = solver W = solver.W self.u_ = u_ if u_ else dolfin.Function(W) # current solution self.u = dolfin.Function(W) # next solution self.du = dolfin.Function(W) # change to current solution self.Qdu = dolfin.PETScVector()
def define_solver_clamped(k_form, l_form, m_form, Dbc): K = df.PETScMatrix() # stiffness matrix b = df.PETScVector() df.assemble_system(k_form, l_form, Dbc, A_tensor=K, b_tensor=b) M = df.PETScMatrix() # mass matrix df.assemble(m_form, tensor=M) eigensolver = set_pmr_solver(K, M) return eigensolver, K, M
def b(self): b = dolfin.PETScVector() self.solver.assembler.assemble(b, self.u_.vector()) # <---- (*) # (*) If you're wondering how we can just apply nonzero Dirichlet BC's # despite du being required to be equal to zero on u's Dirichlet # boundaries, then look no further. The answer is that second argument # to SystemAssembler::assemble(). return b
def __setup_field_petsc(self): """ Same as __setup_field_numpy but with a petsc backend. """ g_form = df.derivative(self.dE_dm, self.m.f) self.g_petsc = df.PETScMatrix() df.assemble(g_form, tensor=self.g_petsc) self.H_petsc = df.PETScVector()
def __init__(self, vbp, options_prefix="", solver={}, ctx={}): super(LinearBlockSolver, self).__init__(vbp, options_prefix, solver, ctx) self.A = df.PETScMatrix() self.b = df.PETScVector() self.log_level = vbp.log_level if self.aP is not None: self.P = df.PETScMatrix()
def __setup_field_direct(self): dofmap = self.m.mesh_dofmap() S3 = df.VectorFunctionSpace( self.m.mesh(), "CG", 1, dim=3, constrained_domain=dofmap.constrained_domain) u3 = df.TrialFunction(S3) v3 = df.TestFunction(S3) self.g_petsc = df.PETScMatrix() df.assemble(-2 * self.dmi_factor * self.D.f * df.inner(v3, df.curl(u3)) * df.dx, tensor=self.g_petsc) self.H_petsc = df.PETScVector()
def setup(self, S3, M, Ms0, unit_length=1): self.S3 = S3 self.M = M v3 = df.TestFunction(S3) E = -df.Constant(self.K1 / Ms0**2) * ( (df.dot(self.axis, self.M))**2) * df.dx # Gradient self.dE_dM = df.Constant(-1.0 / mu0) * df.derivative(E, self.M) self.vol = df.assemble(df.dot(v3, df.Constant([1, 1, 1])) * df.dx).array() self.K = df.PETScMatrix() self.H = df.PETScVector() g_form = df.derivative(self.dE_dM, self.M) df.assemble(g_form, tensor=self.K)
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 soln_fwd2(self, u_actedon): """ Solve the 2nd order forward equation. < dFdstates, states_fwd2 > = < dFdunknown, u_actedon > """ self.states_fwd2 = df.Function(self.W) # 2nd forward states # Solve 2nd forward PDE < dFdstates, states_fwd2 > = < dFdunknown, u_actedon > # df.solve(self.dFdstates == df.action(self.dFdunknown, u_actedon), self.states_fwd2, self.adj_bcs) # ToDo: check the boundary for fwd2 # A,b = df.assemble_system(self.dFdstates, df.action(self.dFdunknown, u_actedon), self.adj_bcs) # df.solve(A, self.states_fwd2.vector(), b) rhs_fwd2 = df.PETScVector() # df.assemble(df.action(self.dFdunknown, u_actedon), tensor=rhs_fwd2) self.dFdunknown_assemb.mult(u_actedon.vector(), rhs_fwd2) [bc.apply(rhs_fwd2) for bc in self.adj_bcs] df.solve(self.dFdstates_assemb, self.states_fwd2.vector(), rhs_fwd2) self.soln_count[2] += 1 u_fwd2, l_fwd2 = df.split(self.states_fwd2) return u_fwd2, l_fwd2
def setup(self, S3, M, M0, unit_length=1.0): self.S3 = S3 self.M = M self.M0 = M0 self.unit_length = unit_length self.Ms2 = np.array(self.M.vector().array()) self.mu0 = mu0 self.exchange_factor = 2.0 * self.C / (self.mu0 * M0**2 * self.unit_length**2) u3 = df.TrialFunction(S3) v3 = df.TestFunction(S3) self.K = df.PETScMatrix() df.assemble(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.coeff1 = -self.exchange_factor / (self.vol) self.coeff2 = -0.5 / (self.chi * M0**2)
def load_la_objects(self, file_name): """ Load a dictionary of named PETScMatrix and PETScVector objects from a file """ assert self.simulation.ncpu == 1, 'Not supported in parallel' import pickle with open(file_name, 'rb') as inp: data = pickle.load(inp) ret = {} for key, value in data.items(): value_type = value[0] # Vectors if value_type == 'dolfin.PETScVector': arr = value[1] dolf_vec = dolfin.PETScVector(dolfin.MPI.comm_world, arr.size) dolf_vec.set_local(arr) dolf_vec.apply('insert') ret[key] = dolf_vec # Matrices elif value_type == 'dolfin.PETScMatrix': shape, rows, cols, values = value[1:] from petsc4py import PETSc mat = PETSc.Mat().createAIJ(size=shape, csr=(rows, cols, values)) mat.assemble() dolf_mat = dolfin.PETScMatrix(mat) ret[key] = dolf_mat else: raise ValueError('Cannot save object of type %r' % value_type) self.simulation.log.info('Loaded LA objects from %r (%r)' % (file_name, data.keys())) return ret
def get_inactive_set(self): tol = self.parameters['inactiveset_atol'] debug = False Ealpha = dolfin.assemble(self.Ealpha) vec = dolfin.PETScVector(MPI.comm_self) Ealpha.gather(vec, np.array(range(self.Z.sub(1).dim()), "intc")) if debug: print('len vec grad', len(vec[:])) mask = Ealpha[:] / self.cellarea.vector() < tol inactive_set_alpha = set(np.where(mask == True)[0]) # from subspace to global numbering global_inactive_set_alpha = [self.mapa[k] for k in inactive_set_alpha] # add displacement dofs inactive_set = set(global_inactive_set_alpha) | set( self.Z.sub(0).dofmap().dofs()) return inactive_set
def evalFunction(self, ts, t, x, xdot, b): """The callback that the TS executes to compute the residual.""" self.update(t) self.update_x(x) self.update_xdot(xdot) b1 = df.Vector() b2 = df.Vector() #self.assembler.assemble(self.F_fluid_form, tensor = b1) df.assemble(self.F_fluid_form, tensor=b1) [bc.apply(b1) for bc in self.bcs_mesh] #self.assembler.assemble(self.F_solid_form, tensor = b2) df.assemble(self.F_solid_form, tensor=b2) b_wrap = df.PETScVector(b) # zero all entries b_wrap.zero() #df.assemble(b_wrap, self.x) b_wrap.axpy(1, b1) b_wrap.axpy(1, b2) [bc.apply(b_wrap, self.x) for bc in self.bcs]
def setup(self, DG3, m, Ms, unit_length=1.0): self.DG3 = DG3 self.m = m self.Ms = Ms self.unit_length = unit_length mesh = DG3.mesh() self.mesh = mesh DG = df.FunctionSpace(mesh, "DG", 0) BDM = df.FunctionSpace(mesh, "BDM", 1) #deal with three components simultaneously, each represents a vector sigma = df.TrialFunction(BDM) tau = df.TestFunction(BDM) u = df.TrialFunction(DG) v = df.TestFunction(DG) # what we need is A x = K1 m #a0 = (df.dot(sigma0, tau0) + df.dot(sigma1, tau1) + df.dot(sigma2, tau2)) * df.dx a0 = df.dot(sigma, tau) * df.dx self.A = df.assemble(a0) a1 = -(df.div(tau) * u) * df.dx self.K1 = df.assemble(a1) C = sp.lil_matrix(self.K1.array()) self.KK1 = C.tocsr() def boundary(x, on_boundary): return on_boundary # actually, we need to apply the Neumann boundary conditions. zero = df.Constant((0, 0, 0)) self.bc = df.DirichletBC(BDM, zero, boundary) #print 'before',self.A.array() self.bc.apply(self.A) #print 'after',self.A.array() #AA = sp.lil_matrix(self.A.array()) AA = copy_petsc_to_csc(self.A) self.solver = sp.linalg.factorized(AA.tocsc()) #LU = sp.linalg.spilu(AA) #self.solver = LU.solve a2 = (df.div(sigma) * v) * df.dx self.K2 = df.assemble(a2) self.L = df.assemble(v * df.dx).array() self.mu0 = mu0 self.exchange_factor = 2.0 * self.C / (self.mu0 * Ms * self.unit_length**2) self.coeff = self.exchange_factor / self.L self.K2 = copy_petsc_to_csr(self.K2) # b = K m self.b = df.PETScVector() # the vector in BDM space self.sigma_v = df.PETScVector() # to store the exchange fields #self.H = df.PETScVector() self.H_eff = m.vector().array() self.m_x = df.PETScVector(self.m.vector().size() / 3)
drdz = df.Measure("dx")[domains] r = df.Expression("x[0]") # Confining potential potential = df.Constant(100) # Partial derivatives of trial and test functions u_r = u.dx(0) v_r = v.dx(0) u_z = u.dx(1) v_z = v.dx(1) # Initial guess of ground state is 1 inside dot, 0 outside dot psi0 = v * r * drdz(1) Psi0 = df.PETScVector() df.assemble(psi0, tensor=Psi0) # Hamiltonian and mass matrix forms h = (u_r * v_r + u_z * v_z) * r * ( drdz(0) + drdz(1)) + potential * r * u * v * r * drdz(0) m = (u * v * r) * (drdz(0) + drdz(1)) # Mass matrix M = df.PETScMatrix() df.assemble(m, tensor=M) # Hamiltonian matrix H = df.PETScMatrix() df.assemble(h, tensor=H)
p_in = dolfin.Constant(1.0) # pressure inlet p_out = dolfin.Constant(0.0) # pressure outlet noslip = dolfin.Constant([0.0] * mesh.geometry().dim()) # no-slip wall #Boundary conditions gN1 = (-p_out * dolfin.Identity(mesh.geometry().dim())) * n Neumann_outlet = dg.DGNeumannBC(ds(mark["outlet"]), gN1) gN2 = (-p_in * dolfin.Identity(mesh.geometry().dim())) * n Neumann_inlet = dg.DGNeumannBC(ds(mark["inlet"]), gN2) Dirichlet_wall = dg.DGDirichletBC(ds(mark["wall"]), noslip) weak_bcs = [Dirichlet_wall, Neumann_inlet, Neumann_outlet] #Body force term f = dolfin.Constant([0.0] * mesh.geometry().dim()) model = geopart.stokes.StokesModel(eta=mu, f=f) #Form and solve Stokes A, b = dolfin.PETScMatrix(), dolfin.PETScVector() element_cls.solve_stokes(W, U, (A, b), weak_bcs, model) uh, ph = element_cls.get_velocity(U), element_cls.get_pressure(U) #Output solution p,u to paraview dolfin.XDMFFile("pressure.xdmf").write_checkpoint(ph, "p") dolfin.XDMFFile("velocity.xdmf").write_checkpoint(uh, "u") flux = [dolfin.assemble(dolfin.dot(uh, n) * ds(i)) for i in range(len(mark))] if comm.Get_rank() == 0: for key, value in mark.items(): print("Flux_%s= %.15lf" % (key, flux[value]))
def nonlinear_solve(self, lhs, rhs, bcs, nonlinear_tol=1e-10, iter_tol=1e-8, maxNonlinIters=50, maxLinIters=200, show=0, print_norm=True, lin_solver="mumps"): """ Solve the nonlinear system of equations using Newton's method. Parameters ---------- lhs : ufl.Form, list The definition of the left-hand side of the resulting linear system of equations. rhs : ufl.Form, list The definition of the right-hand side of the resulting linear system of equations. bcs : dolfin.DirichletBC, list Object specifying the Dirichlet boundary conditions of the system. nonlinear_tol : float (default 1e-10) Tolerance used to terminate Newton's method. iter_tol : float (default 1e-8) Tolerance used to terminate the iterative linear solver. maxNonlinIters : int (default 50) Maximum number of iterations for Newton's method. maxLinIters : int (default 200) Maximum number of iterations for iterative linear solver. show : int (default 0) Amount of information for iterative.LGMRES to show. See documentation of this class for different log levels. print_norm : bool (default True) True if user wishes to see the norm at every linear iteration and False otherwise. lin_solver : str (default "mumps") Name of the linear solver to be used for steady compressible elastic problems. See the dolfin.solve documentation for a list of available linear solvers. Returns ------- None """ norm = 1.0 count = 0 rank = dlf.MPI.rank(MPI_COMM_WORLD) # Determine if we can use dolfin's assemble_system function or # if we need to assemble a block system. if isinstance(lhs, Form): assemble_system = dlf.assemble_system is_block = False du = dlf.PETScVector() else: assemble_system = block.block_assemble is_block = True while norm >= nonlinear_tol: if count >= maxNonlinIters: raise StopIteration('Maximum number of iterations reached.') # Assemble system with Dirichlet BCs applied symmetrically. A, b = assemble_system(lhs, rhs, bcs) # Decide between a dolfin direct solver or a block iterative solver. if is_block: Ainv = iterative.LGMRES( A, show=show, tolerance=iter_tol, # nonconvergence_is_fatal=True, maxiter=maxLinIters) du = Ainv * b else: dlf.solve(A, du, b, lin_solver) self.update_soln(du) norm = du.norm('l2') if not rank and print_norm: print('(iter %2i) norm %.3e' % (count, norm)) count += 1 return None