def _assemble(self): """ Helper method that assembles the mesh dependent system matrices and caches them once their are calculated. """ if self._assemble_cache: return self._assemble_cache VS = FunctionSpace(self.mesh.with_shell, "Lagrange", self.order) VV = VectorFunctionSpace(self.mesh.with_shell, "Lagrange", 1) v = TestFunction(VS) u = TrialFunction(VS) sample_size = self.mesh.data['sample_size'] transformation_order = 1 if (self.order == 1) else 2 gx = MetricMatrix.create_for_cube(sample_size, 0, transformation_order) gy = MetricMatrix.create_for_cube(sample_size, 1, transformation_order) gz = MetricMatrix.create_for_cube(sample_size, 2, transformation_order) # Dummy magnetization for linear form m = interpolate(Constant((0.0,0.0,0.0)), VV) # set up forms and boundary conditions dx = Measure("dx")[self.mesh.cell_domains()] a = Dx(v, i) * Dx(u, i) * dx(0) + \ Dx(v, i) * Dx(u, i) * dx(1) + \ Dx(v, i) * gx[i,j] * Dx(u, j) * dx(2) + \ Dx(v, i) * gy[i,j] * Dx(u, j) * dx(3) + \ Dx(v, i) * gz[i,j] * Dx(u, j) * dx(4) L = inner(grad(v), m) * dx(0) bc = DirichletBC(VS, Constant(0.0), DomainBoundary()) u = Function(VS) # set up assembler and solver objects A, b = Matrix(), Vector() assembler = SystemAssembler(a, L, bc) assembler.assemble(A) solver = KrylovSolver(A, "cg", "amg") #solver.parameters["report"] = False #solver.parameters["absolute_tolerance"] = 1e-4 #solver.parameters["relative_tolerance"] = 1e-4 solver.parameters["nonzero_initial_guess"] = True #solver.parameters["preconditioner"]["reuse"] = True # TODO seems to do nothing self._assemble_cache = (solver, assembler, A, b, bc, m, u) return self._assemble_cache
def _assemble(self): """ Helper method that assembles the mesh dependent system matrices and caches them once their are calculated. """ if self._assemble_cache: return self._assemble_cache VS = FunctionSpace(self.mesh.with_shell, "Lagrange", self.order) VV = VectorFunctionSpace(self.mesh.with_shell, "Lagrange", 1) v = TestFunction(VS) u = TrialFunction(VS) sample_size = self.mesh.data['sample_size'] transformation_order = 1 if (self.order == 1) else 2 gx = MetricMatrix.create_for_cube(sample_size, 0, transformation_order) gy = MetricMatrix.create_for_cube(sample_size, 1, transformation_order) gz = MetricMatrix.create_for_cube(sample_size, 2, transformation_order) # Dummy magnetization for linear form m = interpolate(Constant((0.0, 0.0, 0.0)), VV) # set up forms and boundary conditions dx = Measure("dx")[self.mesh.cell_domains()] a = Dx(v, i) * Dx(u, i) * dx(0) + \ Dx(v, i) * Dx(u, i) * dx(1) + \ Dx(v, i) * gx[i,j] * Dx(u, j) * dx(2) + \ Dx(v, i) * gy[i,j] * Dx(u, j) * dx(3) + \ Dx(v, i) * gz[i,j] * Dx(u, j) * dx(4) L = inner(grad(v), m) * dx(0) bc = DirichletBC(VS, Constant(0.0), DomainBoundary()) u = Function(VS) # set up assembler and solver objects A, b = Matrix(), Vector() assembler = SystemAssembler(a, L, bc) assembler.assemble(A) solver = KrylovSolver(A, "cg", "amg") #solver.parameters["report"] = False #solver.parameters["absolute_tolerance"] = 1e-4 #solver.parameters["relative_tolerance"] = 1e-4 solver.parameters["nonzero_initial_guess"] = True #solver.parameters["preconditioner"]["reuse"] = True # TODO seems to do nothing self._assemble_cache = (solver, assembler, A, b, bc, m, u) return self._assemble_cache
def _assemble(self): """ Helper method that assembles the mesh dependent system matrices and caches them once their are calculated. """ if self._assemble_cache: return self._assemble_cache VS = FunctionSpace(self.mesh.with_shell, "Lagrange", self.order) v = TestFunction(VS) u = TrialFunction(VS) sample_size = self.mesh.data['sample_size'] transformation_order = 1 if (self.order == 1) else 2 gx = MetricMatrix.create_for_cube(sample_size, 0, transformation_order) gy = MetricMatrix.create_for_cube(sample_size, 1, transformation_order) gz = MetricMatrix.create_for_cube(sample_size, 2, transformation_order) # setup system a = Dx(v, i) * Dx(u, i) * dx(0) + \ Dx(v, i) * Dx(u, i) * dx(1) + \ Dx(v, i) * gx[i,j] * Dx(u, j) * dx(2) + \ Dx(v, i) * gy[i,j] * Dx(u, j) * dx(3) + \ Dx(v, i) * gz[i,j] * Dx(u, j) * dx(4) bc = DirichletBC(VS, Constant(0.0), DomainBoundary()) A, An = symmetric_assemble(a, bc) u = Function(VS) solver = KrylovSolver(A, "cg", "amg") #solver.parameters["report"] = False #solver.parameters["absolute_tolerance"] = 1e-4 #solver.parameters["relative_tolerance"] = 1e-4 solver.parameters["nonzero_initial_guess"] = True #solver.parameters["preconditioner"]["reuse"] = True # TODO seems to do nothing self._assemble_cache = (solver, An, bc, v, u, A) return self._assemble_cache
def calculate_v(self, state, dt): """ Calculate :math:`\\vec{v}` according to the algorithm introduced above. *Arguments* state (:class:`State`) The simulation state containing the magnetization configuration. dt (:class:`float`) The time-step size. """ with Timer("Calculate v"): cache = self._assemble_cache if cache.requires_update(state): if isinstance(state.mesh, WrappedMesh): raise Exception("Use simple mesh with shell instead of WrappedMesh.") # setup function spaces cache.VV = VectorFunctionSpace(state.mesh, "CG", 1) cache.VD = FunctionSpace(state.mesh, "CG", self.demag_order) cache.VL = FunctionSpace(state.mesh, "CG", 1) # setup some stuff for the demag field transformation_order = 2 if (self.demag_order == 1) else 2 shell_width = state.mesh.coordinates().max(axis=0).min() / 2.0 sample_size = state.mesh.coordinates().max(axis=0) - shell_width cache.gx = MetricMatrix.create_for_cube(sample_size, 0, transformation_order) cache.gy = MetricMatrix.create_for_cube(sample_size, 1, transformation_order) cache.gz = MetricMatrix.create_for_cube(sample_size, 2, transformation_order) # Test and Trial Functions u = TrialFunction(cache.VD) v = TrialFunction(cache.VV) sigma = TrialFunction(cache.VL) w1 = TestFunction(cache.VD) w2 = TestFunction(cache.VV) w3 = TestFunction(cache.VL) ####################################################### # Define weak forms ####################################################### f_ex = (- 2.0 * state.material.Aex * Constants.gamma) / \ (Constants.mu0 * state.material.ms * state.scale**2) # Bilinear form a12 = - 0.5 * Constant(dt) * inner(v, grad(w1)) * state.dx('magnetic') # Demag Field, Implicit RHS a11 = inner(grad(w1), grad(u)) * state.dx('all') \ + inner(grad(w1), grad(u)) * state.dx(1000) \ + inner(grad(w1), cache.gx * grad(u)) * state.dx(1001) \ + inner(grad(w1), cache.gy * grad(u)) * state.dx(1002) \ + inner(grad(w1), cache.gz * grad(u)) * state.dx(1003) a21 = - Constant(state.material.ms * Constants.gamma) * inner(grad(u), w2) * state.dx('magnetic') # Demag a22 = Constant(state.material.alpha) * dot(v, w2) * state.dx('magnetic') # LLG a22 += dot(cross(state.m, v), w2) * state.dx('magnetic') a22 += - 0.5 * Constant(dt * f_ex) * Dx(v[i],j) * Dx(w2[i],j) * state.dx('magnetic') # Exchange # Linear form L1 = inner(state.m, grad(w1)) * state.dx('magnetic') # Demag Field L2 = Constant(f_ex) * Dx(state.m[i],j) * Dx(w2[i],j) * state.dx('magnetic') # Exchange for term in self.terms: # Additional Terms L2 += term.form_rhs(state, w2) * state.dx('magnetic') #a22 += term.form_lhs(state, w2, Constant(0.5 * dt) * v) * state.dx('magnetic') ####################################################### # Define boundary conditions ####################################################### bc1 = DirichletBC(cache.VD, Constant(0.0), DomainBoundary()) ####################################################### # Assemble the system ####################################################### A11, b1 = assemble_system(a11, L1, bc1) A12 = assemble(a12) A21 = assemble(a21) A22 = assemble(a22, keep_diagonal=True); A22.ident_zeros() v23 = TestFunction(state.VectorFunctionSpace()) u23 = TrialFunction(state.FunctionSpace()) A23 = assemble(u23 * dot(state.m, v23) * dP) v32 = TestFunction(state.FunctionSpace()) u32 = TrialFunction(state.VectorFunctionSpace()) A32 = assemble(v32 * dot(state.m, u32) * dP) #A23 = DofAssembler.assemble(TransScalarProductMatrix(cache.VL, cache.VV, state.m)) #A32 = DofAssembler.assemble(ScalarProductMatrix(cache.VL, cache.VV, state.m)) b2 = assemble(L2) ####################################################### # Schur Ansatz ####################################################### A11p = ILU(A11) A11inv = ConjGrad(A11, precond=A11p) z1 = A11inv * b1 S11 = A22 - A21 * A11inv * A12 S = block_mat([[S11, A23], [A32, 0]]) Sp11 = ILU(A22) Sp22 = InvDiag(collapse(A32 * LumpedInvDiag(A22) * A23)) Sp = block_mat([[Sp11, A23], [0, -Sp22]]).scheme('sgs') Sinv = BiCGStab(S, precond=Sp, tolerance=1e-8/dt) b = block_vec([b2 - A21*z1, 0]) v, _ = Sinv * b return Function(cache.VV, v)