@@ -362,8 +362,14 @@ cvector3 to_geom_object_coords_VJP(cvector3 v, const geometric_object *o) {
362362 /* case geometric_object::CYLINDER:
363363 NOT YET IMPLEMENTED */
364364 case geometric_object::BLOCK : {
365- vector3 v_real = cvector3_re (v);
366- vector3 v_imag = cvector3_im (v);
365+ /* In order to leverage the underlying libctl infrastructure
366+ *and* the dual library that makes computing derivatives so easy,
367+ me perform a bit of a trick: we use the *complex* libctl vector,
368+ storing the real and dual parts of the dual library and *manually*
369+ propagate the dual through existing libraries as needed.
370+ */
371+ vector3 v_real = cvector3_re (v); // real part
372+ vector3 v_imag = cvector3_im (v); // "dual" part
367373
368374 vector3 size = o->subclass .block_data ->size ;
369375 if (size.x != 0.0 ) {v_real.x /= size.x ; v_imag.x /= size.x ;}
@@ -379,6 +385,9 @@ cvector3 to_geom_object_coords_VJP(cvector3 v, const geometric_object *o) {
379385}
380386
381387cvector3 material_grid_grad (vector3 p, material_data *md, const geometric_object *o) {
388+ /* computes the actual spatial gradient at point `p`
389+ for the specified material grid `md`. */
390+
382391 if (!is_material_grid (md)) {meep::abort (" Invalid material grid detected.\n " ); }
383392
384393 cvector3 gradient = cvector_zero ();
@@ -468,6 +477,14 @@ void map_lattice_coordinates(double &px, double &py, double &pz) {
468477}
469478
470479cvector3 matgrid_grad (vector3 p, geom_box_tree tp, int oi, material_data *md) {
480+ /* loops through all the material grids at a current point
481+ and computes the final *spatial* gradient (w.r.t. x,y,z)
482+ after all appropriate transformations (e.g. due to
483+ overlapping grids). Calls the helper function, `material_grid_grad`,
484+ which is what actually computes the spatial gradient.
485+ */
486+
487+ // check for proper overlapping grids
471488 if (md->material_grid_kinds == material_data::U_MIN ||
472489 md->material_grid_kinds == material_data::U_PROD )
473490 meep::abort (" %s:%i:matgrid_grad does not support overlapping grids with U_MIN or U_PROD\n " ,__FILE__,__LINE__);
@@ -493,6 +510,7 @@ cvector3 matgrid_grad(vector3 p, geom_box_tree tp, int oi, material_data *md) {
493510 ++matgrid_val_count;
494511 }
495512
513+ // compensate for overlapping grids
496514 if (md->material_grid_kinds == material_data::U_MEAN )
497515 gradient = cvector3_scale (1.0 /matgrid_val_count,gradient);
498516
@@ -1250,12 +1268,11 @@ duals::duald get_material_grid_fill(meep::ndim dim, duals::duald d, double r, du
12501268 return -1.0 ; // garbage fill
12511269 } else {
12521270 if (dim == meep::D1 )
1253- rel_fill = (r-d)/(2 *r);
1254- else if (dim == meep::D2 || dim == meep::Dcyl){
1255- rel_fill = (1 /(r*r*meep::pi)) * (r*r*acos (d/r)-d*sqrt (r*r-d*d));
1256- }
1271+ return (r-d)/(2 *r);
1272+ else if (dim == meep::D2 || dim == meep::Dcyl)
1273+ return (1 /(r*r*meep::pi)) * (r*r*acos (d/r)-d*sqrt (r*r-d*d));
12571274 else if (dim == meep::D3 )
1258- rel_fill = (((r-d)*(r-d))/(4 *meep::pi*r*r*r))*(2 *r+d);
1275+ return (((r-d)*(r-d))/(4 *meep::pi*r*r*r))*(2 *r+d);
12591276 }
12601277
12611278 return rel_fill;
@@ -1593,20 +1610,7 @@ void geom_epsilon::fallback_chi1inv_row(meep::component c, double chi1inv_row[3]
15931610 material =
15941611 (material_type)material_of_unshifted_point_in_tree_inobject (p, restricted_tree, &inobject);
15951612 material_data *md = material;
1596- meep::vec gradient (zero_vec (v.dim ));
1597- double uval = 0 ;
1598- // TODO cleanup and remove
1599- if (md->which_subclass == material_data::MATERIAL_GRID ) {
1600- geom_box_tree tp;
1601- int oi;
1602- tp = geom_tree_search (p, restricted_tree, &oi);
1603- // gradient = matgrid_grad(p, tp, oi, md);
1604- // uval = matgrid_val(p, tp, oi, md)+this->u_p;
1605- }
1606- else {
1607- gradient = normal_vector (meep::type (c), v);
1608- }
1609-
1613+ meep::vec gradient = normal_vector (meep::type (c), v);
16101614 get_material_pt (material, v.center ());
16111615 material_epsmu (meep::type (c), material, &chi1p1, &chi1p1_inv);
16121616 material_gc (material);
@@ -1634,73 +1638,47 @@ void geom_epsilon::fallback_chi1inv_row(meep::component c, double chi1inv_row[3]
16341638 integer errflag;
16351639 double meps, minveps;
16361640
1637- if (md->which_subclass == material_data::MATERIAL_GRID ) {
1638- number xmin[1 ], xmax[1 ];
1639- matgrid_volavg mgva;
1640- mgva.dim = v.dim ;
1641- mgva.ugrad_abs = meep::abs (gradient);
1642- mgva.uval = uval;
1643- mgva.rad = v.diameter ()/2 ;
1644- mgva.beta = md->beta ;
1645- mgva.eta = md->eta ;
1646- mgva.eps1 = (md->medium_1 .epsilon_diag .x +md->medium_1 .epsilon_diag .y +md->medium_1 .epsilon_diag .z )/3 ;
1647- mgva.eps2 = (md->medium_2 .epsilon_diag .x +md->medium_2 .epsilon_diag .y +md->medium_2 .epsilon_diag .z )/3 ;
1648- xmin[0 ] = -v.diameter ()/2 ;
1649- xmax[0 ] = v.diameter ()/2 ;
1650- #ifdef CTL_HAS_COMPLEX_INTEGRATION
1651- cnumber ret = cadaptive_integration (matgrid_ceps_func, xmin, xmax, 1 , (void *)&mgva, 0 , tol, maxeval,
1652- &esterr, &errflag);
1653- meps = ret.re ;
1654- minveps = ret.im ;
1655- #else
1656- meps = adaptive_integration (matgrid_eps_func, xmin, xmax, 1 , (void *)&mgva, 0 , tol, maxeval, &esterr,
1657- &errflag);
1658- minveps = adaptive_integration (matgrid_inveps_func, xmin, xmax, 1 , (void *)&mgva, 0 , tol, maxeval, &esterr,
1659- &errflag);
1660- #endif
1641+ integer n;
1642+ number xmin[3 ], xmax[3 ];
1643+ vector3 gvmin, gvmax;
1644+ gvmin = vec_to_vector3 (v.get_min_corner ());
1645+ gvmax = vec_to_vector3 (v.get_max_corner ());
1646+ xmin[0 ] = gvmin.x ;
1647+ xmax[0 ] = gvmax.x ;
1648+ if (dim == meep::Dcyl) {
1649+ xmin[1 ] = gvmin.z ;
1650+ xmin[2 ] = gvmin.y ;
1651+ xmax[1 ] = gvmax.z ;
1652+ xmax[2 ] = gvmax.y ;
16611653 }
16621654 else {
1663- integer n;
1664- number xmin[3 ], xmax[3 ];
1665- vector3 gvmin, gvmax;
1666- gvmin = vec_to_vector3 (v.get_min_corner ());
1667- gvmax = vec_to_vector3 (v.get_max_corner ());
1668- xmin[0 ] = gvmin.x ;
1669- xmax[0 ] = gvmax.x ;
1670- if (dim == meep::Dcyl) {
1671- xmin[1 ] = gvmin.z ;
1672- xmin[2 ] = gvmin.y ;
1673- xmax[1 ] = gvmax.z ;
1674- xmax[2 ] = gvmax.y ;
1675- }
1676- else {
1677- xmin[1 ] = gvmin.y ;
1678- xmin[2 ] = gvmin.z ;
1679- xmax[1 ] = gvmax.y ;
1680- xmax[2 ] = gvmax.z ;
1681- }
1682- if (xmin[2 ] == xmax[2 ])
1683- n = xmin[1 ] == xmax[1 ] ? 1 : 2 ;
1684- else
1685- n = 3 ;
1686- double vol = 1 ;
1687- for (int i = 0 ; i < n; ++i)
1688- vol *= xmax[i] - xmin[i];
1689- if (dim == meep::Dcyl) vol *= (xmin[0 ] + xmax[0 ]) * 0.5 ;
1690- eps_ever_negative = 0 ;
1691- func_ft = meep::type (c);
1655+ xmin[1 ] = gvmin.y ;
1656+ xmin[2 ] = gvmin.z ;
1657+ xmax[1 ] = gvmax.y ;
1658+ xmax[2 ] = gvmax.z ;
1659+ }
1660+ if (xmin[2 ] == xmax[2 ])
1661+ n = xmin[1 ] == xmax[1 ] ? 1 : 2 ;
1662+ else
1663+ n = 3 ;
1664+ double vol = 1 ;
1665+ for (int i = 0 ; i < n; ++i)
1666+ vol *= xmax[i] - xmin[i];
1667+ if (dim == meep::Dcyl) vol *= (xmin[0 ] + xmax[0 ]) * 0.5 ;
1668+ eps_ever_negative = 0 ;
1669+ func_ft = meep::type (c);
16921670#ifdef CTL_HAS_COMPLEX_INTEGRATION
1693- cnumber ret = cadaptive_integration (ceps_func, xmin, xmax, n, (void *)this , 0 , tol, maxeval,
1694- &esterr, &errflag);
1695- meps = ret.re / vol;
1696- minveps = ret.im / vol;
1671+ cnumber ret = cadaptive_integration (ceps_func, xmin, xmax, n, (void *)this , 0 , tol, maxeval,
1672+ &esterr, &errflag);
1673+ meps = ret.re / vol;
1674+ minveps = ret.im / vol;
16971675#else
1698- meps = adaptive_integration (eps_func, xmin, xmax, n, (void *)this , 0 , tol, maxeval, &esterr,
1699- &errflag) / vol;
1700- minveps = adaptive_integration (inveps_func, xmin, xmax, n, (void *)this , 0 , tol, maxeval, &esterr,
1701- &errflag) / vol;
1676+ meps = adaptive_integration (eps_func, xmin, xmax, n, (void *)this , 0 , tol, maxeval, &esterr,
1677+ &errflag) / vol;
1678+ minveps = adaptive_integration (inveps_func, xmin, xmax, n, (void *)this , 0 , tol, maxeval, &esterr,
1679+ &errflag) / vol;
17021680#endif
1703- }
1681+
17041682 if (eps_ever_negative) // averaging negative eps causes instability
17051683 minveps = 1.0 / (meps = eps (v.center ()));
17061684 {
0 commit comments