- 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:
2
conman.c
2
conman.c
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
4
exebuf.c
4
exebuf.c
@ -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);
|
||||||
|
|
||||||
|
@ -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
33
hkl.c
@ -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++)
|
||||||
|
2
hklmot.c
2
hklmot.c
@ -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);
|
||||||
|
7
mesure.c
7
mesure.c
@ -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;
|
||||||
|
@ -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;
|
||||||
|
90
tasdrive.c
90
tasdrive.c
@ -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
251
tasub.c
@ -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]);
|
||||||
|
3
tasub.h
3
tasub.h
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
153
tasublib.c
153
tasublib.c
@ -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,
|
||||||
|
int ori){
|
||||||
|
assert(ori == VERT || ori == HOR);
|
||||||
|
if(ori == VERT){
|
||||||
return B1 + B2/Sind(ABS(theta));
|
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]);
|
|
||||||
if(ABS(sq) < .00001){
|
|
||||||
return BADRMATRIX;
|
|
||||||
}
|
|
||||||
om = Acosd(R[0][0]/sq);
|
|
||||||
om -= 180.;
|
|
||||||
tmp = Asind(R[1][0]/sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]));
|
|
||||||
|
|
||||||
tmp = Acosd(sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]));
|
|
||||||
angles->sgl = Asind(-R[2][0]);
|
angles->sgl = Asind(-R[2][0]);
|
||||||
|
if(ABS(angles->sgl -90.) < .5){
|
||||||
sq = sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]);
|
return BADUBORQ;
|
||||||
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]));
|
Now, this is slightly different then in the publication by M. Lumsden.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
om = Atan2d(R[1][0],R[0][0]);
|
||||||
|
angles->sgu = Atan2d(R[2][1],R[2][2]);
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
10
trigd.c
@ -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)
|
||||||
|
Reference in New Issue
Block a user