145 lines
5.0 KiB
C++
145 lines
5.0 KiB
C++
|
/*
|
||
|
Functions matrix and vector multiplications.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "linalg.h"
|
||
|
#include "constants.h"
|
||
|
#include <math.h>
|
||
|
|
||
|
//macOS only!
|
||
|
//#include <Accelerate/Accelerate.h>
|
||
|
|
||
|
#ifdef __linux__ // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
|
||
|
#include <cblas.h>
|
||
|
#elif _WINDOWS || __WIN32__ // Added for windows by Yi Zhang on 2021-08-26
|
||
|
#include <cblas.h>
|
||
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||
|
#include <Accelerate/Accelerate.h>
|
||
|
#else
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/* Calculate magnetization vector in a coordinate system of a given point */
|
||
|
void conv_vect_cblas(double *vect, double lon1, double lat1, double lon2, double lat2, double *res)
|
||
|
{
|
||
|
double a1 = DEG2RAD*lat1;
|
||
|
double b1 = DEG2RAD*lon1;
|
||
|
double a2 = DEG2RAD*lat2;
|
||
|
double b2 = DEG2RAD*lon2;
|
||
|
|
||
|
double cos_a1 = cos(PI/2.0-a1);
|
||
|
double sin_a1 = sin(PI/2.0-a1);
|
||
|
double cos_a2 = cos(PI/2.0-a2);
|
||
|
double sin_a2 = sin(PI/2.0-a2);
|
||
|
|
||
|
double cos_b1 = cos(b1);
|
||
|
double sin_b1 = sin(b1);
|
||
|
double cos_b2 = cos(b2);
|
||
|
double sin_b2 = sin(b2);
|
||
|
|
||
|
double Z1Y1[9] = {cos_a1*cos_b1, -sin_b1, cos_b1*sin_a1, cos_a1*sin_b1, cos_b1, sin_a1*sin_b1, -sin_a1, 0, cos_a1};
|
||
|
double Z2Y2t[9] = {-cos_a2*cos_b2, -cos_a2*sin_b2, sin_a2, -sin_b2, cos_b2, 0, cos_b2*sin_a2, sin_a2*sin_b2, cos_a2};
|
||
|
double R[9];
|
||
|
|
||
|
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 3, 3, 3, 1.0, Z1Y1, 3, Z2Y2t, 3, 0.0, R, 3);
|
||
|
|
||
|
R[0] = -R[0];
|
||
|
R[3] = -R[3];
|
||
|
R[6] = -R[6];
|
||
|
|
||
|
cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1.0, R, 3, vect, 1, 0.0, res, 1);
|
||
|
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void conv_vect_cblas_precalc(double *vect, double cos_a1, double sin_a1, double cos_b1, double sin_b1, double cos_a2, double sin_a2, double cos_b2, double sin_b2, double *res)
|
||
|
{
|
||
|
// double a1 = DEG2RAD*lat1;
|
||
|
// double b1 = DEG2RAD*lon1;
|
||
|
// double a2 = DEG2RAD*lat2;
|
||
|
// double b2 = DEG2RAD*lon2;
|
||
|
|
||
|
// double cos_a1 = cos(PI/2.0-a1);
|
||
|
// double sin_a1 = sin(PI/2.0-a1);
|
||
|
// double cos_a2 = cos(PI/2.0-a2);
|
||
|
// double sin_a2 = sin(PI/2.0-a2);
|
||
|
|
||
|
// double cos_b1 = cos(b1);
|
||
|
// double sin_b1 = sin(b1);
|
||
|
// double cos_b2 = cos(b2);
|
||
|
// double sin_b2 = sin(b2);
|
||
|
|
||
|
double Z1Y1[9] = {cos_a1*cos_b1, -sin_b1, cos_b1*sin_a1, cos_a1*sin_b1, cos_b1, sin_a1*sin_b1, -sin_a1, 0, cos_a1};
|
||
|
double Z2Y2t[9] = {-cos_a2*cos_b2, -cos_a2*sin_b2, sin_a2, -sin_b2, cos_b2, 0, cos_b2*sin_a2, sin_a2*sin_b2, cos_a2};
|
||
|
double R[9];
|
||
|
|
||
|
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, 3, 3, 3, 1.0, Z1Y1, 3, Z2Y2t, 3, 0.0, R, 3);
|
||
|
|
||
|
R[0] = -R[0];
|
||
|
R[3] = -R[3];
|
||
|
R[6] = -R[6];
|
||
|
|
||
|
cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1.0, R, 3, vect, 1, 0.0, res, 1);
|
||
|
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void from_loc_sphr_to_cart(double* columnvect_xyzloc, double colatitude, double longitude, double* columnvect_res)
|
||
|
{
|
||
|
/*IMPORTANT: this subroutine is in the coordinate system NED*/
|
||
|
|
||
|
double phi = colatitude*DEG2RAD;
|
||
|
double lambda = longitude*DEG2RAD;
|
||
|
|
||
|
double cos_phi = cos(phi);
|
||
|
double sin_phi = sin(phi);
|
||
|
double cos_lambda = cos(lambda);
|
||
|
double sin_lambda = sin(lambda);
|
||
|
|
||
|
double columnvect_phi_unit[3] = {-sin_phi*cos_lambda, -sin_phi*sin_lambda, cos_phi};
|
||
|
double columnvect_lambda_unit[3] = {-sin_lambda, cos_lambda, 0};
|
||
|
double columnvect_r_unit[3] = {cos_phi*cos_lambda, cos_phi*sin_lambda, sin_phi};
|
||
|
|
||
|
columnvect_res[0] = columnvect_phi_unit[0]*columnvect_xyzloc[0]+columnvect_lambda_unit[0]*columnvect_xyzloc[1]+columnvect_r_unit[0]*columnvect_xyzloc[2];
|
||
|
columnvect_res[1] = columnvect_phi_unit[1]*columnvect_xyzloc[0]+columnvect_lambda_unit[1]*columnvect_xyzloc[1]+columnvect_r_unit[1]*columnvect_xyzloc[2];
|
||
|
columnvect_res[2] = columnvect_phi_unit[2]*columnvect_xyzloc[0]+columnvect_lambda_unit[2]*columnvect_xyzloc[1]+columnvect_r_unit[2]*columnvect_xyzloc[2];
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void from_cart_to_loc_sphr(double* columnvect_xyzglob, double colatitude, double longitude, double* columnvect_res)
|
||
|
{
|
||
|
/*IMPORTANT: this subroutine is in the coordinate system NED*/
|
||
|
|
||
|
double phi = colatitude*DEG2RAD;
|
||
|
double lambda = longitude*DEG2RAD;
|
||
|
|
||
|
double cos_phi = cos(phi);
|
||
|
double sin_phi = sin(phi);
|
||
|
double cos_lambda = cos(lambda);
|
||
|
double sin_lambda = sin(lambda);
|
||
|
|
||
|
double rowvect_phi_unit[3] = {-sin_phi*cos_lambda, -sin_phi*sin_lambda, cos_phi};
|
||
|
double rowvect_lambda_unit[3] = {-sin_lambda, cos_lambda, 0};
|
||
|
double rowvect_r_unit[3] = {cos_phi*cos_lambda, cos_phi*sin_lambda, sin_phi};
|
||
|
|
||
|
columnvect_res[0] = rowvect_phi_unit[0]*columnvect_xyzglob[0]+rowvect_phi_unit[1]*columnvect_xyzglob[1]+rowvect_phi_unit[2]*columnvect_xyzglob[2];
|
||
|
columnvect_res[1] = rowvect_lambda_unit[0]*columnvect_xyzglob[0]+rowvect_lambda_unit[1]*columnvect_xyzglob[1]+rowvect_lambda_unit[2]*columnvect_xyzglob[2];
|
||
|
columnvect_res[2] = rowvect_r_unit[0]*columnvect_xyzglob[0]+rowvect_r_unit[1]*columnvect_xyzglob[1]+rowvect_r_unit[2]*columnvect_xyzglob[2];
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void from_loc_sphr_to_loc_sphr(double* columnvect_xyzloc, double colatitude1, double longitude1, double colatitude2, double longitude2, double* columnvect_res)
|
||
|
{
|
||
|
double columnvect_xyzglob[3];
|
||
|
from_loc_sphr_to_cart(columnvect_xyzloc, colatitude1, longitude1, columnvect_xyzglob);
|
||
|
from_cart_to_loc_sphr(columnvect_xyzglob, colatitude2, longitude2, columnvect_res);
|
||
|
return;
|
||
|
|
||
|
}
|