- Fixed sign problems with om in tasub

- Mended tasdrive to drive energy even if Q is askew
- Fixed QM values
- Fixed problems in mesure: om2th, wrong theta selection
- Fixed core dump when driving h,kl, failed
This commit is contained in:
koennecke
2005-06-09 12:04:38 +00:00
parent f33ca7b0d7
commit 3a0b4f293c
16 changed files with 1899 additions and 116 deletions

View File

@ -652,7 +652,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
SICSLogWrite(buffer,iOut); SICSLogWrite(buffer,iOut);
/* write to commandlog if user or manager privilege */ /* write to commandlog if user or manager privilege */
if(SCGetRights(self) <= usUser) if(SCGetRights(self) <= usUser && self->iMacro != 1)
{ {
sprintf(pBueffel,"To sock %d :",iRet); sprintf(pBueffel,"To sock %d :",iRet);
WriteToCommandLog(pBueffel,buffer); WriteToCommandLog(pBueffel,buffer);

View File

@ -419,7 +419,10 @@
case HWFault: /* real HW error: burning, no net etc.. */ case HWFault: /* real HW error: burning, no net etc.. */
ExeInterest(self, pDev, "finished with problem"); ExeInterest(self, pDev, "finished with problem");
DeleteDevEntry(pDev); DeleteDevEntry(pDev);
pDev = NULL;
LLDnodeDataTo(self->iList,&pDev);
LLDnodeDelete(self->iList); LLDnodeDelete(self->iList);
iRet = LLDnodePtr2Prev(self->iList);
self->iStatus = DEVERROR; self->iStatus = DEVERROR;
if(pDrivInt) if(pDrivInt)
{ {

View File

@ -129,7 +129,7 @@ static pDynString findBlockEnd(pExeBuf self){
return NULL; return NULL;
} }
buffer = GetCharArray(self->bufferContent); buffer = GetCharArray(self->bufferContent);
if(self->end != 0){ if(self->end != -1){
self->start = self->end + 1; self->start = self->end + 1;
} }
for(i = self->start; i < strlen(buffer); i++){ for(i = self->start; i < strlen(buffer); i++){
@ -162,7 +162,7 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics,
assert(pSics); assert(pSics);
self->start = 0; self->start = 0;
self->end = 0; self->end = -1;
self->lineno = 0; self->lineno = 0;
pTcl = InterpGetTcl(pSics); pTcl = InterpGetTcl(pSics);

View File

@ -629,7 +629,7 @@
if(isInTOFMode(self->pDriv->data)) if(isInTOFMode(self->pDriv->data))
{ {
iDim[*nDim] = getNoOfTimebins(self->pDriv->data); iDim[*nDim] = getNoOfTimebins(self->pDriv->data);
*nDim ++; *nDim = *nDim + 1;
} }
return 1; return 1;
} }

33
hkl.c
View File

@ -887,6 +887,30 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
return 0; return 0;
} }
/*------------------------------------------------------------------------*/
static void stopHKLMotors(pHKL self)
{
if(self->pTheta != NULL)
{
self->pTheta->pDrivInt->Halt(self->pTheta);
}
if(self->pOmega != NULL)
{
self->pOmega->pDrivInt->Halt(self->pOmega);
}
if(self->pChi != NULL)
{
self->pChi->pDrivInt->Halt(self->pChi);
}
if(self->pPhi != NULL)
{
self->pPhi->pDrivInt->Halt(self->pPhi);
}
if(self->pNu != NULL)
{
self->pNu->pDrivInt->Halt(self->pNu);
}
}
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int RunHKL(pHKL self, float fHKL[3], int RunHKL(pHKL self, float fHKL[3],
float fPsi, int iHamil, SConnection *pCon) float fPsi, int iHamil, SConnection *pCon)
@ -911,7 +935,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
if(!iRet) if(!iRet)
{ {
SCWrite(pCon,"ERROR: cannot start two theta motor",eError); SCWrite(pCon,"ERROR: cannot start two theta motor",eError);
StopExe(pServ->pExecutor,"all"); stopHKLMotors(self);
return 0; return 0;
} }
@ -921,7 +945,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
if(!iRet) if(!iRet)
{ {
SCWrite(pCon,"ERROR: cannot start omega motor",eError); SCWrite(pCon,"ERROR: cannot start omega motor",eError);
StopExe(pServ->pExecutor,"all"); stopHKLMotors(self);
return 0; return 0;
} }
@ -933,7 +957,6 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
pDum->pDescriptor, pDum, pCon,fSet[2]); pDum->pDescriptor, pDum, pCon,fSet[2]);
if(!iRet) if(!iRet)
{ {
StopExe(pServ->pExecutor,"all");
SCWrite(pCon,"ERROR: cannot start nu motor",eError); SCWrite(pCon,"ERROR: cannot start nu motor",eError);
return 0; return 0;
} }
@ -953,7 +976,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
if(!iRet) if(!iRet)
{ {
SCWrite(pCon,"ERROR: cannot start chi motor",eError); SCWrite(pCon,"ERROR: cannot start chi motor",eError);
StopExe(pServ->pExecutor,"all"); stopHKLMotors(self);
return 0; return 0;
} }
pDum = (pDummy)self->pPhi; pDum = (pDummy)self->pPhi;
@ -962,7 +985,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
if(!iRet) if(!iRet)
{ {
SCWrite(pCon,"ERROR: cannot start phi",eError); SCWrite(pCon,"ERROR: cannot start phi",eError);
StopExe(pServ->pExecutor,"all"); stopHKLMotors(self);
return 0; return 0;
} }
for(i = 0; i < 3; i++) for(i = 0; i < 3; i++)

