/* ******** ell_3m_eigensolve_d() ** ** finds eigenvalues and eigenvectors of given matrix m ** ** returns information about the roots according to ellCubeRoot enum, ** see header for ellCubic for details. When eval[i] is set, evec+3*i ** is set to a corresponding eigenvector. The eigenvectors are ** (evec+0)[], (evec+3)[], and (evec+6)[] ** ** NOTE: Even in the post-Teem-1.7 switch from column-major to ** row-major- its still the case that the eigenvectors are at ** evec+0, evec+3, evec+6: this means that they USED to be the ** "columns" of the matrix, and NOW they're the rows. ** ** The eigenvalues (and associated eigenvectors) are sorted in ** descending order. ** ** This does NOT use biff */ int ell_3m_eigensolve_d(double eval[3], double evec[9], const double m[9], const int newton) { int roots; /* if (ell_debug) { printf("ell_3m_eigensolve_d: input matrix:\n"); printf("{{%20.15f,\t%20.15f,\t%20.15f},\n", m[0], m[1], m[2]); printf(" {%20.15f,\t%20.15f,\t%20.15f},\n", m[3], m[4], m[5]); printf(" {%20.15f,\t%20.15f,\t%20.15f}};\n",m[6], m[7], m[8]); } */ roots = ell_3m_eigenvalues_d(eval, m, newton); _ell_3m_evecs_d(evec, eval, roots, m); return roots; }
void _gageVecAnswer(gageContext *ctx, gagePerVolume *pvl) { char me[]="_gageVecAnswer"; double cmag, tmpMat[9], mgevec[9], mgeval[3]; double symm[9], asym[9], tran[9], eval[3], tmpVec[3], norm; gage_t *vecAns, *normAns, *jacAns, *curlAns, *hesAns, *curlGradAns, *helGradAns, *dirHelDirAns, *curlnormgradAns; /* int asw; */ vecAns = pvl->directAnswer[gageVecVector]; normAns = pvl->directAnswer[gageVecNormalized]; jacAns = pvl->directAnswer[gageVecJacobian]; curlAns = pvl->directAnswer[gageVecCurl]; hesAns = pvl->directAnswer[gageVecHessian]; curlGradAns = pvl->directAnswer[gageVecCurlGradient]; curlnormgradAns = pvl->directAnswer[gageVecCurlNormGrad]; helGradAns = pvl->directAnswer[gageVecHelGradient]; dirHelDirAns = pvl->directAnswer[gageVecDirHelDeriv]; if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecVector)) { /* done if doV */ if (ctx->verbose) { fprintf(stderr, "vec = "); ell_3v_PRINT(stderr, vecAns); } } /* done if doV if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecVector{0,1,2})) { } */ if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecLength)) { pvl->directAnswer[gageVecLength][0] = AIR_CAST(gage_t, ELL_3V_LEN(vecAns)); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecNormalized)) { if (pvl->directAnswer[gageVecLength][0]) { ELL_3V_SCALE_TT(normAns, gage_t, 1.0/pvl->directAnswer[gageVecLength][0], vecAns); } else { ELL_3V_COPY(normAns, gageZeroNormal); } } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecJacobian)) { /* done if doD1 */ /* 0:dv_x/dx 1:dv_x/dy 2:dv_x/dz 3:dv_y/dx 4:dv_y/dy 5:dv_y/dz 6:dv_z/dx 7:dv_z/dy 8:dv_z/dz */ if (ctx->verbose) { fprintf(stderr, "%s: jac = \n", me); ell_3m_PRINT(stderr, jacAns); } } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecDivergence)) { pvl->directAnswer[gageVecDivergence][0] = jacAns[0] + jacAns[4] + jacAns[8]; if (ctx->verbose) { fprintf(stderr, "%s: div = %g + %g + %g = %g\n", me, jacAns[0], jacAns[4], jacAns[8], pvl->directAnswer[gageVecDivergence][0]); } } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecCurl)) { ELL_3V_SET(curlAns, jacAns[7] - jacAns[5], jacAns[2] - jacAns[6], jacAns[3] - jacAns[1]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecCurlNorm)) { pvl->directAnswer[gageVecCurlNorm][0] = AIR_CAST(gage_t, ELL_3V_LEN(curlAns)); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecHelicity)) { pvl->directAnswer[gageVecHelicity][0] = ELL_3V_DOT(vecAns, curlAns); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecNormHelicity)) { cmag = ELL_3V_LEN(curlAns); pvl->directAnswer[gageVecNormHelicity][0] = AIR_CAST(gage_t, cmag ? ELL_3V_DOT(normAns, curlAns)/cmag : 0); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecLambda2)) { ELL_3M_TRANSPOSE(tran, jacAns); /* symmetric part */ ELL_3M_SCALE_ADD2(symm, 0.5, jacAns, 0.5, tran); /* antisymmetric part */ ELL_3M_SCALE_ADD2(asym, 0.5, jacAns, -0.5, tran); /* square symmetric part */ ELL_3M_MUL(tmpMat, symm, symm); ELL_3M_COPY(symm, tmpMat); /* square antisymmetric part */ ELL_3M_MUL(tmpMat, asym, asym); /* sum of both */ ELL_3M_ADD2(symm, symm, tmpMat); /* get eigenvalues in sorted order */ /* asw = */ ell_3m_eigenvalues_d(eval, symm, AIR_TRUE); pvl->directAnswer[gageVecLambda2][0] = AIR_CAST(gage_t, eval[1]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecImaginaryPart)) { pvl->directAnswer[gageVecImaginaryPart][0] = AIR_CAST(gage_t, gage_imaginary_part_eigenvalues(jacAns)); } /* 2nd order vector derivative continued */ if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecHessian)) { /* done if doD2 */ /* the ordering is induced by the scalar hessian computation : 0:d2v_x/dxdx 1:d2v_x/dxdy 2:d2v_x/dxdz 3:d2v_x/dydx 4:d2v_x/dydy 5:d2v_x/dydz 6:d2v_x/dzdx 7:d2v_x/dzdy 8:d2v_x/dzdz 9:d2v_y/dxdx [...] [...] 24:dv2_z/dzdx 25:d2v_z/dzdy 26:d2v_z/dzdz */ if (ctx->verbose) { fprintf(stderr, "%s: hes = \n", me); ell_3m_PRINT(stderr, hesAns); /* ?? */ } } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecDivGradient)) { pvl->directAnswer[gageVecDivGradient][0] = hesAns[0] + hesAns[12] + hesAns[24]; pvl->directAnswer[gageVecDivGradient][1] = hesAns[1] + hesAns[13] + hesAns[25]; pvl->directAnswer[gageVecDivGradient][2] = hesAns[2] + hesAns[14] + hesAns[26]; } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecCurlGradient)) { pvl->directAnswer[gageVecCurlGradient][0] = hesAns[21]-hesAns[15]; pvl->directAnswer[gageVecCurlGradient][1] = hesAns[22]-hesAns[16]; pvl->directAnswer[gageVecCurlGradient][2] = hesAns[23]-hesAns[17]; pvl->directAnswer[gageVecCurlGradient][3] = hesAns[ 6]-hesAns[18]; pvl->directAnswer[gageVecCurlGradient][4] = hesAns[ 7]-hesAns[19]; pvl->directAnswer[gageVecCurlGradient][5] = hesAns[ 8]-hesAns[20]; pvl->directAnswer[gageVecCurlGradient][6] = hesAns[ 9]-hesAns[ 1]; pvl->directAnswer[gageVecCurlGradient][7] = hesAns[10]-hesAns[ 2]; pvl->directAnswer[gageVecCurlGradient][8] = hesAns[11]-hesAns[ 3]; } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecCurlNormGrad)) { norm = 1./ELL_3V_LEN(curlAns); tmpVec[0] = hesAns[21] - hesAns[15]; tmpVec[1] = hesAns[ 6] - hesAns[18]; tmpVec[2] = hesAns[ 9] - hesAns[ 3]; pvl->directAnswer[gageVecCurlNormGrad][0]= AIR_CAST(gage_t, norm*ELL_3V_DOT(tmpVec, curlAns)); tmpVec[0] = hesAns[22] - hesAns[16]; tmpVec[1] = hesAns[ 7] - hesAns[19]; tmpVec[2] = hesAns[10] - hesAns[ 4]; pvl->directAnswer[gageVecCurlNormGrad][1]= AIR_CAST(gage_t, norm*ELL_3V_DOT(tmpVec, curlAns)); tmpVec[0] = hesAns[23] - hesAns[17]; tmpVec[1] = hesAns[ 8] - hesAns[20]; tmpVec[2] = hesAns[11] - hesAns[ 5]; pvl->directAnswer[gageVecCurlNormGrad][2]= AIR_CAST(gage_t, norm*ELL_3V_DOT(tmpVec, curlAns)); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecNCurlNormGrad)) { norm = 1./ELL_3V_LEN(curlnormgradAns); ELL_3V_SCALE_TT(pvl->directAnswer[gageVecNCurlNormGrad], gage_t, norm, pvl->directAnswer[gageVecCurlNormGrad]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecHelGradient)) { pvl->directAnswer[gageVecHelGradient][0] = jacAns[0]*curlAns[0]+ jacAns[3]*curlAns[1]+ jacAns[6]*curlAns[2]+ curlGradAns[0]*vecAns[0]+ curlGradAns[3]*vecAns[1]+ curlGradAns[6]*vecAns[2]; pvl->directAnswer[gageVecHelGradient][1] = jacAns[1]*curlAns[0]+ jacAns[4]*curlAns[1]+ jacAns[7]*curlAns[2]+ curlGradAns[1]*vecAns[0]+ curlGradAns[4]*vecAns[1]+ curlGradAns[7]*vecAns[2]; pvl->directAnswer[gageVecHelGradient][0] = jacAns[2]*curlAns[0]+ jacAns[5]*curlAns[1]+ jacAns[8]*curlAns[2]+ curlGradAns[2]*vecAns[0]+ curlGradAns[5]*vecAns[1]+ curlGradAns[8]*vecAns[2]; } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecDirHelDeriv)) { pvl->directAnswer[gageVecDirHelDeriv][0] = ELL_3V_DOT(normAns, helGradAns); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecProjHelGradient)) { pvl->directAnswer[gageVecDirHelDeriv][0] = helGradAns[0]-dirHelDirAns[0]*normAns[0]; pvl->directAnswer[gageVecDirHelDeriv][1] = helGradAns[1]-dirHelDirAns[0]*normAns[1]; pvl->directAnswer[gageVecDirHelDeriv][2] = helGradAns[2]-dirHelDirAns[0]*normAns[2]; } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecGradient0)) { ELL_3V_SET(pvl->directAnswer[gageVecGradient0], jacAns[0], jacAns[1], jacAns[2]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecGradient1)) { ELL_3V_SET(pvl->directAnswer[gageVecGradient1], jacAns[3], jacAns[4], jacAns[5]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecGradient2)) { ELL_3V_SET(pvl->directAnswer[gageVecGradient2], jacAns[6], jacAns[7], jacAns[8]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecMultiGrad)) { ELL_3M_IDENTITY_SET(pvl->directAnswer[gageVecMultiGrad]); ELL_3MV_OUTER_ADD(pvl->directAnswer[gageVecMultiGrad], pvl->directAnswer[gageVecGradient0], pvl->directAnswer[gageVecGradient0]); ELL_3MV_OUTER_ADD(pvl->directAnswer[gageVecMultiGrad], pvl->directAnswer[gageVecGradient1], pvl->directAnswer[gageVecGradient1]); ELL_3MV_OUTER_ADD(pvl->directAnswer[gageVecMultiGrad], pvl->directAnswer[gageVecGradient2], pvl->directAnswer[gageVecGradient2]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecMGFrob)) { pvl->directAnswer[gageVecMGFrob][0] = AIR_CAST(gage_t, ELL_3M_FROB(pvl->directAnswer[gageVecMultiGrad])); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecMGEval)) { ELL_3M_COPY(tmpMat, pvl->directAnswer[gageVecMultiGrad]); /* HEY: look at the return value for root multiplicity? */ ell_3m_eigensolve_d(mgeval, mgevec, tmpMat, AIR_TRUE); ELL_3V_COPY_TT(pvl->directAnswer[gageVecMGEval], gage_t, mgeval); } if (GAGE_QUERY_ITEM_TEST(pvl->query, gageVecMGEvec)) { ELL_3M_COPY_TT(pvl->directAnswer[gageVecMGEvec], gage_t, mgevec); } return; }