source: trunk/GSASIImpsubs.py @ 3049

Last change on this file since 3049 was 3049, checked in by toby, 4 years ago

reset InitMP after SelectConfigSetting?.OnApplyChanges? to allow number of cores to change on the fly

  • Property svn:eol-style set to native
File size: 6.9 KB
Line 
1# -*- coding: utf-8 -*-
2'''
3*GSASIImpsubs - routines used in multiprocessing*
4-------------------------------------------------
5
6The routines here are called either directly when GSAS-II is used without multiprocessing
7or in separate cores when multiprocessing is used.
8
9These routines are designed to be used in one of two ways:
10
11 * when multiprocessing is
12   enabled (see global variable useMP) the computational routines are called in
13   separate Python interpreter that is created and then deleted after use.
14
15 * when useMP is False, these routines are called directly from the main "thread".
16
17Note that :func:`GSASIImpsubs.InitMP` should be called before any of the other routines
18in this module are used.
19'''
20########### SVN repository information ###################
21# $Date: $
22# $Author: $
23# $Revision: $
24# $URL: $
25# $Id: $
26########### SVN repository information ###################
27import multiprocessing as mp
28import numpy as np
29import numpy.ma as ma
30import numpy.linalg as nl
31import GSASIIpath
32GSASIIpath.SetVersionNumber("$Revision: 2895 $")
33import GSASIIpwd as G2pwd
34import GSASIIstrMath as G2stMth
35
36sind = lambda x: np.sin(x*np.pi/180.)
37cosd = lambda x: np.cos(x*np.pi/180.)
38tand = lambda x: np.tan(x*np.pi/180.)
39#asind = lambda x: 180.*np.arcsin(x)/np.pi
40#acosd = lambda x: 180.*np.arccos(x)/np.pi
41#atan2d = lambda y,x: 180.*np.arctan2(y,x)/np.pi
42   
43ncores = None
44
45def ResetMP():
46    '''Call after changing Config var 'Multiprocessing_cores' to force a resetting
47    of the useMP from the parameter.
48    '''
49    global ncores
50    ncores = None
51   
52def InitMP(allowMP=True):
53    '''Called to initialize use of Multiprocessing
54    '''
55    global useMP,ncores
56    if ncores is not None: return useMP,ncores
57    useMP = False
58    if not allowMP:
59        print('Multiprocessing disabled')
60        ncores = 0
61        return useMP,ncores
62    ncores = GSASIIpath.GetConfigValue('Multiprocessing_cores',0)
63    if ncores < 0: ncores = mp.cpu_count()/2
64    if ncores > 1:
65        useMP = True
66    #if GSASIIpath.GetConfigValue('debug') and useMP:
67    if useMP:
68        print('Multiprocessing with {} cores enabled'.format(ncores))
69    return useMP,ncores
70
71################################################################################
72# Fobs Squared computation
73################################################################################       
74def InitFobsSqGlobals(x1,ratio1,shl1,xB1,xF1,im1,lamRatio1,kRatio1,xMask1,Ka21):
75    '''Initialize for the computation of Fobs Squared for powder histograms.
76    Puts lots of junk into the global namespace in this module.
77    '''
78    global x,ratio,shl,xB,xF,im,lamRatio,kRatio,xMask,Ka2
79    x = ma.getdata(x1)
80    ratio = ratio1
81    shl = shl1
82    xB = xB1
83    xF = xF1
84    im = im1
85    lamRatio = lamRatio1
86    kRatio = kRatio1
87    xMask = xMask1
88    Ka2 = Ka21
89
90def ComputeFobsSqCWbatch(profList):
91    sInt = 0
92    resList = []
93    for refl,iref in profList:
94        icod = ComputeFobsSqCW(refl,iref)
95        if type(icod) is tuple:
96            resList.append((icod[0],iref))
97            sInt += icod[1]
98        elif icod == -1:
99            res.append((None,iref))
100        elif icod == -2:
101            break
102    return sInt,resList
103
104def ComputeFobsSqTOFbatch(profList):
105    sInt = 0
106    resList = []
107    for refl,iref in profList:
108        icod = ComputeFobsSqTOF(refl,iref)
109        if type(icod) is tuple:
110            resList.append((icod[0],iref))
111            sInt += icod[1]
112        elif icod == -1:
113            res.append((None,iref))
114        elif icod == -2:
115            break
116    return sInt,resList
117       
118def ComputeFobsSqCW(refl,iref):
119    yp = np.zeros(len(x)) # not masked
120    sInt = 0
121    refl8im = 0
122    Wd,fmin,fmax = G2pwd.getWidthsCW(refl[5+im],refl[6+im],refl[7+im],shl)
123    iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
124    iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
125    iFin2 = iFin
126    if not iBeg+iFin:       #peak below low limit - skip peak
127        return 0
128    if ma.all(xMask[iBeg:iFin]):    #peak entirely masked - skip peak
129        return -1
130    elif not iBeg-iFin:     #peak above high limit - done
131        return -2
132    elif iBeg < iFin:
133        yp[iBeg:iFin] = refl[11+im]*refl[9+im]*G2pwd.getFCJVoigt3(
134            refl[5+im],refl[6+im],refl[7+im],shl,x[iBeg:iFin])
135        sInt = refl[11+im]*refl[9+im]
136        if Ka2:
137            pos2 = refl[5+im]+lamRatio*tand(refl[5+im]/2.0)       # + 360/pi * Dlam/lam * tan(th)
138            Wd,fmin,fmax = G2pwd.getWidthsCW(pos2,refl[6+im],refl[7+im],shl)
139            iBeg2 = max(xB,np.searchsorted(x,pos2-fmin))
140            iFin2 = min(np.searchsorted(x,pos2+fmax),xF)
141            if iFin2 > iBeg2: 
142                yp[iBeg2:iFin2] += refl[11+im]*refl[9+im]*kRatio*G2pwd.getFCJVoigt3(
143                    pos2,refl[6+im],refl[7+im],shl,x[iBeg2:iFin2])
144                sInt *= 1.+kRatio
145    refl8im = np.sum(np.where(ratio[iBeg:iFin2]>0.,yp[iBeg:iFin2]*ratio[iBeg:iFin2]/(refl[11+im]*(1.+kRatio)),0.0))
146    return refl8im,sInt
147
148def ComputeFobsSqTOF(refl,iref):
149    yp = np.zeros(len(x)) # not masked
150    refl8im = 0
151    Wd,fmin,fmax = G2pwd.getWidthsTOF(refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im])
152    iBeg = max(xB,np.searchsorted(x,refl[5+im]-fmin))
153    iFin = max(xB,min(np.searchsorted(x,refl[5+im]+fmax),xF))
154    if not iBeg+iFin:       #peak below low limit - skip peak
155        return 0
156    if ma.all(xMask[iBeg:iFin]):    #peak entirely masked - skip peak
157        return -1
158    elif not iBeg-iFin:     #peak above high limit - done
159        return -2
160    if iBeg < iFin:
161        yp[iBeg:iFin] = refl[11+im]*refl[9+im]*G2pwd.getEpsVoigt(
162            refl[5+im],refl[12+im],refl[13+im],refl[6+im],refl[7+im],x[iBeg:iFin])
163    refl8im = np.sum(np.where(ratio[iBeg:iFin]>0.,yp[iBeg:iFin]*ratio[iBeg:iFin]/refl[11+im],0.0))
164    return refl8im,refl[11+im]*refl[9+im]
165################################################################################
166# Powder Profile computation
167################################################################################       
168def InitPwdrProfGlobals(im1,shl1,x1):
169    '''Initialize for the computation of Fobs Squared for powder histograms.
170    Puts lots of junk into the global namespace in this module.
171    '''
172    global im,shl,x
173    im = im1
174    shl = shl1
175    x = ma.getdata(x1)
176    global cw
177    cw = np.diff(x)
178    cw = np.append(cw,cw[-1])
179    # create local copies of ycalc array
180    global yc
181    yc = np.zeros_like(x)
182
183
184def ComputePwdrProfCW(profList):
185    'Compute the peaks profile for a set of CW peaks and add into the yc array'
186    for pos,refl,iBeg,iFin,kRatio in profList:
187        yc[iBeg:iFin] += refl[11+im]*refl[9+im]*kRatio*G2pwd.getFCJVoigt3(
188            pos,refl[6+im],refl[7+im],shl,x[iBeg:iFin])
189    return yc
190
191def ComputePwdrProfTOF(profList):
192    'Compute the peaks profile for a set of TOF peaks and add into the yc array'
193    for pos,refl,iBeg,iFin in profList:
194        yc[iBeg:iFin] += refl[11+im]*refl[9+im]*G2pwd.getEpsVoigt(
195            pos,refl[12+im],refl[13+im],refl[6+im],refl[7+im],x[iBeg:iFin])/cw[iBeg:iFin]
196    return yc
197   
Note: See TracBrowser for help on using the repository browser.