diff diracDiscr.m @ 1251:6424745e1b58 feature/volcano

Merge in latest changes from default
author Vidar Stiernström <vidar.stiernstrom@it.uu.se>
date Wed, 20 Nov 2019 14:26:57 -0800
parents 25efceb0c392
children 60c875c18de3
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/diracDiscr.m	Wed Nov 20 14:26:57 2019 -0800
@@ -0,0 +1,106 @@
+% n-dimensional delta function
+% g: cartesian grid
+% x_s: source point coordinate vector, e.g. [x; y] or [x; y; z].
+% m_order: Number of moment conditions
+% s_order: Number of smoothness conditions
+% H: cell array of 1D norm matrices
+function d = diracDiscr(g, x_s, m_order, s_order, H)
+    assertType(g, 'grid.Cartesian');
+    
+    dim = g.d;
+    d_1D = cell(dim,1);
+
+    % Allow for non-cell input in 1D
+    if dim == 1
+        H = {H};
+    end
+    % Create 1D dirac discr for each coordinate dir.
+    for i = 1:dim
+        d_1D{i} = diracDiscr1D(x_s(i), g.x{i}, m_order, s_order, H{i});
+    end
+
+    d = d_1D{dim};
+    for i = dim-1: -1: 1
+        % Perform outer product, transpose, and then turn into column vector
+        d = (d_1D{i}*d')';
+        d = d(:);
+    end
+end
+
+
+% Helper function for 1D delta functions
+function ret = diracDiscr1D(x_s, x, m_order, s_order, H)
+
+    % Return zeros if x0 is outside grid
+    if x_s < x(1) || x_s > x(end)
+        ret = zeros(size(x));
+        return
+    end
+       
+    tot_order = m_order+s_order; %This is equiv. to the number of equations solved for
+    S = [];
+    M = [];
+
+    % Get interior grid spacing
+    middle = floor(length(x)/2);
+    h = x(middle+1) - x(middle); % Use middle point to allow for staggered grids.
+
+    index = sourceIndices(x_s, x, tot_order, h);
+
+    polynomial = (x(index)-x(index(1)))/(x(index(end))-x(index(1)));
+    x_0 = (x_s-x(index(1)))/(x(index(end))-x(index(1)));
+
+    quadrature = diag(H);
+    quadrature_weights = quadrature(index)/h;
+
+    h_polynomial = polynomial(2)-polynomial(1);
+    b = zeros(tot_order,1);
+
+    for i = 1:m_order
+        b(i,1) = x_0^(i-1);
+    end
+
+    for i = 1:tot_order
+        for j = 1:m_order
+            M(j,i) = polynomial(i)^(j-1)*h_polynomial*quadrature_weights(i);
+        end
+    end
+
+    for i = 1:tot_order
+        for j = 1:s_order
+            S(j,i) = (-1)^(i-1)*polynomial(i)^(j-1);
+        end
+    end
+
+    A = [M;S];
+
+    d = A\b;
+    ret = x*0;
+    ret(index) = d/h*h_polynomial;
+end
+
+
+function I = sourceIndices(x_s, x, tot_order, h)
+    % Find the indices that are within range of of the point source location
+    I = find(tot_order*h/2 >= abs(x-x_s));
+
+    if length(I) > tot_order
+        if length(I) == tot_order + 2
+            I = I(2:end-1);
+        elseif length(I) == tot_order + 1
+            I = I(1:end-1);
+        end
+    elseif length(I) < tot_order
+        if x_s < x(1) + ceil(tot_order/2)*h
+            I = 1:tot_order;
+        elseif x_s > x(end) - ceil(tot_order/2)*h
+            I = length(x)-tot_order+1:length(x);
+        else
+            if I(end) < length(x)
+                I = [I; I(end)+1];
+            else
+                I = [I(1)-1; I];
+            end
+        end
+    end
+end