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

📄 step.cpp

📁 来自mit的fdtd开放性源代码meep
💻 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.*/#include <stdio.h>#include <stdlib.h>#include <math.h>#include "meep.hpp"#include "meep_internals.hpp"#include "config.h"#ifdef HAVE_MPI#include <mpi.h>#endif#define RESTRICTnamespace meep {void fields::step() {  // however many times the fields have been synched, we want to restore now  int save_synchronized_magnetic_fields = synchronized_magnetic_fields;  if (synchronized_magnetic_fields) {    synchronized_magnetic_fields = 1; // reset synchronization count    restore_magnetic_fields();  }   am_now_working_on(Stepping);  if (!t) {    last_step_output_wall_time = wall_time();    last_step_output_t = t;  }  if (!quiet && wall_time() > last_step_output_wall_time + MIN_OUTPUT_TIME) {    master_printf("on time step %d (time=%g), %g s/step\n", t, time(), 		  (wall_time() - last_step_output_wall_time) / 		  (t - last_step_output_t));    if (save_synchronized_magnetic_fields)      master_printf("  (doing expensive timestepping of synched fields)\n");    last_step_output_wall_time = wall_time();    last_step_output_t = t;  }  phase_material();    // update cached conductivity-inverse array, if needed  for (int i=0;i<num_chunks;i++) chunks[i]->s->update_condinv();  calc_sources(time()); // for B sources  step_db(B_stuff);  if (!disable_sources) step_b_source();  step_boundaries(B_stuff);  update_h_from_b();  step_boundaries(H_stuff);  // because step_boundaries overruns the timing stack...  am_now_working_on(Stepping);  if (fluxes) fluxes->update_half();  calc_sources(time() + 0.5*dt); // for D sources  step_db(D_stuff);  if (!disable_sources) step_d_source();  step_boundaries(D_stuff);  calc_sources(time() + dt); // for integrated E sources  update_e_from_d();  step_boundaries(E_stuff);  // because step_boundaries overruns the timing stack...  am_now_working_on(Stepping);  update_from_e();  step_boundaries(P_stuff);  if (fluxes) fluxes->update();  t += 1;  update_dfts();  finished_working();  // re-synch magnetic fields if they were previously synchronized  if (save_synchronized_magnetic_fields) {    synchronize_magnetic_fields();    synchronized_magnetic_fields = save_synchronized_magnetic_fields;  }}double fields_chunk::peek_field(component c, const vec &where) {  double w[8];  ivec ilocs[8];  v.interpolate(c,where, ilocs, w);  if (v.contains(ilocs[0]) && f[c][0]) {    double hello = 0.0;    if (is_mine()) hello = f[c][0][v.index(c,ilocs[0])];    broadcast(n_proc(), &hello, 1);    return hello;  }  //abort("Got no such %s field at %g %g!\n",  //      component_name(c), v[ilocs[0]].x(), v[ilocs[0]].y());  return 0.0;}void fields::phase_material() {  if (phasein_time > 0) {    for (int i=0;i<num_chunks;i++)      if (chunks[i]->is_mine())	chunks[i]->phase_material(phasein_time);    step_boundaries(E_stuff);    phasein_time--;  }}void fields_chunk::phase_material(int phasein_time) {  if (new_s && phasein_time > 0) {    changing_structure();    s->mix_with(new_s, 1.0/phasein_time);    update_e_from_d(); // ensure E = 1/eps * D  }}void fields::step_boundaries(field_type ft) {  connect_chunks(); // re-connect if !chunk_connections_valid  am_now_working_on(MpiTime);  // Do the metals first!  for (int i=0;i<num_chunks;i++)    if (chunks[i]->is_mine()) chunks[i]->zero_metal(ft);  /* Note that the copying of data to/from buffers is order-sensitive,     and must be kept consistent with the code in boundaries.cpp.     In particular, we require that boundaries.cpp set up the connections     array so that all of the connections for process i come before all     of the connections for process i' for i < i'  */  // First copy outgoing data to buffers...  for (int j=0;j<num_chunks;j++)    if (chunks[j]->is_mine()) {      int wh[3] = {0,0,0};      for (int i=0;i<num_chunks;i++) {	const int pair = j+i*num_chunks;	int n0 = 0;	for (int ip=0;ip<3;ip++) {	  for (int n=0;n<comm_sizes[ft][ip][pair];n++)	    comm_blocks[ft][pair][n0 + n] =	      *(chunks[j]->connections[ft][ip][Outgoing][wh[ip]++]);	  n0 += comm_sizes[ft][ip][pair];	}      }    }  // Communicate the data around!#if 0 // This is the blocking version, which should always be safe!  for (int noti=0;noti<num_chunks;noti++)    for (int j=0;j<num_chunks;j++) {      const int i = (noti+j)%num_chunks;      const int pair = j+i*num_chunks;      DOCMP {        send(chunks[j]->n_proc(), chunks[i]->n_proc(),             comm_blocks[ft][pair], comm_size_tot(ft,pair));      }    }#endif#ifdef HAVE_MPI  const int maxreq = num_chunks*num_chunks;  MPI_Request *reqs = new MPI_Request[maxreq];  MPI_Status *stats = new MPI_Status[maxreq];  int reqnum = 0;  int *tagto = new int[count_processors()];  for (int i=0;i<count_processors();i++) tagto[i] = 0;  for (int noti=0;noti<num_chunks;noti++)    for (int j=0;j<num_chunks;j++) {      const int i = (noti+j)%num_chunks;      const int pair = j+i*num_chunks;      const int comm_size = comm_size_tot(ft,pair);      if (comm_size > 0) {	if (chunks[j]->is_mine() && !chunks[i]->is_mine())	  MPI_Isend(comm_blocks[ft][pair], comm_size,		    MPI_DOUBLE, chunks[i]->n_proc(),		    tagto[chunks[i]->n_proc()]++,		    MPI_COMM_WORLD, &reqs[reqnum++]);	if (chunks[i]->is_mine() && !chunks[j]->is_mine())	  MPI_Irecv(comm_blocks[ft][pair], comm_size,		    MPI_DOUBLE, chunks[j]->n_proc(),		    tagto[chunks[j]->n_proc()]++,		    MPI_COMM_WORLD, &reqs[reqnum++]);      }    }  delete[] tagto;  if (reqnum > maxreq) abort("Too many requests!!!\n");  if (reqnum > 0) MPI_Waitall(reqnum, reqs, stats);  delete[] reqs;  delete[] stats;#endif    // Finally, copy incoming data to the fields themselves, multiplying phases:  for (int i=0;i<num_chunks;i++)    if (chunks[i]->is_mine()) {      int wh[3] = {0,0,0};      for (int j=0;j<num_chunks;j++) {        const int pair = j+i*num_chunks;	connect_phase ip = CONNECT_PHASE;        for (int n = 0; n < comm_sizes[ft][ip][pair]; n += 2, wh[ip] += 2) {          const double phr = real(chunks[i]->connection_phases[ft][wh[ip]/2]);          const double phi = imag(chunks[i]->connection_phases[ft][wh[ip]/2]);          *(chunks[i]->connections[ft][ip][Incoming][wh[ip]]) =            phr*comm_blocks[ft][pair][n] - phi*comm_blocks[ft][pair][n+1];          *(chunks[i]->connections[ft][ip][Incoming][wh[ip]+1]) =            phr*comm_blocks[ft][pair][n+1] + phi*comm_blocks[ft][pair][n];        }	int n0 = comm_sizes[ft][ip][pair];	ip = CONNECT_NEGATE;        for (int n = 0; n < comm_sizes[ft][ip][pair]; ++n)          *(chunks[i]->connections[ft][ip][Incoming][wh[ip]++])	    = -comm_blocks[ft][pair][n0 + n];	n0 += comm_sizes[ft][ip][pair];	ip = CONNECT_COPY;        for (int n = 0; n < comm_sizes[ft][ip][pair]; ++n)          *(chunks[i]->connections[ft][ip][Incoming][wh[ip]++])	    = comm_blocks[ft][pair][n0 + n];      }    }  finished_working();}void fields::step_b_source(int including_integrated) {  for (int i=0;i<num_chunks;i++)    if (chunks[i]->is_mine())      chunks[i]->step_b_source(chunks[i]->b_sources, including_integrated);}void fields_chunk::step_b_source(src_vol *sv, int including_integrated) {  if (sv == NULL) return;  component c = direction_component(Bx, component_direction(sv->c));  if (f[c][0] && is_magnetic(sv->c))    for (int j=0; j<sv->npts; j++) {      const complex<double> A = sv->current(j) * dt;      const int i = sv->index[j];      f[c][0][i] -= real(A);      if (!is_real) f[c][1][i] -= imag(A);    }  step_b_source(sv->next, including_integrated);}void fields::step_d_source(int including_integrated) {  for (int i=0;i<num_chunks;i++)    if (chunks[i]->is_mine())      chunks[i]->step_d_source(chunks[i]->d_sources, including_integrated);}void fields_chunk::step_d_source(src_vol *sv, int including_integrated) {  if (sv == NULL) return;  component c = direction_component(Dx, component_direction(sv->c));  if ((including_integrated || !sv->t->is_integrated)      && f[c][0] && is_electric(sv->c)) {    for (int j=0; j<sv->npts; j++) {      const complex<double> A = sv->current(j) * dt;      const int i = sv->index[j];      f[c][0][i] -= real(A);      if (!is_real) f[c][1][i] -= imag(A);    }  }  step_d_source(sv->next, including_integrated);}void fields::calc_sources(double tim) {  for (src_time *s = sources; s; s = s->next) s->update(tim, dt);  for (int i=0;i<num_chunks;i++)    if (chunks[i]->is_mine())      chunks[i]->calc_sources(tim);}void fields_chunk::calc_sources(double time) {  (void) time; // unused;}} // namespace meep

⌨️ 快捷键说明

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