Adding a new nonlinear crystal
This package becomes more useful as more nonlinear crystal data is added. Contributions to expand the crystal database are highly welcome!
To define a new nonlinear crystal in NonlinearCrystals.jl, you need to:
- Provide metadata such as name, formula, symmetry group, and lattice parameters.
- Define its principal refractive indices using a
SellmeierFunctionfor each crystal axis. - Provide the 3×3×3 nonlinear susceptibility tensor
d_XYZ_fullbased on individual measured tensor components. - Optionally, compute and include a Miller delta correction for frequency scaling.
- Return the crystal as either a
UnidirectionalCrystalorBidirectionalCrystal.
The definition should be wrapped in a create_<name>() function inside a file in src/crystal_data/.
Example: Defining BBO as an unidirectional nonlinear crystal
Below is a complete definition for BBO (Beta-barium borate), a widely used uniaxial nonlinear optical crystal. A similar file can be found in the crystal_data folder.
Each crystal has its own file with the wrapping function, e.g.:
function create_bbo()
#... All the needed information as shown below should be placed here
return BBO
end
# Export and instantiate the crystal
export BBO
const BBO = create_bbo()Inside the function, follow the steps above.
- Metadata: Add basic metadata describing material properties as a dict. Especially the point group is needed to calculate the nonlinear tensor matching the crystal symmetry based on individual components:
metadata = Dict(
:description => "BBO (Beta-barium borate)",
:formula => "β-BaB₂O₄",
:point_group => "3m",
:lattice_params => (12.532u"Å", 12.532u"Å", 12.717u"Å"),
:density => 3.85u"g/cm^3",
:mohs_hardness => 4,
)- Principal refractive indices: Specify the valid spectral range of Sellmeier model and add the refractive data as
SellmeierFunctionwith a refractive index function and a reference temperature:
# Specify the valid spectral range and the reference temperature (typically room temperature) of the Sellmeier model
lambda_min = 0.189u"µm"
lambda_max = 3.5u"µm"
temp_ref = 293.15u"K"
# Define ordinary refractive index as an anonymous function, potentially also incorporating thermo-optic data
n_o = SellmeierFunction(
(λ, T) -> sqrt(2.7359 + 0.01878u"µm^2" / (λ^2 - 0.01822u"µm^2") - 0.01354u"µm^-2" * λ^2) - 16.6e-6u"K^-1" * (T - temp_ref),
(lambda_min, lambda_max);
temp_ref,
)
# Define extraordinary refractive index in a similar way
n_e = SellmeierFunction(
(λ, T) -> sqrt(2.3753 + 0.01224u"µm^2" / (λ^2 - 0.01667u"µm^2") - 0.01516u"µm^-2" * λ^2) - 9.3e-6u"K^-1" * (T - temp_ref),
(lambda_min, lambda_max);
temp_ref,
)- The nonlinear susceptibility tensor:
The function d_XYZ_full lets you compute the full nonlinear tensor in the dielectric frame. Rotations into this frame can be specified as a rotation matrix if needed. See the file for BIBO as an example. In the present case, d15 and d22 are the two non-zero coefficients for BBO's 3m point group; all other components are set automatically based on the crystal's point group:
d_XYZ_full = calc_d_XYZ_full(
metadata[:point_group];
d22 = -2.2u"pm/V",
d15 = 0.08u"pm/V"
)The full or contracted tensors can in the end be shown using BBO.d_XYZ_ref_full or BBO.d_XYZ_ref, respectively.
- Miller delta (optional): Compute Miller scaling data for corrections of
d_effif the wavelengths during the measurements of the specified tensor components are known. For example, if the specified tensor componentsd15andd22are known to be measured using the second-harmonic generation with a fundamental wavelength of 1064 nm, calculate the miller delta tensor using:
miller_delta = calc_miller_delta(
d_XYZ_full,
n_o,
n_e,
temp_ref;
lambda_r1 = 1064u"nm",
lambda_r2 = 1064u"nm"
)- Returning the crystal object: Finally, construct and return the actual crystal object:
BBO = UnidirectionalCrystal(
metadata,
n_o,
n_e,
d_XYZ_full;
miller_delta,
)
return BBOWhen using data or formulae from publications, it is helpful to reference them in the code using comments. This package uses DocumenterCitations.jl to handle the bibtex-based bibliography entries stored in the file bibliography.bibtex. This file can be extended with additional references. These can be referenced in the code by using the corresponding entry keys embedded in a link to the documentation, for example:
# Reference: https://martinkosch.github.io/NonlinearCrystals.jl/dev/bibliography/#dmitriev2013handbookAlso make sure that the specified data is working as expected by adding a corresponding test file for each new nonlinear crystal. They should be placed in the crystal data test folder.