PetscMat
Date: 2013-07-02

    classdef
       petsc-3.4.2 2013-07-02 PetscMat < PetscObject
    %
    %    PetscMat - Holds a PETSc sparse matrix or linear operator
    %
    %   Creation:
    %     A = PetscMat;
    %       A.SetType('seqaij');
    %       A.SetSizes(3,3);
    %
    %     A = PetscMat(speye(3,3));
    %
    %   If A is a PetscMat then a = A(:,:) returns the MATLAB version of the sparse matrix
    %       and A(:,:) = a; assigns the sparse matrix values into the PETScMat
    %       you CANNOT yet use syntax like A(1,2) = 1.0
    %
    %   Indexing into PETSc Vecs and Mats from Matlab starts with index of 1, NOT 0 like
    %     everywhere else in PETSc, but Shri felt MATLAB users could not handle the 0 index
    %
      properties (Constant)
        FLUSH_ASSEMBLY=1;
        FINAL_ASSEMBLY=0;

        SAME_NONZERO_PATTERN=0;
        DIFFERENT_NONZERO_PATTERN=1;
        SAME_PRECONDITIONER=2;
        SUBSET_NONZERO_PATTERN=3;
      end
      methods
        function obj = PetscMat(array,flg)
          if (nargin > 1)
            %  PetscMat(pid,'pobj') uses an already existing PETSc Mat object
            obj.pobj = array;
          elseif (nargin == 1)
            if (~issparse(array))
              error('When creating PetscMat from Matlab matrix the Matlab matrix must be sparse');
            end
            comm = PETSC_COMM_SELF();
            [err,obj.pobj] = calllib('libpetsc', 'MatCreate',comm ,0);PetscCHKERRQ(err);
            err = calllib('libpetsc', 'MatSetType', obj.pobj,'seqaij');PetscCHKERRQ(err);
            err  = calllib('libpetsc', 'MatSeqAIJFromMatlab',array',obj.pobj);PetscCHKERRQ(err);
          else
            comm = PETSC_COMM_SELF();
            [err,obj.pobj] = calllib('libpetsc', 'MatCreate', comm,0);PetscCHKERRQ(err);
          end
        end
        function err = SetType(obj,name)
          err = calllib('libpetsc', 'MatSetType', obj.pobj,name);PetscCHKERRQ(err);
        end
        function err = SetUp(obj)
          err = calllib('libpetsc', 'MatSetUp', obj.pobj);PetscCHKERRQ(err);
        end
        function err = SetFromOptions(obj)
          err = calllib('libpetsc', 'MatSetFromOptions', obj.pobj);PetscCHKERRQ(err);
        end
        function err = SetSizes(obj,m,n,M,N)
          if (nargin == 3)
            M = Petsc.DECIDE;
            N = Petsc.DECIDE;
          end
          err = calllib('libpetsc', 'MatSetSizes', obj.pobj,m,n,M,N);PetscCHKERRQ(err);
        end
        function [m,n,err] = GetSize(obj)
          m = 0;
          n = 0;
          [err,m,n] = calllib('libpetsc', 'MatGetLocalSize', obj.pobj,m,n);PetscCHKERRQ(err);
        end
        function err = SetValues(obj,idx,idy,values,insertmode)
          idx = idx - 1;
          idy = idy - 1;
          if (nargin < 5)
            insertmode = Petsc.INSERT_VALUES;
          end
          err = calllib('libpetsc', 'MatSetValues', obj.pobj,length(idx),idx,length(idy),idy,values,insertmode);PetscCHKERRQ(err);
        end
        function err = AssemblyBegin(obj,mode)
          err = calllib('libpetsc', 'MatAssemblyBegin', obj.pobj,mode);PetscCHKERRQ(err);
        end
        function err = AssemblyEnd(obj,mode)
          err = calllib('libpetsc', 'MatAssemblyEnd', obj.pobj,mode);PetscCHKERRQ(err);
        end
        function err = View(obj,viewer)
          if (nargin == 1)
            err = calllib('libpetsc', 'MatView', obj.pobj,0);PetscCHKERRQ(err);
          else
            err = calllib('libpetsc', 'MatView', obj.pobj,viewer.pobj);PetscCHKERRQ(err);
          end
        end
        function err = Load(obj,viewer)
          err = calllib('libpetsc', 'MatLoad', obj.pobj,viewer.pobj);PetscCHKERRQ(err);
        end
        function err = Destroy(obj)
          err = calllib('libpetsc', 'MatDestroy', obj.pobj);PetscCHKERRQ(err);
        end
        function err = SetValuesStencil(obj,row,col,values,insertmode)
          if (nargin < 5)
            insertmode = Petsc.INSERT_VALUES;
          end
          ndim = isfield(row,'i') + isfield(row,'j') + isfield(row,'k');
          nrow = length(row);
          ncol = length(col);
          if (ndim == 1)  %% 1D DM
    	for (m=1:nrow)
                row(m).i = row(m).i - 1;
            end
            for (m = 1:ncol)
                 col(m).i = col(m).i - 1;
            end
          elseif (ndim == 2)  %% 2D DM
            for (m = 1:nrow)
              row(m).i = row(m).i - 1;
              row(m).j = row(m).j - 1;
            end
            for (m = 1:ncol)
              col(m).i = col(m).i - 1;
              col(m).j = col(m).j - 1;
            end
          elseif (ndim == 3)  %% 3D DM
            for (m = 1:nrow)
              row(m).i = row(m).i - 1;
              row(m).j = row(m).j - 1;
              row(m).k = row(m).k - 1;
            end
            for (m = 1:ncol)
              col(m).i = col(m).i - 1;
              col(m).j = col(m).j - 1;
              col(m).k = col(m).k - 1;
            end
          end
          err = calllib('libpetsc','MatSetValuesStencil',obj.pobj,nrow,row,ncol,col,values,insertmode);PetscCHKERRQ(err);
        end
    %
    %   The following overload a = x(:)
    %
        function varargout = subsref(obj,S)
          %  Matlab design of subsref is MORONIC
          %  To overload () it automatically overloads . which is used
          %  for method calls so we need to force the method calls to use
          %  the 'regular' subsref
          if (S(1).type == '.')
            [varargout{1:nargout}] = builtin('subsref', obj, S);
          else
            [A] = calllib('libpetsc', 'MatSeqAIJToMatlab', obj.pobj);
            varargout = {A}';
          end
        end
    %
    %   The following overload x(:,:) = a
    %
        function obj = subsasgn(obj,S,value)
          if (S(1).type ~= '.')
            err  = calllib('libpetsc', 'MatSeqAIJFromMatlab',value',obj.pobj);PetscCHKERRQ(err);
          end
        end

      end
    end