function MyPLWaveEqSolver()

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Solves the pde system
%
%     du1/dt = u2,  du2/dt + div ( - grad u1) = 0
%
%  with boundary conditions
%
%            n qi = ki (ui - gi),
%
%  and initial conditions
%
%            ui = ui0,  i = 1,2.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% defining geometry and meshing

  g = geometry;

  [p,e,t] = initmesh(g,'HMax',.1);


% defining data functions

  x1 = p(1,:);
  x2 = p(2,:);
  nn = size(p,2);
  d = .1*ones(1,nn);
  m = ones(1,nn);
  k = zeros(1,nn);
  g = zeros(1,nn);        % has no effect because k1 = 0


% initialising matrises
  
  D = sparse(zeros(nn,nn));
  M = sparse(zeros(nn,nn));
  K = sparse(zeros(nn,nn));
  F = zeros(nn,1);
  G = zeros(nn,1);
  U1 = .2*sin(2*pi*x1.*x2)';
  U2 = zeros(nn,1);
  O = zeros(nn,1);


% assembling element contributions

  for el = 1 : size(t,2)
    elNodeInd = t(1: 3, el);
    elCoords = p(:,elNodeInd);
    elDiff = d(elNodeInd);
    dD = elDiffMatrix(elCoords, elDiff);
    D(elNodeInd,elNodeInd) = D(elNodeInd,elNodeInd) + dD;
    elMass = m(elNodeInd);
    dM = elMassMatrix(elCoords, elMass);
    M(elNodeInd,elNodeInd) = M(elNodeInd,elNodeInd) + dM;
  end


% assembling boundary element conributions

  for bel = 1 : size(e, 2)
    belNodeInd = e(1: 2, bel);
    belCoords = p(:, belNodeInd);
    belPerm = k(belNodeInd);
    dK = elBdryMatrix(belCoords, belPerm);
    K(belNodeInd, belNodeInd) = K(belNodeInd, belNodeInd) + dK;
    belLoad = g(belNodeInd);
    dG = elBdryVector(belCoords, belPerm, belLoad);
    G(belNodeInd) = G(belNodeInd) + dG;
  end


% initializations

  time = 0;
  u1 = U1;                             % storing
  u2 = U2;                             % storing
  FinalTime = 2;
  dt = .01;
  ekin = [];
  epot = [];
  etot = [];

  A = [M, -dt/2*M;  dt/2*D+dt/2*K, M+0*dt/2*M];
  L = [M,  dt/2*M; -dt/2*D-dt/2*K, M-0*dt/2*M];
  W = [U1; U2];


% time stepping

  h = waitbar(0,'Just a minute..');

  while time < FinalTime

     F = zeros(nn, 1);
%    F1 = zeros(nn,1);
%    F2 = zeros(nn,1);
    for el = 1 : size(t, 2)
      elNodeInd = t(1: 3, el);
      elCoords = p(:, elNodeInd);
%      f1 = U2(elNodeInd);
      f = -U2(elNodeInd);
%      f2 = 0;
%      dF1 = elLoadVector(elCoords, f1);
%      dF2 = elLoadVector(elCoords, f2);
%      F1(elNodeInd) = F1(elNodeInd) + dF1;
%      F2(elNodeInd) = F2(elNodeInd) + dF2;
    end

    W = [U1; U2];
    b = L * W + dt * [O; F] + dt * [O; G];
    W = A \ b;
    U1 = W(1:nn);;
    U2 = W(nn+1:2*nn);

% checking energy
    ekin = [ekin U2'*M*U2];
    epot = [epot U1'*D*U1];
    etot = [etot U2'*M*U2+U1'*D*U1];
    u1 = [u1 U1];
    u2 = [u2 U2];

    time = time + dt;
    waitbar(time/FinalTime)

  end

  delete(h)


% plotting

  set(gcf,'DoubleBuffer','on')
  for i = 1 : size(u1, 2)
    subplot(121)
    pdeplot(p,e,t,'xydata',U1,'zdata',u1(:,i),'mesh','on');
    set(gca,'ZLim',[-1 1])
    grid on
    zlabel('displacement')
    title(['time = ' num2str((i-1)*dt)])
    subplot(122)
    pdeplot(p,e,t,'xydata',U1,'zdata',u2(:,i),'mesh','on');
    set(gca,'ZLim',[-1 1])
    grid on
    zlabel('velocity')
    title(['time = ' num2str((i-1)*dt)])
    drawnow
  end
  
  plot(dt*(1:length(etot)),[ekin;epot;etot])
  xlabel('time')
  title('energies, total red, pot. green, kin. blue')

% subroutines


function dD = elDiffMatrix(coords, diffusion)

  dx = area(coords);
  x = sum(coords, 2) / 3;
  Dphi = Dphi(coords);
  d = sum(diffusion)/length(diffusion);
  dD = Dphi' * (d * Dphi) * dx;


function dM = elMassMatrix(coords, mass)

  dx = area(coords);
  x = sum(coords, 2) / 3;
  phi = [1/3 1/3 1/3];
  m = sum(mass)/length(mass);
  dM = phi' * (m * phi) * dx;


function dF = elLoadVector(coords, domainLoad)

  dx = area(coords);
  x = sum(coords, 2) / 3;
  phi = [1/3 1/3 1/3];
%  f = feval(Myf, u1, u2);
  f = sum(domainLoad)/length(domainLoad);
  dF = phi' * f * dx;


function dK = elBdryMatrix(coords, bdryPerm)

  v = coords(:, 2) - coords(:, 1);
  ds = sqrt(v' * v);
  p = 0.57735026918963;
  points = [.5-p/2; .5+p/2];
  weights = [.5 .5];
  x = sum(coords, 2) / 2;
  phi = [1/2 1/2];
  phi1 = [1-points(1) points(1)];
  phi2 = [1-points(2) points(2)];
  k = sum(bdryPerm)/length(bdryPerm);
  dK = phi1' * (k * phi1) * ds / 2 ...
     + phi2' * (k * phi2) * ds / 2;


function dG = elBdryVector(coords, bdryPerm, bdryLoad)

  v = coords(:, 2) - coords(:, 1);
  ds = sqrt(v' * v);
  x = sum(coords, 2) / 2;
  phi = [1/2 1/2];
  k = sum(bdryPerm)/length(bdryPerm);
  g = sum(bdryLoad)/length(bdryLoad);
  dG = phi' * k * g * ds;  


function dx = area(coords)

  v = coords(:, 2) - coords(:, 1);
  w = coords(:, 3) - coords(:, 1);
  dx = (v(1) * w(2) - v(2) * w(1)) / 2;


function Dphi = Dphi(coords)

  v = coords(:, 2) - coords(:, 1);
  w = coords(:, 3) - coords(:, 1);

  n2v = [-v(2) v(1)]';                    % normal to v
  n2v = n2v / sqrt(n2v' * n2v);           % normalizing
  pw = w' * n2v;                          % height of triangle
  Dphi(:, 3) = n2v / pw;

  n2w = [w(2) -w(1)]';
  n2w = n2w / sqrt(n2w' * n2w);
  pv = v' * n2w;
  Dphi(:, 2) = n2w / pv;

  Dphi(:, 1) = - Dphi(:, 2) - Dphi(:, 3);



% data functions


function g = geometry()
  e1 = [2 0 1 0 0 1 0]';
  e2 = [2 1 1 0 1 1 0]';
  e3 = [2 1 0 1 1 1 0]';
  e4 = [2 0 0 1 0 1 0]';
  g = [e1 e2 e3 e4];




