changeset 1139:6bc93c091682 feature/laplace_curvilinear_test

Implement minimum check in new scheme.
author Martin Almquist <malmquist@stanford.edu>
date Fri, 21 Jun 2019 16:27:49 +0200
parents afd06a84b69c
children 738de3a4058b
files +scheme/LaplaceCurvilinearMin.m
diffstat 1 files changed, 117 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/+scheme/LaplaceCurvilinearMin.m	Mon Jun 10 14:39:14 2019 +0200
+++ b/+scheme/LaplaceCurvilinearMin.m	Fri Jun 21 16:27:49 2019 +0200
@@ -47,6 +47,9 @@
 
         % Temporary, only used for nonconforming interfaces but should be removed.
         lambda
+
+        % Number of boundary points in minumum check
+        bp
     end
 
     methods
@@ -58,6 +61,16 @@
             default_arg('a', 1);
             default_arg('b', @(x,y) 0*x + 1);
 
+            % Number of boundary points in minimum check
+            switch order
+            case 2
+                obj.bp = 2;
+            case 4
+                obj.bp = 4;
+            case 6
+                obj.bp = 7;
+            end
+
             % assert(isa(g, 'grid.Curvilinear'))
             if isa(a, 'function_handle')
                 a = grid.evalOn(g, a);
@@ -285,24 +298,54 @@
             Hi = obj.Hi;
             a = obj.a;
             b_b = e'*obj.b*e;
+            b = obj.b;
 
             switch type
                 % Dirichlet boundary condition
                 case {'D','d','dirichlet'}
                     tuning = 1.0;
 
-                    sigma = 0*b_b;
+                    sigma = 0*b;
                     for i = 1:obj.dim
-                        sigma = sigma + e'*J*K{i,m}*K{i,m}*e;
+                        sigma = sigma + b*J*K{i,m}*K{i,m};
                     end
+
+                    % Minimum check on sigma
+                    mx = obj.m(1);
+                    my = obj.m(2);
+                    bp = obj.bp;
+                    sigma_mat = reshape(diag(sigma), my, mx);
+                    switch boundary
+                    case 'w'
+                        sigma_min = min(sigma_mat(:,1:bp), [], 2);
+                        sigma_mat = repmat(sigma_min, 1, mx);
+                    case 'e'
+                        sigma_min = min(sigma_mat(:,end-bp+1:end), [], 2);
+                        sigma_mat = repmat(sigma_min, 1, mx);
+                    case 's'
+                        sigma_min = min(sigma_mat(1:bp,:), [], 1);
+                        sigma_mat = repmat(sigma_min, my, 1);
+                    case 'n'
+                        sigma_min = min(sigma_mat(end-bp+1:end,:), [], 1);
+                        sigma_mat = repmat(sigma_min, my, 1);
+                    end
+                    sigma_min = sigma_mat(:);
+                    sigma_min = spdiag(sigma_min);
+
+                    % Window
+                    sigma = e'*sigma*e;
+                    sigma_min = e'*sigma_min*e;
+
                     sigma = sigma/s_b;
-                    tau = tuning*(1/th_R + obj.dim/th_H)*sigma;
+                    sigma_min = sigma_min/s_b;
+
+                    tau = tuning*(1/th_R*sigma/sigma_min*sigma + obj.dim/th_H*sigma);
 
                     closure = a*Hi*d*b_b*H_b*e' ...
-                             -a*Hi*e*tau*b_b*H_b*e';
+                             -a*Hi*e*tau*H_b*e';
 
                     penalty = -a*Hi*d*b_b*H_b ...
-                              +a*Hi*e*tau*b_b*H_b;
+                              +a*Hi*e*tau*H_b;
 
 
                 % Neumann boundary condition. Note that the penalty is for du/dn and not b*du/dn.
@@ -362,6 +405,7 @@
             % Coefficients, u
             K_u = u.K;
             J_u = u.J;
+            b_u = u.b;
             b_b_u = e_u'*u.b*e_u;
 
             % Boundary operators, v
@@ -381,25 +425,84 @@
             % Coefficients, v
             K_v = v.K;
             J_v = v.J;
+            b_v = v.b;
             b_b_v = e_v'*v.b*e_v;
 
             %--- Penalty strength tau -------------
