Hello everyone,
I am currently building a radiative transfer code to calculate synthetic spectra. The way this works is by having a big table containing the parameter of each line, for example line center nu0, intensity S and lineshape width Width
LineParams =
nu0 S Width ...
--------- ------- -----------
2356 5.3e-20 3.2
2359 6.7e-19 7.2
...
I have a Voigt profile function VoigtProfile which takes as input the parameters of the lineshape from LineParams and an array of frequencies as the x axis nu, returning the spectral line.
For now, this is achieved with a for loop where a finite range of the x axis is taken to compute the lineshape
S = [0.53, 6.7] * 10^(-19);
LineParams = table(nu0, S, Width);
Spectrum = zeros(length(nu), 1)
for i = 1:length(LineParams.S)
TempWidth = LineParams.Width(i)
Tempnu0 = LineParams.nu0(i)
nuRangeLogic = (nu >= Tempnu0 - 3*TempWidth & nu <= Tempnu0 + 3*TempWidth)
Spectrum(nuRangeLogic) = Spectrum(nuRangeLogic) + VoigtProfile(TempS, Tempnu0, Tempwidth, nu(nuRangeLogic));
function Out = VoigtProfile(S, nu0, Width, X)
Out = S .* normpdf(X, nu0, Width);
The great amount of lines and the high point density required for the spectrum make this implementation very slow. One idea was to implement Parallel Computing to split the load into different workers, hence reducing the amount of time required.
However, is not very clear to me how to proceed. I followed some suggestions from the Matlab editor and read some documentation, resulting in the following implementation
parfor i = 1:length(LineParams.S)
TempWidth = LineParams.Width(i)
Tempnu0 = LineParams.nu0(i)
Spectrum = Spectrum + VoigtProfile(TempS, Tempnu0, Tempwidth, nu);
Because of how parfor works, I had to ditch the logical indexing, so the lineshape must be computed on the whole array, which may be even more time-consuming (~100.000 points)!
Is there any better and more orthodox implementation for this case?
Thank you all for any help.