abctmz.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. 2D FDTD simulator
  3. Copyright (C) 2019 Emilia Blåsten
  4. This program is free software: you can redistribute it and/or
  5. modify it under the terms of the GNU Affero General Public License
  6. as published by the Free Software Foundation, either version 3 of
  7. the License, or (at your option) any later version.
  8. This program 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 GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public
  13. License along with this program. If not, see
  14. <http://www.gnu.org/licenses/>.
  15. */
  16. /* abctmz.c: Function to apply a second-order ABC to a TMz grid. */
  17. #include <math.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include "gridtmz.h"
  21. #include "abctmz.h"
  22. /* Define 3D arrays that store the previous values of the fields. For
  23. * each one of these arrays the three arguments are as follows:
  24. *
  25. * first argument: displacement back in time
  26. * second argument: spatial displacement from the boundary
  27. * third argument: distance from either the bottom (if EzLeft or
  28. * EzRight) or left (if EzTop or EzBottom) side of
  29. * grid
  30. */
  31. void abcInit(Abc *ab, Grid *g) {
  32. double temp1, temp2;
  33. // calculate ABC coefficients
  34. temp1 = sqrt( g->ezUpdateHcoeff[0][0] * g->hyUpdateEcoeff[0][0] );
  35. temp2 = 1.0 / temp1 + 2.0 + temp1;
  36. ab->coef0 = -(1.0 / temp1 - 2.0 + temp1) / temp2;
  37. ab->coef1 = -2.0 * (temp1 - 1.0 / temp1) / temp2;
  38. ab->coef2 = 4.0 * (temp1 + 1.0 / temp1) / temp2;
  39. return;
  40. }
  41. void abc(Abc *ab, Grid *g) {
  42. int mm, nn;
  43. // ABC at left side of grid
  44. for(nn = 0; nn < g->sizeY; nn++) {
  45. g->ez[0][nn] = ab->coef0 * (g->ez[2][nn] + ab->ezLeft[1][0][nn])
  46. + ab->coef1 * ( ab->ezLeft[0][0][nn] + ab->ezLeft[0][2][nn]
  47. - g->ez[1][nn] - ab->ezLeft[1][1][nn] )
  48. + ab->coef2 * ab->ezLeft[0][1][nn]
  49. - ab->ezLeft[1][2][nn];
  50. // memorize old fields
  51. for(mm = 0; mm < 3; mm++) {
  52. ab->ezLeft[1][mm][nn] = ab->ezLeft[0][mm][nn];
  53. ab->ezLeft[0][mm][nn] = g->ez[mm][nn];
  54. }
  55. }
  56. // ABC at right side of grid
  57. for(nn = 0; nn < g->sizeY; nn++) {
  58. g->ez[g->sizeX-1][nn] =
  59. ab->coef0 * (g->ez[g->sizeX-3][nn] + ab->ezRight[1][0][nn])
  60. + ab->coef1 * ( ab->ezRight[0][0][nn] + ab->ezRight[0][2][nn]
  61. - g->ez[g->sizeX-2][nn] - ab->ezRight[1][1][nn] )
  62. + ab->coef2 * ab->ezRight[0][1][nn]
  63. - ab->ezRight[1][2][nn];
  64. // memorize old fields
  65. for(mm = 0; mm < 3; mm++) {
  66. ab->ezRight[1][mm][nn] = ab->ezRight[0][mm][nn];
  67. ab->ezRight[0][mm][nn] = g->ez[g->sizeX-1-mm][nn];
  68. }
  69. }
  70. // ABC at bottom of grid
  71. for(mm = 0; mm < g->sizeX; mm++) {
  72. g->ez[mm][0] = ab->coef0 * (g->ez[mm][2] + ab->ezBottom[1][0][mm])
  73. + ab->coef1 * ( ab->ezBottom[0][0][mm] + ab->ezBottom[0][2][mm]
  74. - g->ez[mm][1] - ab->ezBottom[1][1][mm] )
  75. + ab->coef2 * ab->ezBottom[0][1][mm]
  76. - ab->ezBottom[1][2][mm];
  77. // memorize old fields
  78. for(nn = 0; nn < 3; nn++) {
  79. ab->ezBottom[1][nn][mm] = ab->ezBottom[0][nn][mm];
  80. ab->ezBottom[0][nn][mm] = g->ez[mm][nn];
  81. }
  82. }
  83. // ABC at top of grid
  84. for(mm = 0; mm < g->sizeX; mm++) {
  85. g->ez[mm][g->sizeY-1] =
  86. ab->coef0 * (g->ez[mm][g->sizeY-3] + ab->ezTop[1][0][mm])
  87. + ab->coef1 * ( ab->ezTop[0][0][mm] + ab->ezTop[0][2][mm]
  88. - g->ez[mm][g->sizeY-2] - ab->ezTop[1][1][mm] )
  89. + ab->coef2 * ab->ezTop[0][1][mm]
  90. - ab->ezTop[1][2][mm];
  91. // memorize old fields
  92. for(nn = 0; nn < 3; nn++) {
  93. ab->ezTop[1][nn][mm] = ab->ezTop[0][nn][mm];
  94. ab->ezTop[0][nn][mm] = g->ez[mm][g->sizeY-1-nn];
  95. }
  96. }
  97. return;
  98. }
  99. Abc *abcCreate(int sizeX, int sizeY) {
  100. // Allocate memory for the Abc struct itself
  101. Abc *ab;
  102. ab = (Abc *)calloc(1, sizeof(Abc));
  103. if(!ab) {
  104. perror("abcCreate()");
  105. fprintf(stderr, "Failed to allocate memory for Abc.\n");
  106. exit(-1);
  107. }
  108. // Allocate memory for the large ABC arrays
  109. // ezAA[T][O][P], T=time, O=orthogonal, P=parallel coord to boundary
  110. ab->ezLeft = (double ***)calloc(2, sizeof(double**));
  111. ab->ezLeftTfixed = (double **)calloc(2*3, sizeof(double*));
  112. ab->ezLeftTOfixed = (double *)calloc(2*3*sizeY, sizeof(double));
  113. for(int t=0; t<2; t++) {
  114. ab->ezLeft[t] = ab->ezLeftTfixed + t*3;
  115. for(int m=0; m<3; m++)
  116. ab->ezLeftTfixed[t*3+m] = ab->ezLeftTOfixed + (t*3+m)*sizeY;
  117. }
  118. ab->ezRight = (double ***)calloc(2, sizeof(double**));
  119. ab->ezRightTfixed = (double **)calloc(2*3, sizeof(double*));
  120. ab->ezRightTOfixed = (double *)calloc(2*3*sizeY, sizeof(double));
  121. for(int t=0; t<2; t++) {
  122. ab->ezRight[t] = ab->ezRightTfixed + t*3;
  123. for(int m=0; m<3; m++)
  124. ab->ezRightTfixed[t*3+m] = ab->ezRightTOfixed + (t*3+m)*sizeY;
  125. }
  126. ab->ezTop = (double ***)calloc(2, sizeof(double**));
  127. ab->ezTopTfixed = (double **)calloc(2*3, sizeof(double*));
  128. ab->ezTopTOfixed = (double *)calloc(2*3*sizeX, sizeof(double));
  129. for(int t=0; t<2; t++) {
  130. ab->ezTop[t] = ab->ezTopTfixed + t*3;
  131. for(int o=0; o<3; o++)
  132. ab->ezTop[t][o] = ab->ezTopTOfixed + (t*3+o)*sizeX;
  133. }
  134. ab->ezBottom = (double ***)calloc(2, sizeof(double**));
  135. ab->ezBottomTfixed = (double **)calloc(2*3, sizeof(double*));
  136. ab->ezBottomTOfixed = (double *)calloc(2*3*sizeX, sizeof(double));
  137. for(int t=0; t<2; t++) {
  138. ab->ezBottom[t] = ab->ezBottomTfixed + t*3;
  139. for(int o=0; o<3; o++)
  140. ab->ezBottom[t][o] = ab->ezBottomTOfixed + (t*3+o)*sizeX;
  141. }
  142. // Check for allocation success
  143. if(!ab->ezLeft || !ab->ezLeftTfixed || !ab->ezLeftTOfixed ||
  144. !ab->ezRight || !ab->ezRightTfixed || !ab->ezRightTOfixed ||
  145. !ab->ezTop || !ab->ezTopTfixed || !ab->ezTopTOfixed ||
  146. !ab->ezBottom || !ab->ezBottomTfixed || !ab->ezBottomTOfixed) {
  147. perror("abcInit");
  148. fprintf(stderr, "Allocation of one of the abc arrays failed\n");
  149. exit(-1);
  150. }
  151. return ab;
  152. }
  153. void abcDestroy(Abc *ab) {
  154. free(ab->ezLeftTOfixed);
  155. free(ab->ezLeftTfixed);
  156. free(ab->ezLeft);
  157. free(ab->ezRightTOfixed);
  158. free(ab->ezRightTfixed);
  159. free(ab->ezRight);
  160. free(ab->ezTopTOfixed);
  161. free(ab->ezTopTfixed);
  162. free(ab->ezTop);
  163. free(ab->ezBottomTOfixed);
  164. free(ab->ezBottomTfixed);
  165. free(ab->ezBottom);
  166. free(ab);
  167. return;
  168. }