📄 h5fields.cpp
字号:
/* Copyright (C) 2005-2008 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 ninvmu; component invmu_cs[3]; direction invmu_ds[3]; complex<long double> sum; field_function fun; void *fun_data_;} h5_output_data;#define UNUSED(x) (void) x // silence compiler warningsstatic 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_){ UNUSED(ichnk);UNUSED(cgrid);UNUSED(s0);UNUSED(s1);UNUSED(e0);UNUSED(e1); UNUSED(dV0);UNUSED(dV1);UNUSED(shift_phase); 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_){ UNUSED(ichnk);UNUSED(cgrid);UNUSED(s0);UNUSED(s1);UNUSED(e0);UNUSED(e1); UNUSED(dV0);UNUSED(dV1); 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; 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; const component *iecs = data->inveps_cs; const direction *ieds = data->inveps_ds; int ieos[6]; const component *imcs = data->invmu_cs; const direction *imds = data->invmu_ds; int imos[6]; for (int i = 0; i < data->num_fields; ++i) { cS[i] = S.transform(data->components[i], -sn); if (cS[i] == Dielectric || cS[i] == Permeability) 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]); for (int k = 0; k < data->ninvmu; ++k) fc->v.yee2diel_offsets(imcs[k], imos[2*k], imos[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 if (cS[i] == Permeability) { double tr = 0.0; for (int k = 0; k < data->ninvmu; ++k) { const double *im = fc->s->invmu[imcs[k]][imds[k]]; if (im) tr += (im[idx] + im[idx+imos[2*k]] + im[idx+imos[1+2*k]] + im[idx+imos[2*k]+imos[1+2*k]]); else tr += 4; // default invmu == 1 } fields[i] = (4 * data->ninvmu) / 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); file->prevent_deadlock(); // can't hold a lock since *_to_all is collective 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -