Optimizer - spectrum

[1]:
import nexus as nx
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import argrelextrema

data = np.loadtxt('reference_spectrum.txt')

detuning_reference = data[:,0]
intensity_reference = data[:,1]

plt.plot(detuning_reference, intensity_reference)
plt.xlabel('detuning (Gamma)')
plt.ylabel('rel. reflectivity')
plt.show()
../../_images/tutorial_optimization_nb_optimizer_spectrum_1_0.png
[2]:
# ------------------------- layers --------------------------
lay_Fe_top = nx.Layer(id = "Fe top",
                  material = nx.Material.Template(nx.lib.material.Fe_enriched),
                  thickness = 1)

lay_Fe_bottom = nx.Layer(id = "Fe bottom",
                  material = nx.Material.Template(nx.lib.material.Fe_enriched),
                  thickness = 1)

site = nx.Hyperfine(id = "no interactions")

lay_Fe_top.material.hyperfine_sites = [site]

lay_Fe_bottom.material.hyperfine_sites = [site]


lay_B4C_top = nx.Layer(id = "B4C top",
                   material = nx.Material.Template(nx.lib.material.B4C),
                   thickness = nx.Var(value = 4, min = 0, max = 10, fit = True, id = "B4C top"))

lay_B4C_mid = nx.Layer(id = "B4C mid",
                   material = nx.Material.Template(nx.lib.material.B4C),
                   thickness = nx.Var(value = 4, min = 0, max = 10, fit = True, id = "B4C mid"))

lay_B4C_bottom = nx.Layer(id = "B4C bottom",
                   material = nx.Material.Template(nx.lib.material.B4C),
                   thickness = nx.Var(value = 16, min = 0, max = 20, fit = True, id = "B4C top"))

# the initial guess for the top layer is 3 nm here
# set it to a Var object with reasonable bounds
lay_Pt_top = nx.Layer(id = "Pt top",
                      material = nx.Material.Template(nx.lib.material.Pt),
                      thickness = nx.Var(3.2, min = 0, max = 10, fit = True, id = "Pt top thickness"))

lay_Pt_bottom = nx.Layer(id = "Pt bottom",
                         material = nx.Material.Template(nx.lib.material.Pt),
                         thickness = 15)


lay_substrate = nx.Layer(id = "substrate",
                         material = nx.Material.Template(nx.lib.material.Si),
                         thickness = nx.inf)

cavity = nx.Sample(id = "cavity",
                   geometry = "r",
                   layers = [lay_Pt_top,
                             lay_B4C_top,
                             lay_Fe_top,
                             lay_B4C_mid,
                             lay_Fe_bottom,
                             lay_B4C_bottom,
                             lay_Pt_bottom,
                             lay_substrate],
                   angle = 0.1505)

beam  = nx.Beam()
beam.LinearSigma()

exp = nx.Experiment(beam = beam,
                    objects = cavity,
                    isotope = nx.lib.moessbauer.Fe57,
                    id = "my exp")

# initialize a reflectivity object used for the optimization
angles = np.linspace(0.01, 0.4, 1001)

reflectivity = nx.Reflectivity(experiment = exp,
                               sample = cavity,
                               energy = nx.lib.energy.Fe57,
                               angles = angles)

intensity = reflectivity()

# third minimum
min_index = np.squeeze(argrelextrema(intensity, np.less))[2]

cavity.angle = angles[min_index]

plt.semilogy(angles, intensity)
plt.xlabel('angle (Gamma)')
plt.ylabel('reflectivity')
plt.show()
../../_images/tutorial_optimization_nb_optimizer_spectrum_2_0.png
[3]:
field_int = nx.FieldIntensity(sample = cavity,
                              energy = nx.moessbauer.Fe57.energy,
                              points = 1001)

depth, int = field_int()

plt.plot(depth, int)

