def calc_factor_in_front_of_density_for_fm_perp( self, hkl, space_group_symop: SpaceGroupSymopL, cell: Cell, atom_site_susceptibility: AtomSiteSusceptibilityL, h_loc, chi_iso_ferro: float = 0., chi_iso_antiferro: float = 0., flag_two_channel: bool = False): """Calculate factor in front of density for FM_perp. Arguments --------- - hkl - space_group_symop - ... """ v_hkl_2d_i, v_ferro, v_antiferro = \ self.calc_factor_in_front_of_density_for_fm( hkl, space_group_symop, cell, atom_site_susceptibility, h_loc, chi_iso_ferro=chi_iso_ferro, chi_iso_antiferro=chi_iso_antiferro, flag_two_channel=flag_two_channel) k_hkl_1, k_hkl_2, k_hkl_3 = cell.calc_k_loc(*hkl) na = numpy.newaxis v_hkl_perp_2d_i = calc_moment_perp( (k_hkl_1[:, na], k_hkl_2[:, na], k_hkl_3[:, na]), v_hkl_2d_i) v_perp_ferro = calc_moment_perp( (k_hkl_1[:, na], k_hkl_2[:, na], k_hkl_3[:, na]), v_ferro) v_perp_antiferro = calc_moment_perp( (k_hkl_1[:, na], k_hkl_2[:, na], k_hkl_3[:, na]), v_antiferro) return v_hkl_perp_2d_i, v_perp_ferro, v_perp_antiferro
def temp_func(l_par): for name, parameter in zip(l_name, l_par): if name[0][0] == "atom_site_susceptibility": atom_site_susceptibility.set_variable_by_name(name, parameter) elif name[0][0] == "mem_parameters": mem_parameters.set_variable_by_name(name, parameter) chi_iso_f = mem_parameters.chi_ferro chi_iso_af = mem_parameters.chi_antiferro atom_site_susceptibility.apply_chi_iso_constraint(cell) atom_site_susceptibility.apply_moment_iso_constraint(cell) atom_site_susceptibility.apply_space_group_constraint( atom_site, space_group) l_chi_sq = [] l_der_chi_sq, l_der_chi_sq_f, l_der_chi_sq_a = [], [], [] # FIXME: add flag for orbital magnetic moment for diffrn, f_nucl, fr_e, fr_s, e_up, h_loc, k_hkl, phase_3d, \ chi_perp_ferro, chi_perp_aferro in \ zip(l_diffrn, l_f_nucl, l_fr_e, l_fr_s, l_e_up, l_h_loc, l_k_hkl, l_phase_3d, l_chi_perp_ferro, l_chi_perp_antiferro): moment_2d, moment_ferro, moment_antiferro = \ density_point.calc_moment_2d( space_group_symop, cell, atom_site_susceptibility, h_loc, chi_iso_ferro=1., chi_iso_antiferro=1., flag_two_channel=flag_two_channel) f_m = calc_fm_by_density(mult_i, den_i, np, volume, moment_2d, phase_3d) f_m_perp = calc_moment_perp(k_hkl, f_m) # # correction on orbital moment # diffrn_refln = diffrn.diffrn_refln # setup = diffrn.setup # field = setup.field # ind_h = diffrn_refln.numpy_index_h # ind_k = diffrn_refln.numpy_index_k # ind_l = diffrn_refln.numpy_index_l # chi_m = crystal.calc_susceptibility_moment_tensor( # ind_h, ind_k, ind_l, flag_only_orbital=True) # sft_ij = chi_m[:9] # sftm_ij = chi_m[9:] # fm_orb_perp_loc = calc_fm_perp_loc(e_up, field, k_hkl, sft_ij, # sftm_ij) # add ferro and anti_ferro f_m_perp_sum = (f_m_perp[0] + chi_iso_f * chi_perp_ferro[0] + chi_iso_af * chi_perp_aferro[0], f_m_perp[1] + chi_iso_f * chi_perp_ferro[1] + chi_iso_af * chi_perp_aferro[1], f_m_perp[2] + chi_iso_f * chi_perp_ferro[2] + chi_iso_af * chi_perp_aferro[2]) fr_m, delta_fr_m = diffrn.calc_fr(cell, f_nucl, f_m_perp_sum, delta_f_m_perp=f_m_perp) delta_fr_m_f = delta_fr_m delta_fr_m_a = delta_fr_m diffrn.diffrn_refln.numpy_fr_calc = fr_m chi_sq, der_chi_sq = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m) der_chi_sq_f = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_f)[1] der_chi_sq_a = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_a)[1] l_chi_sq.append(chi_sq) l_der_chi_sq.append(der_chi_sq) l_der_chi_sq_f.append(der_chi_sq_f) l_der_chi_sq_a.append(der_chi_sq_a) return sum(l_chi_sq)
def refine_susceptibility(crystal: Crystal, l_diffrn: List[Diffrn], density_point: DensityPointL, mem_parameters: MEMParameters, disp: bool = True, d_info: dict = None) -> (float, float): """ Refinement of susceptibility. Parameters ---------- crystal : Crystal DESCRIPTION. l_diffrn : TYPE DESCRIPTION. density_point : DensityPointL DESCRIPTION. chi_iso_ferro : float, optional DESCRIPTION. The default is 0.. chi_iso_antiferro : float, optional DESCRIPTION. The default is 0.. flag_ferro : bool, optional DESCRIPTION. The default is True. flag_antiferro : bool, optional DESCRIPTION. The default is True. disp : bool, optional DESCRIPTION. The default is True. Returns ------- float Chi_iso_ferro. float Chi_iso_antiferro. """ flag_info = d_info is not None if flag_info: d_info_keys = d_info.keys() if "stop" not in d_info_keys: d_info["stop"] = False if "print" not in d_info_keys: d_info["print"] = "" crystal.apply_constraints() flag_two_channel = mem_parameters.method == "2channel" cell = crystal.cell space_group = crystal.space_group atom_site = crystal.atom_site space_group_symop = space_group.full_space_group_symop atom_site_susceptibility = crystal.atom_site_susceptibility # l_magnetic_labes = atom_site_susceptibility.label volume = density_point.volume_unit_cell np = density_point.number_unit_cell den_i = density_point.numpy_density den_ferro_i = density_point.numpy_density_ferro den_antiferro_i = density_point.numpy_density_antiferro mult_i = density_point.numpy_multiplicity l_f_nucl, l_fr_e, l_fr_s, l_e_up, l_h_loc = [], [], [], [], [] l_k_hkl, l_phase_3d = [], [] l_chi_perp_ferro, l_chi_perp_antiferro = [], [] total_peaks = 0 for diffrn in l_diffrn: diffrn_orient_matrix = diffrn.diffrn_orient_matrix u_matrix = diffrn_orient_matrix.u e_up = calc_e_up_loc(0., 0., 0., u_matrix) setup = diffrn.setup field = float(setup.field) h_loc = (field * e_up[0], field * e_up[1], field * e_up[2]) diffrn_refln = diffrn.diffrn_refln index_h = numpy.array(diffrn_refln.index_h, dtype=int) index_k = numpy.array(diffrn_refln.index_k, dtype=int) index_l = numpy.array(diffrn_refln.index_l, dtype=int) total_peaks += index_h.size hkl = (index_h, index_k, index_l) fr_e = numpy.array(diffrn_refln.fr, dtype=float) fr_s = numpy.array(diffrn_refln.fr_sigma, dtype=float) f_nucl = crystal.calc_f_nucl(*hkl) k_hkl = cell.calc_k_loc(*hkl) phase_3d = density_point.calc_phase_3d(hkl, space_group_symop) moment_2d, chi_2d_ferro, chi_2d_antiferro = \ density_point.calc_moment_2d( space_group_symop, cell, atom_site_susceptibility, h_loc, chi_iso_ferro=1., chi_iso_antiferro=1., flag_two_channel=flag_two_channel) chi_ferro = calc_fm_by_density(mult_i, den_ferro_i, np, volume, chi_2d_ferro, phase_3d) chi_perp_ferro = calc_moment_perp(k_hkl, chi_ferro) chi_aferro = calc_fm_by_density(mult_i, den_antiferro_i, np, volume, chi_2d_antiferro, phase_3d) chi_perp_aferro = calc_moment_perp(k_hkl, chi_aferro) l_f_nucl.append(f_nucl) l_fr_e.append(fr_e) l_fr_s.append(fr_s) l_e_up.append(e_up) l_h_loc.append(h_loc) l_k_hkl.append(k_hkl) l_phase_3d.append(phase_3d) l_chi_perp_ferro.append(chi_perp_ferro) l_chi_perp_antiferro.append(chi_perp_aferro) l_name_1 = atom_site_susceptibility.get_variable_names() l_par_1_0 = [ atom_site_susceptibility.get_variable_by_name(name) for name in l_name_1 ] l_name_2 = mem_parameters.get_variable_names() l_par_2_0 = [ mem_parameters.get_variable_by_name(name) for name in l_name_2 ] l_name = l_name_1 + l_name_2 l_par_0 = l_par_1_0 + l_par_2_0 def temp_func(l_par): for name, parameter in zip(l_name, l_par): if name[0][0] == "atom_site_susceptibility": atom_site_susceptibility.set_variable_by_name(name, parameter) elif name[0][0] == "mem_parameters": mem_parameters.set_variable_by_name(name, parameter) chi_iso_f = mem_parameters.chi_ferro chi_iso_af = mem_parameters.chi_antiferro atom_site_susceptibility.apply_chi_iso_constraint(cell) atom_site_susceptibility.apply_moment_iso_constraint(cell) atom_site_susceptibility.apply_space_group_constraint( atom_site, space_group) l_chi_sq = [] l_der_chi_sq, l_der_chi_sq_f, l_der_chi_sq_a = [], [], [] # FIXME: add flag for orbital magnetic moment for diffrn, f_nucl, fr_e, fr_s, e_up, h_loc, k_hkl, phase_3d, \ chi_perp_ferro, chi_perp_aferro in \ zip(l_diffrn, l_f_nucl, l_fr_e, l_fr_s, l_e_up, l_h_loc, l_k_hkl, l_phase_3d, l_chi_perp_ferro, l_chi_perp_antiferro): moment_2d, moment_ferro, moment_antiferro = \ density_point.calc_moment_2d( space_group_symop, cell, atom_site_susceptibility, h_loc, chi_iso_ferro=1., chi_iso_antiferro=1., flag_two_channel=flag_two_channel) f_m = calc_fm_by_density(mult_i, den_i, np, volume, moment_2d, phase_3d) f_m_perp = calc_moment_perp(k_hkl, f_m) # # correction on orbital moment # diffrn_refln = diffrn.diffrn_refln # setup = diffrn.setup # field = setup.field # ind_h = diffrn_refln.numpy_index_h # ind_k = diffrn_refln.numpy_index_k # ind_l = diffrn_refln.numpy_index_l # chi_m = crystal.calc_susceptibility_moment_tensor( # ind_h, ind_k, ind_l, flag_only_orbital=True) # sft_ij = chi_m[:9] # sftm_ij = chi_m[9:] # fm_orb_perp_loc = calc_fm_perp_loc(e_up, field, k_hkl, sft_ij, # sftm_ij) # add ferro and anti_ferro f_m_perp_sum = (f_m_perp[0] + chi_iso_f * chi_perp_ferro[0] + chi_iso_af * chi_perp_aferro[0], f_m_perp[1] + chi_iso_f * chi_perp_ferro[1] + chi_iso_af * chi_perp_aferro[1], f_m_perp[2] + chi_iso_f * chi_perp_ferro[2] + chi_iso_af * chi_perp_aferro[2]) fr_m, delta_fr_m = diffrn.calc_fr(cell, f_nucl, f_m_perp_sum, delta_f_m_perp=f_m_perp) delta_fr_m_f = delta_fr_m delta_fr_m_a = delta_fr_m diffrn.diffrn_refln.numpy_fr_calc = fr_m chi_sq, der_chi_sq = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m) der_chi_sq_f = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_f)[1] der_chi_sq_a = calc_chi_sq(fr_e, fr_s, fr_m, delta_fr_m_a)[1] l_chi_sq.append(chi_sq) l_der_chi_sq.append(der_chi_sq) l_der_chi_sq_f.append(der_chi_sq_f) l_der_chi_sq_a.append(der_chi_sq_a) return sum(l_chi_sq) chi_sq = temp_func(l_par_0) print(f"Chi_sq before optimization {chi_sq/total_peaks:.5f}. ", end="\r") if flag_info: d_info["print"] = \ f"Chi_sq/n before optimization {chi_sq/total_peaks:.5f}." res = scipy.optimize.minimize( temp_func, l_par_0, method="BFGS", callback=lambda x: func_temp(x, param_name=l_name, d_info=d_info), options={"eps": 0.001}) l_param = res.x chi_sq_new = res.fun hess_inv = res["hess_inv"] sigma = (abs(numpy.diag(hess_inv)))**0.5 print(f"Chi_sq after optimization {chi_sq_new/total_peaks:.5f}. ", end="\r") if flag_info: d_info["print"] = \ f"Chi_sq/n after optimization {chi_sq_new/total_peaks:.5f}." for name, parameter, sig in zip(l_name, l_param, sigma): name_sig = name[:-1] + ((f"{name[-1][0]:}_sigma", name[-1][1]), ) if name[0][0] == "atom_site_susceptibility": atom_site_susceptibility.set_variable_by_name(name, parameter) atom_site_susceptibility.set_variable_by_name(name_sig, sig) elif name[0][0] == "mem_parameters": mem_parameters.set_variable_by_name(name, parameter) mem_parameters.set_variable_by_name(name_sig, sig) for diffrn in l_diffrn: diffrn.diffrn_refln.numpy_to_items() chi_sq, points = diffrn.diffrn_refln.calc_chi_sq_points() refine_ls = RefineLs(goodness_of_fit_all=chi_sq / points, number_reflns=points) diffrn.add_items([refine_ls])
def calc_fr(self): """Calculate Flip Ratios for diffraction experiments.""" crystal = self.crystals()[0] # FIXME: l_diffrn = self.experiments() # FIXME: density_point = self.density_point mem_parameters = self.mem_parameters chi_iso_ferro = mem_parameters.chi_ferro chi_iso_antiferro = mem_parameters.chi_antiferro flag_two_channel = mem_parameters.method == "2channel" cell = crystal.cell space_group = crystal.space_group space_group_symop = space_group.full_space_group_symop atom_site_susceptibility = crystal.atom_site_susceptibility # FIXME: temporary solution of calculation rbs_i if it's not defined density_point.calc_rbs_i(space_group_symop, points_a=mem_parameters.points_a, points_b=mem_parameters.points_b, points_c=mem_parameters.points_c) total_peaks = 0 den_i = numpy.array(density_point.density, dtype=float) den_ferro_i = numpy.array(density_point.density_ferro, dtype=float) den_antiferro_i = numpy.array(density_point.density_antiferro, dtype=float) mult_i = numpy.array(density_point.multiplicity, dtype=int) volume = cell.volume n_points = mult_i.sum() for diffrn in l_diffrn: diffrn_orient_matrix = diffrn.diffrn_orient_matrix e_up = diffrn_orient_matrix.calc_e_up() setup = diffrn.setup field = float(setup.field) h_loc = (field * e_up[0], field * e_up[1], field * e_up[2]) diffrn_refln = diffrn.diffrn_refln index_h = numpy.array(diffrn_refln.index_h, dtype=int) index_k = numpy.array(diffrn_refln.index_k, dtype=int) index_l = numpy.array(diffrn_refln.index_l, dtype=int) total_peaks += index_h.size hkl = (index_h, index_k, index_l) f_nucl = crystal.calc_f_nucl(*hkl) k_hkl = cell.calc_k_loc(*hkl) phase_3d = density_point.calc_phase_3d(hkl, space_group_symop) moment_2d, chi_2d_ferro, chi_2d_antiferro = \ density_point.calc_moment_2d( space_group_symop, cell, atom_site_susceptibility, h_loc, chi_iso_ferro=1., chi_iso_antiferro=1., flag_two_channel=flag_two_channel) chi_ferro = calc_fm_by_density(mult_i, den_ferro_i, n_points, volume, chi_2d_ferro, phase_3d) chi_perp_ferro = calc_moment_perp(k_hkl, chi_ferro) chi_aferro = calc_fm_by_density(mult_i, den_antiferro_i, n_points, volume, chi_2d_antiferro, phase_3d) chi_perp_aferro = calc_moment_perp(k_hkl, chi_aferro) f_m = calc_fm_by_density(mult_i, den_i, n_points, volume, moment_2d, phase_3d) f_m_perp = calc_moment_perp(k_hkl, f_m) f_m_perp_sum = (f_m_perp[0] + chi_iso_ferro * chi_perp_ferro[0] + chi_iso_antiferro * chi_perp_aferro[0], f_m_perp[1] + chi_iso_ferro * chi_perp_ferro[1] + chi_iso_antiferro * chi_perp_aferro[1], f_m_perp[2] + chi_iso_ferro * chi_perp_ferro[2] + chi_iso_antiferro * chi_perp_aferro[2]) fr_m, delta_fr_m = diffrn.calc_fr(cell, f_nucl, f_m_perp_sum, delta_f_m_perp=f_m_perp) diffrn.diffrn_refln.numpy_fr_calc = fr_m for diffrn in l_diffrn: diffrn.diffrn_refln.numpy_to_items() chi_sq, points = diffrn.diffrn_refln.calc_chi_sq_points() refine_ls = RefineLs(goodness_of_fit_all=chi_sq / points, number_reflns=points) diffrn.add_items([refine_ls])