ToFuProject / tofu

Project for an open-source python library for synthetic diagnostics and tomography for Fusion devices
https://tofuproject.github.io/tofu/index.html
MIT License
68 stars 11 forks source link

Rocking curve computation of Germanium #654

Open Didou09 opened 2 years ago

Didou09 commented 2 years ago

Motivations:

Proposition:

Getting started:

Proposed todo list:

adriendaros commented 1 year ago

Motivation:


The compute_rockingcurve() routine available at tofu/spectro/_rockingcurve.py makes it possible to compute the diffraction pattern of specific crystals (material, Miller indices, etc). In order to symplify the code, all the main characteristics of the crystals implemented have been relocated into tofu/spectro/_rockingcurve_def.py, creating specific dictionnaries of crystals.

Example:


See below an example for the ArXVII crystal: image

How it is written:

All the geometrical and atomic parameters useful for the computation are stored into sub-dictionnaries such as:

All values which cannot be directly written into the dictionnary (see Nonevalues in front of each sub-dictionnary) are computed in the following parts of the file:

According to the last point, only the phases are stored inside the dictionnary. The formulas of the linear absorption coefficients and the components of the atomic scattering factor are called directly from the compute_rockingcurve() routine because of the dependency on the wavelength.

adriendaros commented 1 year ago

The use of the _compute_rockingcurve() routine works interactively with the tofu/spectro/_rockingcurve_def.py file. The uploading of a CrystalClass is still needed. The line code launching the routine is showed below:

image

The arguments showed here are sufficient:

For more information about the entry arguements, everything is explained at the beginning of the tofu/spectro/_rockingcurve.py routine: image

Results:

Didou09 commented 1 year ago

Well done @adriendaros !

If I may, I would suggest the following minor changes in the dictionnary:

'mesh' : {
    'type': 'hexagonal',
    'positions': {                                                    
        'Si': {                                                             
            'u': np.r_[0.465],                                              
            'x': None,                                                      
            'y': None,                                                      
            'z': None,                                                      
            'N': None,                                                      
        },                                                                  
        'O': {                                                              
            'u': np.r_[0.415, 0.272, 0.120],                                
            'x': None,                                                      
            'y': None,                                                      
            'z': None,                                                      
            'N': None,                                                      
        },                                                                  
    },                                                          
    'source': 'R.W.G. Wyckoff, Crystal Structures (1963)',
}  

and

