NanoComp / meep

free finite-difference time-domain (FDTD) software for electromagnetic simulations
GNU General Public License v2.0
1.19k stars 605 forks source link

MultilevelAtom level populations #2558

Open jakazaplotnik opened 1 year ago

jakazaplotnik commented 1 year ago

Within the Multilevel Atomic Susceptibility extension, it would be extremely useful if, in addition to electric and magnetic fields, level populations ($N_1(x,y,z,t)$, $N_2(x,y,z,t)$ ... ) could also be monitored and, for example, exported to a NumPy array or a text file.

What would need to be done in the code to make this possible? Is there any simple solution? If yes, I would be grateful for some guidance.

Thanks, Jaka

oskooi commented 6 months ago

Currently, the population levels N are a property of the internal state of the multilevel_susceptibility class and stored as a member of the C++ struct multilevel_data defined in src/multilevel-atom.cpp:

https://github.com/NanoComp/meep/blob/995c7178021df872b41eb8aea298b2cc7bcd5b4a/src/multilevel-atom.cpp#L119-L128

These population levels are updated at each timestep as part of the update of the polarization fields in multilevel_susceptibility::update_P:

https://github.com/NanoComp/meep/blob/995c7178021df872b41eb8aea298b2cc7bcd5b4a/src/multilevel-atom.cpp#L319-L325

update_P in turn is invoked at each timestep from fields::update_pols in src/update_pols.cpp which in turn invokes update_P for each fields_chunk.

To provide the functionality to access the instantaneous population levels is not straightforward because of the way support for the various susceptibility features (Lorentzian, gyrotropic, multilevel, white noise) are set up as derived classes of a generic base class susceptibility:

https://github.com/NanoComp/meep/blob/995c7178021df872b41eb8aea298b2cc7bcd5b4a/src/meep.hpp#L340-L346

One approach would be to add a new public member function realnum* fields::get_population_levels(field_type ft) which invokes realnum* fields_chunk::get_population_levels(field_type ft which invokes realnum* multilevel_susceptibility::get_population_levels(void *internal_P_data) which (finally) has access to the internal state and the information we need to return.

Once these C++ functions are all set up, we would then provide a Python type map in python/meep.i for realnum* fields::get_population_levels to map the C++ array return value to a Numpy array.