void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double Jul1,Jul2; int retVal; if(nrhs!=2){ mexErrMsgTxt("Wrong number of inputs"); } /*Extract the input arguments.*/ Jul1 = getDoubleFromMatlab(prhs[0]); Jul2 = getDoubleFromMatlab(prhs[1]); /*Call the function in the SOFA library.*/ retVal=iauTcbtdb(Jul1, Jul2, &Jul1, &Jul2); if(retVal!=0) { mexErrMsgTxt("An error occurred."); } plhs[0]=mxCreateDoubleMatrix(1,1,mxREAL); *(double*)mxGetData(plhs[0])=Jul1; if(nlhs>1) { plhs[1]=mxCreateDoubleMatrix(1,1,mxREAL); *(double*)mxGetData(plhs[1])=Jul2; } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double R, P, T, wl; double A,B; if(nrhs>4) { mexErrMsgTxt("Incorrect number of inputs."); return; } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); return; } //Get the relative humidity if(nrhs>0&&mxGetM(prhs[0])!=0) { R=getDoubleFromMatlab(prhs[0]); } else {//Otherwise get the value from the Constants class. R=getScalarMatlabClassConst("Constants","standardRelHumid"); } //Get the pressure if(nrhs>1&&mxGetM(prhs[1])!=0) { P=getDoubleFromMatlab(prhs[1]); } else {//Otherwise, get the value from the Constants class. P=getScalarMatlabClassConst("Constants","standardAtmosphericPressure"); } //Get the temperature if(nrhs>2&&mxGetM(prhs[2])!=0) { T=getDoubleFromMatlab(prhs[2]); } else {//Otherwise get the value from the Constants class. T=getScalarMatlabClassConst("Constants","standardTemp"); } //wl is inputted in meters, but needs to be in micrometers for the //function iauAtco13 if(nrhs>3&&mxGetM(prhs[3])!=0) { wl= getDoubleFromMatlab(prhs[3]); } else { wl=0.574e-6; } //Convert from Pascals to millibars. P*=0.01; //Convert from degrees Kelvin to degrees Centigrade. T+=-273.15; //Convert from meters to micrometers. wl*=1e6; //Get the parameters for the simple refraction model. iauRefco(P, T, R, wl,&A, &B); //Allocate space for the return values. plhs[0]=doubleMat2Matlab(&A,1,1); if(nlhs>1) { plhs[1]=doubleMat2Matlab(&B,1,1); } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *vec, *retVec, TT1,TT2; double rb[3][3], rp[3][3], rbp[3][3]; mxArray *retMATLAB; size_t i, numItems; if(nrhs!=3) { mexErrMsgTxt("Wrong number of inputs"); return; } if(nlhs>1) { mexErrMsgTxt("Wrong number of outputs"); return; } numItems=mxGetN(prhs[0]); if(mxGetM(prhs[0])!=3) { mexErrMsgTxt("vec has the wrong dimensionality. It must be an 3XN matrix."); return; } checkRealDoubleArray(prhs[0]); vec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //Allocate the return vector retMATLAB=mxCreateDoubleMatrix(3,numItems,mxREAL); retVec=mxGetData(retMATLAB); //Call the IAU function to get the rotation matrix. iauBp06(TT1, TT2, rb, rp, rbp); //Invert the rotation matrix by transposing it. iauTr(rb, rb); for(i=0; i<numItems; i++) { //Multiply the original vectors by the matrix to put it into the ICRS. iauRxp(rb, vec+3*i, retVec+3*i); } //Set the return value. plhs[0]=retMATLAB; }
static double MatlabCallback(int n, const double *x, int *undefined_flag, void *data) { mxArray *rhs[2]; mxArray *lhs[2]; double *oldPtr; double fVal; bool violatesConstraints; //feval in Matlab will take the function handle and the state as //inputs. //The first function handle is f. rhs[0]=(mxArray*)data; rhs[1]=mxCreateNumericMatrix(0, 0, mxDOUBLE_CLASS, mxREAL); //Set the matrix data to x oldPtr=mxGetPr(rhs[1]); //x will not be modified, but the const must be typecast away to use //the mxSetPr function. mxSetPr(rhs[1],(double*)x); mxSetM(rhs[1], (size_t)n); mxSetN(rhs[1], 1); //Get the function value and gradient. mexCallMATLAB(2,lhs,2,rhs,"feval"); //Get the function value. fVal=getDoubleFromMatlab(lhs[0]); violatesConstraints=getBoolFromMatlab(lhs[1]); if(violatesConstraints) { *undefined_flag=1; } //Get rid of the returned Matlab Matrices. mxDestroyArray(lhs[0]); mxDestroyArray(lhs[1]); //Set the data pointer back to what it was during allocation that //mxDestroyArray does not have a problem. mxSetPr(rhs[1],oldPtr); mxSetM(rhs[1], 0); mxSetN(rhs[1], 0); //Get rid of the temporary natrix. mxDestroyArray(rhs[1]); return fVal; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { const mxArray *MatlabFunctionHandle; direct_algorithm theAlgorithm=DIRECT_ORIGINAL; const direct_objective_func f=&MatlabCallback; size_t numDim; double *lowerBounds; double *upperBounds; int maxFEval=500; int maxIter=100; double epsilon=1e-4; double epsilonAbs=0; double volumeRelTol=1e-10; double sigmaRelTol=0; double fGlobal=DIRECT_UNKNOWN_FGLOBAL; double fGlobalRelTol=DIRECT_UNKNOWN_FGLOBAL; int maxDiv=5000; //To hold return values direct_return_code retVal; double *x; double fVal; if(nrhs<3||nrhs>4){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>3) { mexErrMsgTxt("Wrong number of outputs."); } //Check that a function handle was passed. if(!mxIsClass(prhs[0],"function_handle")) { mexErrMsgTxt("The first input must be a function handle."); } MatlabFunctionHandle=prhs[0]; //Check the lower and upper bounds checkRealDoubleArray(prhs[1]); checkRealDoubleArray(prhs[2]); numDim=mxGetM(prhs[1]); if(numDim<1||mxGetN(prhs[1])!=1) { mexErrMsgTxt("The lower bounds have the wrong dimensionality."); } if(mxGetM(prhs[2])!=numDim||mxGetN(prhs[1])!=1) { mexErrMsgTxt("The upper bounds have the wrong dimensionality."); } //The function in the library only uses integers for dimensions. if(numDim>INT_MAX) { mexErrMsgTxt("The problem has too many dimensions to be solved using this function."); } lowerBounds=(double*)mxGetData(prhs[1]); upperBounds=(double*)mxGetData(prhs[2]); //If a structure of options was given if(nrhs>3&&!mxIsEmpty(prhs[3])) { //We have to check for every possible structure member. mxArray *theField; if(!mxIsStruct(prhs[3])) { mexErrMsgTxt("The options must be given in a structure."); } theField=mxGetField(prhs[3],0,"algorithm"); if(theField!=NULL) {//If the field is present. int algType=getIntFromMatlab(theField); //Algorithm type switch(algType) { case 0: theAlgorithm=DIRECT_ORIGINAL; break; case 1: theAlgorithm=DIRECT_GABLONSKY; break; default: mexErrMsgTxt("Invalid algorithm specified"); } } theField=mxGetField(prhs[3],0,"maxDiv"); if(theField!=NULL) {//If the field is present. maxDiv=getIntFromMatlab(theField); if(maxDiv<1) { mexErrMsgTxt("Invalid maxDiv specified"); } } theField=mxGetField(prhs[3],0,"maxIter"); if(theField!=NULL) {//If the field is present. maxIter=getIntFromMatlab(theField); if(maxIter<1) { mexErrMsgTxt("Invalid maxIter specified"); } } theField=mxGetField(prhs[3],0,"maxFEval"); if(theField!=NULL) {//If the field is present. maxFEval=getIntFromMatlab(theField); if(maxIter<1) { mexErrMsgTxt("Invalid maxFEval specified"); } } theField=mxGetField(prhs[3],0,"epsilon"); if(theField!=NULL) {//If the field is present. epsilon=getDoubleFromMatlab(theField); if(fabs(epsilon)>=1) { mexErrMsgTxt("Invalid epsilon specified"); } } theField=mxGetField(prhs[3],0,"epsilonAbs"); if(theField!=NULL) {//If the field is present. epsilonAbs=getDoubleFromMatlab(theField); if(epsilonAbs>=1||epsilonAbs<0) { mexErrMsgTxt("Invalid epsilonAbs specified"); } } theField=mxGetField(prhs[3],0,"volumeRelTol"); if(theField!=NULL) {//If the field is present. volumeRelTol=getDoubleFromMatlab(theField); if(volumeRelTol>=1||volumeRelTol<0) { mexErrMsgTxt("Invalid volumeRelTol specified"); } } theField=mxGetField(prhs[3],0,"sigmaRelTol"); if(theField!=NULL) {//If the field is present. sigmaRelTol=getDoubleFromMatlab(theField); if(sigmaRelTol>=1||sigmaRelTol<0) { mexErrMsgTxt("Invalid sigmaRelTol specified"); } } theField=mxGetField(prhs[3],0,"fGlobal"); if(theField!=NULL) {//If the field is present. fGlobal=getDoubleFromMatlab(theField); fGlobalRelTol=1e-12;//Default value if fGlobal is given. } theField=mxGetField(prhs[3],0,"fGlobalRelTol"); if(theField!=NULL) {//If the field is present. fGlobalRelTol=getDoubleFromMatlab(theField); if(fGlobalRelTol<0) { mexErrMsgTxt("Invalid fGlobalRelTol specified"); } } } //Allocate space for the return values x=mxCalloc(numDim, sizeof(double)); retVal=direct_optimize(f,//Objective function pointer (void*)MatlabFunctionHandle,//Data that passed to the objective function. Here, the function handle passed by the user. (int)numDim,//The dimensionality of the problem lowerBounds,//Array of the lower bound of each dimension. upperBounds,//Array of the upper bound of each dimension. x,//An array that will be set to the optimum value on return. &fVal,//On return, set to the minimum value. maxFEval,//Maximum number of function evaluations. maxIter,//Maximum number of iterations epsilon,//Jones' epsilon parameter (1e-4 is recommended) epsilonAbs,//An absolute version of magic_eps //Relative tolerance on the hypercube volume (use 0 if none). This is //a percentage (0-1) of the volume of the original hypercube volumeRelTol, //Relative tolerance on the hypercube measure (0 if none) sigmaRelTol, //A pointer to a variable that can terminate the optimization. This is //in the library's code so that an external thread can write to this //and force the optimization to stop. Here, we are not using it, so we //can pass NULL. NULL, fGlobal,//Function value of the global optimum, if known. Use DIRECT_UNKNOWN_FGLOBAL if unknown. fGlobalRelTol,//Relative tolerance for convergence if fglobal is known. If unknown, use DIRECT_UNKNOWN_FGLOBAL. NULL,//There is no output to a file. theAlgorithm,//The algorithm to use maxDiv);//The maximum number of hyperrectangle divisions //If an error occurred if(retVal<0) { mxFree(x); switch(retVal){ case DIRECT_INVALID_BOUNDS: mexErrMsgTxt("Upper bounds are <= lower bounds for one or more dimensions."); case DIRECT_MAXFEVAL_TOOBIG: mexErrMsgTxt("maxFEval is too large."); case DIRECT_INIT_FAILED: mexErrMsgTxt("An initialization step failed."); case DIRECT_SAMPLEPOINTS_FAILED: mexErrMsgTxt("An error occurred creating sampling points."); case DIRECT_SAMPLE_FAILED: mexErrMsgTxt("An error occurred while sampling the function."); case DIRECT_OUT_OF_MEMORY: mexErrMsgTxt("Out of memory"); case DIRECT_INVALID_ARGS: mexErrMsgTxt("Invalid arguments provided"); //These errors should not occur either because they should //never be called or because retVal>=0 so these are not //actually errors. case DIRECT_FORCED_STOP: case DIRECT_MAXFEVAL_EXCEEDED: case DIRECT_MAXITER_EXCEEDED: case DIRECT_GLOBAL_FOUND: case DIRECT_VOLTOL: case DIRECT_SIGMATOL: case DIRECT_MAXTIME_EXCEEDED: default: mexErrMsgTxt("An unknown error occurred."); } } //Set the return values plhs[0]=mxCreateNumericMatrix(0, 0, mxDOUBLE_CLASS, mxREAL); mxFree(mxGetPr(plhs[0])); mxSetPr(plhs[0], x); mxSetM(plhs[0], numDim); mxSetN(plhs[0], 1); if(nlhs>1) { plhs[1]=doubleMat2Matlab(&fVal,1,1); if(nlhs>2) { plhs[2]=intMat2MatlabDoubles(&retVal,1,1); } } }
void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { double u, scalFactor; ClusterSetCPP<double> HBar; ClusterSetCPP<double> dHBardu;//The first derivatives ClusterSetCPP<double> d2HBardu2;//The second derivatives size_t M, numH, i; mxArray *CSRetVal; mxArray *clusterElsMATLAB,*clusterSizesMATLAB, *offsetArrayMATLAB; if(nrhs!=3){ mexErrMsgTxt("Incorrect number of inputs."); return; } u=getDoubleFromMatlab(prhs[0]); M=getSizeTFromMatlab(prhs[1]); scalFactor=getDoubleFromMatlab(prhs[2]); if(M<3) { mexErrMsgTxt("The maximum order should be at least 3."); return; } numH=(M+1)*(M+2)/2; //Allocate space for the results. clusterElsMATLAB=mxCreateDoubleMatrix(numH,1,mxREAL); clusterSizesMATLAB=allocUnsignedSizeMatInMatlab(M+1,1); offsetArrayMATLAB=allocUnsignedSizeMatInMatlab(M+1,1); HBar.numClust=M+1; HBar.totalNumEl=numH; HBar.clusterEls=reinterpret_cast<double*>(mxGetData(clusterElsMATLAB)); HBar.offsetArray=reinterpret_cast<size_t*>(mxGetData(offsetArrayMATLAB)); HBar.clusterSizes=reinterpret_cast<size_t*>(mxGetData(clusterSizesMATLAB)); //Initialize the offset array and cluster sizes. HBar.offsetArray[0]=0; HBar.clusterSizes[0]=1; for(i=1;i<=M;i++){ HBar.clusterSizes[i]=i+1; HBar.offsetArray[i]=HBar.offsetArray[i-1]+HBar.clusterSizes[i-1]; } normHelmHoltzCPP(HBar,u,scalFactor); //Set the first return value mexCallMATLAB(1,&CSRetVal,0, 0, "ClusterSet"); mxSetProperty(CSRetVal,0,"clusterEls",clusterElsMATLAB); mxSetProperty(CSRetVal,0,"clusterSizes",clusterSizesMATLAB); mxSetProperty(CSRetVal,0,"offsetArray",offsetArrayMATLAB); plhs[0]=CSRetVal; if(nlhs>1) {//Compute the first derivatives, if they are desired. mxArray *clusterEls1stDerivMATLAB=mxCreateDoubleMatrix(numH,1,mxREAL); dHBardu.numClust=M+1; dHBardu.totalNumEl=numH; dHBardu.clusterEls=reinterpret_cast<double*>(mxGetData(clusterEls1stDerivMATLAB)); dHBardu.offsetArray=reinterpret_cast<size_t*>(mxGetData(offsetArrayMATLAB)); dHBardu.clusterSizes=reinterpret_cast<size_t*>(mxGetData(clusterSizesMATLAB)); normHelmHoltzDerivCPP(dHBardu,HBar); //Set the second return value mexCallMATLAB(1,&CSRetVal,0, 0, "ClusterSet"); mxSetProperty(CSRetVal,0,"clusterEls",clusterEls1stDerivMATLAB); mxSetProperty(CSRetVal,0,"clusterSizes",clusterSizesMATLAB); mxSetProperty(CSRetVal,0,"offsetArray",offsetArrayMATLAB); plhs[1]=CSRetVal; mxDestroyArray(clusterEls1stDerivMATLAB); } if(nlhs>2) {//Compute the second derivatives if they are desired. mxArray *clusterEls2ndDerivMATLAB=mxCreateDoubleMatrix(numH,1,mxREAL); d2HBardu2.numClust=M+1; d2HBardu2.totalNumEl=numH; d2HBardu2.clusterEls=reinterpret_cast<double*>(mxGetData(clusterEls2ndDerivMATLAB)); d2HBardu2.offsetArray=reinterpret_cast<size_t*>(mxGetData(offsetArrayMATLAB)); d2HBardu2.clusterSizes=reinterpret_cast<size_t*>(mxGetData(clusterSizesMATLAB)); normHelmHoltzDeriv2CPP(d2HBardu2,HBar); //Set the third return value mexCallMATLAB(1,&CSRetVal,0, 0, "ClusterSet"); mxSetProperty(CSRetVal,0,"clusterEls",clusterEls2ndDerivMATLAB); mxSetProperty(CSRetVal,0,"clusterSizes",clusterSizesMATLAB); mxSetProperty(CSRetVal,0,"offsetArray",offsetArrayMATLAB); plhs[2]=CSRetVal; mxDestroyArray(clusterEls2ndDerivMATLAB); } //Free the buffers. The mxSetProperty command copied the data. mxDestroyArray(clusterElsMATLAB); mxDestroyArray(clusterSizesMATLAB); mxDestroyArray(offsetArrayMATLAB); }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { size_t numRow,numVec; mxArray *retMat; double *xVec, *retData; double TT1, TT2, UT11, UT12; //The if-statements below should properly initialize all of the EOP. //The following initializations to zero are to suppress warnings when //compiling with -Wconditional-uninitialized. double dX=0; double dY=0; double deltaT=0; double LOD=0; double GCRS2TIRS[3][3]; //Polar motion matrix. ITRS=POM*TIRS. We will just be setting it to the //identity matrix as polar motion is not taken into account when going //to the TIRS. double rident[3][3]={{1,0,0},{0,1,0},{0,0,1}}; double Omega[3];//The rotation vector in the TIRS if(nrhs<3||nrhs>6){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); } checkRealDoubleArray(prhs[0]); numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If some values from the function getEOP will be needed if(nrhs<=5||mxIsEmpty(prhs[3])||mxIsEmpty(prhs[4])||mxIsEmpty(prhs[5])) { mxArray *retVals[5]; double *dXdY; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(5,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); //%We do not need the polar motion coordinates. mxDestroyArray(retVals[0]); checkRealDoubleArray(retVals[1]); if(mxGetM(retVals[1])!=2||mxGetN(retVals[1])!=1) { mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); mexErrMsgTxt("Error using the getEOP function."); return; } dXdY=(double*)mxGetData(retVals[1]); dX=dXdY[0]; dY=dXdY[1]; //This is TT-UT1 deltaT=getDoubleFromMatlab(retVals[3]); LOD=getDoubleFromMatlab(retVals[4]); //Free the returned arrays. mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); } //If deltaT=TT-UT1 is given if(nrhs>3&&!mxIsEmpty(prhs[3])) { deltaT=getDoubleFromMatlab(prhs[3]); } //Obtain UT1 from terestrial time and deltaT. iauTtut1(TT1, TT2, deltaT, &UT11, &UT12); //Get celestial pole offsets, if given. if(nrhs>4&&!mxIsEmpty(prhs[4])) { size_t dim1, dim2; checkRealDoubleArray(prhs[4]); dim1 = mxGetM(prhs[4]); dim2 = mxGetN(prhs[4]); if((dim1==2&&dim2==1)||(dim1==1&&dim2==2)) { double *dXdY=(double*)mxGetData(prhs[4]); dX=dXdY[0]; dY=dXdY[1]; } else { mexErrMsgTxt("The celestial pole offsets have the wrong dimensionality."); return; } } //If LOD is given if(nrhs>5&&mxIsEmpty(prhs[5])) { LOD=getDoubleFromMatlab(prhs[5]); } //Compute the rotation matrix for going from GCRS to ITRS as well as //the instantaneous vector angular momentum due to the Earth's rotation //in TIRS coordinates. { double x, y, s, era; double rc2i[3][3]; double omega; //Get the X,Y coordinates of the Celestial Intermediate Pole (CIP) and //the Celestial Intermediate Origin (CIO) locator s, using the IAU 2006 //precession and IAU 2000A nutation models. iauXys06a(TT1, TT2, &x, &y, &s); //Add the CIP offsets. x += dX; y += dY; //Get the GCRS-to-CIRS matrix iauC2ixys(x, y, s, rc2i); //Find the Earth rotation angle for the given UT1 time. era = iauEra00(UT11, UT12); //Set the polar motion matrix to the identity matrix so that the //conversion stops at the TIRS instead of the ITRS. //Combine the GCRS-to-CIRS matrix, the Earth rotation angle, and use //the identity matrix instead of the polar motion matrix to get a //to get the rotation matrix to go from GCRS to TIRS. iauC2tcio(rc2i, era, rident,GCRS2TIRS); //Next, to be able to transform the velocity, the rotation of the Earth //has to be taken into account. //The angular velocity vector of the Earth in the TIRS in radians. omega=getScalarMatlabClassConst("Constants","IERSMeanEarthRotationRate"); //Adjust for LOD omega=omega*(1-LOD/86400.0);//86400.0 is the number of seconds in a TT //day. Omega[0]=0; Omega[1]=0; Omega[2]=omega; } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(GCRS2TIRS, xVec+numRow*curVec, retData+numRow*curVec); //If a velocity vector was given. if(numRow>3) { double *posGCRS=xVec+numRow*curVec; double posTIRS[3]; double *velGCRS=xVec+numRow*curVec+3;//Velocity in GCRS double velTIRS[3]; double *retDataVel=retData+numRow*curVec+3; double rotVel[3]; //If a velocity was provided with the position, first //convert to TIRS coordinates, then account for the //rotation of the Earth. //Convert velocity from GCRS to TIRS. iauRxp(GCRS2TIRS, velGCRS, velTIRS); //Convert position from GCRS to TIRS iauRxp(GCRS2TIRS, posGCRS, posTIRS); //Evaluate the cross product for the angular velocity due //to the Earth's rotation. iauPxp(Omega, posTIRS, rotVel); //Subtract out the instantaneous velocity due to rotation. iauPmp(velTIRS, rotVel, retDataVel); } } } plhs[0]=retMat; //If the rotation matrix is desired on the output. if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=GCRS2TIRS[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { size_t numRow,numVec; mxArray *retMat; double *retData; double ITRS2TIRS[3][3];//Inverse polar motion matrix double *xVec, TT1, TT2; double xp=0; double yp=0;//The polar motion coordinates if(nrhs<3||nrhs>4){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); } numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } checkRealDoubleArray(prhs[0]); xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If xpyp should be found using the function getEOP. if(nrhs<4||mxIsEmpty(prhs[3])) { mxArray *retVals[1]; double *xpyp; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(1,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); checkRealDoubleArray(retVals[0]); if(mxGetM(retVals[0])!=2||mxGetN(retVals[0])!=1) { mxDestroyArray(retVals[0]); mexErrMsgTxt("Error using the getEOP function."); return; } xpyp=(double*)mxGetData(retVals[0]); xp=xpyp[0]; yp=xpyp[1]; //Free the returned array. mxDestroyArray(retVals[0]); } //Get polar motion coordinates, if given. if(nrhs>3&&!mxIsEmpty(prhs[3])) { size_t dim1, dim2; checkRealDoubleArray(prhs[3]); dim1 = mxGetM(prhs[3]); dim2 = mxGetN(prhs[3]); if((dim1==2&&dim2==1)||(dim1==1&&dim2==2)) { double *xpyp=(double*)mxGetData(prhs[3]); xp=xpyp[0]; yp=xpyp[1]; } else { mexErrMsgTxt("The polar motion coordinates have the wrong dimensionality."); return; } } //Get the rotation matrix from TIRS to ITRS. { double sp; double TIRS2ITRS[3][3];//Polar motion matrix //Get the Terrestrial Intermediate Origin (TIO) locator s' in //radians sp=iauSp00(TT1,TT2); //Get the polar motion matrix iauPom00(xp,yp,sp,TIRS2ITRS); //The inverse polar motion matrix is given by the transpose of the //polar motion matrix. iauTr(TIRS2ITRS, ITRS2TIRS); } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(ITRS2TIRS, xVec+numRow*curVec, retData+numRow*curVec); //Multiply the velocity vector with the rotation matrix. if(numRow>3) { double *velITRS=xVec+numRow*curVec+3;//Velocity in ITRS double *retDataVel=retData+numRow*curVec+3;//Velocity in ITRS //Convert velocity from ITRS to TIRS. iauRxp(ITRS2TIRS, velITRS, retDataVel); } } } plhs[0]=retMat; if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=ITRS2TIRS[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double TT1,TT2,*xVec; double deltaT=0; double LOD=0; size_t numRow,numVec; double CIRS2TIRS[3][3]; double TIRS2CIRS[3][3]; double Omega[3];//The rotation vector in the TIRS mxArray *retMat; double *retData; if(nrhs<3||nrhs>5){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); } checkRealDoubleArray(prhs[0]); numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If some values from the function getEOP will be needed if(nrhs<=4||mxIsEmpty(prhs[3])||mxIsEmpty(prhs[4])) { mxArray *retVals[5]; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(5,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); //We do not need the polar motion coordinates. mxDestroyArray(retVals[0]); //We do not need the celestial pole offsets. mxDestroyArray(retVals[1]); //This is TT-UT1 deltaT=getDoubleFromMatlab(retVals[3]); LOD=getDoubleFromMatlab(retVals[4]); //Free the returned arrays. mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); } //If deltaT=TT-UT1 is given if(nrhs>3&&!mxIsEmpty(prhs[3])) { deltaT=getDoubleFromMatlab(prhs[3]); } //If LOD is given if(nrhs>4&&!mxIsEmpty(prhs[4])) { LOD=getDoubleFromMatlab(prhs[4]); } //Compute the rotation matrix for going from CIRS to TIRS as well as //the instantaneous vector angular momentum due to the Earth's rotation //in GCRS coordinates. { double UT11, UT12; double era, omega; //Obtain UT1 from terestrial time and deltaT. iauTtut1(TT1, TT2, deltaT, &UT11, &UT12); //Find the Earth rotation angle for the given UT1 time. era = iauEra00(UT11, UT12); //Construct the rotation matrix. CIRS2TIRS[0][0]=1; CIRS2TIRS[0][1]=0; CIRS2TIRS[0][2]=0; CIRS2TIRS[1][0]=0; CIRS2TIRS[1][1]=1; CIRS2TIRS[1][2]=0; CIRS2TIRS[2][0]=0; CIRS2TIRS[2][1]=0; CIRS2TIRS[2][2]=1; iauRz(era, CIRS2TIRS); //To go from the TIRS to the GCRS, we need to use the inverse rotation //matrix, which is just the transpose of the rotation matrix. iauTr(CIRS2TIRS, TIRS2CIRS); //Next, to be able to transform the velocity, the rotation of the Earth //has to be taken into account. //The angular velocity vector of the Earth in the TIRS in radians. omega=getScalarMatlabClassConst("Constants","IERSMeanEarthRotationRate"); //Adjust for LOD omega=omega*(1-LOD/86400.0);//86400.0 is the number of seconds in a TT //day. Omega[0]=0; Omega[1]=0; Omega[2]=omega; } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(TIRS2CIRS, xVec+numRow*curVec, retData+numRow*curVec); //If a velocity vector was given. if(numRow>3) { double *posTIRS=xVec+numRow*curVec; double *velTIRS=xVec+numRow*curVec+3;//Velocity in GCRS double *retDataVel=retData+numRow*curVec+3; double rotVel[3]; //Evaluate the cross product for the angular velocity due //to the Earth's rotation. iauPxp(Omega, posTIRS, rotVel); //Add the instantaneous velocity due to rotation. iauPpp(velTIRS, rotVel, retDataVel); //Rotate from TIRS to GCRS iauRxp(TIRS2CIRS, retDataVel, retDataVel); } } } plhs[0]=retMat; if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=TIRS2CIRS[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { //The Julan date in TT at the epoch used in the orbital propagation //algorithm: 0:00 January 1 1950 const double epochDate=2433281.5; double *deltaT; size_t numTimes; double SGP4Elements[7],elementEpochTime; bool opsMode=0; char opsChar; bool gravityModel=0; gravconsttype gravConstType; mxArray *retMat; double *retVec; mxArray *errorMat; double *errorVals; if(nrhs<2||nrhs>6||nrhs==3) { mexErrMsgTxt("Incorrect number of inputs."); return; } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); return; } { const size_t M=mxGetM(prhs[0]); const size_t N=mxGetN(prhs[0]); if(!((M==7&&N==1)||(N==7&&M==1))) { mexErrMsgTxt("The SGP4 elements have the wrong dimensionality."); return; } } checkRealDoubleArray(prhs[0]); { size_t i; double *theEls; theEls=(double*)mxGetData(prhs[0]); //Copy the elements into SGP4Elements, adjusting the units from SI //to the values used here. for(i=0;i<5;i++) { SGP4Elements[i]=theEls[i]; } //The multipliation by 60 changes the value from radians per second //to radians per minute as desired by the SGP4 code. SGP4Elements[5]=theEls[5]*60.0; SGP4Elements[6]=theEls[6]; } { const size_t M=mxGetM(prhs[1]); const size_t N=mxGetN(prhs[1]); if((M!=1&&N!=1)||mxIsEmpty(prhs[1])) { mexErrMsgTxt("The times have the wrong dimensionality."); return; } numTimes=std::max(M,N); } checkRealDoubleArray(prhs[1]); deltaT=(double*)mxGetData(prhs[1]); if(nrhs>2&&!mxIsEmpty(prhs[2])&&!mxIsEmpty(prhs[3])) { const double TT1=getDoubleFromMatlab(prhs[2]); const double TT2=getDoubleFromMatlab(prhs[3]); if(TT1>TT2) { elementEpochTime=(TT1-epochDate)+TT2; } else { elementEpochTime=(TT2-epochDate)+TT1; } } else { //No time is given. Make sure that the deep space propagator is not //going to be used. Otherwise, the time value does not matter. elementEpochTime=0; if(2*pi/SGP4Elements[5]>=225) { mexErrMsgTxt("The elements imply the use of the deep space propagator, but no time was given."); return; } } if(nrhs>4) { opsMode=getBoolFromMatlab(prhs[4]); } if(opsMode==0) { opsChar='a'; } else { opsChar='i'; } if(nrhs>5) { gravityModel=getBoolFromMatlab(prhs[5]); } if(gravityModel==0) { gravConstType=wgs72; } else { gravConstType=wgs84; } //Allocate space for the return values retMat=mxCreateDoubleMatrix(6,numTimes,mxREAL); retVec=(double*)mxGetData(retMat); errorMat=mxCreateDoubleMatrix(numTimes,1,mxREAL); errorVals=(double*)mxGetData(errorMat); { //This will be filled with the ephemeris information needed for //propagating the satellite. elsetrec satRec; size_t i; sgp4init(gravConstType,//Specified WGS-84 or WGS-72 opsChar, elementEpochTime,//Epoch time of the orbital elements. SGP4Elements[6],//BSTAR drag term. SGP4Elements[0],//Eccentricity SGP4Elements[2],//Argument of perigee SGP4Elements[1],//Inclination SGP4Elements[4],//Mean anomaly SGP4Elements[5],//Mean motion SGP4Elements[3],//Righ ascension of the ascending node. satRec);//Gets filled by the function. //Do the actual propagation. //The division by 60 transforms the time value from seconds to //minutes, as the SGP4 code wants the result in minutes. for(i=0;i<numTimes;i++) { double *r=retVec+6*i; double *v=retVec+6*i+3; int j; sgp4(gravConstType, satRec, deltaT[i]/60.0, r, v); //Convert the units from kilometers and kilometers per second //to meters and meters per second. for(j=0;j<3;j++) { r[j]=1000*r[j]; v[j]=1000*v[j]; } errorVals[i]=(double)satRec.error; } } //Save the result plhs[0]=retMat; //If the error value is desired. if(nlhs>1) { plhs[1]=errorMat; } else{ mxDestroyArray(errorMat); } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double TT1,TT2,TDB1,TDB2,Jul2,deltaTTUT1,deltaT,Jul1UT1, Jul2UT1,UT1Frac; double u, v, elon; int retVal; if(nrhs<2||nrhs>4){ mexErrMsgTxt("Wrong number of inputs."); return; } if(nlhs>2){ mexErrMsgTxt("Wrong number of outputs."); return; } TT1=getDoubleFromMatlab(prhs[0]); TT2=getDoubleFromMatlab(prhs[1]); //If the parameter is given and is not just an empty matrix. if(nrhs>2&&!(mxGetM(prhs[2])==0||mxGetN(prhs[2])==0)) { deltaTTUT1=getDoubleFromMatlab(prhs[2]); } else { mxArray *retVals[4]; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(4,retVals,2,JulUTCMATLAB,"getEOP"); //This is TT-UT1 deltaTTUT1=getDoubleFromMatlab(retVals[3]); //Free the returned arrays. mxDestroyArray(retVals[0]); mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); } if(nrhs>3) { double *xyzClock; if(mxGetM(prhs[3])!=3||mxGetN(prhs[3])!=1) { mexErrMsgTxt("The dimensionality of the clock location is incorrect."); return; } checkRealDoubleArray(prhs[3]); xyzClock=(double*)mxGetData(prhs[3]); //Convert from meters to kilometers. xyzClock[0]/=1000;xyzClock[1]/=1000;xyzClock[2]/=1000; u=sqrt(xyzClock[0]*xyzClock[0] + xyzClock[1]*xyzClock[1]); v=xyzClock[2]; elon=atan2(xyzClock[1],xyzClock[0]); } else { u=0; v=0; elon=0; } //Get UT1 retVal=iauTtut1(TT1, TT2, deltaTTUT1, &Jul1UT1, &Jul2UT1); switch(retVal) { case -1: mexErrMsgTxt("Unacceptable date provided."); return; case 1: mexWarnMsgTxt("Dubious year provided\n"); break; default: break; } //Find the fraction of a Julian day in UT1 UT1Frac=(Jul1UT1-floor(Jul1UT1))+(Jul2UT1-floor(Jul2UT1)); UT1Frac=UT1Frac-floor(UT1Frac); /*Compute TDB-TT. The function iauDtdb takes TDB as an input, but we *only have TT. The documentation for iauDtdb says that TT can be *substituted within the precision limits of the function. However, an *extra iteration is performed here to try to make the result *consistent with TDB2TT to a few more digits of precision.*/ TDB1=TT1; TDB2=TT2; { int curIter; for(curIter=0;curIter<2;curIter++) { deltaT = iauDtdb(TDB1, TDB2, UT1Frac, elon, u, v); //TT -> TDB retVal = iauTttdb(TT1, TT2, deltaT, &TDB1, &TDB2); if(retVal!=0) { mexErrMsgTxt("An error occured during an intermediate conversion to TDB.\n"); return; } } } plhs[0]=doubleMat2Matlab(&TDB1,1, 1); if(nlhs>1) { plhs[1]=doubleMat2Matlab(&TDB2,1, 1); } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { size_t numRow,numVec; mxArray *retMat; double *xVec, *retData; double TT1, TT2, UT11, UT12; //The if-statements below should properly initialize all of the EOP. //The following initializations to zero are to suppress warnings when //compiling with -Wconditional-uninitialized. double xp=0; double yp=0; double deltaT=0; double LOD=0; double ITRS2TEME[3][3]; double PEF2TEME[3][3]; double WInv[3][3];//The inverse polar motion matrix to go from ITRS to PEF. double Omega[3];//The angular velocity vector for the Earth's rotation. if(nrhs<3||nrhs>6){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); return; } checkRealDoubleArray(prhs[0]); numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If some values from the function getEOP will be needed if(nrhs<6||mxIsEmpty(prhs[3])||mxIsEmpty(prhs[4])||mxIsEmpty(prhs[5])) { mxArray *retVals[5]; double *xpyp; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(5,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); checkRealDoubleArray(retVals[0]); checkRealDoubleArray(retVals[1]); if(mxGetM(retVals[0])!=2||mxGetN(retVals[0])!=1||mxGetM(retVals[1])!=2||mxGetN(retVals[1])!=1) { mxDestroyArray(retVals[0]); mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); mexErrMsgTxt("Error using the getEOP function."); return; } xpyp=(double*)mxGetData(retVals[0]); xp=xpyp[0]; yp=xpyp[1]; //The celestial pole offsets are not used. //This is TT-UT1 deltaT=getDoubleFromMatlab(retVals[3]); LOD=getDoubleFromMatlab(retVals[4]); //Free the returned arrays. mxDestroyArray(retVals[0]); mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); } //If deltaT=TT-UT1 is given if(nrhs>3&&!mxIsEmpty(prhs[3])) { deltaT=getDoubleFromMatlab(prhs[3]); } //Obtain UT1 from terestrial time and deltaT. iauTtut1(TT1, TT2, deltaT, &UT11, &UT12); //Get polar motion values, if given. if(nrhs>4&&!mxIsEmpty(prhs[4])) { size_t dim1, dim2; checkRealDoubleArray(prhs[4]); dim1 = mxGetM(prhs[4]); dim2 = mxGetN(prhs[4]); if((dim1==2&&dim2==1)||(dim1==1&&dim2==2)) { double *xpyp=(double*)mxGetData(prhs[4]); xp=xpyp[0]; yp=xpyp[1]; } else { mexErrMsgTxt("The celestial pole offsets have the wrong dimensionality."); return; } } //If LOD is given if(nrhs>5&&!mxIsEmpty(prhs[5])) { LOD=getDoubleFromMatlab(prhs[5]); } { double GMST1982=iauGmst82(UT11, UT12); double TEME2PEF[3][3]; double TEME2ITRS[3][3]; double W[3][3]; double omega; //Get Greenwhich mean sidereal time under the IAU's 1982 model. This //is given in radians and will be used to build a rotation matrix to //rotate into the PEF system. GMST1982=iauGmst82(UT11, UT12); { double cosGMST,sinGMST; cosGMST=cos(GMST1982); sinGMST=sin(GMST1982); //Build the rotation matrix to rotate by GMST about the z-axis. This //will put the position vector in the PEF system. TEME2PEF[0][0]=cosGMST; TEME2PEF[0][1]=sinGMST; TEME2PEF[0][2]=0; TEME2PEF[1][0]=-sinGMST; TEME2PEF[1][1]=cosGMST; TEME2PEF[1][2]=0; TEME2PEF[2][0]=0; TEME2PEF[2][1]=0; TEME2PEF[2][2]=1.0; } //The inverse rotation is just the transpose iauTr(TEME2PEF, PEF2TEME); //To go from PEF to ITRS, we need to build the polar motion matrix //using the IAU's 1980 conventions. { double cosXp,sinXp,cosYp,sinYp; cosXp=cos(xp); sinXp=sin(xp); cosYp=cos(yp); sinYp=sin(yp); W[0][0]=cosXp; W[0][1]=sinXp*sinYp; W[0][2]=sinXp*cosYp; W[1][0]=0; W[1][1]=cosYp; W[1][2]=-sinYp; W[2][0]=-sinXp; W[2][1]=cosXp*sinXp; W[2][2]=cosXp*cosYp; } //The inverse rotation is just the transpose iauTr(W, WInv); //The total rotation matrix is thus the product of the two rotations. //TEME2ITRS=W*TEME2PEF; iauRxr(W, TEME2PEF, TEME2ITRS); //We want the inverse rotation iauTr(TEME2ITRS, ITRS2TEME); //The angular velocity vector of the Earth in the TIRS in radians. omega=getScalarMatlabClassConst("Constants","IERSMeanEarthRotationRate"); //Adjust for LOD omega=omega*(1-LOD/86400.0);//86400.0 is the number of seconds in a TT day. Omega[0]=0; Omega[1]=0; Omega[2]=omega; } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(ITRS2TEME, xVec+numRow*curVec, retData+numRow*curVec); //If a velocity vector was given. if(numRow>3) { double *posITRS=xVec+numRow*curVec; double *velITRS=xVec+numRow*curVec+3;//Velocity in TEME double posPEF[3]; double velPEF[3]; double *retDataVel=retData+numRow*curVec+3; double rotVel[3]; //If a velocity was provided with the position, first //convert to PEF coordinates, then account for the rotation //of the Earth, then rotate into TEME coordinates. //Convert velocity from ITRS to PEF. iauRxp(WInv, velITRS, velPEF); //Convert position from ITRS to PEF iauRxp(WInv, posITRS, posPEF); //Evaluate the cross product for the angular velocity due //to the Earth's rotation. iauPxp(Omega, posPEF, rotVel); //Add the instantaneous velocity due to rotation. iauPpp(velPEF, rotVel, retDataVel); //Rotate from the PEF into the TEME iauRxp(PEF2TEME, retDataVel, retDataVel); } } } plhs[0]=retMat; if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=ITRS2TEME[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { size_t i, numRows,numCols, numEls; double minBound, maxBound, *vals, *wrapVals; mxArray *retMat; bool mirrorWrap=false; if(nrhs<3){ mexErrMsgTxt("Not enough inputs."); return; } if(nrhs>4) { mexErrMsgTxt("Too many inputs."); return; } if(nlhs>1) { mexErrMsgTxt("Too many outputs."); return; } checkRealDoubleArray(prhs[0]); numRows=mxGetM(prhs[0]); numCols=mxGetN(prhs[0]); numEls=numRows*numCols; //If given an empty matrix, return an empty matrix. if(numEls==0) { plhs[0]=mxCreateDoubleMatrix(0,0,mxREAL); return; } vals=(double*)mxGetData(prhs[0]); minBound=getDoubleFromMatlab(prhs[1]); maxBound=getDoubleFromMatlab(prhs[2]); if(maxBound<=minBound) { mexErrMsgTxt("the maximum bound must be less than the minimum bound."); } if(nrhs>3) { mirrorWrap=getBoolFromMatlab(prhs[3]); } //Allocate space for the return values. retMat=mxCreateDoubleMatrix(numRows,numCols,mxREAL); wrapVals=(double*)mxGetData(retMat); if(mirrorWrap) { for(i=0;i<numEls;i++) { wrapVals[i]=wrapRangeMirrorCPP(vals[i],minBound,maxBound); } } else { for(i=0;i<numEls;i++) { wrapVals[i]=wrapRangeCPP(vals[i],minBound,maxBound); } } plhs[0]=retMat; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *points,a,b,b2,f,e2,eps2,ec; size_t numVec,i; mxArray *retMat; double *retData; if(nrhs>3||nrhs<1){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>1) { mexErrMsgTxt("Wrong number of outputs."); return; } checkRealDoubleArray(prhs[0]); numVec = mxGetN(prhs[0]); if(mxGetM(prhs[0])!=3) { mexErrMsgTxt("The input vector has a bad dimensionality."); } points=(double*)mxGetData(prhs[0]); //points[0] is x //points[1] is y //points[2] is z if(nrhs>1) { a=getDoubleFromMatlab(prhs[1]); } else { a=getScalarMatlabClassConst("Constants", "WGS84SemiMajorAxis"); } if(nrhs>2) { f=getDoubleFromMatlab(prhs[2]); } else { f=getScalarMatlabClassConst("Constants", "WGS84Flattening"); } b=a*(1-f);//The semi-minor axis of the reference ellipsoid. b2=b*b; //The square of the first numerical eccentricity. e2=2*f-f*f; //The square of the second numerical eccentricity. eps2=a*a/(b2)-1; //This value is used if Fukushima's method is chosen. ec=sqrt(1-e2); //Allocate space for the return variables. retMat=mxCreateDoubleMatrix(3,numVec,mxREAL); retData=(double*)mxGetData(retMat); for(i=0;i<numVec;i++) { double *phi, *lambda, *h; double x0,y0,z0; double r0,p,s,q; //Get the Cartesian point to convert. x0=points[3*i]; y0=points[3*i+1]; z0=points[3*i+2]; //Get the addresses of where the converted components will go phi=retData+3*i; lambda=retData+3*i+1; h=retData+3*i+2; r0=sqrt(x0*x0+y0*y0); p=fabs(z0)/eps2; s=r0*r0/(e2*eps2); q=p*p-b2+s; *lambda=atan2(y0,x0); if(q>=0) {//Use Sofair's algorithm double u,v,P,Q,t,c,w,z,Ne,val; u=p/sqrt(q); v=b2*u*u/q; P=27.0*v*s/q; Q=pow(sqrt(P+1.0)+sqrt(P),2.0/3.0); t=(1.0+Q+1/Q)/6.0; c=u*u-1+2*t; //This condition prevents finite precision problems due to //subtraction within the square root. c=fMax(c,0); c=sqrt(c); w=(c-u)/2.0; //The z coordinate of the closest point projected on the ellipsoid. //The fmax command deals with precision problems when the argument //is nearly zero. The problems arise due to the subtraction within //the square root. z=sqrt(t*t+v)-u*w-t/2.0-1.0/4.0; z=fMax(z,0); z=copySign(sqrt(q)*(w+sqrt(z)),z0); Ne=a*sqrt(1+eps2*z*z/b2); //The min and max terms deals with finite precision problems. val=fMin(z*(eps2+1)/Ne,1); val=fMax(val,-1.0); *phi=asin(val); *h=r0*cos(*phi)+z0*sin(*phi)-a*a/Ne; } else {//Use Fukushima's algorithm. double Cc,P,Z,S,C; //A gets a value within the loop. This initialization is just //to silence a warning when compiling with //-Wconditional-uninitialized double A=0; size_t curIter; const size_t maxIter=6; P=r0/a; Z=(ec/a)*fabs(z0); S=Z; C=ec*P; //Loop until convergence. Assume convergence in 6 iterations. for(curIter=0;curIter<maxIter;curIter++) { double B,F,D,SNew,CNew; A=sqrt(S*S+C*C); B=1.5*e2*S*C*C*((P*S-Z*C)*A-e2*S*C); F=P*A*A*A-e2*C*C*C; D=Z*A*A*A+e2*S*S*S; SNew=D*F-B*S; CNew=F*F-B*C; SNew=SNew/CNew; if(!isFinite(SNew)) { S=SNew; C=1; A=sqrt(S*S+C*C); break; } else { S=SNew; C=1; } } Cc=ec*C; //If the point is along the z-axis, then SNew and CNew will //both be zero, leading to a non-finite result. if(!isFinite(S)) { *phi=copySign(pi/2,z0); *h=fabs(z0)-b; } else { *phi=copySign(atan(S/Cc),z0); *h=(r0*Cc+fabs(z0)*S-b*A)/sqrt(Cc*Cc+S*S); } } } plhs[0]=retMat; }
void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { double a,c,scalFactor; double *point; ClusterSetCPP<double> CStdDev; ClusterSetCPP<double> SStdDev; size_t numPoints; size_t i, M, totalNumEls; mxArray *sigma2MATLAB; //This variable is only used if nlhs>1. It is set to zero here to //suppress a warning if compiled using -Wconditional-uninitialized. mxArray *SigmaMATLAB=NULL; double *sigma2,*Sigma; bool didOverflow; size_t *theOffsetArray, *theClusterSizes; if(nrhs!=6) { mexErrMsgTxt("Wrong number of inputs."); } if(nlhs>3) { mexErrMsgTxt("Invalid number of outputs."); } //Check the validity of the ClusterSets checkRealDoubleArray(prhs[0]); checkRealDoubleArray(prhs[1]); //Make sure that both of the coefficient sets have the same number of //elements and are not empty. if(mxIsEmpty(prhs[0])||mxIsEmpty(prhs[1])||mxGetM(prhs[0])!=mxGetM(prhs[1])||mxGetN(prhs[0])!=mxGetN(prhs[1])) { mexErrMsgTxt("Invalid ClusterSet data passed."); } CStdDev.clusterEls=reinterpret_cast<double*>(mxGetData(prhs[0])); SStdDev.clusterEls=reinterpret_cast<double*>(mxGetData(prhs[1])); //The number of elements in the ClusterSets totalNumEls=mxGetM(prhs[0])*mxGetN(prhs[0]); //We do not want to trust that the offset arrays and the cluster arrays //are valid. Also, the data types of the passed values can vary (e.g., //might be doubles). Thus, we this function does not take the offset //and number of clusters data from a ClusterSet class. Rather, it //recreates the values based on the length of the data. This avoids //possibly reading past the end of an array. //Since the total number of points in a ClusterSet //is (M+1)*(M+2)/2, where M is the number of clusters -1, we can easily //verify that a valid number of points was passed. //Some versions of Windows SDK have problems with passing an integer //type to the sqrt function, so this explicit typecasting should take //care of the problem. M=(-3+static_cast<size_t>(sqrt(static_cast<double>(1+8*totalNumEls))))/2; if((M+1)*(M+2)/2!=totalNumEls) { mexErrMsgTxt("The ClusterSets contain an inconsistent number of elements."); } //Otherwise, fill in the values for the cluster sizes and the ofset //array. CStdDev.numClust=M+1; SStdDev.numClust=M+1; theOffsetArray=new size_t[M+1]; theClusterSizes=new size_t[M+1]; theClusterSizes[0]=1; theOffsetArray[0]=0; for(i=1;i<=M;i++) { theOffsetArray[i]=theOffsetArray[i-1]+theClusterSizes[i-1]; theClusterSizes[i]=i+1; } CStdDev.totalNumEl=totalNumEls; SStdDev.totalNumEl=totalNumEls; CStdDev.offsetArray=theOffsetArray; SStdDev.offsetArray=theOffsetArray; CStdDev.clusterSizes=theClusterSizes; SStdDev.clusterSizes=theClusterSizes; //Get the other parameters. checkRealDoubleArray(prhs[2]); point=reinterpret_cast<double*>(mxGetData(prhs[2])); numPoints=mxGetN(prhs[2]); a=getDoubleFromMatlab(prhs[3]); c=getDoubleFromMatlab(prhs[4]); scalFactor=getDoubleFromMatlab(prhs[5]); //Allocate space for the return values sigma2MATLAB=mxCreateDoubleMatrix(numPoints, 1,mxREAL); sigma2=reinterpret_cast<double*>(mxGetData(sigma2MATLAB)); if(nlhs>1) { mwSize dims[3]; //A 3X3X numPoints array is needed for the covariance matrices. dims[0]=3; dims[1]=3; dims[2]=numPoints; SigmaMATLAB=mxCreateNumericArray(3,dims,mxDOUBLE_CLASS,mxREAL); Sigma=reinterpret_cast<double*>(mxGetData(SigmaMATLAB)); } else { Sigma=NULL; } didOverflow=spherHarmonicCovCPP(sigma2,Sigma,CStdDev,SStdDev,point,numPoints,a,c,scalFactor); //Free the allocated space for the offet array and cluster sizes delete[] theOffsetArray; delete[] theClusterSizes; plhs[0]=sigma2MATLAB; if(nlhs>1) { plhs[1]=SigmaMATLAB; if(nlhs>2) { plhs[2]=boolMat2Matlab(&didOverflow,1,1); } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double TT1, TT2, dX, dY, *xVec; size_t numRow, numVec; mxArray *retMat; double *retData; double GCRS2CIRS[3][3]; if(nrhs<3||nrhs>4){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); } checkRealDoubleArray(prhs[0]); numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If some values from the function getEOP will be needed. if(nrhs<4||mxGetM(prhs[3])==0) { mxArray *retVals[2]; double *dXdY; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(2,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); //%We do not need the polar motion coordinates. mxDestroyArray(retVals[0]); checkRealDoubleArray(retVals[1]); if(mxGetM(retVals[1])!=2||mxGetN(retVals[1])!=1) { mxDestroyArray(retVals[1]); mexErrMsgTxt("Error using the getEOP function."); return; } dXdY=(double*)mxGetData(retVals[1]); dX=dXdY[0]; dY=dXdY[1]; //Free the returned arrays. mxDestroyArray(retVals[1]); } else {//Get the celestial pole offsets size_t dim1, dim2; checkRealDoubleArray(prhs[4]); dim1 = mxGetM(prhs[4]); dim2 = mxGetN(prhs[4]); if((dim1==2&&dim2==1)||(dim1==1&&dim2==2)) { double *dXdY=(double*)mxGetData(prhs[4]); dX=dXdY[0]; dY=dXdY[1]; } else { mexErrMsgTxt("The celestial pole offsets have the wrong dimensionality."); return; } } { double x, y, s; double omega; //Get the X,Y coordinates of the Celestial Intermediate Pole (CIP) and //the Celestial Intermediate Origin (CIO) locator s, using the IAU 2006 //precession and IAU 2000A nutation models. iauXys06a(TT1, TT2, &x, &y, &s); //Add the CIP offsets. x += dX; y += dY; //Get the GCRS-to-CIRS matrix iauC2ixys(x, y, s, GCRS2CIRS); } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(GCRS2CIRS, xVec+numRow*curVec, retData+numRow*curVec); //If a velocity vector was given. if(numRow>3) { double *velGCRS=xVec+numRow*curVec+3;//Velocity in GCRS double *retDataVel=retData+numRow*curVec+3; //Convert velocity from GCRS to CIRS. iauRxp(GCRS2CIRS, velGCRS, retDataVel); } } } plhs[0]=retMat; //If the rotation matrix is desired on the output. if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=GCRS2CIRS[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double TT1, TT2, UT11,UT12, deltaT,GMST; int algToUse=2006; int retVal; if(nrhs<2||nrhs>4){ mexErrMsgTxt("Wrong number of inputs."); return; } if(nlhs>1){ mexErrMsgTxt("Wrong number of outputs."); return; } TT1=getDoubleFromMatlab(prhs[0]); TT2=getDoubleFromMatlab(prhs[1]); if(nrhs>2) { algToUse=getIntFromMatlab(prhs[2]); } if(nrhs>3) { deltaT=getDoubleFromMatlab(prhs[3]); } else { mxArray *retVals[4]; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(4,retVals,2,JulUTCMATLAB,"getEOP"); //This is TT-UT1 deltaT=getDoubleFromMatlab(retVals[3]); //Free the returned arrays. mxDestroyArray(retVals[0]); mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); } //Get UT1 retVal=iauTtut1(TT1, TT2, deltaT, &UT11, &UT12); if(retVal!=0) { mexErrMsgTxt("An error occurred computing UT1."); } //Get Greenwhich mean sidereal time in radians using the chosen //algorithm switch(algToUse) { case 1982: GMST=iauGmst82(UT11, UT12); break; case 2000: GMST=iauGmst00(UT11, UT12, TT1, TT2); break; case 2006: GMST=iauGmst06(UT11, UT12, TT1, TT2); break; default: mexErrMsgTxt("An invalid algorithm version was given."); } plhs[0]=doubleMat2Matlab(&GMST,1, 1); }