-            sigma_u = 0*b_b_u;
-            sigma_v = 0*b_b_v;
+            sigma_u = 0*b_u;
+            sigma_v = 0*b_v;
             for i = 1:obj.dim
-                sigma_u = sigma_u + e_u'*J_u*K_u{i,m_u}*K_u{i,m_u}*e_u;
-                sigma_v = sigma_v + e_v'*J_v*K_v{i,m_v}*K_v{i,m_v}*e_v;
+                sigma_u = sigma_u + b_u*J_u*K_u{i,m_u}*K_u{i,m_u};
+                sigma_v = sigma_v + b_v*J_v*K_v{i,m_v}*K_v{i,m_v};
+            end
+
+            %--- Minimum check on sigma_u ----
+            mx = u.m(1);
+            my = u.m(2);
+            bp = u.bp;
+            sigma_mat = reshape(diag(sigma_u), my, mx);
+            switch boundary
+            case 'w'
+                sigma_min = min(sigma_mat(:,1:bp), [], 2);
+                sigma_mat = repmat(sigma_min, 1, mx);
+            case 'e'
+                sigma_min = min(sigma_mat(:,end-bp+1:end), [], 2);
+                sigma_mat = repmat(sigma_min, 1, mx);
+            case 's'
+                sigma_min = min(sigma_mat(1:bp,:), [], 1);
+                sigma_mat = repmat(sigma_min, my, 1);
+            case 'n'
+                sigma_min = min(sigma_mat(end-bp+1:end,:), [], 1);
+                sigma_mat = repmat(sigma_min, my, 1);
             end
-            sigma_u = sigma_u/s_b_u;
-            sigma_v = sigma_v/s_b_v;
+            sigma_min_u = sigma_mat(:);
+            sigma_min_u = spdiag(sigma_min_u);
+
+            % Window
+            sigma_u = e_u'*sigma_u*e_u;
+            sigma_min_u = e_u'*sigma_min_u*e_u;
+            % -------------------------------
 
-            tau_R_u = 1/th_R_u*sigma_u;
-            tau_R_v = 1/th_R_v*sigma_v;
+            %--- Minimum check on sigma_v ----
+            mx = v.m(1);
+            my = v.m(2);
+            bp = v.bp;
+            sigma_mat = reshape(diag(sigma_v), my, mx);
+            switch neighbour_boundary
+            case 'w'
+                sigma_min = min(sigma_mat(:,1:bp), [], 2);
+                sigma_mat = repmat(sigma_min, 1, mx);
+            case 'e'
+                sigma_min = min(sigma_mat(:,end-bp+1:end), [], 2);
+                sigma_mat = repmat(sigma_min, 1, mx);
+            case 's'
+                sigma_min = min(sigma_mat(1:bp,:), [], 1);
+                sigma_mat = repmat(sigma_min, my, 1);
+            case 'n'
+                sigma_min = min(sigma_mat(end-bp+1:end,:), [], 1);
+                sigma_mat = repmat(sigma_min, my, 1);
+            end
+            sigma_min_v = sigma_mat(:);
+            sigma_min_v = spdiag(sigma_min_v);
+
+            % Window
+            sigma_v = e_v'*sigma_v*e_v;
+            sigma_min_v = e_v'*sigma_min_v*e_v;
+            % -------------------------------
+
+            sigma_u = sigma_u/s_b_u;
+            sigma_min_u = sigma_min_u/s_b_u;
+
+            sigma_v = sigma_v/s_b_v;
+            sigma_min_v = sigma_min_v/s_b_v;
+
+            tau_R_u = 1/th_R_u*sigma_u/sigma_min_u*sigma_u;
+            tau_R_v = 1/th_R_v*sigma_v/sigma_min_v*sigma_v;
 
             tau_H_u = dim*1/th_H_u*sigma_u;
             tau_H_v = dim*1/th_H_v*sigma_v;
 
-            tau = 1/4*tuning*(b_b_u*(tau_R_u + tau_H_u) + b_b_v*(tau_R_v + tau_H_v));
+            tau = 1/4*tuning*((tau_R_u + tau_H_u) + (tau_R_v + tau_H_v));
             %--------------------------------------
 
             % Operators/coefficients that are only required from this side