def test_fit_multi_ion_and_spectra(self): from CrystalField.fitting import makeWorkspace from CrystalField import CrystalField, CrystalFieldFit from mantid.simpleapi import CalculateChiSquared params = {'B20': 0.37737, 'B22': 3.9770, 'B40': -0.031787, 'B42': -0.11611, 'B44': -0.12544, 'Temperature': [44.0, 50.0], 'FWHM': [1.1, 0.9]} cf1 = CrystalField('Ce', 'C2v', **params) cf2 = CrystalField('Pr', 'C2v', **params) cf = cf1 + cf2 r = [0.0, 1.45, 2.4, 3.0, 3.85] ws1 = makeWorkspace(*cf.getSpectrum(0, r)) ws2 = makeWorkspace(*cf.getSpectrum(1, r)) params = {'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion0.B40': -0.031787, 'ion0.B42': -0.11611, 'ion0.B44': -0.12544, 'ion1.B20': 0.37737, 'ion1.B22': 3.9770, 'ion1.B40': -0.031787, 'ion1.B42': -0.11611, 'ion1.B44': -0.12544} cf = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0, 50.0], FWHM=[1.0, 1.0], ToleranceIntensity=6.0, ToleranceEnergy=1.0, FixAllPeaks=True, parameters=params) cf.fix('ion0.BmolX', 'ion0.BmolY', 'ion0.BmolZ', 'ion0.BextX', 'ion0.BextY', 'ion0.BextZ', 'ion0.B40', 'ion0.B42', 'ion0.B44', 'ion0.B60', 'ion0.B62', 'ion0.B64', 'ion0.B66', 'ion0.IntensityScaling', 'ion1.BmolX', 'ion1.BmolY', 'ion1.BmolZ', 'ion1.BextX', 'ion1.BextY', 'ion1.BextZ', 'ion1.B40', 'ion1.B42', 'ion1.B44', 'ion1.B60', 'ion1.B62', 'ion1.B64', 'ion1.B66', 'ion1.IntensityScaling', 'sp0.IntensityScaling', 'sp1.IntensityScaling') chi2 = CalculateChiSquared(str(cf.function), InputWorkspace=ws1, InputWorkspace_1=ws2)[1] fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws1, ws2], MaxIterations=10) fit.fit() self.assertTrue(cf.chi2 > 0.0) self.assertTrue(cf.chi2 < chi2)
def test_fit_multi_ion_single_spectrum(self): from CrystalField.fitting import makeWorkspace from CrystalField import CrystalField, CrystalFieldFit from mantid.simpleapi import CalculateChiSquared params = { 'B20': 0.37737, 'B22': 3.9770, 'B40': -0.031787, 'B42': -0.11611, 'B44': -0.12544, 'Temperature': 44.0, 'FWHM': 1.1 } cf1 = CrystalField('Ce', 'C2v', **params) cf2 = CrystalField('Pr', 'C2v', **params) cf = cf1 + cf2 r = [0.0, 1.45, 2.4, 3.0, 3.85] x, y = cf.getSpectrum(r) ws = makeWorkspace(x, y) params = { 'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion0.B40': -0.031787, 'ion0.B42': -0.11611, 'ion0.B44': -0.12544, 'ion1.B20': 0.37737, 'ion1.B22': 3.9770, 'ion1.B40': -0.031787, 'ion1.B42': -0.11611, 'ion1.B44': -0.12544 } cf = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0], FWHM=[1.1], ToleranceIntensity=6.0, ToleranceEnergy=1.0, FixAllPeaks=True, parameters=params) cf.fix('ion0.BmolX', 'ion0.BmolY', 'ion0.BmolZ', 'ion0.BextX', 'ion0.BextY', 'ion0.BextZ', 'ion0.B40', 'ion0.B42', 'ion0.B44', 'ion0.B60', 'ion0.B62', 'ion0.B64', 'ion0.B66', 'ion0.IntensityScaling', 'ion1.BmolX', 'ion1.BmolY', 'ion1.BmolZ', 'ion1.BextX', 'ion1.BextY', 'ion1.BextZ', 'ion1.B40', 'ion1.B42', 'ion1.B44', 'ion1.B60', 'ion1.B62', 'ion1.B64', 'ion1.B66', 'ion1.IntensityScaling') chi2 = CalculateChiSquared(cf.makeSpectrumFunction(), InputWorkspace=ws)[1] fit = CrystalFieldFit(Model=cf, InputWorkspace=ws, MaxIterations=10) fit.fit() self.assertGreater(cf.chi2, 0.0) self.assertLess(cf.chi2, chi2)
Temperature=5, FWHM=1, B20=0.19, B22=0.11, B40=-0.0004, B42=-0.002, B44=-0.012, B60=5.e-05, B62=0.00054, B64=-0.0006, B66=0.0008) cf.PeakShape = 'Lorentzian' cf.IntensityScaling = 2 # Scale factor if data is not in absolute units (mbarn/sr/f.u./meV), will be fitted. # Runs the fit fit = CrystalFieldFit(Model=cf, InputWorkspace=data_ws1, MaxIterations=200) fit.fit() # Plots the data and print fitted parameters l = plotSpectrum('fit_Workspace', [0, 1, 2], error_bars=False) l.activeLayer().setAxisScale(Layer.Left, 0, 100) l.activeLayer().setAxisScale(Layer.Bottom, -10, 30) for parnames in [ 'B20', 'B22', 'B40', 'B42', 'B44', 'B60', 'B62', 'B64', 'B66' ]: print parnames + ' = ' + str(fit.model[parnames]) + ' meV' table = mtd['fit_Parameters'] print 'Cost function value = ' + str(table.row(table.rowCount() - 1)['Value'])
def runTest(self): from CrystalField import CrystalField, CrystalFieldFit, CrystalFieldMultiSite, Background, Function, ResolutionModel cf = CrystalField('Ce', 'C2v') cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770) cf['B40'] = -0.031 b = cf['B40'] # Calculate and return the Hamiltonian matrix as a 2D numpy array. h = cf.getHamiltonian() print(h) # Calculate and return the eigenvalues of the Hamiltonian as a 1D numpy array. e = cf.getEigenvalues() print(e) # Calculate and return the eigenvectors of the Hamiltonian as a 2D numpy array. w = cf.getEigenvectors() print(w) # Using the keyword argument cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44) # Using the property cf.Temperature = 44 print(cf.getPeakList()) #[[ 0.00000000e+00 2.44006198e+01 4.24977124e+01 1.80970926e+01 -2.44006198e+01] # [ 2.16711565e+02 8.83098530e+01 5.04430056e+00 1.71153708e-01 1.41609425e-01]] cf.ToleranceIntensity = 1 print(cf.getPeakList()) #[[ 0. 24.40061976 42.49771237] # [ 216.71156467 88.30985303 5.04430056]] cf.PeakShape = 'Gaussian' cf.FWHM = 0.9 sp = cf.getSpectrum() print(cf.function) CrystalField_Ce = CreateWorkspace(*sp) print(CrystalField_Ce) # If the peak shape is Gaussian cf.peaks.param[1]['Sigma'] = 2.0 cf.peaks.param[2]['Sigma'] = 0.01 # If the peak shape is Lorentzian cf.PeakShape = 'Lorentzian' cf.peaks.param[1]['FWHM'] = 2.0 cf.peaks.param[2]['FWHM'] = 0.01 cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=44.0, FWHM=1.1) cf.background = Background(peak=Function('Gaussian', Height=10, Sigma=1), background=Function('LinearBackground', A0=1.0, A1=0.01)) h = cf.background.peak.param['Height'] a1 = cf.background.background.param['A1'] print(h) print(a1) cf.ties(B20=1.0, B40='B20/2') cf.constraints('1 < B22 <= 2', 'B22 < 4') print(cf.function[1].getTies()) print(cf.function[1].getConstraints()) cf.background.peak.ties(Height=10.1) cf.background.peak.constraints('Sigma > 0') cf.background.background.ties(A0=0.1) cf.background.background.constraints('A1 > 0') print(cf.function[0][0].getConstraints()) print(cf.function[0][1].getConstraints()) print(cf.function.getTies()) print(cf.function.getConstraints()) cf.peaks.ties({'f2.FWHM': '2*f1.FWHM', 'f3.FWHM': '2*f2.FWHM'}) cf.peaks.constraints('f0.FWHM < 2.2', 'f1.FWHM >= 0.1') cf.PeakShape = 'Gaussian' cf.peaks.tieAll('Sigma=0.1', 3) cf.peaks.constrainAll('0 < Sigma < 0.1', 4) cf.peaks.tieAll('Sigma=f0.Sigma', 1, 3) cf.peaks.ties({'f1.Sigma': 'f0.Sigma', 'f2.Sigma': 'f0.Sigma', 'f3.Sigma': 'f0.Sigma'}) rm = ResolutionModel(([1, 2, 3, 100], [0.1, 0.3, 0.35, 2.1])) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm) rm = ResolutionModel(self.my_func, xstart=0.0, xend=24.0, accuracy=0.01) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm) marires = Instrument('MARI') marires.setChopper('S') marires.setFrequency(250) marires.setEi(30) rm = ResolutionModel(marires.getResolution, xstart=0.0, xend=29.0, accuracy=0.01) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm, FWHMVariation=0.1) # --------------------------- cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=[44.0, 50.], FWHM=[1.1, 0.9]) cf.PeakShape = 'Lorentzian' cf.peaks[0].param[0]['FWHM'] = 1.11 cf.peaks[1].param[1]['FWHM'] = 1.12 cf.background = Background(peak=Function('Gaussian', Height=10, Sigma=0.3), background=Function('FlatBackground', A0=1.0)) cf.background[1].peak.param['Sigma'] = 0.8 cf.background[1].background.param['A0'] = 1.1 # The B parameters are common for all spectra - syntax doesn't change cf.ties(B20=1.0, B40='B20/2') cf.constraints('1 < B22 <= 2', 'B22 < 4') # Backgrounds and peaks are different for different spectra - must be indexed cf.background[0].peak.ties(Height=10.1) cf.background[0].peak.constraints('Sigma > 0.1') cf.background[1].peak.ties(Height=20.2) cf.background[1].peak.constraints('Sigma > 0.2') cf.peaks[1].tieAll('FWHM=2*f1.FWHM', 2, 5) cf.peaks[0].constrainAll('FWHM < 2.2', 1, 4) rm = ResolutionModel([self.my_func, marires.getResolution], 0, 100, accuracy = 0.01) cf.ResolutionModel = rm # Calculate second spectrum, use the generated x-values sp = cf.getSpectrum(1) # Calculate second spectrum, use the first spectrum of a workspace sp = cf.getSpectrum(1, 'CrystalField_Ce') # Calculate first spectrum, use the i-th spectrum of a workspace i=0 sp = cf.getSpectrum(0, 'CrystalField_Ce', i) print(cf.function) cf.Temperature = [5, 50, 150] print() print(cf.function) ws = 'CrystalField_Ce' ws1 = 'CrystalField_Ce' ws2 = 'CrystalField_Ce' cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=5) # In case of a single spectrum (ws is a workspace) fit = CrystalFieldFit(Model=cf, InputWorkspace=ws) # Or for multiple spectra fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws1, ws2]) cf.Temperature = [5, 50] fit.fit() params = {'B20': 0.377, 'B22': 3.9, 'B40': -0.03, 'B42': -0.116, 'B44': -0.125, 'Temperature': [44.0, 50.], 'FWHM': [1.1, 0.9]} cf1 = CrystalField('Ce', 'C2v', **params) cf2 = CrystalField('Pr', 'C2v', **params) cfms = cf1 + cf2 cf = 2*cf1 + cf2 cfms = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0], FWHMs=[1.1]) cfms['ion0.B40'] = -0.031 cfms['ion1.B20'] = 0.37737 b = cfms['ion0.B22'] print(b) print(cfms.function) cfms = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0], FWHMs=[1.1], parameters={'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion1.B40':-0.031787, 'ion1.B42':-0.11611, 'ion1.B44':-0.12544}) cfms = CrystalFieldMultiSite(Ions='Ce', Symmetries='C2v', Temperatures=[20], FWHMs=[1.0], Background='name=Gaussian,Height=0,PeakCentre=1,Sigma=0;name=LinearBackground,A0=0,A1=0') cfms = CrystalFieldMultiSite(Ions=['Ce'], Symmetries=['C2v'], Temperatures=[50], FWHMs=[0.9], Background=LinearBackground(A0=1.0), BackgroundPeak=Gaussian(Height=10, Sigma=0.3)) cfms = CrystalFieldMultiSite(Ions='Ce', Symmetries='C2v', Temperatures=[20], FWHMs=[1.0], Background= Gaussian(PeakCentre=1) + LinearBackground()) cfms = CrystalFieldMultiSite(Ions=['Ce','Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44, 50], FWHMs=[1.1, 0.9], Background=FlatBackground(), BackgroundPeak=Gaussian(Height=10, Sigma=0.3), parameters={'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion1.B40':-0.031787, 'ion1.B42':-0.11611, 'ion1.B44':-0.12544}) cfms.ties({'sp0.bg.f0.Height': 10.1}) cfms.constraints('sp0.bg.f0.Sigma > 0.1') cfms.constraints('ion0.sp0.pk1.FWHM < 2.2') cfms.ties({'ion0.sp1.pk2.FWHM': '2*ion0.sp1.pk1.FWHM', 'ion1.sp1.pk3.FWHM': '2*ion1.sp1.pk2.FWHM'}) # -------------------------- params = {'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion1.B40':-0.031787, 'ion1.B42':-0.11611, 'ion1.B44':-0.12544} cf = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0, 50.0], FWHMs=[1.0, 1.0], ToleranceIntensity=6.0, ToleranceEnergy=1.0, FixAllPeaks=True, parameters=params) cf.fix('ion0.BmolX', 'ion0.BmolY', 'ion0.BmolZ', 'ion0.BextX', 'ion0.BextY', 'ion0.BextZ', 'ion0.B40', 'ion0.B42', 'ion0.B44', 'ion0.B60', 'ion0.B62', 'ion0.B64', 'ion0.B66', 'ion0.IntensityScaling', 'ion1.BmolX', 'ion1.BmolY', 'ion1.BmolZ', 'ion1.BextX', 'ion1.BextY', 'ion1.BextZ', 'ion1.B40', 'ion1.B42', 'ion1.B44', 'ion1.B60', 'ion1.B62', 'ion1.B64', 'ion1.B66', 'ion1.IntensityScaling', 'sp0.IntensityScaling', 'sp1.IntensityScaling') chi2 = CalculateChiSquared(str(cf.function), InputWorkspace=ws1, InputWorkspace_1=ws2)[1] fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws1, ws2], MaxIterations=10) fit.fit() print(chi2) cfms = CrystalFieldMultiSite(Ions='Ce', Symmetries='C2', Temperatures=[25], FWHMs=[1.0], PeakShape='Gaussian', BmolX=1.0, B40=-0.02) print(str(cfms.function).split(',')[0]) # -------------------------- # Create some crystal field data origin = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=44.0, FWHM=1.1) x, y = origin.getSpectrum() ws = makeWorkspace(x, y) # Define a CrystalField object with parameters slightly shifted. cf = CrystalField('Ce', 'C2v', B20=0, B22=0, B40=0, B42=0, B44=0, Temperature=44.0, FWHM=1.0, ResolutionModel=([0, 100], [1, 1]), FWHMVariation=0) # Set any ties on the field parameters. cf.ties(B20=0.37737) # Create a fit object fit = CrystalFieldFit(cf, InputWorkspace=ws) # Find initial values for the field parameters. # You need to define the energy splitting and names of parameters to estimate. # Optionally additional constraints can be set on tied parameters (eg, peak centres). fit.estimate_parameters(EnergySplitting=50, Parameters=['B22', 'B40', 'B42', 'B44'], Constraints='20<f1.PeakCentre<45,20<f2.PeakCentre<45', NSamples=1000) print('Returned', fit.get_number_estimates(), 'sets of parameters.') # The first set (the smallest chi squared) is selected by default. # Select a different parameter set if required fit.select_estimated_parameters(3) print(cf['B22'], cf['B40'], cf['B42'], cf['B44']) # Run fit fit.fit() # -------------------------- from CrystalField import PointCharge axial_pc_model = PointCharge([[-2, 0, 0, -4], [-2, 0, 0, 4]], 'Nd') axial_blm = axial_pc_model.calculate() print(axial_blm) from CrystalField import PointCharge from mantid.geometry import CrystalStructure perovskite_structure = CrystalStructure('4 4 4 90 90 90', 'P m -3 m', 'Ce 0 0 0 1 0; Al 0.5 0.5 0.5 1 0; O 0.5 0.5 0 1 0') cubic_pc_model = PointCharge(perovskite_structure, 'Ce', Charges={'Ce':3, 'Al':3, 'O':-2}, MaxDistance=7.5) cubic_pc_model = PointCharge(perovskite_structure, 'Ce', Charges={'Ce':3, 'Al':3, 'O':-2}, Neighbour=2) print(cubic_pc_model) cif_pc_model = PointCharge('Sm2O3.cif') print(cif_pc_model.getIons()) cif_pc_model.Charges = {'O1':-2, 'O2':-2, 'Sm1':3, 'Sm2':3, 'Sm3':3} cif_pc_model.IonLabel = 'Sm2' cif_pc_model.Neighbour = 1 cif_blm = cif_pc_model.calculate() print(cif_blm) bad_pc_model = PointCharge('Sm2O3.cif', MaxDistance=7.5, Neighbour=2) print(bad_pc_model.Neighbour) print(bad_pc_model.MaxDistance) cif_pc_model.Charges = {'O':-2, 'Sm':3} cif_blm = cif_pc_model.calculate() print(cif_blm) cf = CrystalField('Sm', 'C2', Temperature=5, FWHM=10, **cif_pc_model.calculate()) fit = CrystalFieldFit(cf, InputWorkspace=ws) fit = CrystalFieldFit(cf, InputWorkspace=ws) fit.fit() # -------------------------- cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0) Cv = cf.getHeatCapacity() # Calculates Cv(T) for 1<T<300K in 1K steps (default) T = np.arange(1,900,5) Cv = cf.getHeatCapacity(T) # Calculates Cv(T) for specified values of T (1 to 900K in 5K steps here) # Temperatures from a single spectrum workspace ws = CreateWorkspace(T, T, T) Cv = cf.getHeatCapacity(ws) # Use the x-values of a workspace as the temperatures ws_cp = CreateWorkspace(*Cv) # Temperatures from a multi-spectrum workspace ws = CreateWorkspace(T, T, T, NSpec=2) Cv = cf.getHeatCapacity(ws, 1) # Uses the second spectrum's x-values for T (e.g. 450<T<900) chi_v = cf.getSusceptibility(T, Hdir=[1, 1, 1]) chi_v_powder = cf.getSusceptibility(T, Hdir='powder') chi_v_cgs = cf.getSusceptibility(T, Hdir=[1, 1, 0], Unit='SI') chi_v_bohr = cf.getSusceptibility(T, Unit='bohr') print(type([chi_v, chi_v_powder, chi_v_cgs, chi_v_bohr])) moment_t = cf.getMagneticMoment(Temperature=T, Hdir=[1, 1, 1], Hmag=0.1) # Calcs M(T) with at 0.1T field||[111] H = np.linspace(0, 30, 121) moment_h = cf.getMagneticMoment(Hmag=H, Hdir='powder', Temperature=10) # Calcs M(H) at 10K for powder sample moment_SI = cf.getMagneticMoment(H, [1, 1, 1], Unit='SI') # M(H) in Am^2/mol at 1K for H||[111] moment_cgs = cf.getMagneticMoment(100, Temperature=T, Unit='cgs') # M(T) in emu/mol in a field of 100G || [001] print(type([moment_t, moment_h, moment_SI, moment_cgs])) # -------------------------- from CrystalField import CrystalField, CrystalFieldFit, PhysicalProperties # Fits a heat capacity dataset - you must have subtracted the phonon contribution by some method already # and the data must be in J/mol/K. cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, PhysicalProperty=PhysicalProperties('Cv')) fitcv = CrystalFieldFit(Model=cf, InputWorkspace=ws) fitcv.fit() params = {'B20':0.37737, 'B22':3.9770, 'B40':-0.031787, 'B42':-0.11611, 'B44':-0.12544} cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('Cv') fitcv = CrystalFieldFit(Model=cf, InputWorkspace=ws) fitcv.fit() # Fits a susceptibility dataset. Data is the volume susceptibility in SI units cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('susc', Hdir='powder', Unit='SI') fit_chi = CrystalFieldFit(Model=cf, InputWorkspace=ws) fit_chi.fit() # Fits a magnetisation dataset. Data is in emu/mol, and was measured at 5K with the field || [111]. cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('M(H)', Temperature=5, Hdir=[1, 1, 1], Unit='cgs') fit_mag = CrystalFieldFit(Model=cf, InputWorkspace=ws) fit_mag.fit() # Fits a magnetisation vs temperature dataset. Data is in Am^2/mol, measured with a 0.1T field || [110] cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('M(T)', Hmag=0.1, Hdir=[1, 1, 0], Unit='SI') fit_moment = CrystalFieldFit(Model=cf, InputWorkspace=ws) fit_moment.fit() # -------------------------- # Pregenerate the required workspaces for tt in [10, 44, 50]: cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=tt, FWHM=0.5) x, y = cf.getSpectrum() self.my_create_ws('ws_ins_'+str(tt)+'K', x, y) ws_ins_10K = mtd['ws_ins_10K'] ws_ins_44K = mtd['ws_ins_44K'] ws_ins_50K = mtd['ws_ins_50K'] ws_cp = self.my_create_ws('ws_cp', *cf.getHeatCapacity()) ws_chi = self.my_create_ws('ws_chi', *cf.getSusceptibility(np.linspace(1,300,100), Hdir='powder', Unit='cgs')) ws_mag = self.my_create_ws('ws_mag', *cf.getMagneticMoment(Hmag=np.linspace(0, 30, 100), Hdir=[1,1,1], Unit='bohr', Temperature=5)) # -------------------------- # Fits an INS spectrum (at 10K) and the heat capacity simultaneously cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544) cf.Temperature = 10 cf.FWHM = 1.5 cf.PhysicalProperty = PhysicalProperties('Cv') fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws_ins_10K, ws_cp]) fit.fit() # Fits two INS spectra (at 44K and 50K) and the heat capacity, susceptibility and magnetisation simultaneously. PPCv = PhysicalProperties('Cv') PPchi = PhysicalProperties('susc', 'powder', Unit='cgs') PPMag = PhysicalProperties('M(H)', [1, 1, 1], 5, 'bohr') cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=[44.0, 50.], FWHM=[1.1, 0.9], PhysicalProperty=[PPCv, PPchi, PPMag] ) fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws_ins_44K, ws_ins_50K, ws_cp, ws_chi, ws_mag]) fit.fit()
def runTest(self): from CrystalField import CrystalField, CrystalFieldFit, CrystalFieldMultiSite, Background, Function, ResolutionModel cf = CrystalField('Ce', 'C2v') cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770) cf['B40'] = -0.031 b = cf['B40'] # Calculate and return the Hamiltonian matrix as a 2D numpy array. h = cf.getHamiltonian() print(h) # Calculate and return the eigenvalues of the Hamiltonian as a 1D numpy array. e = cf.getEigenvalues() print(e) # Calculate and return the eigenvectors of the Hamiltonian as a 2D numpy array. w = cf.getEigenvectors() print(w) # Using the keyword argument cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44) # Using the property cf.Temperature = 44 print(cf.getPeakList()) #[[ 0.00000000e+00 2.44006198e+01 4.24977124e+01 1.80970926e+01 -2.44006198e+01] # [ 2.16711565e+02 8.83098530e+01 5.04430056e+00 1.71153708e-01 1.41609425e-01]] cf.ToleranceIntensity = 1 print(cf.getPeakList()) #[[ 0. 24.40061976 42.49771237] # [ 216.71156467 88.30985303 5.04430056]] cf.PeakShape = 'Gaussian' cf.FWHM = 0.9 sp = cf.getSpectrum() print(cf.function) CrystalField_Ce = CreateWorkspace(*sp) print(CrystalField_Ce) # If the peak shape is Gaussian cf.peaks.param[1]['Sigma'] = 2.0 cf.peaks.param[2]['Sigma'] = 0.01 # If the peak shape is Lorentzian cf.PeakShape = 'Lorentzian' cf.peaks.param[1]['FWHM'] = 2.0 cf.peaks.param[2]['FWHM'] = 0.01 cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=44.0, FWHM=1.1) cf.background = Background(peak=Function('Gaussian', Height=10, Sigma=1), background=Function('LinearBackground', A0=1.0, A1=0.01)) h = cf.background.peak.param['Height'] a1 = cf.background.background.param['A1'] print(h) print(a1) cf.ties(B20=1.0, B40='B20/2') cf.constraints('1 < B22 <= 2', 'B22 < 4') print(cf.function[1].getTies()) print(cf.function[1].getConstraints()) cf.background.peak.ties(Height=10.1) cf.background.peak.constraints('Sigma > 0') cf.background.background.ties(A0=0.1) cf.background.background.constraints('A1 > 0') print(cf.function[0][0].getConstraints()) print(cf.function[0][1].getConstraints()) print(cf.function.getTies()) print(cf.function.getConstraints()) cf.peaks.ties({'f2.FWHM': '2*f1.FWHM', 'f3.FWHM': '2*f2.FWHM'}) cf.peaks.constraints('f0.FWHM < 2.2', 'f1.FWHM >= 0.1') cf.PeakShape = 'Gaussian' cf.peaks.tieAll('Sigma=0.1', 3) cf.peaks.constrainAll('0 < Sigma < 0.1', 4) cf.peaks.tieAll('Sigma=f0.Sigma', 1, 3) cf.peaks.ties({'f1.Sigma': 'f0.Sigma', 'f2.Sigma': 'f0.Sigma', 'f3.Sigma': 'f0.Sigma'}) rm = ResolutionModel(([1, 2, 3, 100], [0.1, 0.3, 0.35, 2.1])) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm) rm = ResolutionModel(self.my_func, xstart=0.0, xend=24.0, accuracy=0.01) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm) marires = PyChop2('MARI') marires.setChopper('S') marires.setFrequency(250) marires.setEi(30) rm = ResolutionModel(marires.getResolution, xstart=0.0, xend=29.0, accuracy=0.01) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm) cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0, ResolutionModel=rm, FWHMVariation=0.1) # --------------------------- cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=[44.0, 50], FWHM=[1.1, 0.9]) cf.PeakShape = 'Lorentzian' cf.peaks[0].param[0]['FWHM'] = 1.11 cf.peaks[1].param[1]['FWHM'] = 1.12 cf.background = Background(peak=Function('Gaussian', Height=10, Sigma=0.3), background=Function('FlatBackground', A0=1.0)) cf.background[1].peak.param['Sigma'] = 0.8 cf.background[1].background.param['A0'] = 1.1 # The B parameters are common for all spectra - syntax doesn't change cf.ties(B20=1.0, B40='B20/2') cf.constraints('1 < B22 <= 2', 'B22 < 4') # Backgrounds and peaks are different for different spectra - must be indexed cf.background[0].peak.ties(Height=10.1) cf.background[0].peak.constraints('Sigma > 0.1') cf.background[1].peak.ties(Height=20.2) cf.background[1].peak.constraints('Sigma > 0.2') cf.peaks[1].tieAll('FWHM=2*f1.FWHM', 2, 5) cf.peaks[0].constrainAll('FWHM < 2.2', 1, 4) rm = ResolutionModel([self.my_func, marires.getResolution], 0, 100, accuracy = 0.01) cf.ResolutionModel = rm # Calculate second spectrum, use the generated x-values sp = cf.getSpectrum(1) # Calculate second spectrum, use the first spectrum of a workspace sp = cf.getSpectrum(1, 'CrystalField_Ce') # Calculate first spectrum, use the i-th spectrum of a workspace i=0 sp = cf.getSpectrum(0, 'CrystalField_Ce', i) print(cf.function) cf.Temperature = [5, 50, 150] print() print(cf.function) ws = 'CrystalField_Ce' ws1 = 'CrystalField_Ce' ws2 = 'CrystalField_Ce' cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=5) # In case of a single spectrum (ws is a workspace) fit = CrystalFieldFit(Model=cf, InputWorkspace=ws) # Or for multiple spectra fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws1, ws2]) cf.Temperature = [5, 50] fit.fit() params = {'B20': 0.377, 'B22': 3.9, 'B40': -0.03, 'B42': -0.116, 'B44': -0.125, 'Temperature': [44.0, 50], 'FWHM': [1.1, 0.9]} cf1 = CrystalField('Ce', 'C2v', **params) cf2 = CrystalField('Pr', 'C2v', **params) cfms = cf1 + cf2 cf = 2*cf1 + cf2 cfms = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0], FWHMs=[1.1]) cfms['ion0.B40'] = -0.031 cfms['ion1.B20'] = 0.37737 b = cfms['ion0.B22'] print(b) print(cfms.function) cfms = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0], FWHMs=[1.1], parameters={'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion1.B40':-0.031787, 'ion1.B42':-0.11611, 'ion1.B44':-0.12544}) cfms = CrystalFieldMultiSite(Ions='Ce', Symmetries='C2v', Temperatures=[20], FWHMs=[1.0], Background='name=Gaussian,Height=0,PeakCentre=1,Sigma=0;name=LinearBackground,A0=0,A1=0') cfms = CrystalFieldMultiSite(Ions=['Ce'], Symmetries=['C2v'], Temperatures=[50], FWHMs=[0.9], Background=LinearBackground(A0=1.0), BackgroundPeak=Gaussian(Height=10, Sigma=0.3)) cfms = CrystalFieldMultiSite(Ions='Ce', Symmetries='C2v', Temperatures=[20], FWHMs=[1.0], Background= Gaussian(PeakCentre=1) + LinearBackground()) cfms = CrystalFieldMultiSite(Ions=['Ce','Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44, 50], FWHMs=[1.1, 0.9], Background=FlatBackground(), BackgroundPeak=Gaussian(Height=10, Sigma=0.3), parameters={'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion1.B40':-0.031787, 'ion1.B42':-0.11611, 'ion1.B44':-0.12544}) cfms.ties({'sp0.bg.f0.Height': 10.1}) cfms.constraints('sp0.bg.f0.Sigma > 0.1') cfms.constraints('ion0.sp0.pk1.FWHM < 2.2') cfms.ties({'ion0.sp1.pk2.FWHM': '2*ion0.sp1.pk1.FWHM', 'ion1.sp1.pk3.FWHM': '2*ion1.sp1.pk2.FWHM'}) # -------------------------- params = {'ion0.B20': 0.37737, 'ion0.B22': 3.9770, 'ion1.B40':-0.031787, 'ion1.B42':-0.11611, 'ion1.B44':-0.12544} cf = CrystalFieldMultiSite(Ions=['Ce', 'Pr'], Symmetries=['C2v', 'C2v'], Temperatures=[44.0, 50.0], FWHMs=[1.0, 1.0], ToleranceIntensity=6.0, ToleranceEnergy=1.0, FixAllPeaks=True, parameters=params) cf.fix('ion0.BmolX', 'ion0.BmolY', 'ion0.BmolZ', 'ion0.BextX', 'ion0.BextY', 'ion0.BextZ', 'ion0.B40', 'ion0.B42', 'ion0.B44', 'ion0.B60', 'ion0.B62', 'ion0.B64', 'ion0.B66', 'ion0.IntensityScaling', 'ion1.BmolX', 'ion1.BmolY', 'ion1.BmolZ', 'ion1.BextX', 'ion1.BextY', 'ion1.BextZ', 'ion1.B40', 'ion1.B42', 'ion1.B44', 'ion1.B60', 'ion1.B62', 'ion1.B64', 'ion1.B66', 'ion1.IntensityScaling', 'sp0.IntensityScaling', 'sp1.IntensityScaling') chi2 = CalculateChiSquared(str(cf.function), InputWorkspace=ws1, InputWorkspace_1=ws2)[1] fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws1, ws2], MaxIterations=10) fit.fit() print(chi2) cfms = CrystalFieldMultiSite(Ions='Ce', Symmetries='C2', Temperatures=[25], FWHMs=[1.0], PeakShape='Gaussian', BmolX=1.0, B40=-0.02) print(str(cfms.function).split(',')[0]) # -------------------------- # Create some crystal field data origin = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=44.0, FWHM=1.1) x, y = origin.getSpectrum() ws = makeWorkspace(x, y) # Define a CrystalField object with parameters slightly shifted. cf = CrystalField('Ce', 'C2v', B20=0, B22=0, B40=0, B42=0, B44=0, Temperature=44.0, FWHM=1.0, ResolutionModel=([0, 100], [1, 1]), FWHMVariation=0) # Set any ties on the field parameters. cf.ties(B20=0.37737) # Create a fit object fit = CrystalFieldFit(cf, InputWorkspace=ws) # Find initial values for the field parameters. # You need to define the energy splitting and names of parameters to estimate. # Optionally additional constraints can be set on tied parameters (eg, peak centres). fit.estimate_parameters(EnergySplitting=50, Parameters=['B22', 'B40', 'B42', 'B44'], Constraints='20<f1.PeakCentre<45,20<f2.PeakCentre<45', NSamples=1000) print('Returned', fit.get_number_estimates(), 'sets of parameters.') # The first set (the smallest chi squared) is selected by default. # Select a different parameter set if required fit.select_estimated_parameters(3) print(cf['B22'], cf['B40'], cf['B42'], cf['B44']) # Run fit fit.fit() # -------------------------- from CrystalField import PointCharge axial_pc_model = PointCharge([[-2, 0, 0, -4], [-2, 0, 0, 4]], 'Nd') axial_blm = axial_pc_model.calculate() print(axial_blm) from CrystalField import PointCharge from mantid.geometry import CrystalStructure perovskite_structure = CrystalStructure('4 4 4 90 90 90', 'P m -3 m', 'Ce 0 0 0 1 0; Al 0.5 0.5 0.5 1 0; O 0.5 0.5 0 1 0') cubic_pc_model = PointCharge(perovskite_structure, 'Ce', Charges={'Ce':3, 'Al':3, 'O':-2}, MaxDistance=7.5) cubic_pc_model = PointCharge(perovskite_structure, 'Ce', Charges={'Ce':3, 'Al':3, 'O':-2}, Neighbour=2) print(cubic_pc_model) cif_pc_model = PointCharge('Sm2O3.cif') print(cif_pc_model.getIons()) cif_pc_model.Charges = {'O1':-2, 'O2':-2, 'Sm1':3, 'Sm2':3, 'Sm3':3} cif_pc_model.IonLabel = 'Sm2' cif_pc_model.Neighbour = 1 cif_blm = cif_pc_model.calculate() print(cif_blm) bad_pc_model = PointCharge('Sm2O3.cif', MaxDistance=7.5, Neighbour=2) print(bad_pc_model.Neighbour) print(bad_pc_model.MaxDistance) cif_pc_model.Charges = {'O':-2, 'Sm':3} cif_blm = cif_pc_model.calculate() print(cif_blm) cf = CrystalField('Sm', 'C2', Temperature=5, FWHM=10, **cif_pc_model.calculate()) fit = CrystalFieldFit(cf, InputWorkspace=ws) fit = CrystalFieldFit(cf, InputWorkspace=ws) fit.fit() # -------------------------- cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, Temperature=44.0) Cv = cf.getHeatCapacity() # Calculates Cv(T) for 1<T<300K in 1K steps (default) T = np.arange(1,900,5) Cv = cf.getHeatCapacity(T) # Calculates Cv(T) for specified values of T (1 to 900K in 5K steps here) # Temperatures from a single spectrum workspace ws = CreateWorkspace(T, T, T) Cv = cf.getHeatCapacity(ws) # Use the x-values of a workspace as the temperatures ws_cp = CreateWorkspace(*Cv) # Temperatures from a multi-spectrum workspace ws = CreateWorkspace(T, T, T, NSpec=2) Cv = cf.getHeatCapacity(ws, 1) # Uses the second spectrum's x-values for T (e.g. 450<T<900) chi_v = cf.getSusceptibility(T, Hdir=[1, 1, 1]) chi_v_powder = cf.getSusceptibility(T, Hdir='powder') chi_v_cgs = cf.getSusceptibility(T, Hdir=[1, 1, 0], Unit='SI') chi_v_bohr = cf.getSusceptibility(T, Unit='bohr') print(type([chi_v, chi_v_powder, chi_v_cgs, chi_v_bohr])) moment_t = cf.getMagneticMoment(Temperature=T, Hdir=[1, 1, 1], Hmag=0.1) # Calcs M(T) with at 0.1T field||[111] H = np.linspace(0, 30, 121) moment_h = cf.getMagneticMoment(Hmag=H, Hdir='powder', Temperature=10) # Calcs M(H) at 10K for powder sample moment_SI = cf.getMagneticMoment(H, [1, 1, 1], Unit='SI') # M(H) in Am^2/mol at 1K for H||[111] moment_cgs = cf.getMagneticMoment(100, Temperature=T, Unit='cgs') # M(T) in emu/mol in a field of 100G || [001] print(type([moment_t, moment_h, moment_SI, moment_cgs])) # -------------------------- from CrystalField import CrystalField, CrystalFieldFit, PhysicalProperties # Fits a heat capacity dataset - you must have subtracted the phonon contribution by some method already # and the data must be in J/mol/K. cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, PhysicalProperty=PhysicalProperties('Cv')) fitcv = CrystalFieldFit(Model=cf, InputWorkspace=ws) fitcv.fit() params = {'B20':0.37737, 'B22':3.9770, 'B40':-0.031787, 'B42':-0.11611, 'B44':-0.12544} cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('Cv') fitcv = CrystalFieldFit(Model=cf, InputWorkspace=ws) fitcv.fit() # Fits a susceptibility dataset. Data is the volume susceptibility in SI units cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('susc', Hdir='powder', Unit='SI') fit_chi = CrystalFieldFit(Model=cf, InputWorkspace=ws) fit_chi.fit() # Fits a magnetisation dataset. Data is in emu/mol, and was measured at 5K with the field || [111]. cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('M(H)', Temperature=5, Hdir=[1, 1, 1], Unit='cgs') fit_mag = CrystalFieldFit(Model=cf, InputWorkspace=ws) fit_mag.fit() # Fits a magnetisation vs temperature dataset. Data is in Am^2/mol, measured with a 0.1T field || [110] cf = CrystalField('Ce', 'C2v', **params) cf.PhysicalProperty = PhysicalProperties('M(T)', Hmag=0.1, Hdir=[1, 1, 0], Unit='SI') fit_moment = CrystalFieldFit(Model=cf, InputWorkspace=ws) fit_moment.fit() # -------------------------- # Pregenerate the required workspaces for tt in [10, 44, 50]: cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=tt, FWHM=0.5) x, y = cf.getSpectrum() self.my_create_ws('ws_ins_'+str(tt)+'K', x, y) ws_ins_10K = mtd['ws_ins_10K'] ws_ins_44K = mtd['ws_ins_44K'] ws_ins_50K = mtd['ws_ins_50K'] ws_cp = self.my_create_ws('ws_cp', *cf.getHeatCapacity()) ws_chi = self.my_create_ws('ws_chi', *cf.getSusceptibility(np.linspace(1,300,100), Hdir='powder', Unit='cgs')) ws_mag = self.my_create_ws('ws_mag', *cf.getMagneticMoment(Hmag=np.linspace(0, 30, 100), Hdir=[1,1,1], Unit='bohr', Temperature=5)) # -------------------------- # Fits an INS spectrum (at 10K) and the heat capacity simultaneously cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544) cf.Temperature = 10 cf.FWHM = 1.5 cf.PhysicalProperty = PhysicalProperties('Cv') fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws_ins_10K, ws_cp]) fit.fit() # Fits two INS spectra (at 44K and 50K) and the heat capacity, susceptibility and magnetisation simultaneously. PPCv = PhysicalProperties('Cv') PPchi = PhysicalProperties('susc', 'powder', Unit='cgs') PPMag = PhysicalProperties('M(H)', [1, 1, 1], 5, 'bohr') cf = CrystalField('Ce', 'C2v', B20=0.37737, B22=3.9770, B40=-0.031787, B42=-0.11611, B44=-0.12544, Temperature=[44.0, 50], FWHM=[1.1, 0.9], PhysicalProperty=[PPCv, PPchi, PPMag] ) fit = CrystalFieldFit(Model=cf, InputWorkspace=[ws_ins_44K, ws_ins_50K, ws_cp, ws_chi, ws_mag]) fit.fit()
lit_par = { 'B20': -.27, 'B22': -.34, 'B40': 1e-6, 'B42': 0.04158, 'B44': 0.01369, 'B60': 0.112e-3, 'B62': 0.4185e-3, 'B64': -0.555e-3, 'B66': 0.588e-3 } # K for parameter in lit_par.keys(): lit_par[parameter] *= Kelvin_to_meV # Set up the crystal field model. cf = CrystalField('Ho', 'D2', Temperature=[55, 159], FWHM=0.3, **lit_par) cf.PeakShape = 'Lorentzian' cf.IntensityScaling = [ 0.2, 0.2 ] # Scale factor if data is not in absolute units (mbarn/sr/f.u./meV), will be fitted. cf.background = Background( peak=Function('Gaussian', Height=700, Sigma=0.4 / 2.3)) cf.ResolutionModel = [resmod, resmod] # Runs the fit fit = CrystalFieldFit(Model=cf, InputWorkspace=[data_ws3, data_ws4], MaxIterations=2000, Output='Fit_159K') fit.fit()
B42=-0.002, B44=-0.012, B60=5.e-05, B62=0.00054, B64=-0.0006, B66=0.0008) # Simultaneously fit data measured in a, b and c directions cf.PhysicalProperty = [ PhysicalProperties('susc', Hdir=[1, 0, 0], Inverse=True, Unit='cgs'), PhysicalProperties('susc', Hdir=[0, 1, 0], Inverse=True, Unit='cgs'), PhysicalProperties('susc', Hdir=[0, 0, 1], Inverse=True, Unit='cgs') ] fit = CrystalFieldFit(Model=cf, InputWorkspace=[sus_a, sus_b, sus_c], MaxIterations=100, Output='fit_susc') fit.fit() # Print fitted parameters and plot results blm = {} for parname in ['B20', 'B22', 'B40', 'B42', 'B44', 'B60', 'B62', 'B64', 'B66']: blm[parname] = cf[parname] print parname + "=" + str(cf[parname]) calc_a = mtd['fit_susc_Workspaces'][0] calc_b = mtd['fit_susc_Workspaces'][1] calc_c = mtd['fit_susc_Workspaces'][2] plt.plot(calc_a.readX(1), calc_a.readY(1), '-k', label='$\chi^a$ Fit') plt.plot(mtd['sus_a'].readX(0), mtd['sus_a'].readY(0), 'ok',