function M = obtem_matriz_M(parametros,p,malha,base,...
    tensorial,np_comp,NP,A0,A)
%Supoe que p eh o
%conjunto de pontos de amostragem a usar para essa malha (um subconjunto
%da grade de amostragem completa com np_comp pontos) e que todos esses 
%pontos estao dentro da uniao D' das celulas da malha. Supoe que o suporte de
%todo elemento da base esta contido em D'. 

%Se possivel tenta ler a coluna 0 da matriz M do disco e replica-la no
%resto da matriz
%M, em vez de calcular. Nesse caso a grade de amostragem completa deve ser 
%regular com NP(1) x NP(2) pontos. Nesse caso tambem se nao conseguir ler
%do disco, tenta calcular a coluna 0 da matriz M a partir da coluna A0 da matriz
%A; essa coluna deve estar calculada na grade completa. Se a matriz A0 
%for vazia entao desiste e calcula M a partir da matriz A.


np = size(p,1);
nb = size(base.elementos,2);
assert(parametros.tensorial == tensorial);
assert(size(A,1) == np)
assert(size(A,2) == nb)
if parametros.metodo == 2
    assert(np == nb)
    M = A;
    return
end

if  (base.uniforme) && (~isnan(NP(1)))
    assert(~isnan(NP(2)))
    %Neste caso,
    %supoe que os pontos de p sao um subconjunto da grade regular com
    %NP(1) x NP(2) pontos no dominio.
    %Supoe tambem que
    %todos os elementos da base sao copias transladadas do mesmo elemento.
    %O vetor p pode estar em qualquer ordem
    
    %Vamos tentar ler do disco ou entao calcular a coluna zero da matriz M,
    %e replica-la nas demais colunas.
    %No disco sempre gravamos a coluna zero da matriz M correspondente ao
    %elemento de posicao [0, 0] supondo uma grade de amostragem completa, e
    %uma base completa, com os elementos numerados por colunas.
    
    raio_abs = base.elementos(1).raio_abs;
    assert(base.elementos(1).tipobase == parametros.tipobase)
    raio_rel_dom = raio_abs ./ malha.LD;  %raio relativo ao dominio
    
    assert(np_comp == prod(NP)); %numero de pontos na grade de amostragem completa
    nc_comp = malha.NC(1)*malha.NC(2); %numero de celula na malha completa
    nb_comp = nc_comp; %numero de elementos na base completa
    
    dir1 = sprintf('tb%02d-ten%d-dob%d',parametros.tipobase,...
        parametros.tensorial,1);
    dir2 = sprintf('rx%08.5f-ry%08.5f-NX%04d-NY%04d',...
        raio_rel_dom(1),raio_rel_dom(2),NP(1),NP(2));
    pasta = cria_pasta(sprintf('~/Desktop/matrizes/%s/%s',dir1,dir2));
    if parametros.le_matriz
        fprintf(2,'lendo a coluna padrao da matriz M da pasta %s\n',pasta);
        M0 = le_matriz(pasta,'M0',nb_comp,1);
        fprintf(2,'tamanho = %d x %d elementos nao nulos = %d\n', ...
            size(M0), nnz(M0));
    end
    if (~parametros.le_matriz) || (nnz(M0) == 0)
        assert(size(A0,1) == NP(1)*NP(2))
        assert(size(A0,2) == 1)
        assert(nnz(A0) > 0)
        fprintf(2,'calculando a coluna padrao da matriz M \n');
        M0 = calcula_coluna_padrao_da_matriz_M(A0,parametros.metodo,...
            malha.NC,NP);
        assert(size(M0,1) == malha.NC(1)*malha.NC(2))
        fprintf(2,'gravando a coluna padrao de M na pasta %s\n',pasta);
        grava_matriz(pasta,'M0',M0)
    end
    fprintf(2,'preenchendo a matriz M \n');
    M = replica_coluna_da_matriz_M(M0,malha,base);
    confere_matriz_M(parametros,M,A,p,np_comp,base,malha.LD);
else
    fprintf(2,'calculando a matriz M\n');
    
    %Minimos Quadrados
    M = (A'*A)/np_comp;
    M = sparse(M);
end


