def define_solver_free_free(k_form, m_form): K = df.PETScMatrix() # stiffness matrix df.assemble(k_form, tensor=K) M = df.PETScMatrix() # mass matrix df.assemble(m_form, tensor=M) eigensolver = set_pmr_solver(K, M) return eigensolver, K, M
def __init__(self, F_fluid, F_solid, w, wdot, bcs_mesh, bcs, dF_fluid_u, dF_fluid_udot, dF_solid_u, dF_solid_udot, update=None, report=None, *args, **kwargs): self.F_fluid_form = F_fluid self.dF_fluid_u_form = dF_fluid_u self.dF_fluid_udot_form = dF_fluid_udot self.F_solid_form = F_solid self.dF_solid_u_form = dF_solid_u self.dF_solid_udot_form = dF_solid_udot self.bcs_mesh = bcs_mesh self.bcs = bcs self.w = w self.wdot = wdot self.a = df.Constant(1.0) self.dF_fluid_form = self.dF_fluid_u_form + self.a * self.dF_fluid_udot_form self.dF_solid_form = self.dF_solid_u_form + self.a * self.dF_solid_udot_form self.report = report self.update = update self.form_compiler_parameters = {"optimize": True} if "form_compiler_parameters" in kwargs: self.form_compiler_parameters = kwargs["form_compiler_parameters"] self.assembler = df.SystemAssembler( self.dF_fluid_form + self.dF_solid_form, self.F_fluid_form + self.F_solid_form, self.bcs + self.bcs_mesh) self.x = df.as_backend_type(w.vector()) self.x_petsc = self.x.vec() self.xdot = df.as_backend_type(wdot.vector()) self.xdot_petsc = self.xdot.vec() self.b_petsc = self.x_petsc.duplicate() # We need to initialise the matrix size and local-to-global maps self.A_dolfin = df.PETScMatrix() self.assembler.init_global_tensor( self.A_dolfin, df.Form(self.dF_fluid_form + self.dF_fluid_form)) self.A_petsc = self.A_dolfin.mat() self.xx = self.A_petsc.createVecRight() self.xxdot = self.A_petsc.createVecRight() self.A1_dolfin = df.PETScMatrix() self.assembler.init_global_tensor( self.A1_dolfin, df.Form(self.dF_fluid_form + self.dF_fluid_form)) self.A2_dolfin = df.PETScMatrix() self.assembler.init_global_tensor( self.A2_dolfin, df.Form(self.dF_fluid_form + self.dF_fluid_form))
def _get_rtmass(self,output_petsc=True): """ Get the square root of assembled mass matrix M using lumping. --credit to: Umberto Villa """ test = df.TestFunction(self.V) V_deg = self.V.ufl_element().degree() try: V_q_fe = df.FiniteElement('Quadrature',self.V.mesh().ufl_cell(),2*V_deg,quad_scheme='default') V_q = df.FunctionSpace(self.V.mesh(),V_q_fe) except: print('Use FiniteElement in specifying FunctionSpace after version 1.6.0!') V_q = df.FunctionSpace(self.V.mesh(), 'Quadrature', 2*self.V._FunctionSpace___degree) trial_q = df.TrialFunction(V_q) test_q = df.TestFunction(V_q) M_q = df.PETScMatrix() df.assemble(trial_q*test_q*df.dx,tensor=M_q,form_compiler_parameters={'quadrature_degree': 2*V_deg}) ones = df.interpolate(df.Constant(1.), V_q).vector() dM_q = M_q*ones M_q.zero() dM_q_2fill = ones.array() / np.sqrt(dM_q.array() ) dM_q.set_local( dM_q_2fill ) M_q.set_diagonal(dM_q) mixedM = df.PETScMatrix() df.assemble(trial_q*test*df.dx,tensor=mixedM,form_compiler_parameters={'quadrature_degree': 2*V_deg}) if output_petsc and df.has_petsc4py(): rtM = df.PETScMatrix(df.as_backend_type(mixedM).mat().matMult(df.as_backend_type(M_q).mat())) else: rtM = sps.csr_matrix(mixedM.array()*dM_q_2fill) csr_trim0(rtM,1e-12) return rtM
def _get_cov(self,output_petsc=True): """ Get the covariance matrix C with C = K M. """ if output_petsc and df.has_petsc4py(): from petsc4py import PETSc C_f=os.path.join(os.getcwd(),'C_petsc.dat') try: viewer = PETSc.Viewer().createBinary(C_f, 'r') C_petsc=df.PETScMatrix(PETSc.Mat().load(viewer)) print('Read the covariance successfully!') except: C_petsc= df.PETScMatrix(df.as_backend_type(self.K).mat().matMult(df.as_backend_type(self.M).mat())) viewer = PETSc.Viewer().createBinary(C_f, 'w') viewer(df.as_backend_type(C_petsc).mat()) return C_petsc else: import cPickle C_f=os.path.join(os.getcwd(),'C_sps.dat') try: f = open(C_f, 'rb') C_sps = cPickle.load(f) f.close() print('Read the covariance successfully!') except: C_sps=sps.csr_matrix(self.K.dot(self.M.array())) csr_trim0(C_sps) f = open(C_f, 'wb') cPickle.dump(C_sps,f,-1) f.close() return C_sps
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 __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 __init__(self, Va, Vphi, ratioM=None): """ Va = FunctionSpace for weight-parameter in mass matrix Vphi = FunctionSpace for test and trial functions in mass matrix ratioM = ratio used for the lumping of mass matrix """ u = dl.Function(Vphi) self.uvector = u.vector() # prepare weak form test, trial = dl.TestFunction(Vphi), dl.TrialFunction(Vphi) alpha = dl.Function(Va) self.ratioM = ratioM wkform = dl.inner(alpha*test, trial)*dl.dx M = dl.assemble(wkform) mpicomm = Va.mesh().mpi_comm() MprimePETSc, VaDM, VphiDM = setupPETScmatrix(Va, Vphi, 'aij', mpicomm) # populate the PETSc matrix for ii in xrange(Va.dim()): alpha.vector().zero() setglobalvalue(alpha, ii, 1.0) dl.assemble(wkform, tensor=M) diagM = get_diagonal(M) normdiagM = diagM.norm('l2') diagM = diagM.array() cols = np.where(np.abs(diagM) > 1e-16*normdiagM)[0] for cc, val in zip(cols, diagM[cols]): global_cc = VphiDM.dofs()[cc] MprimePETSc[ii, global_cc] = val MprimePETSc.assemblyBegin() MprimePETSc.assemblyEnd() # convert PETSc matrix to PETSc-wrapper in Fenics self.Mprime = dl.PETScMatrix(MprimePETSc)
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 solve_petsc(self): """ Solves the linear problem using PETSc interface, and manipulates with PETSc matrices. :return: list[state vectors] """ form = self.forms._rhs_forms( shift=self.frequency) + self.forms._lhs_forms() w = dolf.Function(self.forms.function_space) lhs_matrix = dolf.PETScMatrix() lhs_matrix = dolf.assemble(dolf.lhs(form), tensor=lhs_matrix) for bc in self.forms.dirichlet_boundary_conditions(): bc.apply(lhs_matrix) lhs_matrix = lhs_matrix.mat() averaged_boundary_terms = self.forms.boundary_averaged_velocity() if averaged_boundary_terms: lhs_matrix.axpy(-1.0, averaged_boundary_terms) solver = self.create_ksp_solver(lhs_matrix) rhs_vector = dolf.assemble(dolf.rhs(form)) for bc in self.forms.dirichlet_boundary_conditions(): bc.apply(rhs_vector) solver.solve( dolf.as_backend_type(rhs_vector).vec(), dolf.as_backend_type(w.vector()).vec(), ) state = w.split(True) return state
def A(self): A = dolfin.PETScMatrix() self.solver.assembler.assemble(A) q = self.q if q is not None: A.mat().diagonalScale(None, q) return A
def collapse(self): '''Return a matrix representation''' # Check cache if hasattr(self, 'matrix_repr'): return self.matrix_repr # Otherwise compute it, but only once x = self.create_vec(dim=1) x_values = x.get_local() columns = [] df.info('Collapsing to %d x %d matrix' % (self.V0.dim(), self.V1.dim())) timer = df.Timer('Collapse') for i in range(self.V1.dim()): # Basis of row space x_values[i] = 1. x.set_local(x_values) column = sparse.csc_matrix((self * x).get_local()) columns.append(column) # Reset x_values[i] = 0. # Alltogether mat = (sparse.vstack(columns).T).tocsr() df.info('\tDone in %g' % timer.stop()) # As PETSc.Mat A = PETSc.Mat().createAIJ(comm=PETSc.COMM_WORLD, size=mat.shape, csr=(mat.indptr, mat.indices, mat.data)) # Finally for dolfin self.matrix_repr = df.PETScMatrix(A) return self.matrix_repr
def evalJacobian(self, ts, t, x, xdot, a, A, P): """The callback that the TS executes to compute the jacobian.""" self.update(t) self.update_x(x) self.update_xdot(xdot) self.a.assign(a) A_wrap = df.PETScMatrix(A) # set all entries to zero A_wrap.zero() A_wrap.apply('insert') #self.assembler.assemble(self.dF_mesh, tensor = self.A1_dolfin, keep_diagonal=True) df.assemble(self.dF_fluid_form, tensor=self.A1_dolfin, keep_diagonal=True) [bc.zero(self.A1_dolfin) for bc in self.bcs_mesh] #self.assembler.ssemble(self.dF, tensor = self.A2_dolfin, keep_diagonal=True) df.assemble(self.dF_solid_form, tensor=self.A2_dolfin, keep_diagonal=True) A_wrap.axpy(1, self.A1_dolfin, False) A_wrap.axpy(1, self.A2_dolfin, False) [bc.apply(A_wrap) for bc in self.bcs] #df.assemble(self.J_form, tensor=A_wrap, form_compiler_parameters=self.form_compiler_parameters) #for bc in self.bcs : bc.apply(A_wrap) return True # same nonzero pattern
def __init__(self, Vs): """ Arguments: Vs = list of function spaces """ Vdim = Vs[0].dim() Vdofmapdofs = Vs[0].dofmap().dofs() Vmeshsize = Vs[0].mesh().size(0) for V in Vs: assert Vdim == V.dim(), "Vs must have same dimension" assert (Vdofmapdofs == V.dofmap().dofs()).prod() == 1, \ "Vs must have same dofmap" assert Vmeshsize == V.mesh().size(0), \ "Vs must be built on same mesh" VV = createMixedFSi(Vs) self.SplitOperator = [] self.AssignOperator = [] for ii, V in enumerate(Vs): V_dofs = V.dofmap().dofs() VV_dofs = VV.sub(ii).dofmap().dofs() mpicomm = V.mesh().mpi_comm() SplitOperatorPETSc, _, _ = setupPETScmatrix(V, VV, 'aij', mpicomm) for jj in xrange(len(V_dofs)): SplitOperatorPETSc[V_dofs[jj], VV_dofs[jj]] = 1.0 SplitOperatorPETSc.assemblyBegin() SplitOperatorPETSc.assemblyEnd() SplitOperator = dl.PETScMatrix(SplitOperatorPETSc) self.SplitOperator.append(SplitOperator) self.AssignOperator.append(Transpose(SplitOperator))
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() # 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 petsc_identity(N, dofs=None): """ Create an identity matrix using petsc4py. Note: this currently only works in one process. """ from petsc4py import PETSc v = PETSc.Vec() v.create() v.setSizes(N) v.setType('standard') v.setValues(range(N), [1.0] * N) A = PETSc.Mat() A.createAIJ([N, N], nnz=N) if dofs is not None: lgmap = PETSc.LGMap().create(dofs) A.setLGMap(lgmap, lgmap) A.setDiagonal(v) A.assemble() return dlf.PETScMatrix(A)
def initialize(self, pc): ## Assemble aP ## self.P_mat = df.PETScMatrix() if 'aP' not in self.ctx: raise ValueError("Must provide aP form to ctx") else: self.aP = self.ctx['aP'] df.assemble(self.aP, tensor=self.P_mat) ## Optionally apply BCs ## if 'bcs_aP' in self.ctx: self.applyBCs(self.P_mat,self.ctx['bcs_aP']) ## Extract submatrix ## self.P_submat = self.P_mat.mat().createSubMatrix(self.isset,self.isset) ## Create KSP solver ## self.ksp = PETSc.KSP().create(comm=pc.comm) self.ksp.setType(PETSc.KSP.Type.PREONLY) self.ksp.incrementTabLevel(1, parent=pc) self.ksp.setOperators(self.P_submat) self.ksp.setOptionsPrefix(self.options_prefix) self.ksp.setFromOptions() self.ksp.setUp()
def _get_sqrtm(A, m_name='K', output_petsc=True, SAVE=True): """ Get the root of matrix A. """ if output_petsc and df.has_petsc4py(): from petsc4py import PETSc rtA_f = os.path.join( os.getcwd(), 'rt' + m_name + '_petsc_dim' + str(A.size(0)) + '.dat') try: viewer = PETSc.Viewer().createBinary(rtA_f, 'r') rtA_petsc = df.PETScMatrix(PETSc.Mat().load(viewer)) print('Read the root of ' + { 'K': 'kernel', 'C': 'covariance' }[m_name] + ' successfully!') except: import scipy.linalg as spla rtA_sps = sps.csr_matrix(spla.sqrtm(A.array()).real) csr_trim0(rtA_sps, 1e-10) rtA_petsc = df.PETScMatrix(csr2petscmat(rtA_sps)) if SAVE: viewer = PETSc.Viewer().createBinary(rtA_f, 'w') viewer(df.as_backend_type(rtA_petsc).mat()) return rtA_petsc else: import cPickle rtA_f = os.path.join( os.getcwd(), 'rt' + m_name + '_sps_dim' + str(A.shape[0]) + '.dat') try: f = open(rtA_f, 'rb') rtA_sps = cPickle.load(f) f.close() print('Read the root of ' + { 'K': 'kernel', 'C': 'covariance' }[m_name] + ' successfully!') except: import scipy.linalg as spla rtA_sps = sps.csr_matrix(spla.sqrtm(A.toarray()).real) csr_trim0(rtA_sps, 1e-10) if SAVE: f = open(rtA_f, 'wb') cPickle.dump(rtA_sps, f, -1) f.close() return rtA_sps
def _get_ker(self, output_petsc=True): """ Get the kernel matrix K with K_ij = k(x_i,x_j). """ load_success = False if output_petsc and df.has_petsc4py(): from petsc4py import PETSc K_f = os.path.join(os.getcwd(), 'K_petsc_dim' + str(self.dim) + '.dat') try: viewer = PETSc.Viewer().createBinary(K_f, 'r') K = df.PETScMatrix(PETSc.Mat().load(viewer)) load_success = True except: pass else: import cPickle K_f = os.path.join(os.getcwd(), 'K_sps_dim' + str(self.dim) + '.dat') try: f = open(K_f, 'rb') K = cPickle.load(f) f.close() load_success = True except: pass if load_success: print('Read the kernel successfully!') return K else: import scipy.spatial.distance K_sps = sps.csr_matrix( self.sigma**2 * np.exp(-sp.spatial.distance.squareform( sp.spatial.distance.pdist(self.dof_coords)) / (2 * self.s))) csr_trim0(K_sps, 1e-10) if output_petsc and df.has_petsc4py(): K_petsc = df.PETScMatrix(csr2petscmat(K_sps)) viewer = PETSc.Viewer().createBinary(K_f, 'w') viewer(df.as_backend_type(K_petsc).mat()) return K_petsc else: f = open(K_f, 'wb') cPickle.dump(K_sps, f, -1) f.close() return K_sps
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 transpose_matrix(A): '''Create a transpose of PETScMatrix/PETSc.Mat''' if isinstance(A, PETSc.Mat): At = PETSc.Mat() # Alloc A.transpose(At) # Transpose to At return At At = transpose_matrix(df.as_backend_type(A).mat()) return df.PETScMatrix(At)
def assemble_forms(self, geom_ord=[0]): """ Assemble some forms required for calculating geometric quantities. """ # do some assembling here to avoid repetition if any(s >= 1 for s in geom_ord): # for adjoints: self.adj_dFdstates_assemb = df.PETScMatrix() df.assemble(self.adj_dFdstates, tensor=self.adj_dFdstates_assemb) # for grad and metact: self.adj_dFdunknown_assemb = df.PETScMatrix() df.assemble(self.adj_dFdunknown, tensor=self.adj_dFdunknown_assemb) if any(s > 1 for s in geom_ord): # for fwd2 (and fwd for nonlinear problem): self.dFdstates_assemb = df.PETScMatrix() df.assemble(self.dFdstates, tensor=self.dFdstates_assemb) [bc.apply(self.dFdstates_assemb) for bc in self.adj_bcs] self.dFdunknown_assemb = df.PETScMatrix() df.assemble(self.dFdunknown, tensor=self.dFdunknown_assemb)
def rhs(self): """ Constructs the RHS matrix (temporal components), BB of the eigenvalue problem. """ rhs_matrix = dolf.PETScMatrix() rhs_matrix = dolf.assemble(self.forms._rhs_forms(), tensor=rhs_matrix) for bc in self.forms.dirichlet_boundary_conditions(is_linearised=True): bc.zero(rhs_matrix) return rhs_matrix.mat()
def _as_petscmat(self): if df.has_petsc4py(): from petsc4py import PETSc mat = PETSc.Mat().createPython(df.as_backend_type(self.prior.M).mat().getSizes(), comm = self.prior.mpi_comm) # mat = PETSc.Mat().createPython(self.dim, comm = self.prior.mpi_comm) mat.setPythonContext(self) return df.PETScMatrix(mat) else: df.warning('Petsc4py not installed: cannot generate PETScMatrix with specified size!') pass
def Transpose(A): """ Compute the matrix transpose """ Amat = dl.as_backend_type(A).mat() AT = PETSc.Mat() Amat.transpose(AT) rmap, cmap = Amat.getLGMap() AT.setLGMap(cmap, rmap) return dl.Matrix(dl.PETScMatrix(AT))
def MatPtAP(A, P): """ Compute the triple matrix product :math:`P^T A P`. """ Amat = dl.as_backend_type(A).mat() Pmat = dl.as_backend_type(P).mat() out = Amat.PtAP(Pmat, fill=1.0) _, out_map = Pmat.getLGMap() out.setLGMap(out_map, out_map) return dl.Matrix(dl.PETScMatrix(out))
def MatMatMult(A, B): """ Compute the matrix-matrix product :math:`AB`. """ Amat = df.as_backend_type(A).mat() Bmat = df.as_backend_type(B).mat() out = Amat.matMult(Bmat) rmap, _ = Amat.getLGMap() _, cmap = Bmat.getLGMap() out.setLGMap(rmap, cmap) return df.Matrix(df.PETScMatrix(out))
def MatAtB(A, B): """ Compute the matrix-matrix product :math:`A^T B`. """ Amat = dl.as_backend_type(A).mat() Bmat = dl.as_backend_type(B).mat() out = Amat.transposeMatMult(Bmat) _, rmap = Amat.getLGMap() _, cmap = Bmat.getLGMap() out.setLGMap(rmap, cmap) return dl.Matrix(dl.PETScMatrix(out))
def lhs(self): """ Constructs the LHS matrix (spatial components), AA of the eigenvalue problem. """ lhs_matrix = dolf.PETScMatrix() lhs_forms = -self.forms._lhs_forms() - self.forms._rhs_forms( shift=self.complex_shift) lhs_matrix = dolf.assemble(dolf.lhs(lhs_forms), tensor=lhs_matrix) for bc in self.forms.dirichlet_boundary_conditions(is_linearised=True): bc.apply(lhs_matrix) return lhs_matrix.mat()
def restriction_matrix(V, TV, rmesh): '''TV's mesh is the EmbeddedMesh of V''' assert V.ufl_element() == TV.ufl_element() assert TV.mesh().id() == rmesh.id() mesh = V.mesh() tdim = mesh.topology().dim() # Let's get the mapping or cell of TV mesh to V mesh cells mapping = rmesh.parent_entity_map[mesh.id()][tdim] # The idea is to evaluate TV's degrees of freedom at basis functions of V Tdmap = TV.dofmap() TV_dof = DegreeOfFreedom(TV) dmap = V.dofmap() V_basis_f = FEBasisFunction(V) # Rows visited_dofs = [False]*TV.dim() # Column values dof_values = np.zeros(V_basis_f.elm.space_dimension(), dtype='double') with petsc_serial_matrix(TV, V) as mat: for trace_cell in range(TV.mesh().num_cells()): TV_dof.cell = trace_cell trace_dofs = Tdmap.cell_dofs(trace_cell) # The corresponding cell in V mesh cell = mapping[trace_cell] V_basis_f.cell = cell dofs = dmap.cell_dofs(cell) for local_T, dof_T in enumerate(trace_dofs): if visited_dofs[dof_T]: continue else: visited_dofs[dof_T] = True # Define trace dof TV_dof.dof = local_T # Eval at V basis functions for local, dof in enumerate(dofs): # Set which basis foo V_basis_f.dof = local dof_values[local] = TV_dof.eval(V_basis_f) # Can fill the matrix now col_indices = np.array(dofs, dtype='int32') # Insert mat.setValues([dof_T], col_indices, dof_values, PETSc.InsertMode.INSERT_VALUES) return df.PETScMatrix(mat)
def __init__(self, V1, V2, mpicomm): """ WARNING: MixedFunctionSpace is assumed to be V1*V2 only works if V1 and V2 are CG of same dimension """ assert V1.dim() == V2.dim(), "V1, V2 must have same dimension" assert (V1.dofmap().dofs() == V2.dofmap().dofs()).prod() == 1, \ "V1 and V2 must have same dofmap" assert V1.mesh().size(0) == V2.mesh().size(0), \ "V1, V2 must be built on same mesh" V1V2 = createMixedFS(V1, V2) SplitOperator1PETSc, _, _ = setupPETScmatrix(V1, V1V2, 'aij', mpicomm) SplitOperator2PETSc, _, _ = setupPETScmatrix(V2, V1V2, 'aij', mpicomm) V1V2_1dofs = V1V2.sub(0).dofmap().dofs() V1V2_2dofs = V1V2.sub(1).dofmap().dofs() V1dofs = V1.dofmap().dofs() V2dofs = V2.dofmap().dofs() for ii in xrange(len(V1dofs)): SplitOperator1PETSc[V1dofs[ii], V1V2_1dofs[ii]] = 1.0 for ii in xrange(len(V2dofs)): SplitOperator2PETSc[V2dofs[ii], V1V2_2dofs[ii]] = 1.0 SplitOperator1PETSc.assemblyBegin() SplitOperator1PETSc.assemblyEnd() SplitOperator2PETSc.assemblyBegin() SplitOperator2PETSc.assemblyEnd() self.SplitOperator1 = dl.PETScMatrix(SplitOperator1PETSc) self.SplitOperator2 = dl.PETScMatrix(SplitOperator2PETSc) self.AssignOperator1 = Transpose(self.SplitOperator1) self.AssignOperator2 = Transpose(self.SplitOperator2)