# add lines and labels
axes = plt.gca()
y_min, y_max = axes.get_ylim()
plt.vlines(cavity.Interfaces(), y_min, y_max, colors='g', linestyles='dashed')
for id, location in zip(cavity.Ids(), np.array(cavity.Interfaces()) + 0.5):
    plt.text(location, y_max, id, fontsize = 10)
    y_max = y_max - 0.5

plt.xlabel('depth (nm)')
plt.ylabel('relative intensity')
plt.show()
../../_images/tutorial_optimization_nb_optimizer_spectrum_3_0.png
[4]:
energy_spectrum = nx.EnergySpectrum(experiment = exp,
                                    detuning = detuning_reference,
                                    electronic = True,
                                    id = "my energy spectrum")

intensity = energy_spectrum.Calculate()

plt.plot(detuning_reference, intensity)
plt.xlabel('detuning (Gamma)')
plt.ylabel('rel. reflectivity')
plt.show()
../../_images/tutorial_optimization_nb_optimizer_spectrum_4_0.png
[5]:
# setup the optimizer
class NexusOptimizer(nx.Optimizer):
    def __init__(self, measurements, id):
        super().__init__(measurements, id)

    # the defienition of the residual calculation
    def Residual(self):
        # calculate the reflectivity to find the third minimum
        ref = reflectivity()
        # get the index of the third minimum
        # in case threre is no third minimum due to the combination of thicknesses
        if (len(argrelextrema(ref, np.less)[0]) < 3):
             return 1e30
        min_index = np.squeeze(argrelextrema(ref, np.less))[2]
        # set cavity angle to third minimum
        cavity.angle = angles[min_index]
        # calculate energy_spectrum
        intensity = energy_spectrum()
        # calculate residual
        differences = intensity - intensity_reference
        residual = np.sum(np.square(differences))
        return residual

# pass the reflectivity object to the optimizer
opt = NexusOptimizer(measurements = [reflectivity, energy_spectrum],
                     id = "opt id")

# let's just use a local gradient-free algorithm here
opt.options.method = "LevMar"

# run the optimization
opt()

plt.plot(detuning_reference, intensity_reference)
plt.plot(detuning_reference, energy_spectrum.result)
plt.xlabel('detuning (Gamma)')
plt.ylabel('rel. reflectivity')
plt.show()

Run Optimizer instance with id: opt id

Starting optimizer with 2 provided measurement dependencies and 4 fit parameter(s):

  no. |                           id |       initial value |              min |              max
    0 |             Pt top thickness |                 3.2 |                0 |               10
    1 |                      B4C top |                   4 |                0 |               10
    2 |                      B4C mid |                   4 |                0 |               10
    3 |                      B4C top |                  16 |                0 |               20

Using 0 equality constraint(s) on parameter(s):

Using 0 inequality constraint(s).

Residual start value: 12.4597


Calling ceres solver with fit method LevMar

Ceres Solver Report: Iterations: 4, Initial cost: 7.762264e+01, Final cost: 1.070671e+01, Termination: CONVERGENCE

Optimizer finished with 4 fit parameter(s):

  no. |                           id |           fit value |       initial value |              min |              max
    0 |             Pt top thickness |             4.27613 |                 3.2 |                0 |               10
    1 |                      B4C top |             4.69123 |                   4 |                0 |               10
    2 |                      B4C mid |             4.64041 |                   4 |                0 |               10
    3 |                      B4C top |             16.7134 |                  16 |                0 |               20

and 0 equality constraint(s) on parameter(s):

and 0 inequality constraint(s).

Optimized residual from 12.4597 to 4.62746

Optimizer instance finished. id:opt id


../../_images/tutorial_optimization_nb_optimizer_spectrum_5_1.png
[6]:
opt.options.method = "Subplex"

opt.SetInitialVars()

# run the optimization
opt()

plt.plot(detuning_reference, intensity_reference)
plt.plot(detuning_reference, energy_spectrum.result)
plt.xlabel('detuning (Gamma)')
plt.ylabel('rel. reflectivity')
plt.show()

Run Optimizer instance with id: opt id

