Adding all the atom coordinates in the expanded unit cell as variable for rigid body constrains

10 views
Skip to first unread message

Tomasz Stawski

unread,
Jun 12, 2024, 4:34:18 AMJun 12
to diffpy-users
Dear all,

I am performing fitting with a model which contains from the start many atoms. My superstructure is composed of 1080 atoms, but it has also high cubic symmetry (Pa-3), so it can be reduced. If I add xyz coordinates as fitting parameters using standar "for par in sgpar.xyzpars:" my fitting works flawlessly.
However, now I am developing a set of constrains defining polyhedra in the unit cell comprising bond length and bond angle conditions. For this, I would like to skip symmetry and add all the atoms in the unit cell. I am following a method written under this message. Let's assume that right now I treat coordinates as free variable without any other additional constrains.
This code adds variables to the recipe correctly, regardless if I use addVar (default) or newVar (just playing). I can see them with fit.getNames(). But when I run fitting, the xyz variables seem to be stuck on single values. When eventually the leastsq optimiser gives up, the values are unchanged, and the errors are crazy high at 1e12. All other variable like scale, or d2 are changing. I am using unified values of Uiso for each element, so these are reduced in my case to only 3, and they also are adjusted.

Is it a problem with having too many parameters? If I follow the sgpar.xyzpars route but for P1 symmetry, this seems to do something, although I have those extra coordinates. Or am I missing something in the code?
Any help would be highly appreciated!

Cheers,
Tomasz

 # =============================================================================
        pos_restrain = 2.0
        phase = 'Phase0'
        print('Adding all atoms in the unit cell.')     
added_params = set()

        for atom in getattr(cpdf, phase).phase.getScatterers():
            try:
                atom_label = atom.name
                atom_symbol= atom.element
                tags = ['xyz', 'xyz_' + atom_label, 'xyz_' + atom_symbol, 'xyz_' + atom_symbol + '_' + str(phase),'xyz_'+str(phase), str(phase)]
                # Add X coordinate
               
                x_var_name = f'x_{atom_label}_{phase}'
                if x_var_name not in added_params:
                    #fit.newVar(name = x_var_name, value = atom.x.value, fixed = False, tags = tags)
                    # fit.constrain(atom.x, x_var_name)
                    fit.addVar(atom.x, value = atom.x.value, name=x_var_name,fixed = False, tags=tags)
                    fit.restrain(x_var_name, lb = atom.x.value *(1-pos_restrain), ub =atom.x.value*(1+pos_restrain), sig = 0.0005)
                    added_params.add(x_var_name)
                    print(f"{x_var_name} : atom position added to variables.")
               
                # Add Y coordinate
                y_var_name = f'y_{atom_label}_{phase}'
                if y_var_name not in added_params:
                    # fit.newVar(name = y_var_name, value = atom.y.value, fixed = False, tags = tags)
                    # fit.constrain(atom.y, y_var_name)
                    fit.addVar(atom.y, value = atom.y.value, name=y_var_name, fixed = False, tags=tags)
                    added_params.add(y_var_name)
                    #fit.restrain(y_var_name, lb = atom.y.value *(1-pos_restrain), ub =atom.y.value*(1+pos_restrain), sig = 0.0005)
                    print(f"{y_var_name} : atom position added to variables.")
               
                # Add Z coordinate
                z_var_name = f'z_{atom_label}_{phase}'
                if z_var_name not in added_params:
                    # fit.newVar(name = z_var_name, value = atom.z.value, fixed = False, tags = tags)
                    # fit.constrain(atom.z, z_var_name)
                    fit.addVar(atom.z, value = atom.z.value, name=z_var_name, fixed = False, tags=tags)
                    added_params.add(z_var_name)
                    #fit.restrain(z_var_name, lb = atom.z.value *(1-pos_restrain), ub =atom.z.value*(1+pos_restrain), sig = 0.0005)
                    print(f"{z_var_name} : atom position added to variables.")
            except:
                pass
# =============================================================================
An output from .getNames():

for var in fit0.getNames():
   
    print(f"Added variable: {var}")
Added variable: delta2_Phase0
Added variable: s_Phase0
Added variable: a_Phase0
Added variable: Uiso_O_Phase0
Added variable: Uiso_Zr_Phase0
Added variable: Uiso_V_Phase0
Added variable: x_V0_Phase0
Added variable: y_V0_Phase0
Added variable: z_V0_Phase0
Added variable: x_V1_Phase0
Added variable: y_V1_Phase0
Added variable: z_V1_Phase0
Added variable: x_V2_Phase0
Added variable: y_V2_Phase0
Added variable: z_V2_Phase0
Added variable: x_V3_Phase0


Reply all
Reply to author
Forward
0 new messages