classdef green3d_test < genlib_test
  % Test for 3D Green's functions
  %
  % [+GenLib General Purpose Library+] Swiss Plasma Center EPFL Lausanne 2022. All rights reserved.
  properties
    tolr = 1e-6;
    nt   = 2e3+1; % One must reduce tolr too when reducing nt.
  end
  
  properties (TestParameter)
    mode = {0,1,2,3}
  end
  
  methods (TestClassSetup)
    function parallel_toolbox_notneeded(testCase)
      if ~isempty(which('parallel.Settings'))
        % Disable automatic creation of parallel pool since it's not strictly
        % needed here.
        ps = parallel.Settings;
        testCase.addTeardown(@() set(ps.Pool,'AutoCreate',ps.Pool.AutoCreate));
        ps.Pool.AutoCreate = false;
      end
    end
  end
  
  methods (Test)
    function test_green3d_circular(testCase,mode)
      % Check different options in green3d against greenem for purely
      % circular cases. Use a single loop in each set.
      
      % 2 circular loops
      r1 = 1.2;
      z1 = 0.2;
      r2 = 1.5;
      z2 = 0.8;
      mut = greenem('mut',r1,z1,r2,z2);
      
      if ~mode
        % 2D description
        y = green3d(r1,z1,[],r2,z2,[]);
        testCase.verifyEqual(y,mut,'RelTol',testCase.tolr,'green3d with circular 2d loops does not match greenem');
      else
      
        % 3d loops
        nt = testCase.nt; %#ok<*PROP,*PROPLC>
        t = (0:nt-1).'*2*pi/(nt-1);
        switch mode
          case 1
            y = green3d(repmat(r1,nt,1),repmat(z1,nt,1),t,r2,z2,[]);
            testCase.verifyEqual(y,mut,'RelTol',testCase.tolr,'green3d with circular 2.5d loops does not match greenem');
          case 2
            y = green3d(r1,z1,[],repmat(r2,nt,1),repmat(z2,nt,1),t);
            testCase.verifyEqual(y,mut,'RelTol',testCase.tolr,'green3d with circular 2.5d loops does not match greenem');
          case 3
            testCase.assumeTrue(~verLessThan('MATLAB','9.1'),'Skipping green3d tests with 3d loops for versions prior to 9.1.0');
            
            y = green3d(repmat(r1,nt,1),repmat(z1,nt,1),t,repmat(r2,nt,1),repmat(z2,nt,1),t);
            testCase.verifyEqual(y,mut,'RelTol',testCase.tolr,'green3d with circular 3d loops does not match greenem');
        end
      end
      
    end
    
    function test_green3d_2d5_loops(testCase)
      % Check green2d5 implementation against general greenxyz computation
      % Use multiple loops in each set
      
      testCase.assumeTrue(~verLessThan('MATLAB','9.1'),'Skipping green3d tests with 3d loops for versions prior to 9.1.0');
      
      % First set of loops - circular
      r1 = linspace(1,1.2,21);
      z1 = 0.2*ones(1,21);
      
      % Second set of loops - 3d
      nt = testCase.nt;
      t = (0:nt-1).'*2*pi/(nt-1);
      r2 = 1.5*ones(1,11)+0.2*cos(t);
      z2 = repmat(linspace(0.8,1,11),nt,1);
      
      % Compute with both 3d geometries
      y_ = green3d(repmat(r1,nt,1),repmat(z1,nt,1),repmat(t,1,21),r2,z2,repmat(t,1,11));
      
      % Compute using green2d5
      y  = green3d(r1,z1,[],r2,z2,repmat(t,1,11));
      
      testCase.verifyEqual(y,y_,'RelTol',testCase.tolr,'green2d5 result does not match greenxyz when (r1,z1) are 2d');
      
      % Compute using green2d5
      y  = green3d(r2,z2,repmat(t,1,11),r1,z1,[]);
      
      testCase.verifyEqual(y.',y_,'RelTol',testCase.tolr,'green2d5 result does not match greenxyz when (r2,z2) are 2d');
    end
  end
  
end
