From 539695208ed1ad8c532876ac7f7759c9790e2b48 Mon Sep 17 00:00:00 2001 From: Homer Reid Date: Fri, 18 May 2018 19:10:30 -0400 Subject: [PATCH] Prisms (#341) * set initial-guess k vector to bloch vector for get_eigenmode_coefficients in periodic geometries * updates to periodic get_eigenmode_coefficient * pulled changes from master * updates * updates * updated libmeepgeom/bend-flux-ll to define geometry using libctl prisms instead of traditional blocks if new command-line flag is present --- libmeepgeom/bend-flux-ll.cpp | 83 +++++++++----- mkdocs.yml | 8 +- src/dft.cpp | 216 ++++++++++++++++++++++++++--------- src/meep.hpp | 6 +- src/near2far.cpp | 17 +-- src/stress.cpp | 12 +- 6 files changed, 236 insertions(+), 106 deletions(-) diff --git a/libmeepgeom/bend-flux-ll.cpp b/libmeepgeom/bend-flux-ll.cpp index 5619c43bc..99ae7a6ff 100644 --- a/libmeepgeom/bend-flux-ll.cpp +++ b/libmeepgeom/bend-flux-ll.cpp @@ -41,7 +41,7 @@ double dummy_eps(const vec &) { return 1.0; } /***************************************************************/ /***************************************************************/ /***************************************************************/ -void bend_flux(bool no_bend) +void bend_flux(bool no_bend, bool use_prisms) { double sx=16.0; // size of cell in X direction double sy=32.0; // size of cell in Y direction @@ -84,33 +84,57 @@ void bend_flux(bool no_bend) meep_geom::material_type dielectric = meep_geom::make_dielectric(12.0); if (no_bend) { - geometric_object objects[1]; - objects[0] = make_block(dielectric, - v3(0.0, wvg_ycen), - e1, e2, e3, - v3(ENORMOUS, w, ENORMOUS) - ); - geometric_object_list g={ 1, objects }; - meep_geom::set_materials_from_geometry(&the_structure, g); + if (use_prisms) + { vector3 vertices[4]; + vertices[0]=v3(-0.5*sx, wvg_ycen - 0.5*w, 0.0); + vertices[1]=v3(+0.5*sx, wvg_ycen - 0.5*w, 0.0); + vertices[2]=v3(+0.5*sx, wvg_ycen + 0.5*w, 0.0); + vertices[3]=v3(-0.5*sx, wvg_ycen + 0.5*w, 0.0); + double height=0.0; + vector3 axis=v3(0.0,0.0,1.0); + geometric_object objects[1]; + objects[0] = make_prism( dielectric, vertices, 4, height, axis); + geometric_object_list g={ 1, objects }; + meep_geom::set_materials_from_geometry(&the_structure, g); + } + else + { + vector3 center = v3(0.0, wvg_ycen, 0.0); + vector3 size = v3(sx, w, 0.0); + geometric_object objects[1]; + objects[0] = make_block( dielectric, center, e1, e2, e3, size ); + geometric_object_list g={ 1, objects }; + meep_geom::set_materials_from_geometry(&the_structure, g); + } } else { - geometric_object objects[2]; - objects[0] = make_block(dielectric, - v3(-0.5*pad, wvg_ycen), - e1, e2, e3, - v3(sx-pad, w, ENORMOUS) - ); - - objects[1] = make_block(dielectric, - v3(wvg_xcen, 0.5*pad), - e1, e2, e3, - v3(w, sy-pad, ENORMOUS) - ); - - geometric_object_list g={ 2, objects }; - meep_geom::set_materials_from_geometry(&the_structure, g); - }; + if (use_prisms) + { vector3 vertices[6]; + vertices[0]=v3( -0.5*sx, wvg_ycen -0.5*w); + vertices[1]=v3(wvg_xcen+0.5*w, wvg_ycen -0.5*w); + vertices[2]=v3(wvg_xcen+0.5*w, +0.5*sy); + vertices[3]=v3(wvg_xcen-0.5*w, +0.5*sy); + vertices[4]=v3(wvg_xcen-0.5*w, wvg_ycen +0.5*w); + vertices[5]=v3( -0.5*sx, wvg_ycen +0.5*w); + double height=0.0; + vector3 axis=v3(0.0,0.0,1.0); + geometric_object objects[1]; + objects[0] = make_prism( dielectric, vertices, 6, height, axis); + geometric_object_list g={ 1, objects }; + meep_geom::set_materials_from_geometry(&the_structure, g); + } + else + { + geometric_object objects[2]; + vector3 hcenter = v3(-0.5*pad, wvg_ycen), hsize = v3(sx-pad, w); + vector3 vcenter = v3(wvg_xcen, 0.5*pad), vsize = v3(w, sy-pad); + objects[0] = make_block(dielectric, hcenter, e1, e2, e3, hsize); + objects[1] = make_block(dielectric, vcenter, e1, e2, e3, vsize); + geometric_object_list g={ 2, objects }; + meep_geom::set_materials_from_geometry(&the_structure, g); + } + } fields f(&the_structure); @@ -215,8 +239,13 @@ int main(int argc, char *argv[]) { initialize mpi(argc, argv); - bend_flux(true); - bend_flux(false); + bool use_prisms=false; + for(int narg=1; narggv, is, ie, idx) + } // LOOP_OVER_IVECS(fc->gv, is, ie, idx) if (file) file->write_chunk(rank, start, file_count, buffer); return integral; - } /***************************************************************/ @@ -783,8 +782,7 @@ cdouble fields::process_dft_component(dft_chunk **chunklists, int num_chunklists reim_max = 1; } else if (pfield_array) - { *pfield_array = field_array = new cdouble[array_size]; - } + *pfield_array = field_array = new cdouble[array_size]; bool append_data = false; bool single_precision = false; @@ -798,7 +796,7 @@ cdouble fields::process_dft_component(dft_chunk **chunklists, int num_chunklists char dataname[100]; snprintf(dataname,100,"%s_%i.%c",component_name(c),num_freq, reim ? 'i' : 'r'); file->create_or_extend_data(dataname, rank, dims, append_data, single_precision); - }; + } for (int ncl=0; nclnext_in_dft) @@ -844,14 +842,126 @@ cdouble fields::process_dft_component(dft_chunk **chunklists, int num_chunklists return overlap; } +/***************************************************************/ +/***************************************************************/ +/***************************************************************/ +bool increment(int n[3], int nMax[3], int rank) +{ for(rank--; rank>=0; rank--) + if ( ++n[rank] < nMax[rank] ) + return false; + else + n[rank]=0; + return true; +} + +cdouble *collapse_empty_dimensions(cdouble *array, int *rank, int dims[3], volume dft_volume) +{ + /*--------------------------------------------------------------*/ + /*- identify empty dimensions ----------------------------------*/ + /*--------------------------------------------------------------*/ + int full_rank = *rank, reduced_rank=0, reduced_dims[3], reduced_stride[3]={1,1,1}, nd=0; + LOOP_OVER_DIRECTIONS(dft_volume.dim, d) + if (dft_volume.in_direction(d)>0.0) + reduced_dims[reduced_rank++]=dims[nd++]; + else + reduced_stride[nd++]=0; // this marks a degenerate dimension + if (reduced_rank==full_rank) return array; // nothing to collapse + + /*--------------------------------------------------------------*/ + /*- set up strides into full and reduced arrays */ + /*--------------------------------------------------------------*/ + int stride[3]={1,1,1}; // non-reduced array strides + if (full_rank==2) + { + stride[0]=dims[1]; // rstride is already all set in this case + } + else if (full_rank==3) + { stride[0] = dims[1]*dims[2]; + stride[1] = dims[2]; + if (reduced_stride[0]!=0) + reduced_stride[0]=reduced_dims[1]; + else if (reduced_stride[1]!=0) + reduced_stride[1]=reduced_dims[1]; + // else: two degenerate dimensions->reduced array is 1-diml, no strides needed + } + + /*--------------------------------------------------------------*/ + /*- allocate reduced array and compress full array into it -*/ + /*--------------------------------------------------------------*/ + int reduced_size = reduced_dims[0] * (reduced_rank==2 ? reduced_dims[1] : 1); + cdouble *reduced_array = new cdouble[reduced_size]; + if (!reduced_array) abort("%s:%i: out of memory (%i)",__FILE__,__LINE__,reduced_size); + memset(reduced_array,0,reduced_size*sizeof(cdouble)); + + int n[3]={0,0,0}; + do + { int index = n[0]*stride[0] + n[1]*stride[1] + n[2]*stride[2]; + int rindex = n[0]*reduced_stride[0] + n[1]*reduced_stride[1] + n[2]*reduced_stride[2]; + reduced_array[rindex] += array[index]; + } while ( !increment(n,dims,full_rank) ); + + *rank = reduced_rank; + dims[0] = reduced_dims[0]; + if (reduced_rank==2) dims[1]=reduced_dims[1]; + delete[] array; + return reduced_array; +} + +/***************************************************************/ +/* routines for fetching arrays of dft fields */ +/***************************************************************/ +cdouble *fields::get_dft_array(dft_flux flux, component c, int num_freq, int *rank, int dims[3]) +{ + dft_chunk *chunklists[2]; + chunklists[0] = flux.E; + chunklists[1] = flux.H; + cdouble *array; + process_dft_component(chunklists, 2, num_freq, c, 0, &array, rank, dims); + return collapse_empty_dimensions(array, rank, dims, flux.where); +} + +cdouble *fields::get_dft_array(dft_force force, component c, int num_freq, int *rank, int dims[3]) +{ + dft_chunk *chunklists[3]; + chunklists[0] = force.offdiag1; + chunklists[1] = force.offdiag2; + chunklists[2] = force.diag; + cdouble *array; + process_dft_component(chunklists, 3, num_freq, c, 0, &array, rank, dims); + return collapse_empty_dimensions(array, rank, dims, force.where); +} + +cdouble *fields::get_dft_array(dft_near2far n2f, component c, int num_freq, int *rank, int dims[3]) +{ + dft_chunk *chunklists[1]; + chunklists[0] = n2f.F; + cdouble *array; + process_dft_component(chunklists, 1, num_freq, c, 0, &array, rank, dims); + return collapse_empty_dimensions(array, rank, dims, n2f.where); +} + +cdouble *fields::get_dft_array(dft_fields fdft, component c, int num_freq, int *rank, int dims[3]) +{ + dft_chunk *chunklists[1]; + chunklists[0] = fdft.chunks; + cdouble *array; + process_dft_component(chunklists, 1, num_freq, c, 0, &array, rank, dims); + return collapse_empty_dimensions(array, rank, dims, fdft.where); +} + /***************************************************************/ /* wrapper around process_dft_component that writes HDF5 */ /* datasets for all components at all frequencies stored in */ /* the given collection of DFT chunks */ /***************************************************************/ void fields::output_dft_components(dft_chunk **chunklists, int num_chunklists, - const char *HDF5FileName) + volume dft_volume, const char *HDF5FileName) { + bool have_empty_dimensions=false; + LOOP_OVER_DIRECTIONS(dft_volume.dim, d) + if (dft_volume.in_direction(d)==0.0) + have_empty_dimensions=true; + int NumFreqs=0; for(int nc=0; nc1 ? dims[1] : 1); + double *real_array = new double[array_size]; + if (!real_array) abort("%s:%i:out of memory(%lu)",__FILE__,__LINE__,array_size); + if (am_master()) + { + h5file::access_mode mode = (first_component ? h5file::WRITE : h5file::READWRITE); + bool parallel=false, single_precision=true; + h5file f(HDF5FileName, mode, parallel); + for(int reim=0; reim<2; reim++) + { for(size_t n=0; nget_min_corner(), f.where->get_max_corner()); -} +dft_near2far::dft_near2far(const dft_near2far &f): + freq_min(f.freq_min), dfreq(f.dfreq), Nfreq(f.Nfreq), + F(f.F), eps(f.eps), mu(f.mu), where(f.where) +{ } void dft_near2far::remove() { diff --git a/src/stress.cpp b/src/stress.cpp index 50c4384c9..df5dd0faf 100644 --- a/src/stress.cpp +++ b/src/stress.cpp @@ -24,22 +24,22 @@ using namespace std; namespace meep { -dft_force::dft_force(dft_chunk *offdiag1_, dft_chunk *offdiag2_, - dft_chunk *diag_, - double fmin, double fmax, int Nf, const volume &where_) +dft_force::dft_force(dft_chunk *offdiag1_, dft_chunk *offdiag2_, dft_chunk *diag_, + double fmin, double fmax, int Nf, const volume &where_) : where(where_) { if (Nf <= 1) fmin = fmax = (fmin + fmax) * 0.5; freq_min = fmin; Nfreq = Nf; dfreq = Nf <= 1 ? 0.0 : (fmax - fmin) / (Nf - 1); offdiag1 = offdiag1_; offdiag2 = offdiag2_; diag = diag_; - where = new volume(where_.get_min_corner(), where_.get_max_corner()); + //where = new volume(where_.get_min_corner(), where_.get_max_corner()); } -dft_force::dft_force(const dft_force &f) { +dft_force::dft_force(const dft_force &f): where(f.where) +{ freq_min = f.freq_min; Nfreq = f.Nfreq; dfreq = f.dfreq; offdiag1 = f.offdiag1; offdiag2 = f.offdiag2; diag = f.diag; - where = new volume(f.where->get_min_corner(), f.where->get_max_corner()); + //where = new volume(f.where->get_min_corner(), f.where->get_max_corner()); } void dft_force::remove()