'Inter-atomic': {
    'distances': {
        'a0': 4.91304,                                                      
        'c0': 5.40463,                                                      
       },        
    'units': 'A',
    'comments': 'within the unit cell',
    ' Tref': {                         # 'refetence temperature', but shorter
        'data': 25.,
        'units': 'C', 
    },

and

'Thermal expansion': {
    'coefs': {                                            
        'alpha_a': 1.337e-5,                                                
        'alpha_c': 7.97e-6,                                                 
    },
    'units': '1/C',                          
    'comments':   'in parallel directions to a0 and c0',               
    'source': 'R.W.G. Wyckoff, Crystal Structures',
}

and

'atomic scattering': { 
    'factor': {                                          
        'Si': np.r_[                                                        
            12., 11., 9.5, 8.8, 8.3, 7.7, 7.27, 6.25, 5.3,                  
            4.45, 3.75, 3.15, 2.7, 2.35, 2.07, 1.87, 1.71, 1.6,             
        ],                                                                  
        'O': np.r_[                                                         
            9., 7.836, 5.756, 4.068, 2.968, 2.313, 1.934, 1.710, 1.566,     
            1.462, 1.373, 1.294,                                            
        ],                                                                  
    },                                                                      
    'source': 'Intern. Tables for X-Ray Crystallography, Vol.I,II,III,IV (1985)',
}

=> it will allow to re-use some key words like 'source', 'units', ... which makes them more generic

Didou09 commented 1 year ago

@cjperks7 , once @adriendaros will have implemented those last minor changes, you're good to go

Didou09 commented 1 year ago

@adriendaros, @cjperks7 , just to let you know:

I am also adding a basic unit test to make sure the computation always works. It just runs it for akk known crystals at the same wavelength. It simply makes sure it is not broken and there is no bug that would stop the computation, does not check the value of the result and does not check plots.

Didou09 commented 1 year ago

@adriendaros , I have a question:

The key sin(theta)/lambda (now called sin_theta_lambda, see above for reasons), seems to never be used in the routine compute_rockingcurve(). => why is it never used ? => is it useful in the computation ? => if it is not useful, should we remove it ?

adriendaros commented 1 year ago

@adriendaros , I have a question:

The key sin(theta)/lambda (now called sin_theta_lambda, see above for reasons), seems to never be used in the routine compute_rockingcurve(). => why is it never used ? => is it useful in the computation ? => if it is not useful, should we remove it ?

@Didou09 don't do that you fool, it's very useful to get the values of the atomic scattering factor, real and imaginary parts, of each kind of atoms within the crystal.

Into tofu/spectro/_rocking_def.py, there is data corresponding to the variation of the atomic scattering[factors] with respect to this variable sin_theta_lambda for each atom.

In order to interpolate the value of the scattering factor in our crystals, the routine CrystBragg_comp_lattice_spacing() called by compute_rockingcurve() is computing the appropriated value of sin_theta_lambda for the crystal used, depending on the Miller indices and the wavelength targetted.

Then, you'll find into the compute_rockingcurve() routine line 214 part Calculation of the structure factor that this constant is called in the computation of each real and imaginary scattering factor for each atom.

So no, we can't do without it because of its great importance in the determination of the crystal structure factor.

Didou09 commented 1 year ago

OK, good reasons, keeping it (I did not delete it, was waiting for your answer)

cjperks7 commented 1 year ago

Documentation as of the last commit

Changes implemented --- (i) One can now calculate the rocking curve for Quartz with flexible choice on Miller indice by either:

Computes rocking curve

dout2 = rc.compute_rockingcurve( crystal = dcry2['name'], din=dcry2, lamb = 3.96, plot_power_ratio = False )

- Note that the two methods shown above give the same rocking curve since the target wavelength in the pre-defined crystals get over-written
- Benchmarking against the x0h code for two crystals of potential interest as been conducted to good agreement between the two models
- <img width="1264" alt="Screenshot 2023-06-20 at 1 44 47 PM" src="https://github.com/ToFuProject/tofu/assets/71457911/48832bf0-4b17-4203-8c77-b350ac914fb7">

(ii) It is now simple to loop over instances of `tofu.spectro._rockingcurve.compute_rockingcurve()` for Quartz with a target wavelength and arbitrary Miller indices to scope Bragg angle v. integrated reflectivity. All one needs to do is alter the array in `dcry2['miller']` as given above
- <img width="601" alt="Screenshot 2023-06-20 at 1 49 25 PM" src="https://github.com/ToFuProject/tofu/assets/71457911/24befce2-7c18-4882-96c9-8a54bbc02bc8">
- Note that this looping will be inserted into the tofu_sparc workflow under Issue015

(iii) These changes have been propagated up into `tofu.data._class5_check()` so that one can initiate a crystal using `coll.add_crystal()` choosing the `dmat` input to either be a string or dictionary as discussed in point (i). For example, building CMOD's Johann He-like Ar spectrometer:

dcry ={

Defines crystal geometry

'dgeom': {
    'cent': np.array([1,1,1]), # [m], center in global axis
    'nin': np.array([1,0,0]), # inward normal vec
    'e0': np.array([0,1,0]), # horizontal vec
    'e1': np.array([0,0,1]), # vertical vec
    'curve_r': np.array([1385e-3, 1385e-3]), # [m], crystal radius of curvature
    'extenthalf': np.array([64e-3/2, 27e-3/2]), # [m], disp. of corners wrt cent in (hor. ver.)
},
# Defines crystal material
'dmat': {
    'material': 'Quartz',
    'name': 'HIREX',
    'symbol': 'Qz102',
    'miller': np.r_[1., 0., 2.],
    'target':{
        'ion': 'Ar16+',
        'lamb': 3.96, # [1e-10 m], photon wavelength
        'units': 'm',
        }, 
    'd_hkl': 2.281124272650091, # [m], crystal lattice spacing
    },
}

Adds diffraction crystal object to diagnostic

coll.add_crystal( key='cry', dgeom=dcry['dgeom'], dmat=dcry['dmat'],

dmat='Quartz_102'

)

- It has been benchmarked that the expected rocking curve is stored in the `Collection` object
- <img width="591" alt="Screenshot 2023-06-20 at 1 56 09 PM" src="https://github.com/ToFuProject/tofu/assets/71457911/070e144a-3a5b-40f4-91b0-3afbb71b5ba1">
cjperks7 commented 1 year ago

@Didou09 @adriendaros Germanium rocking curves work now 🎉

Screenshot 2023-06-29 at 6 04 21 PM
cjperks7 commented 1 year ago

Will do a PR in ToFu and tofu_sparc tomorrow