Ignore:
Timestamp:
Jul 21, 2021 3:04:47 PM (4 years ago)
Author:
toby
Message:

partial fix of magnetic constraints (still need to deal w/unvaried items; fullrmc minor stuff

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/GSASIIlattice.py ΒΆ

    r4974 r4998  
    282282    newCell[6] = calc_V(cell2A(newCell[:6]))
    283283    return newCell
    284    
     284
     285# code to generate lattice constraint relationships between two phases
     286# (chemical & magnetic) related by a transformation matrix.
     287
     288def symInner(M1,M2):
     289    '''Compute inner product of two square matrices with symbolic processing
     290    Use dot product because sympy does not define an inner product primitive
     291
     292    This requires that M1 & M2 be two sympy objects, as created in
     293    GenerateCellConstraints().
     294
     295    Note that this is only used to do the symbolic math needed to generate
     296    cell relationships. It is not used normally in GSAS-II.
     297    '''
     298    import sympy as sym
     299    prodOuter = []
     300    for i in range(3):
     301        prod = []
     302        for j in range(3):
     303            prod.append(M1[i,:].dot(M2[j,:]))
     304        prodOuter.append(prod)
     305    return sym.Matrix(prodOuter)
     306
     307def GenerateCellConstraints():
     308    '''Generate unit cell constraints for transforming one set of A tensor
     309    values to another using symbolic math (requires the sympy package)
     310
     311    Note that this is only used to do the symbolic math needed to generate
     312    cell relationships. It is not used normally in GSAS-II.
     313    '''
     314    import sympy as sym
     315    # define A tensor for starting cell
     316    A0, A1, A2, A3, A4, A5 = sym.symbols('A0, A1, A2, A3, A4, A5')
     317    G = sym.Matrix([ [A0,    A3/2.,  A4/2.],
     318                     [A3/2.,  A1,    A5/2.],
     319                     [A4/2.,  A5/2.,   A2 ]] )
     320    # define transformation matrix
     321    T00, T10, T20, T01, T11, T21, T02, T12, T22 = sym.symbols(
     322        'T00, T10, T20, T01, T11, T21, T02, T12, T22')
     323    Tr = sym.Matrix([ [T00, T10, T20], [T01, T11, T21], [T02, T12, T22],])
     324    # apply transform
     325    newG = symInner(symInner(Tr,G),Tr).expand()
     326    # define A tensor for converted cell
     327    return [newG[0,0],newG[1,1],newG[2,2],2.*newG[0,1],2.*newG[0,2],2.*newG[1,2]]
     328
     329def subVals(expr,A,T):
     330    '''Evaluate the symbolic expressions by substituting for A0-A5 & Tij
     331
     332    This can be used on the cell relationships created in
     333    :func:`GenerateCellConstraints` like this::
     334
     335       Trans = np.array([ [2/3, 4/3, 1/3], [-1, 0, 0], [-1/3, -2/3, 1/3] ])
     336       T = np.linalg.inv(Trans).T
     337       print([subVals(i,Aold,T) for i in GenerateCellConstraints()])
     338
     339    :param list expr: a list of sympy expressions.
     340    :param list A: This is the A* tensor as defined above.
     341    :param np.array T: a 3x3 transformation matrix where,
     342       Trans = np.array([ [2/3, 4/3, 1/3], [-1, 0, 0], [-1/3, -2/3, 1/3] ])
     343       (for a' = 2/3a + 4/3b + 1/3c; b' = -a; c' = -1/3, -2/3, 1/3)
     344       then T = np.linalg.inv(Trans).T
     345
     346    Note that this is only used to do the symbolic math needed to generate
     347    cell relationships. It is not used normally in GSAS-II.
     348    '''
     349    import sympy as sym
     350    A0, A1, A2, A3, A4, A5 = sym.symbols('A0, A1, A2, A3, A4, A5')
     351    # transformation matrix
     352    T00, T10, T20, T01, T11, T21, T02, T12, T22 = sym.symbols(
     353        'T00, T10, T20, T01, T11, T21, T02, T12, T22')
     354    vals = dict(zip([T00, T10, T20, T01, T11, T21, T02, T12, T22],T.ravel()))
     355    vals.update(dict(zip([A0, A1, A2, A3, A4, A5],A)))
     356    return float(expr.subs(vals))
     357
     358# some sample test code using the routines above follows::
     359# Trans = np.array([ [2/3, 4/3, 1/3], [-1, 0, 0], [-1/3, -2/3, 1/3] ])
     360# Mat = np.linalg.inv(Trans).T
     361# Aold = [0.05259986634758891, 0.05259986634758891, 0.005290771904550856, 0.052599866347588925, 0, 0]
     362# Anew = [0.018440738491448085, 0.03944989976069168, 0.034313054205100654, 0, -0.00513684555559103, 0]
     363# cellConstr = G2lat.GenerateCellConstraints()
     364# calcA = [G2lat.subVals(i,Aold,Mat) for i in cellConstr]
     365# print('original   xform A',Anew)
     366# print('calculated xfrom A',calcA)
     367# print('input')
     368# print('  old cell',G2lat.A2cell(Aold))
     369# print('  new cell',G2lat.A2cell(Anew))
     370# print('derived results')
     371# print('  from eq.',G2lat.A2cell(calcA))
     372# print('  diffs   ',np.array(G2lat.A2cell(calcA)) - G2lat.A2cell(Anew))
     373
     374def fmtCellConstraints(cellConstr):
     375    '''Format the cell relationships created in :func:`GenerateCellConstraints`
     376    in a format that can be used to generate constraints.
     377
     378    Use::
     379
     380      cXforms = G2lat.fmtCellConstraints(G2lat.GenerateCellConstraints())
     381
     382    Note that this is only used to do the symbolic math needed to generate
     383    cell relationships. It is not used normally in GSAS-II.
     384    '''
     385    import re
     386    import sympy as sym
     387    A3, A4, A5 = sym.symbols('A3, A4, A5')
     388    consDict = {}
     389    for num,cons in enumerate(cellConstr):
     390        cons = str(cons.factor(A3,A4,A5,deep=True).simplify())
     391        cons = re.sub('T([0-2]?)([0-2]?)',r'T[\2,\1]',cons) # Tij to T[j,i]
     392        l = []
     393        for i in str(cons).split('+'):
     394            if ')' in i:
     395                l[-1] += ' + ' + i.strip()
     396            else:
     397                l.append(i.strip())
     398        print("\nA'{} = ".format(num),str(cons))
     399        consDict[num] = l
     400    return consDict
     401
     402cellXformRelations = {0: ['1.0*A0*T[0,0]**2',
     403                              '1.0*A1*T[0,1]**2',
     404                              '1.0*A2*T[0,2]**2',
     405                              '1.0*A3*T[0,0]*T[0,1]',
     406                              '1.0*A4*T[0,0]*T[0,2]',
     407                              '1.0*A5*T[0,1]*T[0,2]'],
     408                    1: ['1.0*A0*T[1,0]**2',
     409                            '1.0*A1*T[1,1]**2',
     410                            '1.0*A2*T[1,2]**2',
     411                            '1.0*A3*T[1,0]*T[1,1]',
     412                            '1.0*A4*T[1,0]*T[1,2]',
     413                            '1.0*A5*T[1,1]*T[1,2]'],
     414                    2: ['1.0*A0*T[2,0]**2',
     415                            '1.0*A1*T[2,1]**2',
     416                            '1.0*A2*T[2,2]**2',
     417                            '1.0*A3*T[2,0]*T[2,1]',
     418                            '1.0*A4*T[2,0]*T[2,2]',
     419                            '1.0*A5*T[2,1]*T[2,2]'],
     420                    3: ['2.0*A0*T[0,0]*T[1,0]',
     421                            '2.0*A1*T[0,1]*T[1,1]',
     422                            '2.0*A2*T[0,2]*T[1,2]',
     423                            '1.0*A3*(T[0,0]*T[1,1] + T[1,0]*T[0,1])',
     424                            '1.0*A4*(T[0,0]*T[1,2] + T[1,0]*T[0,2])',
     425                            '1.0*A5*(T[0,1]*T[1,2] + T[1,1]*T[0,2])'],
     426                    4: ['2.0*A0*T[0,0]*T[2,0]',
     427                            '2.0*A1*T[0,1]*T[2,1]',
     428                            '2.0*A2*T[0,2]*T[2,2]',
     429                            '1.0*A3*(T[0,0]*T[2,1] + T[2,0]*T[0,1])',
     430                            '1.0*A4*(T[0,0]*T[2,2] + T[2,0]*T[0,2])',
     431                            '1.0*A5*(T[0,1]*T[2,2] + T[2,1]*T[0,2])'],
     432                    5: ['2.0*A0*T[1,0]*T[2,0]',
     433                            '2.0*A1*T[1,1]*T[2,1]',
     434                            '2.0*A2*T[1,2]*T[2,2]',
     435                            '1.0*A3*(T[1,0]*T[2,1] + T[2,0]*T[1,1])',
     436                            '1.0*A4*(T[1,0]*T[2,2] + T[2,0]*T[1,2])',
     437                            '1.0*A5*(T[1,1]*T[2,2] + T[2,1]*T[1,2])']}
     438
     439'''cellXformRelations provide the constraints on newA[i] values for a new
     440cell generated from oldA[i] values.
     441'''
     442# cellXformRelations values were generated using::
     443#   from GSASIIlattice import fmtCellConstraints,GenerateCellConstraints
     444#   cellXformRelations = fmtCellConstraints(GenerateCellConstraints())
     445
     446def GenCellConstraints(Trans,origPhase,newPhase,origA,debug=False):
     447    '''Generate the constraints between two unit cells constants for a phase transformed
     448    by matrix Trans.
     449
     450    :param np.array Trans: a 3x3 direct cell transformation matrix where,
     451       Trans = np.array([ [2/3, 4/3, 1/3], [-1, 0, 0], [-1/3, -2/3, 1/3] ])
     452       (for a' = 2/3a + 4/3b + 1/3c; b' = -a; c' = -1/3, -2/3, 1/3)
     453    :param int origPhase: phase id (pId) for original phase
     454    :param int newPhase: phase id for the transformed phase to be constrained from
     455      original phase
     456    :param list origA: reciprocal cell ("A*") tensor
     457    :param bool debug: If true, the constraint input is used to compute and print A*
     458      and from that the direct cell for the transformed phase.
     459    '''
     460    import GSASIIobj as G2obj
     461    T = Mat = np.linalg.inv(Trans).T
     462    Anew = []
     463    constrList = []
     464    for i in range(6):
     465        constr = [[-1.0,G2obj.G2VarObj('{}::A{}'.format(newPhase,i))]]
     466        mult = []
     467        for j,item in enumerate(cellXformRelations[i]):
     468            const, aTerm, tTerm = item.split('*',2)
     469            const = float(const) * eval(tTerm)
     470            # ignore terms where either the Transform contribution is zero.
     471            #if abs(const * origA[j]) > 1e-8:
     472            # If A term is zero this may indicate a symmetry constraint or an
     473            # accidentally zero. If required as zero then it will not be refined
     474            # and we do not want to include it, but if accidentally zero we do,
     475            # so include them for now and remove later.
     476            if abs(const) > 1e-8:
     477                constr.append([const,G2obj.G2VarObj('{}::{}'.format(origPhase,aTerm))])
     478                mult.append(const)
     479            else:
     480                mult.append(0)
     481        constrList.append(constr + [0.0,None,'c'])
     482        if debug: Anew.append(np.dot(origA,mult))           
     483    if debug:
     484        print('xformed A*  ',Anew)
     485        print('xformed cell',A2cell(Anew))
     486    return constrList
     487
    285488def TransformXYZ(XYZ,Trans,Vec):
    286489    return np.inner(XYZ,Trans)+Vec
Note: See TracChangeset for help on using the changeset viewer.