View File

@ -107,10 +107,10 @@ static int HKLCheckStatus(void *pData, SConnection *pCon){
assert(self != NULL); assert(self != NULL);
if(self->pHkl->targetDirty == 1){ if(self->pHkl->targetDirty == 1){
status = RunHKL(self->pHkl,self->pHkl->targetHKL,.0,0,pCon); status = RunHKL(self->pHkl,self->pHkl->targetHKL,.0,0,pCon);
self->pHkl->targetDirty = 0;
if(status != 1){ if(status != 1){
return HWFault; return HWFault;
} }
self->pHkl->targetDirty = 0;
return HWBusy; return HWBusy;
} else { } else {
return checkMotors(self,pCon); return checkMotors(self,pCon);

View File

@ -633,6 +633,8 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
ClearScanVar(self->pScanner); ClearScanVar(self->pScanner);
AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega, AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega,
fStart, stepWidth); fStart, stepWidth);
snprintf(pBueffel,131,"Scanning om from %f with step %f", fStart, stepWidth);
SCWrite(pCon,pBueffel,eValue);
/* /*
Oksana does not want o2t scans to be tightly coupled, this is why we Oksana does not want o2t scans to be tightly coupled, this is why we
cannot use the normal o2t scan variable. Instead we calculate new limits and cannot use the normal o2t scan variable. Instead we calculate new limits and
@ -648,6 +650,8 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
fStart -= (np/2.)*stepWidth; fStart -= (np/2.)*stepWidth;
AddScanVar(self->pScanner, pServ->pSics,pCon,self->pC2Theta, AddScanVar(self->pScanner, pServ->pSics,pCon,self->pC2Theta,
fStart, stepWidth); fStart, stepWidth);
snprintf(pBueffel,131,"Scanning 2theta from %f with step %f", fStart, stepWidth);
SCWrite(pCon,pBueffel,eValue);
} }
/* /*
@ -665,10 +669,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
} }
/* do the scan */ /* do the scan */
snprintf(pBueffel,131,"Scanning %s, step %f, np = %d",scanVar, stepWidth, np);
SCWrite(pCon,pBueffel,eWarning);
free(scanVar); free(scanVar);
if(self->iCompact) if(self->iCompact)
{ {
self->pScanner->CollectScanData = CompactScanData; self->pScanner->CollectScanData = CompactScanData;

View File

@ -154,8 +154,8 @@ CreateSocketAdress(
i = sizeof(struct linger); i = sizeof(struct linger);
lili.l_onoff = 1; lili.l_onoff = 1;
lili.l_linger = 1; lili.l_linger = 1;
/* setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i); setsockopt(pRes->sockid,SOL_SOCKET,SO_LINGER,&lili,i);
*/
pRes->iType = PORT; pRes->iType = PORT;
pRes->lMagic = NETMAGIC; pRes->lMagic = NETMAGIC;
return pRes; return pRes;

1443
nxxml.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
#define ACH 11 #define ACH 11
/*============== Drivable Interface functions =====================*/ /*============== Drivable Interface functions =====================*/
static int TASSetValue(void *pData, SConnection *pCon, static long TASSetValue(void *pData, SConnection *pCon,
float value){ float value){
ptasMot self = (ptasMot)pData; ptasMot self = (ptasMot)pData;
assert(self); assert(self);
@ -142,7 +142,8 @@ static float TASQMGetValue(void *pData, SConnection *pCon){
if(status != 1){ if(status != 1){
return -999.99; return -999.99;
} }
status = calcTasPowderPosition(&self->math->machine, angles, &self->math->current); status = calcTasPowderPosition(&self->math->machine,
angles, &self->math->current);
if(status < 0){ if(status < 0){
SCWrite(pCon,"ERROR: out of memory calculating Q-E variables",eError); SCWrite(pCon,"ERROR: out of memory calculating Q-E variables",eError);
return -999.99; return -999.99;
@ -176,7 +177,7 @@ static int TASHalt(void *pData){
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int startMotors(ptasMot self, tasAngles angles, static int startMotors(ptasMot self, tasAngles angles,
SConnection *pCon){ SConnection *pCon, int driveQ){
float val; float val;
double curve; double curve;
int status; int status;
@ -276,6 +277,9 @@ static int startMotors(ptasMot self, tasAngles angles,
} }
} }
} }
if(driveQ == 0){
return OKOK;
}
/* /*
crystal crystal
@ -319,39 +323,95 @@ static int startMotors(ptasMot self, tasAngles angles,
self->math->mustDrive = 0; self->math->mustDrive = 0;
return OKOK; return OKOK;
} }
/*---------------------------------------------------------------------------*/
static int checkQMotorLimits(ptasMot self, SConnection *pCon,
tasAngles angles){
int status, retVal = 1;
char error[131];
char pBueffel[256];
status = self->math->motors[A3]->pDrivInt->CheckLimits(self->math->motors[A3],
angles.a3,
error,
131);
if(status != 1) {
retVal = 0;
snprintf(pBueffel,256,"ERROR: limit violation an a3: %s", error);
SCWrite(pCon,pBueffel,eError);
}
status = self->math->motors[A4]->pDrivInt->CheckLimits(self->math->motors[A4],
angles.sample_two_theta,
error,
131);
if(status != 1) {
retVal = 0;
snprintf(pBueffel,256,"ERROR: limit violation an a4: %s", error);
SCWrite(pCon,pBueffel,eError);
}
status = self->math->motors[A3]->pDrivInt->CheckLimits(self->math->motors[SGU],
angles.sgu,
error,
131);
if(status != 1) {
retVal = 0;
snprintf(pBueffel,256,"ERROR: limit violation an SGU: %s", error);
SCWrite(pCon,pBueffel,eError);
}
status = self->math->motors[SGL]->pDrivInt->CheckLimits(self->math->motors[SGL],
angles.sgl,
error,
131);
if(status != 1) {
retVal = 0;
snprintf(pBueffel,256,"ERROR: limit violation an SGL: %s", error);
SCWrite(pCon,pBueffel,eError);
}
return retVal;
}
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
static int calculateAndDrive(ptasMot self, SConnection *pCon){ static int calculateAndDrive(ptasMot self, SConnection *pCon){
tasAngles angles; tasAngles angles;
int status; int status, driveQ = 1;
if(self->math->ubValid == 0){
SCWrite(pCon,"WARNING: UB matrix invalid",eWarning);
}
status = calcAllTasAngles(&self->math->machine, self->math->target, status = calcAllTasAngles(&self->math->machine, self->math->target,
&angles); &angles);
self->math->mustDrive = 0;
switch(status){ switch(status){
case ENERGYTOBIG: case ENERGYTOBIG:
SCWrite(pCon,"ERROR: desired energy to big",eError); SCWrite(pCon,"ERROR: desired energy to big",eError);
self->math->mustDrive = 0;
return HWFault; return HWFault;
break; break;
case UBNOMEMORY: case UBNOMEMORY:
SCWrite(pCon,"ERROR: out of memory calculating angles",eError); SCWrite(pCon,"ERROR: out of memory calculating angles",eError);
self->math->mustDrive = 0; driveQ = 0;
return HWFault;
break; break;
case BADRMATRIX: case BADRMATRIX:
SCWrite(pCon,"ERROR: bad crystallographic parameters or bad UB",eError); SCWrite(pCon,"ERROR: bad crystallographic parameters or bad UB",eError);
self->math->mustDrive = 0; driveQ = 0;
return HWFault; break;
case BADUBORQ:
SCWrite(pCon,"ERROR: bad UB matrix or bad Q-vector",eError);
driveQ = 0;
break; break;
case TRIANGLENOTCLOSED: case TRIANGLENOTCLOSED:
SCWrite(pCon,"ERROR: cannot close scattering triangle",eError); SCWrite(pCon,"ERROR: cannot close scattering triangle",eError);
self->math->mustDrive = 0; driveQ = 0;
return HWFault;
break; break;
default:
return startMotors(self,angles,pCon);
} }
return HWFault; if(!checkQMotorLimits(self,pCon,angles)){
driveQ = 0;
}
if(driveQ == 0){
SCWrite(pCon,"WARNING: NOT driving Q-vector because of errors",eError);
}
return startMotors(self,angles,pCon, driveQ);
} }
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
static int checkMotors(ptasMot self, SConnection *pCon){ static int checkMotors(ptasMot self, SConnection *pCon){

251
tasub.c
View File

@ -53,6 +53,7 @@ static void saveReflections(ptasUB self, char *name, FILE *fd){
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
static int tasUBSave(void *pData, char *name, FILE *fd){ static int tasUBSave(void *pData, char *name, FILE *fd){
ptasUB self = (ptasUB)pData; ptasUB self = (ptasUB)pData;
tasReflection r;
if(self == NULL){ if(self == NULL){
return 0; return 0;
@ -83,8 +84,16 @@ static int tasUBSave(void *pData, char *name, FILE *fd){
name, name,
self->target.qh, self->target.qk, self->target.ql, self->target.qm, self->target.qh, self->target.qk, self->target.ql, self->target.qm,
self->target.ki, self->target.kf); self->target.ki, self->target.kf);
fprintf(fd,"%s setidx %d %d\n", r = self->r1;
name, self->r1, self->r2); fprintf(fd,"%s r1 %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
name, r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, r.angles.sample_two_theta,
r.angles.sgu, r.angles.sgl,
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
r = self->r2;
fprintf(fd,"%s r2 %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
name, r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, r.angles.sample_two_theta,
r.angles.sgu, r.angles.sgl,
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
fprintf(fd,"%s update\n", name); fprintf(fd,"%s update\n", name);
return 1; return 1;
} }
@ -455,6 +464,8 @@ static int tasReadCell(SConnection *pCon, ptasUB self, int argc, char *argv[]){
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return 0; return 0;
} }
self->ubValid = 0;
SCWrite(pCon,"WARNING: UB is now invalid",eWarning);
SCparChange(pCon); SCparChange(pCon);
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
@ -477,8 +488,7 @@ static void clearReflections(ptasUB self){
LLDnodeDelete(self->reflectionList); LLDnodeDelete(self->reflectionList);
status = LLDnodePtr2Next(self->reflectionList); status = LLDnodePtr2Next(self->reflectionList);
} }
self->r1 = -1; self->ubValid = 0;
self->r2 = -1;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
static void listReflections(ptasUB self, SConnection *pCon){ static void listReflections(ptasUB self, SConnection *pCon){
@ -621,6 +631,84 @@ static int addReflection(ptasUB self, SicsInterp *pSics,
SCparChange(pCon); SCparChange(pCon);
return 1; return 1;
} }
/*------------------------------------------------------------------------------*/
static int readReflection(SConnection *pCon, SicsInterp *pSics,
ptasReflection res,
int argc, char *argv[]){
tasReflection r;
int status;
char pBueffel[256];
if(!SCMatchRights(pCon,usUser)){
return 0;
}
if(argc < 11){
SCWrite(pCon,"ERROR: not enough parameters to read reflection",eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&r.qe.qh);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&r.qe.qk);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&r.qe.ql);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&r.angles.a3);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&r.angles.sample_two_theta);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[7],&r.angles.sgu);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[8],&r.angles.sgl);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[8]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[9],&r.qe.ki);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[9]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
r.qe.ki = energyToK(r.qe.ki);
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[10],&r.qe.kf);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[10]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
r.qe.kf = energyToK(r.qe.kf);
if(ABS(r.qe.ki - r.qe.kf) > .01) {
SCWrite(pCon,"WARNING: KI != KF!",eWarning);
}
*res = r;
return 1;
}
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
int findReflection(int list, int idx, ptasReflection r){ int findReflection(int list, int idx, ptasReflection r){
int count = 0; int count = 0;
@ -642,7 +730,7 @@ static void listUB(ptasUB self , SConnection *pCon){
Tcl_DString list; Tcl_DString list;
char pBueffel[255]; char pBueffel[255];
int i; int i;
tasReflection r;
Tcl_DStringInit(&list); Tcl_DStringInit(&list);
if(self->machine.UB == NULL){ if(self->machine.UB == NULL){
@ -658,9 +746,32 @@ static void listUB(ptasUB self , SConnection *pCon){
Tcl_DStringAppend(&list,pBueffel,-1); Tcl_DStringAppend(&list,pBueffel,-1);
} }
} }
snprintf(pBueffel,255,"UB generated from reflections %d and %d in list\n", snprintf(pBueffel,255,"UB generated from reflections:\n");
self->r1, self->r2);
Tcl_DStringAppend(&list,pBueffel,-1); Tcl_DStringAppend(&list,pBueffel,-1);
snprintf(pBueffel,255,
" QH QK QL A3 A4 SGU SGL EI EF\n");
Tcl_DStringAppend(&list,pBueffel,-1);
r = self->r1;
snprintf(pBueffel,255,
" %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
Tcl_DStringAppend(&list,pBueffel,-1);
r = self->r2;
snprintf(pBueffel,255,
" %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
Tcl_DStringAppend(&list,pBueffel,-1);
snprintf(pBueffel,255,"Plane Normal: %8.4f %8.4f %8.4f\n",
self->machine.planeNormal[0][0], self->machine.planeNormal[1][0],
self->machine.planeNormal[2][0]);
Tcl_DStringAppend(&list,pBueffel,-1);
if(self->ubValid == 0){
Tcl_DStringAppend(&list,"WARNING: UB matrix is invalid\n",-1);
}
SCWrite(pCon,Tcl_DStringValue(&list),eValue); SCWrite(pCon,Tcl_DStringValue(&list),eValue);
Tcl_DStringFree(&list); Tcl_DStringFree(&list);
} }
@ -723,7 +834,7 @@ static void listDiagnostik(ptasUB self, SConnection *pCon){
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics, static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
int argc, char *argv[]){ int argc, char *argv[]){
int idx, status; int idx1, idx2, status;
tasReflection r1, r2; tasReflection r1, r2;
char pBueffel[256]; char pBueffel[256];
MATRIX UB = NULL; MATRIX UB = NULL;
@ -739,32 +850,32 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
return 0; return 0;
} }
status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&idx); status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&idx1);
if(status != TCL_OK){ if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]); snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return 0; return 0;
} }
status = findReflection(self->reflectionList, idx-1,&r1); idx1--;
status = findReflection(self->reflectionList, idx1,&r1);
if(status != 1){ if(status != 1){
snprintf(pBueffel,255,"ERROR: cannot find reflection with index %d",idx); snprintf(pBueffel,255,"ERROR: cannot find reflection with index %d",idx1+1);
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return 0; return 0;
} }
self->r1 = idx; status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&idx2);
status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&idx);
if(status != TCL_OK){ if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]); snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return 0; return 0;
} }
status = findReflection(self->reflectionList, idx-1,&r2); idx2--;
status = findReflection(self->reflectionList, idx2,&r2);
if(status != 1){ if(status != 1){
snprintf(pBueffel,255,"ERROR: cannot find reflection with index %d",idx); snprintf(pBueffel,255,"ERROR: cannot find reflection with index %d",idx2+1);
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return 0; return 0;
} }
self->r2 = idx;
UB = calcTasUBFromTwoReflections(self->cell,r1,r2,&status); UB = calcTasUBFromTwoReflections(self->cell,r1,r2,&status);
if(UB == NULL){ if(UB == NULL){
@ -778,6 +889,10 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
} }
return 0; return 0;
} }
if(mat_det(UB) < .000001){
SCWrite(pCon,"ERROR: invalid UB matrix, check reflections",eError);
return 0;
}
if(self->machine.UB != NULL){ if(self->machine.UB != NULL){
mat_free(self->machine.UB); mat_free(self->machine.UB);
} }
@ -786,6 +901,9 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
} }
self->machine.UB = UB; self->machine.UB = UB;
self->machine.planeNormal = calcPlaneNormal(r1,r2); self->machine.planeNormal = calcPlaneNormal(r1,r2);
self->r1 = r1;
self->r2 = r2;
self->ubValid = 1;
listUB(self,pCon); listUB(self,pCon);
listDiagnostik(self,pCon); listDiagnostik(self,pCon);
SCparChange(pCon); SCparChange(pCon);
@ -866,6 +984,74 @@ static int calcRefAngles(ptasUB self, SConnection *pCon,
return 1; return 1;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
static int calcQFromAngles(ptasUB self, SConnection *pCon,
SicsInterp *pSics,
int argc, char *argv[]){
tasQEPosition q;
tasAngles angles;
char pBueffel[256];
int status;
if(argc < 8){
SCWrite(pCon,"ERROR: need a2, a3, a4, sgu, sgl, a6 for calculation",
eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],
&angles.monochromator_two_theta);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&angles.a3);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&angles.sample_two_theta);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&angles.sgu);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&angles.sgl);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[7],&angles.analyzer_two_theta);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = calcTasQEPosition(&self->machine,angles,&q);
switch(status){
case UBNOMEMORY:
SCWrite(pCon,"ERROR: Out of memory calculating angles",eError);
return 0;
break;
}
snprintf(pBueffel,255,"%8.4f %8.4f %8.4f %8.4f %8.4f",
q.qh,
q.qk,
q.ql,
KtoEnergy(q.ki),
KtoEnergy(q.kf));
SCWrite(pCon,pBueffel,eValue);
return 1;
}
/*------------------------------------------------------------------*/
static int setUB(SConnection *pCon, SicsInterp *pSics, ptasUB self, static int setUB(SConnection *pCon, SicsInterp *pSics, ptasUB self,
int argc, char *argv[]){ int argc, char *argv[]){
double value; double value;
@ -953,28 +1139,13 @@ static int setUB(SConnection *pCon, SicsInterp *pSics, ptasUB self,
return 0; return 0;
} }
self->machine.UB[2][2] = value; self->machine.UB[2][2] = value;
self->ubValid = 1;
SCSendOK(pCon); SCSendOK(pCon);
SCparChange(pCon); SCparChange(pCon);
return 1; return 1;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
static int setIDX(SConnection *pCon, SicsInterp *pSics, ptasUB self,
int argc, char *argv[]){
if(argc < 4) {
SCWrite(pCon,"ERROR: not enough arguments to setidx", eError);
return 0;
}
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
self->r1 = atoi(argv[2]);
self->r2 = atoi(argv[3]);
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------*/
static int setNormal(SConnection *pCon, SicsInterp *pSics, ptasUB self, static int setNormal(SConnection *pCon, SicsInterp *pSics, ptasUB self,
int argc, char *argv[]){ int argc, char *argv[]){
double value; double value;
@ -1114,11 +1285,6 @@ static int deleteReflection(SConnection *pCon, SicsInterp *pSics,
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return 0; return 0;
} }
if(idx == self->r1 || idx == self->r2) {
SCWrite(pCon,"ERROR: I refuse to delete reflections used for current UB",
eError);
return 0;
}
idx--; idx--;
status = LLDnodePtr2First(self->reflectionList); status = LLDnodePtr2First(self->reflectionList);
while(status == 1){ while(status == 1){
@ -1162,6 +1328,7 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
} else if(strcmp(argv[1],"clear") == 0){ } else if(strcmp(argv[1],"clear") == 0){
clearReflections(self); clearReflections(self);
clearReflections(self); clearReflections(self);
SCWrite(pCon,"WARNING: UB is now invalid",eWarning);
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
} else if(strcmp(argv[1],"listref") == 0){ } else if(strcmp(argv[1],"listref") == 0){
@ -1174,20 +1341,24 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
return 1; return 1;
} else if(strcmp(argv[1],"makeub") == 0){ } else if(strcmp(argv[1],"makeub") == 0){
return calcUB(self,pCon,pSics,argc,argv); return calcUB(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"calcref") == 0){ } else if(strcmp(argv[1],"calcang") == 0){
return calcRefAngles(self,pCon,pSics,argc,argv); return calcRefAngles(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"calcqe") == 0){
return calcQFromAngles(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"setub") == 0){ } else if(strcmp(argv[1],"setub") == 0){
return setUB(pCon,pSics,self,argc,argv); return setUB(pCon,pSics,self,argc,argv);
} else if(strcmp(argv[1],"setnormal") == 0){ } else if(strcmp(argv[1],"setnormal") == 0){
return setNormal(pCon,pSics,self,argc,argv); return setNormal(pCon,pSics,self,argc,argv);
} else if(strcmp(argv[1],"setidx") == 0){
return setIDX(pCon,pSics,self,argc,argv);
} else if(strcmp(argv[1],"settarget") == 0){ } else if(strcmp(argv[1],"settarget") == 0){
return setTarget(pCon,pSics,self,argc,argv); return setTarget(pCon,pSics,self,argc,argv);
} else if(strcmp(argv[1],"update") == 0){ } else if(strcmp(argv[1],"update") == 0){
return tasUpdate(pCon,self); return tasUpdate(pCon,self);
} else if(strcmp(argv[1],"del") == 0){ } else if(strcmp(argv[1],"del") == 0){
return deleteReflection(pCon,pSics,self,argc,argv); return deleteReflection(pCon,pSics,self,argc,argv);
} else if(strcmp(argv[1],"r1") == 0){
return readReflection(pCon,pSics,&self->r1,argc,argv);
} else if(strcmp(argv[1],"r2") == 0){
return readReflection(pCon,pSics,&self->r2,argc,argv);
} else if(strcmp(argv[1],"const") == 0){ } else if(strcmp(argv[1],"const") == 0){
if(argc > 2){ if(argc > 2){
strtolower(argv[2]); strtolower(argv[2]);

View File

@ -27,7 +27,8 @@
int mustRecalculate; int mustRecalculate;
int mustDrive; int mustDrive;
pMotor motors[12]; pMotor motors[12];
int r1, r2; tasReflection r1, r2;
int ubValid;
}tasUB, *ptasUB; }tasUB, *ptasUB;

View File

@ -18,6 +18,8 @@
#define PI 3.141592653589793 #define PI 3.141592653589793
#define ECONST 2.072 #define ECONST 2.072
#define DEGREE_RAD (PI/180.0) /* Radians per degree */ #define DEGREE_RAD (PI/180.0) /* Radians per degree */
#define VERT 0
#define HOR 1
/*============== monochromator/analyzer stuff =========================*/ /*============== monochromator/analyzer stuff =========================*/
double energyToK(double energy){ double energyToK(double energy){
double K; double K;
@ -33,8 +35,14 @@ double KtoEnergy(double k){
return energy; return energy;
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
static double calcCurvature(double B1, double B2, double theta){ static double calcCurvature(double B1, double B2, double theta,
return B1 + B2/Sind(ABS(theta)); int ori){
assert(ori == VERT || ori == HOR);
if(ori == VERT){
return B1 + B2/Sind(ABS(theta));
} else {
return B1 + B2*Sind(ABS(theta));
}
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
int maCalcTwoTheta(maCrystal data, double k, double *two_theta){ int maCalcTwoTheta(maCrystal data, double k, double *two_theta){
@ -51,11 +59,11 @@ int maCalcTwoTheta(maCrystal data, double k, double *two_theta){
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
double maCalcVerticalCurvature(maCrystal data, double two_theta){ double maCalcVerticalCurvature(maCrystal data, double two_theta){
return calcCurvature(data.VB1,data.VB2, two_theta/2.); return calcCurvature(data.VB1,data.VB2, two_theta/2.,VERT);
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
double maCalcHorizontalCurvature(maCrystal data, double two_theta){ double maCalcHorizontalCurvature(maCrystal data, double two_theta){
return calcCurvature(data.HB1,data.HB2, two_theta/2.); return calcCurvature(data.HB1,data.HB2, two_theta/2.,HOR);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
double maCalcK(maCrystal data, double two_theta){ double maCalcK(maCrystal data, double two_theta){
@ -155,11 +163,22 @@ static MATRIX calcTasUVectorFromAngles(tasReflection r){
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2){ MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2){
MATRIX u1 = NULL, u2 = NULL, planeNormal = NULL; MATRIX u1 = NULL, u2 = NULL, planeNormal = NULL;
int i;
u1 = calcTasUVectorFromAngles(r1); u1 = calcTasUVectorFromAngles(r1);
u2 = calcTasUVectorFromAngles(r2); u2 = calcTasUVectorFromAngles(r2);
if(u1 != NULL && u2 != NULL){ if(u1 != NULL && u2 != NULL){
return vectorCrossProduct(u1,u2); planeNormal = vectorCrossProduct(u1,u2);
/*
The plane normal has to point to the stars and not to the earth
core in order for the algorithm to work.
*/
if(planeNormal[2][0] < .0){
for(i = 0; i < 3; i++){
planeNormal[i][0] = -1.*planeNormal[i][0];
}
}
return planeNormal;
} else { } else {
return NULL; return NULL;
} }
@ -187,11 +206,15 @@ MATRIX calcTasUBFromTwoReflections(lattice cell, tasReflection r1,
h2 = tasReflectionToHC(r2.qe,B); h2 = tasReflectionToHC(r2.qe,B);
if(h1 == NULL || h2 == NULL){ if(h1 == NULL || h2 == NULL){
*errorCode = UBNOMEMORY; *errorCode = UBNOMEMORY;
mat_free(B);
return NULL; return NULL;
} }
HT = matFromTwoVectors(h1,h2); HT = matFromTwoVectors(h1,h2);
if(HT == NULL){ if(HT == NULL){
*errorCode = UBNOMEMORY; *errorCode = UBNOMEMORY;
mat_free(B);
mat_free(h1);
mat_free(h2);
return NULL; return NULL;
} }
@ -202,39 +225,59 @@ MATRIX calcTasUBFromTwoReflections(lattice cell, tasReflection r1,
u2 = calcTasUVectorFromAngles(r2); u2 = calcTasUVectorFromAngles(r2);
if(u1 == NULL || u2 == NULL){ if(u1 == NULL || u2 == NULL){
*errorCode = UBNOMEMORY; *errorCode = UBNOMEMORY;
mat_free(B);
mat_free(h1);
mat_free(h2);
return NULL; return NULL;
} }
UT = matFromTwoVectors(u1,u2); UT = matFromTwoVectors(u1,u2);
if(UT == NULL){ if(UT == NULL){
*errorCode = UBNOMEMORY; *errorCode = UBNOMEMORY;
mat_free(B);
mat_free(h1);
mat_free(h2);
mat_free(u1);
mat_free(u2);
mat_free(HT);
return NULL; return NULL;
} }
/*
debugging output
printf("B-matrix\n");
mat_dump(B);
printf("HT-matrix\n");
mat_dump(HT);
printf("UT-matrix\n");
mat_dump(UT);
*/
/* /*
UT = U * HT UT = U * HT
*/ */
HTT = mat_tran(HT); HTT = mat_tran(HT);
if(HTT == NULL){ if(HTT == NULL){
*errorCode = UBNOMEMORY; *errorCode = UBNOMEMORY;
mat_free(B);
mat_free(h1);
mat_free(h2);
mat_free(u1);
mat_free(u2);
mat_free(HT);
return NULL; return NULL;
} }
U = mat_mul(UT,HTT); U = mat_mul(UT,HTT);
if(U == NULL){ if(U == NULL){
*errorCode = UBNOMEMORY; *errorCode = UBNOMEMORY;
mat_free(B);
mat_free(h1);
mat_free(h2);
mat_free(u1);
mat_free(u2);
mat_free(HT);
mat_free(HTT);
return NULL; return NULL;
} }
UB = mat_mul(U,B); UB = mat_mul(U,B);
if(UB == NULL){ if(UB == NULL){
mat_free(B);
mat_free(h1);
mat_free(h2);
mat_free(u1);
mat_free(u2);
mat_free(HT);
mat_free(HTT);
mat_free(U);
*errorCode = UBNOMEMORY; *errorCode = UBNOMEMORY;
} }
@ -296,12 +339,14 @@ static MATRIX tasReflectionToQC(tasQEPosition r, MATRIX UB){
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal, static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal,
tasQEPosition qe){ tasQEPosition qe, int *errorCode){
MATRIX U1V, U2V, TV, TVINV, M; MATRIX U1V, U2V, TV, TVINV, M;
*errorCode = 1;
U1V = tasReflectionToQC(qe,UB); U1V = tasReflectionToQC(qe,UB);
if(U1V == NULL){ if(U1V == NULL){
*errorCode = UBNOMEMORY;
return NULL; return NULL;
} }
normalizeVector(U1V); normalizeVector(U1V);
@ -309,6 +354,13 @@ static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal,
U2V = vectorCrossProduct(planeNormal,U1V); U2V = vectorCrossProduct(planeNormal,U1V);
if(U2V == NULL){ if(U2V == NULL){
killVector(U1V); killVector(U1V);
*errorCode = UBNOMEMORY;
return NULL;
}
if(vectorLength(U2V) < .0001){
*errorCode = BADUBORQ;
killVector(U1V);
killVector(U2V);
return NULL; return NULL;
} }
@ -316,9 +368,14 @@ static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal,
if(TV == NULL){ if(TV == NULL){
killVector(U1V); killVector(U1V);
killVector(U2V); killVector(U2V);
*errorCode = UBNOMEMORY;
return NULL; return NULL;
} }
TVINV = mat_inv(TV); TVINV = mat_inv(TV);
if(TVINV == NULL){
*errorCode = BADUBORQ;
}
killVector(U1V); killVector(U1V);
killVector(U2V); killVector(U2V);
@ -329,30 +386,36 @@ static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal,
int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe, int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
ptasAngles angles){ ptasAngles angles){
MATRIX R, QC; MATRIX R, QC;
double om, q, theta, cos2t, tmp, sq; double om, q, theta, cos2t;
int errorCode = 1;
R = buildRMatrix(UB, planeNormal, qe); R = buildRMatrix(UB, planeNormal, qe, &errorCode);
if(R == NULL){ if(R == NULL){
return UBNOMEMORY; return errorCode;
} }
sq = sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]); angles->sgl = Asind(-R[2][0]);
if(ABS(sq) < .00001){ if(ABS(angles->sgl -90.) < .5){
return BADRMATRIX; return BADUBORQ;
} }
om = Acosd(R[0][0]/sq); /*
om -= 180.; Now, this is slightly different then in the publication by M. Lumsden.
tmp = Asind(R[1][0]/sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0])); The reason is that the atan2 helps to determine the sign of om
whereas the sin, cos formula given by M. Lumsden yield ambiguous signs
especially for om.
sgu = atan(R[2][1],R[2][2]) where:
R[2][1] = cos(sgl)sin(sgu)
R[2][2] = cos(sgu)cos(sgl)
om = atan(R[1][0],R[0][0]) where:
R[1][0] = sin(om)cos(sgl)
R[0][0] = cos(om)cos(sgl)
The definitions of th R components are taken from M. Lumsden
R-matrix definition.
*/
tmp = Acosd(sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0])); om = Atan2d(R[1][0],R[0][0]);
angles->sgl = Asind(-R[2][0]); angles->sgu = Atan2d(R[2][1],R[2][2]);
sq = sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]);
if(ABS(sq) < .00001){
return BADRMATRIX;
}
angles->sgu = Asind(R[2][1]/sq);
tmp = Acosd(R[2][2]/sqrt(R[0][0]*R[0][0]+R[1][0]*R[1][0]));
QC = tasReflectionToQC(qe,UB); QC = tasReflectionToQC(qe,UB);
if(QC == NULL){ if(QC == NULL){
@ -370,6 +433,15 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
theta = calcTheta(qe.ki, qe.kf,angles->sample_two_theta); theta = calcTheta(qe.ki, qe.kf,angles->sample_two_theta);
angles->a3 = om + theta; angles->a3 = om + theta;
/*
put a3 into -180, 180 properly. We cal always turn by 180 because the
scattering geometry is symmetric in this respect. It is like looking at
the scattering plane from the other side
*/
angles->a3 -= 180.;
if(angles->a3 < -180.){
angles->a3 += 360.;
}
killVector(QC); killVector(QC);
mat_free(R); mat_free(R);
@ -395,9 +467,10 @@ int calcTasQH(MATRIX UB, tasAngles angles, ptasQEPosition qe){
Thereby take into account the physicists magic fudge Thereby take into account the physicists magic fudge
2PI factor 2PI factor
*/ */
q = sqrt(qe->ki*qe->ki + qe->kf*qe->kf - 2.*qe->ki*qe->kf*Cosd(angles.sample_two_theta)); q = sqrt(qe->ki*qe->ki + qe->kf*qe->kf -
q /= 2. * PI; 2.*qe->ki*qe->kf*Cosd(angles.sample_two_theta));
qe->qm = q; qe->qm = q;
q /= 2. * PI;
for(i = 0; i < 3; i++){ for(i = 0; i < 3; i++){
QV[i][0] *= q; QV[i][0] *= q;
@ -431,14 +504,14 @@ int calcAllTasAngles(ptasMachine machine, tasQEPosition qe,
return status; return status;
} }
status = calcTasQAngles(machine->UB, machine->planeNormal, status = maCalcTwoTheta(machine->analyzer,qe.kf,&
machine->ss_sample, qe,angles); angles->analyzer_two_theta);
if(status != 1){ if(status != 1){
return status; return status;
} }
status = maCalcTwoTheta(machine->analyzer,qe.kf,& status = calcTasQAngles(machine->UB, machine->planeNormal,
angles->analyzer_two_theta); machine->ss_sample, qe,angles);
if(status != 1){ if(status != 1){
return status; return status;
} }
@ -498,7 +571,6 @@ int calcTasPowderPosition(ptasMachine machine, tasAngles angles,
qe->qm = sqrt(qe->ki*qe->ki + qe->kf*qe->kf - qe->qm = sqrt(qe->ki*qe->ki + qe->kf*qe->kf -
2.*qe->ki*qe->kf*Cosd(angles.sample_two_theta)); 2.*qe->ki*qe->kf*Cosd(angles.sample_two_theta));
return 1; return 1;
} }
/*====================== Logic implementation =========================*/ /*====================== Logic implementation =========================*/
@ -582,6 +654,3 @@ double getTasPar(tasQEPosition qe, int tasVar){
assert(0); assert(0);
} }
} }

View File

@ -17,6 +17,7 @@
#define UBNOMEMORY -702 #define UBNOMEMORY -702
#define TRIANGLENOTCLOSED -703 #define TRIANGLENOTCLOSED -703
#define BADRMATRIX -704 #define BADRMATRIX -704
#define BADUBORQ -705
/*========================== defines for tasMode ====================*/ /*========================== defines for tasMode ====================*/
#define KICONST 1 #define KICONST 1
#define KFCONST 2 #define KFCONST 2

10
trigd.c
View File

@ -53,6 +53,16 @@ extern double Atand (double x)
return (data); return (data);
} }
/******************************************************************************* /*******************************************************************************
* Atan of angle in degrees.
*******************************************************************************/
extern double Atan2d (double x, double y)
{
double data;
data = (atan2(x,y)/DEGREE_RAD);
return (data);
}
/*******************************************************************************
* Atan2 of angle in degrees. * Atan2 of angle in degrees.
*******************************************************************************/ *******************************************************************************/
extern double Atand2 (double x) extern double Atand2 (double x)

View File

@ -14,4 +14,5 @@
double Atand2 (double x); double Atand2 (double x);
double Acosd (double x); double Acosd (double x);
double Asind (double x); double Asind (double x);
double Atan2d(double x, double y);
#endif #endif