From d923c464147eeee20147d431ba48cb6ca368df5a Mon Sep 17 00:00:00 2001 From: Jiri Janos Date: Thu, 27 Nov 2025 14:25:29 +0100 Subject: [PATCH 1/2] Upgrading readme and PDAW weights analysis README.md updated with possibility to use polarization of the field (prompted by colleagues from the group). PDAW analysis of the weights was not very consistent. I've now modified it such that it makes more sense. --- README.md | 5 +++++ src/promdens/promdens.py | 29 +++++++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b93744f..14fb02a 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,11 @@ This index is used in the output to specify the selected position-momentum pairs The following columns come in pairs for each excited state: the first column contains the excitation energy while the second column bears the magnitudes of the transition dipole moment. Note that the header is not mandatory in the input file. We will use this input file in the following examples and refer to it as `input_file.dat`. +> [!NOTE] +> **Laser field polarization:** Both PDA and PDAW were derived to account for a linear laser field polarization. Although **PROMDENS** does not take the polarization vector $\vec{E}_0$ as a parameter, it can still account for the laser field polarization implicitly through the user input: the user just needs to provide the projection of the transition dipole moments to the laser field polarization $|\vec{\mu}_{0i}\cdot \vec{E}_0|$ in the input file instead of the magnitude $|\vec{\mu}_{0i}|$ as suggested above. In this manner, the code will account for a linearly polarized laser field. Note that if you provide $|\vec{\mu}_{0i}\cdot \vec{E}_0|$, the absorption spectrum calculated by **PROMDENS** corresponds to an effective absorption spectrum seen by the polarized laser pulse, not to the standard absorption spectrum measured in experiments. + +TODO: problem with absorption spectrum. Maybe I can revert all the changes in the absorption spectrum calculation and leave only the changes in the PDA/PDAW part? + ## Usage The code requires information about the method (PDA or PDAW, `--method`), the number of excited states to consider (`--nstates`), the number of initial conditions to be generated (`--npsamples`), and the characteristics of the laser pulse, such as the envelope type diff --git a/src/promdens/promdens.py b/src/promdens/promdens.py index f45f1ec..b6f5ae3 100755 --- a/src/promdens/promdens.py +++ b/src/promdens/promdens.py @@ -537,9 +537,8 @@ def windowing(self, output_fname='pdaw.dat'): to an output file. """ - print("* Generating weights and convolution for windowing.") + print("* Generating weights and convolution for PDAW.") - # determine and print convolution function # determine and print convolution function conv_eq = { 'gauss' : "I(t) = exp(-4*ln(2)*(t-t0)^2/fwhm^2)", @@ -551,7 +550,7 @@ def windowing(self, output_fname='pdaw.dat'): f" - Parameters: fwhm = {self.pulse.fwhm/self.fstoau:.3f} fs, " f"t0 = {self.pulse.t0/self.fstoau:.3f} fs") - print(" - Calculating normalized weights:") + print(" - Calculating weights") # creating a field for weights self.weights = np.zeros((self.nstates, self.nsamples)) # sample index, weights in different states @@ -559,17 +558,23 @@ def windowing(self, output_fname='pdaw.dat'): for state in range(0, self.nstates): self.weights[state] = self.tdm[state]**2*np.interp(self.de[state], self.field_ft_omega, self.field_ft)**2 + # normalization of all the weights + print(" - Normalization of the weights (sum of all weights equals 1)") + self.weights /= np.sum(self.weights) + + # analysis of the weights + print(" - Analysis of the normalized weights for each state:") + for state in range(0, self.nstates): + # sorting from the largest weight to smallest + state_sum = np.sum(self.weights[state, :]) + sorted = np.sort(self.weights[state, :]/state_sum)[::-1] # analysis - sorted = np.sort(self.weights[state, :]/np.sum(self.weights[state, :]))[ - ::-1] # sorting from the largest weight to smallest print( - f" > State {state + 1} - analysis of normalized weights (weights/sum of weights on state {state + 1}):\n" + f" > State {state + 1}:\n" + f" - State contribution: {state_sum * 100:.3f} %\n" f" - Largest weight: {np.max(self.weights[state, :]):.3e}\n" - f" - Number of ICs making up 90% of S{state + 1} weights: {np.sum(np.cumsum(sorted) < 0.9) + 1:d}\n" - f" - Number of ICs with weights bigger than 0.001: {np.sum(self.weights[state, :] > 0.001):d}") - - # normalization of weights at given state - self.weights /= np.sum(self.weights) + f" - Number of ICs with weights > 0.001: {np.sum(self.weights[state, :] > 0.001):d}\n" + f" - Number of ICs making up 90% of S{state + 1} weights: {np.sum(np.cumsum(sorted) < 0.9) + 1:d}") # creating a variable for printing with first column being sample indexes arr_print = np.zeros((self.nstates + 1, self.nsamples)) # index, weights in different states @@ -584,7 +589,7 @@ def windowing(self, output_fname='pdaw.dat'): f"index {weights_str}") np.savetxt(output_fname, arr_print.T, fmt=['%8d'] + ['%16.5e']*self.nstates, header=header) - print(f" - Weights saved to file '{output_fname}'") + print(f" - Weights (normalized) saved to file '{output_fname}'") def plot_spectrum(ics: InitialConditions) -> None: From b4b604de5453048f4934ff662cf93d6396fd70c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Jano=C5=A1?= <88504448+JanosJiri@users.noreply.github.com> Date: Thu, 27 Nov 2025 14:52:08 +0100 Subject: [PATCH 2/2] Revise laser field polarization note in README GitHub's markdown is unable to show vectors and absolute values normally; it turns them into columns somehow. This stupid way of splitting equations into parts is the only way I could force GitHub to show the correct equation. There are other solutions, but they are typically not compatible with other renderers. --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 14fb02a..67ddad5 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,7 @@ The following columns come in pairs for each excited state: the first column con We will use this input file in the following examples and refer to it as `input_file.dat`. > [!NOTE] -> **Laser field polarization:** Both PDA and PDAW were derived to account for a linear laser field polarization. Although **PROMDENS** does not take the polarization vector $\vec{E}_0$ as a parameter, it can still account for the laser field polarization implicitly through the user input: the user just needs to provide the projection of the transition dipole moments to the laser field polarization $|\vec{\mu}_{0i}\cdot \vec{E}_0|$ in the input file instead of the magnitude $|\vec{\mu}_{0i}|$ as suggested above. In this manner, the code will account for a linearly polarized laser field. Note that if you provide $|\vec{\mu}_{0i}\cdot \vec{E}_0|$, the absorption spectrum calculated by **PROMDENS** corresponds to an effective absorption spectrum seen by the polarized laser pulse, not to the standard absorption spectrum measured in experiments. - -TODO: problem with absorption spectrum. Maybe I can revert all the changes in the absorption spectrum calculation and leave only the changes in the PDA/PDAW part? +> **Laser field polarization:** Both PDA and PDAW were derived to account for a linear laser field polarization. Although **PROMDENS** does not take the polarization vector $`\vec{E}_0`$ as a parameter, it can still account for the laser field polarization implicitly through the user input: the user just needs to provide the projection of the transition dipole moments to the laser field polarization |$`\vec{\mu}_{0i}`$ $\cdot$ $`\vec{E}_0`$| in the input file instead of the magnitude |$`\vec{\mu}_{0i}`$| as suggested above. In this manner, the code will account for a linearly polarized laser field. Note that if you provide |$`\vec{\mu}_{0i}`$ $\cdot$ $`\vec{E}_0`$|, the absorption spectrum calculated by **PROMDENS** corresponds to an effective absorption spectrum seen by the polarized laser pulse, not to the standard absorption spectrum measured in experiments. ## Usage The code requires information about the method (PDA or PDAW, `--method`), the number of excited states to consider (`--nstates`),