function eta4e = DGESTIMATE(c4n,n4e,n4ed,ed4e,ed4Db,e4ed,x,dof4e,alpha)
m = size(n4e,1); n = size(e4ed,1);
eta4e = zeros(m,1); grad4e = zeros(m,2);
for j = 1 : m
    grad4e(j,:) = x(dof4e(j,:))'*([ones(1,3);c4n(n4e(j,:),:)']\[zeros(1,2);eye(2)]);
    eta4e(j) = (abs(det([ones(1,3);c4n(n4e(j,:),:)'])/2)).^2;
end
etaGradJump4ed = zeros(n,3);
etaJump4ed = zeros(n,3);
dof4ed = zeros(n,4);
for j = 1 : n
    % local edge patch enumeration
    nodes = zeros(4,1);
    nodes(1) = find(n4e(e4ed(j,1),:)==n4ed(j,1));
    nodes(2) = find(n4e(e4ed(j,1),:)==n4ed(j,2));
    if e4ed(j,2)~=0 % interior edge
        nodes(3) = find(n4e(e4ed(j,2),:)==n4ed(j,1));
        nodes(4) = find(n4e(e4ed(j,2),:)==n4ed(j,2));
    end
    % edge dofs indices
    dof4ed(j,1:2) = dof4e(e4ed(j,1),nodes(1:2));
    if e4ed(j,2)~=0
        dof4ed(j,3:4) = dof4e(e4ed(j,2),nodes(3:4));
    end
    % grad jumps
    t = (c4n(n4ed(j,2),:)-c4n(n4ed(j,1),:));
    n = [t(2),-t(1)];
    etaGradJump4ed(j,:) = grad4e(e4ed(j,1),:)*n';
    if e4ed(j,2)~=0 % interior edge
        etaGradJump4ed(j,:) = etaGradJump4ed(j,:) - grad4e(e4ed(j,2),:)*n';
    end
    %jumps
    etaJump4ed(j,:) = [x(dof4ed(j,1)), 1/2*(x(dof4ed(j,1))+x(dof4ed(j,2))), x(dof4ed(j,2))];
    if e4ed(j,2)~=0 % interior edge
        etaJump4ed(j,:) = etaJump4ed(j,:) - [x(dof4ed(j,3)), 1/2*(x(dof4ed(j,3))+x(dof4ed(j,4))), x(dof4ed(j,4))];
    end
end
etaGradJump4ed = etaGradJump4ed.^2*[1/6 4/6 1/6]';
etaGradJump4ed(ed4Db) = 0;
etaJump4ed = etaJump4ed.^2*[1/6 4/6 1/6]';
etaJump4ed(ed4Db) = 2*etaJump4ed(ed4Db);
% complete
eta4e = sqrt(eta4e + 0.5*sum(etaGradJump4ed(ed4e),2) + 0.5*alpha*sum(etaJump4ed(ed4e),2));
end