thliebig / openEMS

openEMS is a free and open-source electromagnetic field solver using the EC-FDTD method.
http://openEMS.de
GNU General Public License v3.0
459 stars 156 forks source link

Dump Time Resolution #143

Open ALEEF02 opened 4 months ago

ALEEF02 commented 4 months ago

Good afternoon,

I've scoured the docs, and I don't see a way to increase the quantity of frames included in a time-domain dump (e.g. E-field). SetTimeStepFactor does not increase the quantity of data dumped, only the timestep. OverSampling also doesn't do the trick.

Please let me know what you think.

JTSvejda commented 4 months ago

Hello,

With FDTD, the time step is the applied time increment for the simulation. In order to store the E-field, for example, in a shorter interval than the time step sample, the time step must be adjusted accordingly, i.e. reduced.

Regarding the function SetTimeStepFactor: Following the comment from the file openEMS/python/openEMS/openEMS.pyx, it should be possible to reduce the time step with this function.

With the function SetOverSampling, I think it is not possible to go below the time step.

If you want to save fields for an animation, but the simulation runs cleanly with a sampling rate (or time step) greater than that used for the animation, you might as an alternative interpolate the fields in time.

ALEEF02 commented 4 months ago

SetTimeStepFactor does indeed reduce the timestep, but the number of dump frames generated stays the same. i.e., setting timestep to 1 will generate ~50 frames of E-field dump in my sim. Setting timestep to 0.5 doubles the run time, but still generates ~50 frames of E-field data.

jeremyrumpf commented 1 week ago

I just came onto this issue when trying to create an animation. From a cursory search of the code, it appears that field dumps occur around the nyquist rate or at the process step positions.

An internal variable named: m_FD_Interval indicates the number of timesteps to meet the nyquist rate. Decreasing the timestep value simply increases the m_FD_Interval. So this stays fixed based upon excitation.

In the output, nyquist rate:

FDTD simulation size: 413x428x251 --> 4.4367e+07 FDTD cells FDTD timestep is: 1.88218e-13 s; Nyquist rate: 1518 timesteps @1.75e+09 Hz

Dumps appear to also occur at predefined process step positions, internally identified in m_ProcessSteps:

this is set in openems.cpp:

    //add all timesteps to end-crit field processing with max excite amplitude
    unsigned int maxExcite = FDTD_Op->GetExcitationSignal()->GetMaxExcitationTimestep();
//  for (unsigned int n=0; n<FDTD_Op->Exc->Volt_Count; ++n)
//      ProcField->AddStep(FDTD_Op->Exc->Volt_delay[n]+maxExcite);
    ProcField->AddStep(maxExcite);

Not digging too deep, the Volt_delay may be the peak time of the excitation? Not sure... But the commented code would seem to indicate that adding other steps here may be feasible?

This is all tied together in processing.cpp. CheckTimestep() is used by the field dumps to trigger a dump:

bool Processing::CheckTimestep()
{
    unsigned int ts = m_Eng_Interface->GetNumberOfTimesteps();
    if (ts<startTS || ts>stopTS)
        return false;
    if (m_ProcessSteps.size()>m_PS_pos)
    {
        if (m_ProcessSteps.at(m_PS_pos)==ts)
        {
            ++m_PS_pos;
            return true;
        }
    }
    if (ProcessInterval)
    {
        if (ts%ProcessInterval==0) return true;
    }

    if (m_FD_Interval)
    {
        if (ts%m_FD_Interval==0) return true;
    }
    return false;
}

TLDR would be that the field dump rate is tied to the excitation frequency or the max excitation frequency in the gaussian case. I could stand corrected though, but I don't think there is currently a way to influence this directly. Nor is my understanding of the internals enough to know if it is ultimately possible.

jeremyrumpf commented 1 week ago

Ok, looking further, I may have a solution. In the above, we can influence the ProcessInterval. Which is, by default, also tied to the nyquist rate. The way to do this is to set excitation oversampling. Oversampling appears to default to a value of 4, so be sure to set a value above this. In python this would be set like:

FDTD = openEMS(EndCriteria=1e-4,NrTS=500000, TimeStepFactor=0.5)
FDTD.SetSinusExcite(f0)
FDTD.SetOverSampling(8)
FDTD.SetBoundaryCond( ['PML_8', 'PML_8', 'PML_8', 'PML_8', 'PML_8', 'PML_8'] )

Thus we should see the process interval decrease via the simulation output.

With the default oversampling value of 4 i see dumps at timesteps of:

379 758 1137 1516 1895

Changing oversampling to a value of 8 i see dumps at timesteps of:

189 378 567 756 945 ...

This appears to be the needed trick. Hope this helps someone along the way...