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

📄 h5fields.cpp

📁 麻省理工的计算光子晶体的程序
💻 CPP
字号:
/* 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, 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.*//* HDF5 output of fields and arbitrary functions thereof.  Works   very similarly to integrate.cpp (using fields::loop_in_chunks). */#include <stdio.h>#include <string.h>#include <math.h>#include "meep_internals.hpp"namespace meep {/***************************************************************************/typedef struct {  // information related to the HDF5 dataset (its size, etcetera)  h5file *file;  ivec min_corner, max_corner;  int num_chunks;  double *buf;  int bufsz;  int rank;  direction ds[3];  int reim; // whether to output the real or imaginary part  // the function to output and related info (offsets for averaging, etc.)  int num_fields;  const component *components;  component *cS;  complex<double> *ph;  complex<double> *fields;  int *offsets;  int ninveps;  component inveps_cs[3];  direction inveps_ds[3];  int inveps_offsets[6];  complex<long double> sum;  double maxabs;  field_function fun;  void *fun_data_;} h5_output_data;static void h5_findsize_chunkloop(fields_chunk *fc, int ichnk, component cgrid,				  ivec is, ivec ie,				  vec s0, vec s1, vec e0, vec e1,				  double dV0, double dV1,				  ivec shift, complex<double> shift_phase,				  const symmetry &S, int sn,				  void *data_){  h5_output_data *data = (h5_output_data *) data_;  ivec isS = S.transform(is, sn) + shift;  ivec ieS = S.transform(ie, sn) + shift;  data->min_corner = min(data->min_corner, min(isS, ieS));  data->max_corner = max(data->max_corner, max(isS, ieS));  data->num_chunks++;  int bufsz = 1;  LOOP_OVER_DIRECTIONS(fc->v.dim, d)    bufsz *= (ie.in_direction(d) - is.in_direction(d)) / 2 + 1;  data->bufsz = max(data->bufsz, bufsz);}static void h5_output_chunkloop(fields_chunk *fc, int ichnk, component cgrid,				ivec is, ivec ie,				vec s0, vec s1, vec e0, vec e1,				double dV0, double dV1,				ivec shift, complex<double> shift_phase,				const symmetry &S, int sn,				void *data_){  h5_output_data *data = (h5_output_data *) data_;  //-----------------------------------------------------------------------//  // Find output chunk dimensions and strides, etc.  int start[3]={0,0,0}, count[3]={1,1,1};  int offset[3]={0,0,0}, stride[3]={1,1,1};  ivec isS = S.transform(is, sn) + shift;  ivec ieS = S.transform(ie, sn) + shift;    // figure out what yucky_directions (in LOOP_OVER_IVECS)  // correspond to what directions in the transformed vectors (in output).  ivec permute(zero_ivec(fc->v.dim));  for (int i = 0; i < 3; ++i)     permute.set_direction(fc->v.yucky_direction(i), i);  permute = S.transform_unshifted(permute, sn);  LOOP_OVER_DIRECTIONS(permute.dim, d)    permute.set_direction(d, abs(permute.in_direction(d)));    // compute the size of the chunk to output, and its strides etc.  for (int i = 0; i < data->rank; ++i) {    direction d = data->ds[i];    int isd = isS.in_direction(d), ied = ieS.in_direction(d);    start[i] = (min(isd, ied) - data->min_corner.in_direction(d)) / 2;    count[i] = abs(ied - isd) / 2 + 1;    int j = permute.in_direction(d);    if (ied < isd) offset[permute.in_direction(d)] = count[i] - 1;  }  for (int i = 0; i < data->rank; ++i) {    direction d = data->ds[i];    int j = permute.in_direction(d);    for (int k = i + 1; k < data->rank; ++k) stride[j] *= count[k];    offset[j] *= stride[j];    if (offset[j]) stride[j] *= -1;  }    //-----------------------------------------------------------------------//  // Compute the function to output, exactly as in fields::integrate,  // except that here we store its values in a buffer instead of integrating.  int *off = data->offsets;  component *cS = data->cS;  complex<double> *fields = data->fields, *ph = data->ph;  complex<long double> sum = 0.0;  double maxabs = 0;  const component *iecs = data->inveps_cs;  const direction *ieds = data->inveps_ds;  int *ieos = data->inveps_offsets;  for (int i = 0; i < data->num_fields; ++i) {    cS[i] = S.transform(data->components[i], -sn);    if (cS[i] == Dielectric)      ph[i] = 1.0;    else {      fc->v.yee2diel_offsets(cS[i], off[2*i], off[2*i+1]);      ph[i] = shift_phase * S.phase_shift(cS[i], sn);    }  }  for (int k = 0; k < data->ninveps; ++k)    fc->v.yee2diel_offsets(iecs[k], ieos[2*k], ieos[2*k+1]);  vec rshift(shift * (0.5*fc->v.inva));  LOOP_OVER_IVECS(fc->v, is, ie, idx) {    IVEC_LOOP_LOC(fc->v, loc);    loc = S.transform(loc, sn) + rshift;    for (int i = 0; i < data->num_fields; ++i) {      if (cS[i] == Dielectric) {	double tr = 0.0;	for (int k = 0; k < data->ninveps; ++k)	  tr += (fc->s->inveps[iecs[k]][ieds[k]][idx]		 + fc->s->inveps[iecs[k]][ieds[k]][idx+ieos[2*k]]		 + fc->s->inveps[iecs[k]][ieds[k]][idx+ieos[1+2*k]]		 + fc->s->inveps[iecs[k]][ieds[k]][idx+ieos[2*k]+ieos[1+2*k]]);	fields[i] = (4 * data->ninveps) / tr;      }      else {	double f[2];	for (int k = 0; k < 2; ++k)	  if (fc->f[cS[i]][k])	    f[k] = 0.25 * (fc->f[cS[i]][k][idx]			   + fc->f[cS[i]][k][idx+off[2*i]]			   + fc->f[cS[i]][k][idx+off[2*i+1]]			   + fc->f[cS[i]][k][idx+off[2*i]+off[2*i+1]]);	  else	    f[k] = 0;	fields[i] = complex<double>(f[0], f[1]) * ph[i];      }    }    complex<double> fun = data->fun(fields, loc, data->fun_data_);    int idx2 = ((((offset[0] + offset[1] + offset[2])		  + loop_i1 * stride[0]) 		 + loop_i2 * stride[1]) + loop_i3 * stride[2]);    data->buf[idx2] = data->reim ? imag(fun) : real(fun);  }  //-----------------------------------------------------------------------//  data->file->write_chunk(data->rank, start, count, data->buf);}void fields::output_hdf5(h5file *file, const char *dataname,			 int num_fields, const component *components,			 field_function fun, void *fun_data_, int reim,			 const geometric_volume &where,			 bool append_data,                         bool single_precision) {  am_now_working_on(FieldOutput);  h5_output_data data;  data.file = file;  data.min_corner = v.round_vec(where.get_max_corner()) + one_ivec(v.dim);  data.max_corner = v.round_vec(where.get_min_corner()) - one_ivec(v.dim);  data.num_chunks = 0;  data.bufsz = 0;  data.reim = reim;  loop_in_chunks(h5_findsize_chunkloop, (void *) &data, 	    where, Dielectric, true, true);  data.max_corner = max_to_all(data.max_corner);  data.min_corner = -max_to_all(-data.min_corner); // i.e., min_to_all  data.num_chunks = sum_to_all(data.num_chunks);  if (data.num_chunks == 0 || !(data.min_corner <= data.max_corner))    return; // no data to write;  int rank = 0, dims[3];  LOOP_OVER_DIRECTIONS(v.dim, d) {    if (rank >= 3) abort("too many dimensions in output_hdf5");    int n = (data.max_corner.in_direction(d)	     - data.min_corner.in_direction(d)) / 2 + 1;    if (n > 1) {      data.ds[rank] = d;      dims[rank++] = n;    }  }  data.rank = rank;  file->create_or_extend_data(dataname, rank, dims,                              append_data, single_precision);  data.buf = new double[data.bufsz];  data.num_fields = num_fields;  data.components = components;  data.cS = new component[num_fields];  data.ph = new complex<double>[num_fields];  data.fields = new complex<double>[num_fields];  data.sum = 0;  data.maxabs = 0;  data.fun = fun;  data.fun_data_ = fun_data_;  /* compute inverse-epsilon directions for computing Dielectric fields */  data.ninveps = 0;  bool needs_dielectric = false;  for (int i = 0; i < num_fields; ++i)    if (components[i] == Dielectric) { needs_dielectric = true; break; }  if (needs_dielectric)     FOR_ELECTRIC_COMPONENTS(c) if (v.has_field(c)) {      if (data.ninveps == 3) abort("more than 3 field components??");      data.inveps_cs[data.ninveps] = c;      data.inveps_ds[data.ninveps] = component_direction(c);      ++data.ninveps;    }    data.offsets = new int[2 * num_fields];  for (int i = 0; i < 2 * num_fields; ++i)    data.offsets[i] = 0;    loop_in_chunks(h5_output_chunkloop, (void *) &data, 		 where, Dielectric, true, true);  delete[] data.offsets;  delete[] data.fields;  delete[] data.ph;  delete[] data.cS;  delete[] data.buf;  file->done_writing_chunks();  finished_working();}/***************************************************************************/void fields::output_hdf5(const char *dataname,                         int num_fields, const component *components,                         field_function fun, void *fun_data_,                         const geometric_volume &where,			 h5file *file,                         bool append_data,                         bool single_precision,			 const char *prefix,			 bool real_part_only){  bool delete_file;  if ((delete_file = !file))    file = open_h5file(dataname, h5file::WRITE, prefix, true);  if (real_part_only) {    output_hdf5(file, dataname, num_fields, components, fun, fun_data_, 		0, where, append_data, single_precision);  }  else {    int len = strlen(dataname) + 5;    char *dataname2 = new char[len];    snprintf(dataname2, len, "%s%s", dataname, ".r");    output_hdf5(file, dataname2, num_fields, components, fun, fun_data_, 		0, where, append_data, single_precision);    snprintf(dataname2, len, "%s%s", dataname, ".i");    output_hdf5(file, dataname2, num_fields, components, fun, fun_data_, 		1, where, append_data, single_precision);    delete[] dataname2;  }  if (delete_file) delete file;}/***************************************************************************/typedef struct {  field_rfunction fun;  void *fun_data_;} rintegrand_data;static complex<double> rintegrand_fun(const complex<double> *fields,                                     const vec &loc,                                     void *data_){  rintegrand_data *data = (rintegrand_data *) data_;  return data->fun(fields, loc, data->fun_data_);}void fields::output_hdf5(const char *dataname,                         int num_fields, const component *components,                         field_rfunction fun, void *fun_data_,                         const geometric_volume &where,			 h5file *file,                         bool append_data,                         bool single_precision,			 const char *prefix){  bool delete_file;  if ((delete_file = !file))    file = open_h5file(dataname, h5file::WRITE, prefix, true);  rintegrand_data data; data.fun = fun; data.fun_data_ = fun_data_;  output_hdf5(file, dataname, num_fields, components, rintegrand_fun,	      (void *) &data, 0, where, append_data, single_precision);  if (delete_file) delete file;}/***************************************************************************/static complex<double> component_fun(const complex<double> *fields,				     const vec &loc,				     void *data_){     (void) loc; // unused     (void) data_; // unused     return fields[0];}void fields::output_hdf5(component c,			 const geometric_volume &where,			 h5file *file,			 bool append_data,                         bool single_precision,			 const char *prefix) {  if (is_derived(int(c))) {    output_hdf5(derived_component(c), 		where, file, append_data, single_precision, prefix);    return;  }  if (coordinate_mismatch(v.dim, c)) return;  char dataname[256];  bool has_imag = !is_real && c != Dielectric;  bool delete_file;  if ((delete_file = !file))    file = open_h5file(component_name(c), h5file::WRITE, prefix, true);  snprintf(dataname, 256, "%s%s", component_name(c), has_imag ? ".r" : "");  output_hdf5(file, dataname, 1, &c, component_fun, 0, 0, where,	      append_data, single_precision);  if (has_imag) {    snprintf(dataname, 256, "%s.i", component_name(c));    output_hdf5(file, dataname, 1, &c, component_fun, 0, 1, where,		append_data, single_precision);  }  if (delete_file) delete file;}/***************************************************************************/void fields::output_hdf5(derived_component c,			 const geometric_volume &where,			 h5file *file,			 bool append_data,                         bool single_precision,			 const char *prefix) {  if (!is_derived(int(c))) {    output_hdf5(component(c), 		where, file, append_data, single_precision, prefix);    return;  }  if (coordinate_mismatch(v.dim, c)) return;  int nfields;  component cs[6];  field_rfunction fun = derived_component_func(c, v, nfields, cs);  output_hdf5(component_name(c), nfields, cs, fun, &nfields, where,	      file, append_data, single_precision, prefix);}/***************************************************************************/const char *fields::h5file_name(const char *name, 				const char *prefix, bool timestamp){  const int buflen = 1024;  static char filename[buflen];  char time_step_string[32] = "";  if (timestamp) snprintf(time_step_string, 32, "-%09.2f", time());  snprintf(filename, buflen, "%s/" "%s%s" "%s" "%s" ".h5",	   outdir,	   prefix ? prefix : "", prefix && prefix[0] ? "-" : "",	   name, time_step_string);  return filename;}h5file *fields::open_h5file(const char *name, h5file::access_mode mode, 			    const char *prefix, bool timestamp){  const char *filename = h5file_name(name, prefix, timestamp);  if (!quiet && mode == h5file::WRITE)    master_printf("creating output file \"%s\"...\n", filename);  return new h5file(filename, mode, true);}} // namespace meep

⌨️ 快捷键说明

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