Starting optimizer with 2 provided measurement dependencies and 4 fit parameter(s):

  no. |                           id |       initial value |              min |              max
    0 |             Pt top thickness |                 3.2 |                0 |               10
    1 |                      B4C top |                   4 |                0 |               10
    2 |                      B4C mid |                   4 |                0 |               10
    3 |                      B4C top |                  16 |                0 |               20

Using 0 equality constraint(s) on parameter(s):

Using 0 inequality constraint(s).

Residual start value: 12.4597


Calling NLopt solver with fit method Subplex

Termination: parameter tolerance reached.

  cost = 1.263866e-06
  iterations: 278

Optimizer finished with 4 fit parameter(s):

  no. |                           id |           fit value |       initial value |              min |              max
    0 |             Pt top thickness |             3.39095 |                 3.2 |                0 |               10
    1 |                      B4C top |             8.61354 |                   4 |                0 |               10
    2 |                      B4C mid |             5.48537 |                   4 |                0 |               10
    3 |                      B4C top |             15.4239 |                  16 |                0 |               20

and 0 equality constraint(s) on parameter(s):

and 0 inequality constraint(s).

Optimized residual from 12.4597 to 0.00158988

Optimizer instance finished. id:opt id


../../_images/tutorial_optimization_nb_optimizer_spectrum_6_1.png
[7]:
opt.options.method = "PagmoDiffEvol"

opt.SetInitialVars()

# run the optimization
opt()

plt.plot(detuning_reference, intensity_reference)
plt.plot(detuning_reference, energy_spectrum.result)
plt.xlabel('detuning (Gamma)')
plt.ylabel('rel. reflectivity')
plt.show()

Run Optimizer instance with id: opt id

Starting optimizer with 2 provided measurement dependencies and 4 fit parameter(s):

  no. |                           id |       initial value |              min |              max
    0 |             Pt top thickness |                 3.2 |                0 |               10
    1 |                      B4C top |                   4 |                0 |               10
    2 |                      B4C mid |                   4 |                0 |               10
    3 |                      B4C top |                  16 |                0 |               20

Using 0 equality constraint(s) on parameter(s):

Using 0 inequality constraint(s).

Residual start value: 12.4597


Calling Pagmo solver with fit method PagmoDiffEvol

  population: 50
  iterations: 100

  cost = 3.822179e-06

Calling ceres solver with fit method LevMar

Ceres Solver Report: Iterations: 2, Initial cost: 3.822179e-06, Final cost: 2.776746e-06, Termination: CONVERGENCE

Optimizer finished with 4 fit parameter(s):

  no. |                           id |           fit value |       initial value |              min |              max
    0 |             Pt top thickness |             3.35985 |                 3.2 |                0 |               10
    1 |                      B4C top |             8.66606 |                   4 |                0 |               10
    2 |                      B4C mid |             5.40852 |                   4 |                0 |               10
    3 |                      B4C top |             15.6214 |                  16 |                0 |               20

and 0 equality constraint(s) on parameter(s):

and 0 inequality constraint(s).

Optimized residual from 12.4597 to 0.00235658

Optimizer instance finished. id:opt id


../../_images/tutorial_optimization_nb_optimizer_spectrum_7_1.png
[8]:
# calcualte field intensity inside the sample
field_int = nx.FieldIntensity(sample = cavity,
                              energy = nx.moessbauer.Fe57.energy,
                              points = 1001)

depth, int = field_int()

plt.plot(depth, int)

# add lines and labels
axes = plt.gca()
y_min, y_max = axes.get_ylim()
plt.vlines(cavity.Interfaces(), y_min, y_max, colors='g', linestyles='dashed')
for id, location in zip(cavity.Ids(), np.array(cavity.Interfaces()) + 0.5):
    plt.text(location, y_max, id, fontsize = 10)
    y_max = y_max - 0.5

plt.xlabel('depth (nm)')
plt.ylabel('relative intensity')
plt.show()
../../_images/tutorial_optimization_nb_optimizer_spectrum_8_0.png