⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loop_in_chunks.cpp

📁 麻省理工的计算光子晶体的程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2006 Massachusetts Institute of Technology. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <stdlib.h>#include <math.h>#include "meep.hpp"#include "meep_internals.hpp"/* This file contains a generic function for looping over all of the   points in all of the chunks that intersect some given volume.  This   is used for everything from HDF5 output to applying source volumes to   integrating energy and flux.  It's fairly tricky because of the   parallelization, arbitrary chunk divisions, symmetries, and periodic   boundary conditions, but at least all of the trickiness is in one   place.  It is designed so that the inner loops over the actual grid   points can be tight and fast (using the LOOP_OVER_IVECS macro).   Many of the loops over chunks involve some sort of integration-like   computation, and so we also perform the additional task of calculating   the integration weights for each point -- mainly, this involves weighting   the boundary points appropriately so that the sum approximates (via   linear interpolation) a continuous integral over the supplied volume. *//****************************************************************************                     Integration WeightsWe want the integral from a to b, assuming linear interpolation of fn(function values on grid points n).  Most interior points have weight1, but the points just inside and outside the boundaries havedifferent weights.  Call the weights for the points just *outside* thestarting and ending boundaries s0 and e0, respectively, and weightsfor the points just *inside* the boundaries s1 and e1.  Then we haveto handle the following cases:1) a and b separated by at least 2 grid points, e.g.:x  |    x       x       x  |    x0  a    1       2       3  b    4first segment: f(x) = f0 (1 - x) + f1 x      -- \int_a^1 f(x) dx = f0 (1 - a)^2/2 + f1 (1 - a^2) / 2last segment: f(x) = f3 (4 - x) + f4 (x - 3)     -- \int_3^b f(x) dx = f3 [1 - (4-b)^2] / 2 + f4 (b - 3)^2 / 2integral = f0 (1 - a)^2/2         <---- f0 s0         + f1 (1 - a^2/2)         <---- f1 s1         + f2         + f3 (1 - (4-b)^2 / 2)   <---- f3 e1         + f4 (b - 3)^2 / 2       <---- f4 e0In terms of starting and ending weights:	 w0 = 1 - a	 w1 = b - 3	 s0 = w0^2 / 2	 s1 = 1 - (1 - w0)^2 / 2	 e0 = w1^2 / 2	 e1 = 1 - (1 - w1)^2 / 22) one grid point between a and b.x  |    x  |    x0  a    1  b    2integral = f0 (1 - a)^2 / 2         + f1 [(1 - a^2) + 1 - (2 - b)^2] / 2         + f3 (b - 1)^2 / 2s0 = w0^2 / 2e0 = w1^2 / 2s1 = e1 = 1 - (1 - w0)^2 / 2 - (1 - w1)^2 / 23) no grid points between a and b.x  |      |    x0  a      b    1integral = f0 [ (1-a)^2 - (1-b)^2 ] / 2 + f1 [ b^2 - a^2 ] / 2         = f0 [ w0^2 - (1-w1)^2 ]  / 2 + f1 [ w1^2 - (1-w0)^2 ] / 2s0 = e1 = w0^2/2 - (1-w1)^2/2e0 = s1 = w1^2/2 - (1-w0)^2/24) as (3), but a = b: interpolation, not integration: -- want: f0 * w0 + f1 * w1s0 = w0e0 = w1 = 1 - w0                        --------------          Integration Weights in Cylindrical Coordinates                   FIXME: implement this below?Ideally, we should have different weights for the R direction ofcylindrical coordinates, i.e. for integrating f(r) r dr, because againwe want to perfectly integrate any linear f(r).  Thus, the integrationweights will depend upon r.  Note, however, that we also have an r inthe dV, so we will have to divide the weights by this factor.1) a and b separated by at least 2 grid points, e.g.:x  |    x       x       x  |    xi  a   i+1     i+2     i+3  b  i+4(where r = i * inva).linear interpolation in [i,i+1): f(x) = f_i (i+1 - x) + f_{i+1} (x-i)   want: \int_a^b f(x) x dxin terms of starting and ending weights:	 w0 = (i+1) - a	 w1 = b - (i+3)integral = f_i [-w0^3 / 3 + (i+1) w0^2 / 2]                       <- s0 i      + f_{j=i+1} [w0^3 / 3 - (j+1) w0^2 / 2 + j w0 + j/2 + 1/6]  <- s1 (i+1)      + f_{j=i+2} j                                               <- 1 (i+2)      + f_{j=i+3} [-w1^3 / 3 - (j-1) w1^2 / 2 + j w1 + j/2 - 1/6] <- e1 (i+3)      + f_{j=i+4} [w1^3 / 3 + (j-1) w1^2 / 2]                     <- e0 (i+4)      (thanks to Maple for doing the annoying algebra)  (yes, I have tested that it correctly integrates linear f(r))Note that the coefficients need to be divided by i, i+1, etcetera toget s0, s1, etcetera; this gives an interior-point weight of 1 asbefore.  For i->infinity, this should converge to the weights frombefore.  Avoiding division by zero is more tricky, because the weightat j=0 is not necessarily zero, due to the interpolation.  It might bebetter to pre-include the dV in the weight for edge elements, withappropriate logic in the IVEC_LOOP_WEIGHT macro.  Tricky.The above is also not correct for integrals that cross x=0, becauseit should really be the integral of f(x) |x|.  Even interior pointsprobably need special handling in that case.  For sanity, we wouldjust divide the integration region into positive and negative r andintegrate them separately somehow.  Grrr.2) one grid point between a and b.x  |    x   |    xi  a   i+1  b   i+2integral = f_i [-w0^3 / 3 + (i+1) w0^2 / 2]                 <- s0 i      + f_{j=i+1} [w0^3 / 3 - (j+1) w0^2 / 2 + j w0 +                  -w1^3 / 3 - (j-1) w1^2 / 2 + j w1]        <- {s1,e1} (i+1)      + f_{j=i+2} [w1^3 / 3 + (j-1) w1^2 / 2]               <- e0 (i+2)3) no grid points between a and b.x  |      |    xi  a      b   i+1integral = f_i [-w0^3/3 + (i+1) w0^2/2              + -w1^3/3 - (i-1) w1^2/2 + i w1 - i/2 - 1/6]  <- s0 i   + f_{j=i+1} [ w0^3/3 - (j+1) w0^2/2 + j w0              +  w1^3/3 + (j-1) w1^2/2 - j/2 + 1/6]         <- e0 (i+1)4) as (3), but a = b: interpolation, not integration: same as above****************************************************************************/namespace meep {/* The following two functions convert a vec to the nearest ivec   in the dielectric (odd-coordinate) grid, either rounding down (floor)   or up (ceil).  In the special case where a component of the vec is   *exactly* on a component of the ivec, we add the corresponding   component of equal_shift (which should be either -2, 0, or +2).   (equal_shift is there to prevent us from counting edge points twice.) */   static ivec vec2diel_floor(const vec &v, double a, const ivec &equal_shift) {  ivec iv(v.dim);  LOOP_OVER_DIRECTIONS(v.dim, d) {    iv.set_direction(d, 1+2*int(floor(v.in_direction(d)*a-.5)));    if (iv.in_direction(d) == v.in_direction(d))      iv.set_direction(d, iv.in_direction(d) + equal_shift.in_direction(d));  }  return iv;}static ivec vec2diel_ceil(const vec &v, double a, const ivec &equal_shift) {  ivec iv(v.dim);  LOOP_OVER_DIRECTIONS(v.dim, d) {    iv.set_direction(d, 1+2*int(ceil(v.in_direction(d)*a-.5)));    if (iv.in_direction(d) == v.in_direction(d))      iv.set_direction(d, iv.in_direction(d) + equal_shift.in_direction(d));  }  return iv;}static inline int iabs(int i) { return (i < 0 ? -i : i); }/* Generic function for computing loops within the chunks, often   integral-like things, over a volume WHERE.  The job of this   function is to call CHUNKLOOP() for each chunk that intersects   WHERE, passing it the chunk, the range of integer coordinates to   loop over, the integration weights for the boundary points, and the   bloch phase shift, translational shift, and symmetry operation to   transform the chunk to the actual integration location.  (N.B.   we apply the symmetry first to the chunk, *then* the shift.)   We also pass CHUNKLOOP() dV0 and dV1, such that the integration   "volume" dV is dV0 + dV1 * iloopR, where iloopR is the loop   variable (starting from 0 at the starting integer coord and   incrementing by 1) corresponding to the direction R.  Note that, in   the LOOP_OVER_IVECS macro, iloopR corresponds to the loop variable   loop_i2 in Dcyl (cylindrical coordinates).  In other coordinates,   dV1 is 0.  Note also that by "volume" dV we mean the integration   unit corresponding to the dimensionality of WHERE (e.g. an area if   WHERE is 2d, etc.)   In particular, the loop's point coordinates are calculated on the   Yee grid for component cgrid.  cgrid == Dielectric is a good choice   if you want to work with a combination of multiple field   components, because all of the field components can be interpolated   onto this grid without communication between chunks.   The integration weights are chosen to correspond to integrating the   linear interpolation of the function values from these grid points.   For a simple example of an chunkloop routine, see the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -