def test(): # Two random vectors vec_a = matrix.col((uniform(-20,20), uniform(-20,20), uniform(-20,20))) vec_b = matrix.col((uniform(-20,20), uniform(-20,20), uniform(-20,20))) # The test may fail if the angle between the vectors is small or close to pi # (see gradient of acos(x) for x close to 1 or -1) but we are not interested # in such cases anyway. Skip test if the acute angle is less than 1 degree if vec_a.accute_angle(vec_b, deg=True) < 1: return False a = vec_a.length() b = vec_b.length() a_dot_b = vec_a.dot(vec_b) gamma = acos(a_dot_b / (a*b)) # Analytical dg = AngleDerivativeWrtVectorElts(vec_a, vec_b) # FD dgFD = FDAngleDerivativeWrtVectorElts(vec_a, vec_b) assert approx_equal(dg.dtheta_du_1(), dgFD.dtheta_du_1()) assert approx_equal(dg.dtheta_du_2(), dgFD.dtheta_du_2()) assert approx_equal(dg.dtheta_du_3(), dgFD.dtheta_du_3()) assert approx_equal(dg.dtheta_dv_1(), dgFD.dtheta_dv_1()) assert approx_equal(dg.dtheta_dv_2(), dgFD.dtheta_dv_2()) assert approx_equal(dg.dtheta_dv_3(), dgFD.dtheta_dv_3()) # Test vector version assert approx_equal(dg.derivative_wrt_u(), matrix.col( (dg.dtheta_du_1(), dg.dtheta_du_2(), dg.dtheta_du_3()))) assert approx_equal(dg.derivative_wrt_v(), matrix.col( (dg.dtheta_dv_1(), dg.dtheta_dv_2(), dg.dtheta_dv_3()))) return True
a, b, c, aa, bb, cc = crystal.get_unit_cell().parameters() aa *= DEG2RAD bb *= DEG2RAD cc *= DEG2RAD Ut = crystal.get_U().transpose() avec, bvec, cvec = [Ut * vec for vec in crystal.get_real_space_vectors()] # calculate d[B^T]/dp dB_dp = xluc_param.get_ds_dp() dBT_dp = [dB.transpose() for dB in dB_dp] # calculate d[O]/dp dO_dp = [-O * dBT * O for dBT in dBT_dp] # objects to get derivative of angles wrt vectors dalpha = AngleDerivativeWrtVectorElts(bvec, cvec) dbeta = AngleDerivativeWrtVectorElts(avec, cvec) dgamma = AngleDerivativeWrtVectorElts(avec, bvec) # get all FD derivatives fd_grad = check_fd_gradients(xluc_param) # look at each parameter for i, dO in enumerate(dO_dp): print print "***** PARAMETER {0} *****".format(i) #print "dB_dp analytical" #print dB_dp[i] #print "dB_dp FD"