Changeset 4998 for trunk/GSASIIlattice.py
- Timestamp:
- Jul 21, 2021 3:04:47 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/GSASIIlattice.py ΒΆ
r4974 r4998 282 282 newCell[6] = calc_V(cell2A(newCell[:6])) 283 283 return newCell 284 284 285 # code to generate lattice constraint relationships between two phases 286 # (chemical & magnetic) related by a transformation matrix. 287 288 def 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 307 def 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 329 def 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 374 def 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 402 cellXformRelations = {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 440 cell generated from oldA[i] values. 441 ''' 442 # cellXformRelations values were generated using:: 443 # from GSASIIlattice import fmtCellConstraints,GenerateCellConstraints 444 # cellXformRelations = fmtCellConstraints(GenerateCellConstraints()) 445 446 def 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 285 488 def TransformXYZ(XYZ,Trans,Vec): 286 489 return np.inner(XYZ,Trans)+Vec
Note: See TracChangeset
for help on using the changeset viewer.