def assemble(self): """Actually assemble this :class:`Matrix`. This calls the stashed assembly callback or does nothing if the matrix is already assembled. .. note:: If the boundary conditions stashed on the :class:`Matrix` have changed since the last time it was assembled, this will necessitate reassembly. So for example: .. code-block:: python A = assemble(a, bcs=[bc1]) solve(A, x, b) bc2.apply(A) solve(A, x, b) will apply boundary conditions from `bc1` in the first solve, but both `bc1` and `bc2` in the second solve. """ if self._assembly_callback is None: raise RuntimeError('Trying to assemble a Matrix, but no thunk found') if self._assembled: if self._needs_reassembly: solving._assemble(self.a, tensor=self, bcs=self.bcs) return self.assemble() return self._bcs_at_point_of_assembly = copy.copy(self.bcs) self._assembly_callback(self.bcs) self._assembled = True
def _form_action(self, u): """Assemble the form action of this :class:`Matrix`' bilinear form onto the :class:`Function` ``u``. .. note:: This is the form **without** any boundary conditions.""" if not hasattr(self, '_a_action'): self._a_action = ufl.action(self._a, u) if hasattr(self, '_a_action_coeff'): self._a_action = ufl.replace(self._a_action, {self._a_action_coeff: u}) self._a_action_coeff = u # Since we assemble the cached form, the kernels will already have # been compiled and stashed on the form the second time round return solving._assemble(self._a_action)