Exemplo n.º 1
0
StateVector BoundaryModuleDrivenBase::getBoundary( const StateVector& Reference, const char dim, const double t){
    // TODO Make the boundary both transmissive and driven.
    //      As it stands, it is possible to generate instabilities when backscattered waves meet the boundary.
    (void)Reference;
    double driventerm = getDrivenTerm(t);
    StateVector Boundary;

    // Set to zero
    Boundary = ZEROSTATE;

    // Calculate driven part
    double electric, magnetic;
    magnetic = driventerm;
    electric = c_eta0 * magnetic;

    // Add to boundary
    switch(dim){
        case 'x':
            switch(mPOL){
                case TE: 
                    Boundary.Ey() += electric;
                    Boundary.Hz() += magnetic;
                    break;
                case TM:
                    Boundary.Ez() += electric;
                    Boundary.Hy() += magnetic;
                    break;
            }
            break;
        case 'y':
            switch(mPOL){
                case TE: 
                    Boundary.Ex() += electric;
                    Boundary.Hz() += magnetic;
                    break;
                case TM:
                    Boundary.Ez() += electric;
                    Boundary.Hx() += magnetic;
                    break;
            }
            break;
    }
    
    return Boundary;
}
Exemplo n.º 2
0
void FT_Controller::exec(){

    // Temporary function: should be replaced with something sturdier
    // Perhaps implement an 'overseer' class that controls the solver, which data should be printed, when to print, etc.

    // Get length of a single period
    Setting& BoundCfg = mCfg.lookup("Boundaries");
    int BoundSize = BoundCfg.getLength();
    double freq = 0.;
    double T;
    for( int ii=0; ii<BoundSize; ii++){
        Setting& thisCfg = BoundCfg[ii];
        try{
            Setting& params = thisCfg.lookup("params");
            freq = params.lookup("frequency");
        } catch(const std::exception&) {}
    }
    if( freq == 0.){
        std::cerr << "ERROR: zero frequency" << std::endl;
        exit(EXIT_FAILURE);
    } else {
        T = 2*M_PI/freq;
    }
    // Get circle center
    Setting& InitCfg = mCfg.lookup("Initialisation");
    Setting& CircleCfg = InitCfg.lookup("Circle");
    double circleX, circleY;
    circleX = CircleCfg.lookup("params.center.x");
    circleY = CircleCfg.lookup("params.center.y");

    // Get number of time steps in single period
    // Assumes constant timestep. Valid for free-space Maxwell's equations, but not always true otherwise.
    int N = ceil(T/mSolver.pTimer->dt());
    
    std::cout << "Frequency: " << freq << std::endl;
    std::cout << "Period: " << T << std::endl;
    std::cout << "Timestep: " << mSolver.pTimer->dt() << std::endl;
    std::cout << "Number of timesteps per period: " << N << std::endl;

    // Determine number of cells in the near-field near PEC
    int n_cells = 0;
    int x_start = mSolver.pGrid->startX();
    int x_end   = mSolver.pGrid->endX();
    int y_start = mSolver.pGrid->startY();
    int y_end   = mSolver.pGrid->endY();
    BoundaryGeometry Boundary;
    double levelset;
    for( int ii=x_start; ii<x_end; ii++){
        for( int jj=y_start; jj<y_end; jj++){
            Boundary = mSolver.pGrid->boundary(ii,jj);
            levelset = mSolver.pGrid->levelset(ii,jj);
            if( Boundary.isCut() ) n_cells++;
        }
    }

    // Populate phi vector in the order that near-field cells are detected
    std::vector<double> Phi(n_cells);
    double phi;
    double x, y;
    int kk=0;
    for( int ii=x_start; ii<x_end; ii++){
        for( int jj=y_start; jj<y_end; jj++){
            Boundary = mSolver.pGrid->boundary(ii,jj);
            levelset = mSolver.pGrid->levelset(ii,jj);
            if( Boundary.isCut() ){
                x = (ii-mSolver.pGrid->bound()+0.5)*mSolver.pGrid->dx()-circleX;
                y = (jj-mSolver.pGrid->bound()+0.5)*mSolver.pGrid->dy()-circleY;
                phi = atan2(y,x) * 180 / M_PI;
                if(phi>=0.){
                    Phi[kk] = phi;
                } else {
                    Phi[kk] = 360 + phi;
                }
                kk++;
            }  
        }
    }

    // Advance 10 full periods. This is enough time for the system to reach steady state
    while( mSolver.pTimer->t() < 10*T ) mSolver.advance();

    // Set N to power of 2
    int new_N = 1;
    while(new_N<N) new_N*=2;
    mSolver.pTimer->setDt(T/new_N);
    N = new_N;
    std::cout << "Calibrated number of timesteps per period: " << N << std::endl;

    // Set up storage
    std::vector<double> allTimeDomain( N*n_cells); // Stores time domain data at all cells
    std::vector<double> TimeDomainReal(N); // Stores real time domain data at a single grid location
    std::vector<double> TimeDomainImag(N); // Stores imaginary time domain data at a single grid location (all zeroes)
    std::vector<double> FreqDomainReal(N); // Stores real frequency domain data at a single grid location
    std::vector<double> FreqDomainImag(N); // Stores imaginary frequency domain data at a single grid location
    std::vector<double> Amplitude(n_cells); // Stores amplitude of frequency domain data


    // Iterate over another full period, storing data at each time step
    int cells = 0;
    StateVector State;
    for( int timestep = 0; timestep < N; timestep++){
        if(timestep>0) mSolver.advance();
        for( int ii=x_start; ii<x_end; ii++){
            for( int jj=y_start; jj<y_end; jj++){
                Boundary = mSolver.pGrid->boundary(ii,jj);
                levelset = mSolver.pGrid->levelset(ii,jj);
                if( Boundary.isCut() ){
                    State = mSolver.pGrid->state(ii,jj);
                    allTimeDomain[ cells*N + timestep] = State.Hz();
                    cells++;
                }  
            }
        }
        cells = 0;
    }

    // Fourier transform one point at a time and print;
    FT_Module FT(N);
    double realpart;
    double imagpart;
    std::ofstream PEC_test_file("PEC_test_file.dat");
    for( cells=0; cells<n_cells; cells++){
        
        // copy allTimeDomain into TimeDomain
        for( int timestep=0; timestep<N; timestep++){
            TimeDomainReal[timestep] = allTimeDomain[ cells*N + timestep];
            TimeDomainImag[timestep] = 0.;
        }
        
        // Perform Fourier transform
        FT.exec( TimeDomainReal, TimeDomainImag, FreqDomainReal, FreqDomainImag);
        realpart = 2*FreqDomainReal[1]/N;
        imagpart = 2*FreqDomainImag[1]/N;

        // Calculate amplitude
        Amplitude[cells] = sqrt(realpart*realpart + imagpart*imagpart);
    }

    // Get normalising constant
    double max=1.0;//0.;
   /* for( cells=0; cells<n_cells; cells++){
        max = (Amplitude[cells] > max) ? Amplitude[cells] : max;
    }*/

    // Print normalised data
    for( cells=0; cells<n_cells; cells++){
        PEC_test_file << Phi[cells]           << '\t'
                      << Amplitude[cells]/max << std::endl;   
    }
(void)levelset;
    return;

}