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

📄 structure.cpp

📁 麻省理工的计算光子晶体的程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "meep-ctl.hpp"#include <ctlgeom.h>using namespace ctlio;#define master_printf meep::master_printf#define MTS material_type_structstatic meep::ndim dim = meep::D3;/***********************************************************************/void set_dimensions(int dims){  if (dims == CYLINDRICAL) {    dimensions = 2;    dim = meep::Dcyl;  }  else {    dimensions = dims;    dim = meep::ndim(dims - 1);  }}vector3 vec_to_vector3(const meep::vec &v){  vector3 v3;    switch (v.dim) {  case meep::D1:    v3.x = 0;    v3.y = 0;    v3.z = v.z();    break;  case meep::D2:    v3.x = v.x();    v3.y = v.y();    v3.z = 0;    break;  case meep::D3:    v3.x = v.x();    v3.y = v.y();    v3.z = v.z();    break;  case meep::Dcyl:    v3.x = v.r();    v3.y = 0;    v3.z = v.z();    break;  }  return v3;}meep::vec vector3_to_vec(const vector3 v3){  switch (dim) {  case meep::D1:    return meep::vec(v3.z);  case meep::D2:    return meep::vec(v3.x, v3.y);  case meep::D3:    return meep::vec(v3.x, v3.y, v3.z);  case meep::Dcyl:    return meep::veccyl(v3.x, v3.z);  default:    meep::abort("unknown dimensionality in vector3_to_vec");  }}static geom_box gv2box(const meep::geometric_volume &gv){  geom_box box;  box.low = vec_to_vector3(gv.get_min_corner());  box.high = vec_to_vector3(gv.get_max_corner());  return box;}/***********************************************************************/class geom_epsilon : public meep::material_function {  geometric_object_list geometry;  geom_box_tree geometry_tree;  geom_box_tree restricted_tree;  public:  geom_epsilon(geometric_object_list g,	       const meep::geometric_volume &gv);  virtual ~geom_epsilon();    virtual void set_volume(const meep::geometric_volume &gv);  virtual void unset_volume(void);  virtual double eps(const meep::vec &r);  virtual bool has_chi3();  virtual double chi3(const meep::vec &r);  virtual bool has_chi2();  virtual double chi2(const meep::vec &r);  virtual meep::vec normal_vector(const meep::geometric_volume &gv);  virtual void meaneps(double &meps, double &minveps, meep::vec &normal,		       const meep::geometric_volume &gv, 		       double tol, int maxeval);  void fallback_meaneps(double &meps, double &minveps,			const meep::geometric_volume &gv,			double tol, int maxeval);  virtual double sigma(const meep::vec &r);  void add_polarizabilities(meep::structure *s);};geom_epsilon::geom_epsilon(geometric_object_list g,			   const meep::geometric_volume &gv){  geometry = g; // don't bother making a copy, only used in one place    if (meep::am_master()) {    for (int i = 0; i < geometry.num_items; ++i) {      display_geometric_object_info(5, geometry.items[i]);            if (geometry.items[i].material.which_subclass 	  == MTS::DIELECTRIC)	printf("%*sdielectric constant epsilon = %g\n",	       5 + 5, "",	       geometry.items[i].material.	       subclass.dielectric_data->epsilon);    }  }    geom_fix_objects0(geometry);  geom_box box = gv2box(gv);  geometry_tree = create_geom_box_tree0(geometry, box);  if (verbose && meep::am_master()) {    printf("Geometric-object bounding-box tree:\n");    display_geom_box_tree(5, geometry_tree);        int tree_depth, tree_nobjects;    geom_box_tree_stats(geometry_tree, &tree_depth, &tree_nobjects);    master_printf("Geometric object tree has depth %d "		  "and %d object nodes (vs. %d actual objects)\n",		  tree_depth, tree_nobjects, geometry.num_items);  }    restricted_tree = geometry_tree;}geom_epsilon::~geom_epsilon(){  unset_volume();  destroy_geom_box_tree(geometry_tree);}void geom_epsilon::unset_volume(void){  if (restricted_tree != geometry_tree) {    destroy_geom_box_tree(restricted_tree);    restricted_tree = geometry_tree;  }}void geom_epsilon::set_volume(const meep::geometric_volume &gv){  unset_volume();    geom_box box = gv2box(gv);  restricted_tree = create_geom_box_tree0(geometry, box);}static material_type eval_material_func(function material_func, vector3 p){  SCM pscm = ctl_convert_vector3_to_scm(p);  material_type material;  SCM mo;    mo = gh_call1(material_func, pscm);  material_type_input(mo, &material);    while (material.which_subclass == MTS::MATERIAL_FUNCTION) {    material_type m;        mo = gh_call1(material.subclass.		  material_function_data->material_func,		  pscm);    material_type_input(mo, &m);    material_type_destroy(material);    material = m;  }    if (material.which_subclass == MTS::MATERIAL_TYPE_SELF) {    material_type_copy(&default_material, &material);  }  CK(material.which_subclass != MTS::MATERIAL_FUNCTION,     "infinite loop in material functions");    return material;}static int variable_material(int which_subclass){     return (which_subclass == MTS::MATERIAL_FUNCTION);}static void material_eps(material_type material, double &eps, double &eps_inv) {  switch (material.which_subclass) {  case MTS::DIELECTRIC:    eps = material.subclass.dielectric_data->epsilon;    eps_inv = 1.0 / eps;    break;  case MTS::PERFECT_METAL:    eps = -meep::infinity;    eps_inv = -0.0;    break;  default:    meep::abort("unknown material type");  }}double geom_epsilon::eps(const meep::vec &r){  double eps = 1.0, eps_inv;  vector3 p = vec_to_vector3(r);#ifdef DEBUG  if (p.x < restricted_tree->b.low.x ||      p.y < restricted_tree->b.low.y ||      p.z < restricted_tree->b.low.z ||      p.x > restricted_tree->b.high.x ||      p.y > restricted_tree->b.high.y ||      p.z > restricted_tree->b.high.z)    meep::abort("invalid point (%g,%g,%g)\n", p.x,p.y,p.z);#endif  boolean inobject;  material_type material =    material_of_unshifted_point_in_tree_inobject(p, restricted_tree, &inobject);    int destroy_material = 0;  if (material.which_subclass == MTS::MATERIAL_TYPE_SELF) {    material = default_material;  }  if (variable_material(material.which_subclass)) {    material = eval_material_func(material.subclass.				  material_function_data->material_func,				  p);    destroy_material = 1;  }  material_eps(material, eps, eps_inv);      if (destroy_material)    material_type_destroy(material);    return eps;}/* Find frontmost object in gv, along with the constant material behind it.   Returns false if material behind the object is not constant.      Requires moderately horrifying logic to figure things out properly,   stolen from MPB. */static bool get_front_object(const meep::geometric_volume &gv,			     geom_box_tree geometry_tree,			     vector3 &pcenter,			     const geometric_object **o_front,			     vector3 &shiftby_front,			     material_type &mat_front,			     material_type &mat_behind) {  vector3 p;  const geometric_object *o1 = 0, *o2 = 0;  vector3 shiftby1, shiftby2;  geom_box pixel;  material_type mat1, mat2;  int id1 = -1, id2 = -1;  const int num_neighbors[3] = { 3, 5, 9 };  const int neighbors[3][9][3] = {    { {0,0,0}, {-1,0,0}, {1,0,0},      {0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0} },    { {0,0,0},      {-1,-1,0}, {1,1,0}, {-1,1,0}, {1,-1,0},      {0,0,0},{0,0,0},{0,0,0},{0,0,0} },    { {0,0,0},      {1,1,1},{1,1,-1},{1,-1,1},{1,-1,-1},      {-1,1,1},{-1,1,-1},{-1,-1,1},{-1,-1,-1} }  };   pixel = gv2box(gv);  pcenter = p = vec_to_vector3(gv.center());  double d1, d2, d3;  d1 = (pixel.high.x - pixel.low.x) * 0.5;  d2 = (pixel.high.y - pixel.low.y) * 0.5;  d3 = (pixel.high.z - pixel.low.z) * 0.5;  for (int i = 0; i < num_neighbors[dimensions - 1]; ++i) {    const geometric_object *o;    material_type mat;    vector3 q, shiftby;    int id;    q.x = p.x + neighbors[dimensions - 1][i][0] * d1;    q.y = p.y + neighbors[dimensions - 1][i][1] * d2;    q.z = p.z + neighbors[dimensions - 1][i][2] * d3;    o = object_of_point_in_tree(q, geometry_tree, &shiftby, &id);    if ((id == id1 && vector3_equal(shiftby, shiftby1)) ||	(id == id2 && vector3_equal(shiftby, shiftby2)))      continue;    mat = (o && o->material.which_subclass != MTS::MATERIAL_TYPE_SELF)      ? o->material : default_material;    if (id1 == -1) {      o1 = o;      shiftby1 = shiftby;      id1 = id;      mat1 = mat;    }    else if (id2 == -1 || ((id >= id1 && id >= id2) &&			   (id1 == id2 			    || material_type_equal(&mat1,&mat2)))) {      o2 = o;      shiftby2 = shiftby;      id2 = id;      mat2 = mat;    }    else if (!(id1 < id2 && 	       (id1 == id || material_type_equal(&mat1,&mat))) &&	     !(id2 < id1 &&	       (id2 == id || material_type_equal(&mat2,&mat))))      return false;  }  // CHECK(id1 > -1, "bug in object_of_point_in_tree?");  if (id2 == -1) { /* only one nearby object/material */    id2 = id1;    o2 = o1;    mat2 = mat1;    shiftby2 = shiftby1;  }  if ((o1 && variable_material(o1->material.which_subclass)) ||      (o2 && variable_material(o2->material.which_subclass)) ||      (variable_material(default_material.which_subclass)       && (!o1 || !o2 ||	   o1->material.which_subclass == MTS::MATERIAL_TYPE_SELF ||	   o2->material.which_subclass == MTS::MATERIAL_TYPE_SELF)))    return false;  if (id1 >= id2) {    *o_front = o1;    shiftby_front = shiftby1;    mat_front = mat1;    if (id1 == id2) mat_behind = mat1; else mat_behind = mat2;  }  if (id2 > id1) {    *o_front = o2;    shiftby_front = shiftby2;    mat_front = mat2;    mat_behind = mat1;  }  return true;}meep::vec geom_epsilon::normal_vector(const meep::geometric_volume &gv) {  const geometric_object *o;  material_type mat, mat_behind;  vector3 p, shiftby, normal;  if (!get_front_object(gv, geometry_tree,			p, &o, shiftby, mat, mat_behind))    return material_function::normal_vector(gv); // fallback to default  /* check for trivial case of only one object/material */  if (material_type_equal(&mat, &mat_behind))    return meep::zero_vec(gv.dim);  normal = normal_to_fixed_object(vector3_minus(p, shiftby), *o);  return vector3_to_vec(unit_vector3(normal));}void geom_epsilon::meaneps(double &meps, double &minveps, 			   meep::vec &n,			   const meep::geometric_volume &gv,			   double tol, int maxeval) {  const geometric_object *o;  material_type mat, mat_behind;  vector3 p, shiftby, normal;  if (!get_front_object(gv, geometry_tree,			p, &o, shiftby, mat, mat_behind)) {    fallback_meaneps(meps, minveps, gv, tol, maxeval);    n = material_function::normal_vector(gv);    return;  }  material_eps(mat, meps, minveps);  /* check for trivial case of only one object/material */  if (material_type_equal(&mat, &mat_behind)) {     n = meep::zero_vec(gv.dim);    return;  }    normal = normal_to_fixed_object(vector3_minus(p, shiftby), *o);  n = vector3_to_vec(unit_vector3(normal));  geom_box pixel = gv2box(gv);  pixel.low = vector3_minus(pixel.low, shiftby);  pixel.high = vector3_minus(pixel.high, shiftby);  // fixme: don't ignore maxeval?  double fill = 1.0 - box_overlap_with_object(pixel, *o, tol, maxeval);    double epsb, epsinvb;  material_eps(mat_behind, epsb, epsinvb);  meps += fill * (epsb - meps);  minveps += fill * (epsinvb - minveps);}

⌨️ 快捷键说明

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