Hard constraint on Uisoequiv

73 views
Skip to first unread message

Sarah Thoma

unread,
Jan 6, 2023, 11:00:28 AM1/6/23
to diffpy-users
Hi everyone, 


I am a beginner in diffpy (and PDF analysis) and would like to impose a hard constraint on Uiso values to lie between 0 and 1. In previous conversations I read that there is the possibility to impose hard constraints as opposed to soft restraints. 

I assumed that the method Uiso.boundRange(lb=0, ub=1) would do the job but in my refinement results I see the Uisoequiv value significantly exceed 1 in some cases. 

I used:

atoms = generator.phase.atoms
for ap in atoms:
   ap.Uiso.boundRange(lb=0, ub=1)


Is it possible that my constraint got overridden by setting the atom to be anisotropically displaced? How can I set a hard constraint that keeps Uisoeqiuv to lie between 0 and 1?


Thank you in advance for your help!
Cheers,
Sarah

Mikkel Juelsholt

unread,
Jan 10, 2023, 5:42:13 PM1/10/23
to diffpy-users
Hi Sarah 

You want to use the recipe.restraincommand. 

Should work like recipe.restrain("Parameter name", lb = lower bond value, ub = upper bond value, sig = parameter to set the strictness of the constrain. Just set it to 0.001)

Hope it makes sense 

Cheers Mikkel

Simon Billinge

unread,
Jan 12, 2023, 6:47:09 AM1/12/23
to diffpy...@googlegroups.com
Hi Sarah,

Thanks Mikkel for that tip.

Let me take this opportunity to remind everyone of the difference between parameters and variables.   Parameters are quantities that are needed to define the physical/structural model.  In this sense, Uiso is a parameter.  It is a number that, for each atom, is encoding the uncertainty in the position of that atom.   It is an attribute of the structural model. 

On the other hand, Variables are things that are varied by the regression engine  when it does its work of fitting the data.  These are just numbers that the regression engine can vary to minimize the objective (agreement).

People often confuse these two concepts/things and it is understandable because we often want the parameters themselves to be varied and therefore the parameters to be the variables.  But in fact they are conceptually different. Sarah wanted to apply a hard constraint for the allowed range that a parameter was allowed to vary, but to do this we apply the constraint to the variable, not to the parameter.

We use constraint equations to link parameters to variables. This is done in the addVar() method for example, which has the pattern addVar(constraint_expression)  where it is implied that the resulting variable = constraint_expression. So 
recipe.addVar(atom1.Biso,
       name="atom1_biso_variable", 
       value=1., 
       fixed=True,
    )
will, in this case, assign a variable (in the FitRecipe object called "recipe") with the name atom1_biso_variable to the Biso parameter of the atom atom1 in the atom list in the structure object (phew).

We can then put strict bounds on this variable using the boundRange() method, e.g.,

recipe.addVar(atom1.Biso,
       name="atom1_biso_variable", 
       value=1.0, 
       fixed=True,
    ).boundRange(0.,5.)

Unfortunately the cmi docs are a little vague about the distinction between variables and parameters, in fact to my chagrin they get it all mixed up (anyone volunteer to fix that?) which makes them particularly confusing to follow.

This insight can give you superpowers though, because the constraint expressions can be much more complicated than just variable = parameter.  So, for example, variable = tan(parameter) allows the variable to range between +/- infinity but the parameter will range between -1 and 1, and things like that.

The details need to be worked out (I may have them wrong), but I just wanted to share the general concepts.  Hopefully, discussion and code snippets can follow.

One last comment...hard constraints can do nasty things to regressors which, in general, prefer smoothly varying functions than discontinuous functions.  A hard bound will take a value that exceeds the bound and set it back to the lowest/highest in-bound value, which is a rather harsh and not very physical thing to do and can result in poor convergence in a regressor.  It may be better to use a soft constraint but with rather sharp (but smooth) "edges".  This is the solution that Mikkel suggested.

S


--
You received this message because you are subscribed to the Google Groups "diffpy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to diffpy-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/diffpy-users/c02bbdb7-c48f-48f4-8dfc-f86a2fcc4747n%40googlegroups.com.


--
Simon Billinge
Professor, Columbia University
Physicist, Brookhaven National Laboratory

Sarah Thoma

unread,
Feb 19, 2023, 5:43:30 PM2/19/23
to diffpy-users
Hi Mikkel and Simon,

thank you for both of your responses, I ended up using the restraint option (after now knowing about the trickyness with hard constraints) and it worked great.

Cheers, Sarah

Simon Billinge

unread,
Feb 20, 2023, 4:41:25 AM2/20/23
to diffpy...@googlegroups.com
Glad to hear it!

Reply all
Reply to author
Forward
0 new messages