mul_SM.m 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. %{
  2. Copyright © 2020 Alexey A. Shcherbakov. All rights reserved.
  3. This file is part of GratingFMM.
  4. GratingFMM is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 2 of the License, or
  7. (at your option) any later version.
  8. GratingFMM is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GratingFMM. If not, see <https://www.gnu.org/licenses/>.
  14. %}
  15. %% description:
  16. % multiplication of two S-matrices
  17. %% input:
  18. % SM1, SM2: S-matrices of size (n,n,2,2) or (n,2,2)
  19. % the multiplication order is meaningful!
  20. %% output:
  21. % SM: S-matrix of size (n,n,2,2) or (n,2,2)
  22. %% implementation:
  23. function [SM] = mul_SM(SM1, SM2)
  24. if (numel(size(SM1)) == 4) && (numel(size(SM2)) == 4) % both S-matrices are full
  25. if ~isequal(size(SM1),size(SM2))
  26. error("mul_SM: different size input");
  27. end
  28. n = size(SM1,1);
  29. SM = zeros(n,n,2,2);
  30. TM = -SM2(:,:,1,1)*SM1(:,:,2,2);
  31. TM(1:n+1:end) = TM(1:n+1:end) + 1;
  32. TM = SM1(:,:,1,2)/TM;
  33. SM(:,:,1,2) = TM*SM2(:,:,1,2);
  34. SM(:,:,1,1) = SM1(:,:,1,1) + TM*SM2(:,:,1,1)*SM1(:,:,2,1);
  35. TM = -SM1(:,:,2,2)*SM2(:,:,1,1);
  36. TM(1:n+1:end) = TM(1:n+1:end) + 1;
  37. TM = SM2(:,:,2,1)/TM;
  38. SM(:,:,2,1) = TM*SM1(:,:,2,1);
  39. SM(:,:,2,2) = SM2(:,:,2,2) + TM*SM1(:,:,2,2)*SM2(:,:,1,2);
  40. elseif (numel(size(SM1)) == 3) && (numel(size(SM2)) == 4) % first S-matrix is diagonal
  41. if size(SM1,1) ~= size(SM2,1)
  42. error("mul_SM: different size input");
  43. end
  44. n = size(SM1,1);
  45. SM = zeros(n,n,2,2);
  46. TM = -SM2(:,:,1,1).*transpose(SM1(:,2,2));
  47. TM(1:n+1:end) = TM(1:n+1:end) + 1;
  48. TM = diag(SM1(:,1,2))/TM;
  49. SM(:,:,1,2) = TM*SM2(:,:,1,2);
  50. SM(:,:,1,1) = diag(SM1(:,1,1)) + TM*(SM2(:,:,1,1).*transpose(SM1(:,2,1)));
  51. TM = -SM1(:,2,2).*SM2(:,:,1,1);
  52. TM(1:n+1:end) = TM(1:n+1:end) + 1;
  53. TM = SM2(:,:,2,1)/TM;
  54. SM(:,:,2,1) = TM.*transpose(SM1(:,2,1));
  55. SM(:,:,2,2) = SM2(:,:,2,2) + TM*(SM1(:,2,2).*SM2(:,:,1,2));
  56. elseif (numel(size(SM1)) == 4) && (numel(size(SM2)) == 3) % second S-matrix is diagonal
  57. if size(SM1,2) ~= size(SM2,1)
  58. error("mul_SM_SMD: different size input");
  59. end
  60. n = size(SM1,2);
  61. SM = zeros(n,n,2,2);
  62. TM = -SM2(:,1,1).*SM1(:,:,2,2);
  63. TM(1:n+1:end) = TM(1:n+1:end) + 1;
  64. TM = SM1(:,:,1,2)/TM;
  65. SM(:,:,1,2) = TM.*transpose(SM2(:,1,2));
  66. SM(:,:,1,1) = SM1(:,:,1,1) + TM*(SM2(:,1,1).*SM1(:,:,2,1));
  67. TM = -SM1(:,:,2,2).*transpose(SM2(:,1,1));
  68. TM(1:n+1:end) = TM(1:n+1:end) + 1;
  69. TM = diag(SM2(:,2,1))/TM;
  70. SM(:,:,2,1) = TM*SM1(:,:,2,1);
  71. SM(:,:,2,2) = diag(SM2(:,2,2)) + TM*(SM1(:,:,2,2).*transpose(SM2(:,1,2)));
  72. elseif (numel(size(SM1)) == 3) && (numel(size(SM2)) == 3) % both S-matrices are diagonal
  73. if ~isequal(size(SM1),size(SM2))
  74. error("mul_SM: different size input");
  75. end
  76. n = size(SM1,1);
  77. SM = zeros(n,2,2);
  78. TM = SM1(:,1,2)./(1 - SM1(:,2,2).*SM2(:,1,1));
  79. SM(:,1,2) = SM2(:,1,2).*TM;
  80. SM(:,1,1) = SM1(:,1,1) + TM.*SM2(:,1,1).*SM1(:,2,1);
  81. TM = SM2(:,2,1)./(1 - SM2(:,1,1).*SM1(:,2,2));
  82. SM(:,2,1) = SM1(:,2,1).*TM;
  83. SM(:,2,2) = SM2(:,2,2) + SM2(:,1,2).*SM1(:,2,2).*TM;
  84. else
  85. error("mul_SM: incorrect input size");
  86. end
  87. end
  88. %
  89. % end of mul_SM
  90. %