From 1bb7741e4e4c1990d5d16173faaf00ad394decb9 Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Tue, 29 Aug 2023 10:09:48 -0400 Subject: [PATCH 01/61] Planar Coils are working now --- CMakeLists.txt | 2 +- src/simsopt/geo/curve.py | 40 +- src/simsopt/geo/curveplanarfourier.py | 39 ++ src/simsoptpp/curveplanarfourier.cpp | 632 ++++++++++++++++++++++++ src/simsoptpp/curveplanarfourier.h | 122 +++++ src/simsoptpp/python_curves.cpp | 35 ++ tests/geo/test_curve.py | 10 +- tests/test_files/input.NewConfiguration | 113 +++++ 8 files changed, 986 insertions(+), 7 deletions(-) create mode 100644 src/simsopt/geo/curveplanarfourier.py create mode 100644 src/simsoptpp/curveplanarfourier.cpp create mode 100644 src/simsoptpp/curveplanarfourier.h create mode 100644 tests/test_files/input.NewConfiguration diff --git a/CMakeLists.txt b/CMakeLists.txt index eb573c647..1371d44ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ pybind11_add_module(${PROJECT_NAME} src/simsoptpp/biot_savart_py.cpp src/simsoptpp/biot_savart_vjp_py.cpp src/simsoptpp/regular_grid_interpolant_3d_py.cpp - src/simsoptpp/curve.cpp src/simsoptpp/curverzfourier.cpp src/simsoptpp/curvexyzfourier.cpp + src/simsoptpp/curve.cpp src/simsoptpp/curverzfourier.cpp src/simsoptpp/curvexyzfourier.cpp src/simsoptpp/curveplanarfourier.cpp src/simsoptpp/surface.cpp src/simsoptpp/surfacerzfourier.cpp src/simsoptpp/surfacexyzfourier.cpp src/simsoptpp/integral_BdotN.cpp src/simsoptpp/dipole_field.cpp src/simsoptpp/permanent_magnet_optimization.cpp diff --git a/src/simsopt/geo/curve.py b/src/simsopt/geo/curve.py index 104d4c1d5..40f48e188 100644 --- a/src/simsopt/geo/curve.py +++ b/src/simsopt/geo/curve.py @@ -11,7 +11,7 @@ from .jit import jit from .plotting import fix_matplotlib_3d -__all__ = ['Curve', 'RotatedCurve', 'curves_to_vtk', 'create_equally_spaced_curves'] +__all__ = ['Curve', 'RotatedCurve', 'curves_to_vtk', 'create_equally_spaced_curves', 'create_equally_spaced_planar_curves'] @jit @@ -879,3 +879,41 @@ def create_equally_spaced_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, order=6 curve.x = curve.x # need to do this to transfer data to C++ curves.append(curve) return curves + +def create_equally_spaced_planar_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, order=6, numquadpoints=None): + """ + Insert text here + """ + + if numquadpoints is None: + numquadpoints = 15 * order + curves = [] + from simsopt.geo.curveplanarfourier import CurvePlanarFourier + for k in range(ncurves): + angle = k*(2*np.pi) / ((1+int(stellsym))*nfp*ncurves) + curve = CurvePlanarFourier(numquadpoints, order, nfp, stellsym) + + rcCoeffs = np.zeros(order+1) + rcCoeffs[0] = R1 + rsCoeffs = np.zeros(order) + center = [R0 * cos(angle), R0 * sin(angle), 0] + rotation = [1, -cos(angle), -sin(angle), 0] + dofs = np.zeros(len(curve.get_dofs())) + + j = 0 + for i in rcCoeffs: + dofs[j] = i + j += 1 + for i in rsCoeffs: + dofs[j] = i + j += 1 + for i in rotation: + dofs[j] = i + j += 1 + for i in center: + dofs[j] = i + j += 1 + + curve.set_dofs(dofs) + curves.append(curve) + return curves \ No newline at end of file diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py new file mode 100644 index 000000000..78b590548 --- /dev/null +++ b/src/simsopt/geo/curveplanarfourier.py @@ -0,0 +1,39 @@ +import numpy as np + +import simsoptpp as sopp +from .._core.json import GSONDecoder +from .curve import Curve + +__all__ = ['CurvePlanarFourier'] + + +class CurvePlanarFourier(sopp.CurvePlanarFourier, Curve): + r""" + Insert text here + """ + + def __init__(self, quadpoints, order, nfp, stellsym, dofs=None): + if isinstance(quadpoints, int): + quadpoints = list(np.linspace(0, 1., quadpoints, endpoint=False)) + elif isinstance(quadpoints, np.ndarray): + quadpoints = list(quadpoints) + sopp.CurvePlanarFourier.__init__(self, quadpoints, order, nfp, stellsym) + if dofs is None: + Curve.__init__(self, external_dof_setter=CurvePlanarFourier.set_dofs_impl, + x0=self.get_dofs()) + else: + Curve.__init__(self, external_dof_setter=CurvePlanarFourier.set_dofs_impl, + dofs=dofs) + + def get_dofs(self): + """ + This function returns the dofs associated to this object. + """ + return np.asarray(sopp.CurvePlanarFourier.get_dofs(self)) + + def set_dofs(self, dofs): + """ + This function sets the dofs associated to this object. + """ + self.local_x = dofs + sopp.CurvePlanarFourier.set_dofs(self, dofs) diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp new file mode 100644 index 000000000..66398db6b --- /dev/null +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -0,0 +1,632 @@ +#include "curveplanarfourier.h" + + +template +void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { + int numquadpoints = quadpoints.size(); + data *= 0; + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 0; i < order+1; ++i) { + data(k, 0) += rc[i] * cos(i*phi) * cos(phi); + data(k, 1) += rc[i] * cos(i*phi) * sin(phi); + } + } + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 1; i < order+1; ++i) { + data(k, 0) += rs[i-1] * sin(i*phi) * cos(phi); + data(k, 1) += rs[i-1] * sin(i*phi) * sin(phi); + } + } + for (int m = 0; m < numquadpoints; ++m) { + double i; + double j; + double k; + i = data(m, 0); + j = data(m, 1); + k = data(m, 2); + + data(m, 0) = (i - 2 * (q[2] * q[2] + q[3] * q[3]) * i + 2 * (q[1] * q[2] - q[3] * q[0]) * j + 2 * (q[1] * q[3] + q[2] * q[0]) * k) + center[0]; + data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i + j - 2 * (q[1] * q[1] + q[3] * q[3]) * j + 2 * (q[2] * q[3] - q[1] * q[0]) * k) + center[1]; + data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i + 2 * (q[2] * q[3] + q[1] * q[0]) * j + k - 2 * (q[1] * q[1] + q[2] * q[2]) * k) + center[2]; + } +} + +template +void CurvePlanarFourier::gammadash_impl(Array& data) { + data *= 0; + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 0; i < order+1; ++i) { + data(k, 0) += rc[i] * ( -(i) * sin(i*phi) * cos(phi) - cos(i*phi) * sin(phi)); + data(k, 1) += rc[i] * ( -(i) * sin(i*phi) * sin(phi) + cos(i*phi) * cos(phi)); + } + } + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 1; i < order+1; ++i) { + data(k, 0) += rs[i-1] * ( (i) * cos(i*phi) * cos(phi) - sin(i*phi) * sin(phi)); + data(k, 1) += rs[i-1] * ( (i) * cos(i*phi) * sin(phi) + sin(i*phi) * cos(phi)); + } + } + data *= (2*M_PI); + for (int m = 0; m < numquadpoints; ++m) { + Array i = xt::zeros({1}); + i[0] = data(m, 0); + Array j = xt::zeros({1}); + j[0] = data(m, 1); + Array k = xt::zeros({1}); + k[0] = data(m, 2); + + data(m, 0) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + } + +} + +template +void CurvePlanarFourier::gammadashdash_impl(Array& data) { + data *= 0; + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 0; i < order+1; ++i) { + data(k, 0) += rc[i] * (+2*(i)*sin(i*phi)*sin(phi)-(pow(i, 2)+1)*cos(i*phi)*cos(phi)); + data(k, 1) += rc[i] * (-2*(i)*sin(i*phi)*cos(phi)-(pow(i, 2)+1)*cos(i*phi)*sin(phi)); + } + data(k, 2) = 0; + } + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 1; i < order+1; ++i) { + data(k, 0) += rs[i-1] * (-(pow(i,2)+1)*sin(i*phi)*cos(phi) - 2*(i)*cos(i*phi)*sin(phi)); + data(k, 1) += rs[i-1] * (-(pow(i,2)+1)*sin(i*phi)*sin(phi) + 2*(i)*cos(i*phi)*cos(phi)); + } + data(k, 2) = 0; + } + data *= 2*M_PI*2*M_PI; + for (int m = 0; m < numquadpoints; ++m) { + Array i = xt::zeros({1}); + i[0] = data(m, 0); + Array j = xt::zeros({1}); + j[0] = data(m, 1); + Array k = xt::zeros({1}); + k[0] = data(m, 2); + + data(m, 0) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + } +} + +template +void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { + data *= 0; + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 0; i < order+1; ++i) { + data(k, 0) += rc[i]*( + +(3*pow(i, 2) + 1)*cos(i*phi)*sin(phi) + +(pow(i, 2) + 3)*(i)*sin(i*phi)*cos(phi) + ); + data(k, 1) += rc[i]*( + +(pow(i, 2) + 3)*(i)*sin(i*phi)*sin(phi) + -(3*pow(i, 2) + 1)*cos(i*phi)*cos(phi) + ); + } + } + for (int k = 0; k < numquadpoints; ++k) { + double phi = 2 * M_PI * quadpoints[k]; + for (int i = 1; i < order+1; ++i) { + data(k, 0) += rs[i-1]*( + -(pow(i,2)+3) * (i) * cos(i*phi)*cos(phi) + +(3*pow(i,2)+1) * sin(i*phi)*sin(phi) + ); + data(k, 1) += rs[i-1]*( + -(pow(i,2)+3)*(i)*cos(i*phi)*sin(phi) + -(3*pow(i,2)+1)*sin(i*phi)*cos(phi) + ); + } + } + data *= 2*M_PI*2*M_PI*2*M_PI; + for (int m = 0; m < numquadpoints; ++m) { + Array i = xt::zeros({1}); + i[0] = data(m, 0); + Array j = xt::zeros({1}); + j[0] = data(m, 1); + Array k = xt::zeros({1}); + k[0] = data(m, 2); + + data(m, 0) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + } +} + +template +void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { + data *= 0; + for (int m = 0; m < numquadpoints; ++m) { + double phi = 2 * M_PI * quadpoints[m]; + int counter = 0; + Array i = xt::zeros({1}); + Array j = xt::zeros({1}); + Array k = xt::zeros({1}); + + for (int n = 0; n < order+1; ++n) { + i[0] = cos(n*phi) * cos(phi); + j[0] = cos(n*phi) * sin(phi); + k[0] = 0; + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + counter++; + } + + for (int n = 1; n < order+1; ++n) { + i[0] = sin(n*phi) * cos(phi); + j[0] = sin(n*phi) * sin(phi); + k[0] = 0; + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + counter++; + } + + i[0] = 0; + j[0] = 0; + k[0] = 0; + + for (int n = 0; n < order+1; ++n) { + i[0] += rc[n] * cos(n*phi) * cos(phi); + j[0] += rc[n] * cos(n*phi) * sin(phi); + } + for (int n = 1; n < order+1; ++n) { + i[0] += rs[n-1] * sin(n*phi) * cos(phi); + j[0] += rs[n-1] * sin(n*phi) * sin(phi); + } + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] + - 2 * j[0] * q[3]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] + + 2 * i[0] * q[3] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] + - 2 * i[0] * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] + + 2 * j[0] * q[1]; + counter++; + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] + + 2 * j[0] * q[2]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] + + 2 * i[0] * q[2] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] + - 4 * j[0] * q[1]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] + + 2 * i[0] * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] + + 2 * j[0] * q[0]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] + + 2 * j[0] * q[1]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] + + 2 * i[0] * q[1] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; + data(m, 2, counter) = - 2 * i[0] * q[0] + - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] + + 2 * j[0] * q[3]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] + - 2 * j[0] * q[0]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] + + 2 * i[0] * q[0] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] + - 4 * j[0] * q[3]; + data(m, 2, counter) = 2 * i[0] * q[1] + + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] + + 2 * j[0] * q[2]; + counter++; + + + for (int i = 0; i < 3; ++i) { + data(m, 0, counter) = 0; + data(m, 1, counter) = 0; + data(m, 2, counter) = 0; + data(m, i, counter) = 1; + + counter++; + } + } +} + +template +void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { + data *= 0; + for (int m = 0; m < numquadpoints; ++m) { + double phi = 2 * M_PI * quadpoints[m]; + int counter = 0; + Array i = xt::zeros({1}); + Array j = xt::zeros({1}); + Array k = xt::zeros({1}); + for (int n = 0; n < order+1; ++n) { + i[0] = ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)); + j[0] = ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)); + k[0] = 0; + + i[0] *= (2*M_PI); + j[0] *= (2*M_PI); + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + + counter++; + } + + for (int n = 1; n < order+1; ++n) { + i[0] = ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)); + j[0] = ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)); + k[0] = 0; + + i[0] *= (2*M_PI); + j[0] *= (2*M_PI); + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + counter++; + + } + + i[0] = 0; + j[0] = 0; + k[0] = 0; + for (int n = 0; n < order+1; ++n) { + i[0] += rc[n] * ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)) * 2 * M_PI; + j[0] += rc[n] * ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)) * 2 * M_PI; + } + for (int n = 1; n < order+1; ++n) { + i[0] += rs[n-1] * ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)) * 2 * M_PI; + j[0] += rs[n-1] * ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)) * 2 * M_PI; + } + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] + - 2 * j[0] * q[3]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] + + 2 * i[0] * q[3] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] + - 2 * i[0] * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] + + 2 * j[0] * q[1]; + counter++; + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] + + 2 * j[0] * q[2]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] + + 2 * i[0] * q[2] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] + - 4 * j[0] * q[1]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] + + 2 * i[0] * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] + + 2 * j[0] * q[0]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] + + 2 * j[0] * q[1]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] + + 2 * i[0] * q[1] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; + data(m, 2, counter) = - 2 * i[0] * q[0] + - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] + + 2 * j[0] * q[3]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] + - 2 * j[0] * q[0]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] + + 2 * i[0] * q[0] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] + - 4 * j[0] * q[3]; + data(m, 2, counter) = 2 * i[0] * q[1] + + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] + + 2 * j[0] * q[2]; + counter++; + + for (int i = 0; i < 2; ++i) { + data(m, 0, counter) = 0; + data(m, 1, counter) = 0; + data(m, 2, counter) = 0; + + counter++; + } + + } +} + +template +void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { + data *= 0; + for (int m = 0; m < numquadpoints; ++m) { + double phi = 2 * M_PI * quadpoints[m]; + int counter = 0; + Array i = xt::zeros({1}); + Array j = xt::zeros({1}); + Array k = xt::zeros({1}); + for (int n = 0; n < order+1; ++n) { + i[0] = (+2*(n)*sin(n*phi)*sin(phi)-(pow(n, 2)+1)*cos(n*phi)*cos(phi)); + j[0] = (-2*(n)*sin(n*phi)*cos(phi)-(pow(n, 2)+1)*cos(n*phi)*sin(phi)); + k[0] = 0; + + i[0] *= 2*M_PI*2*M_PI; + j[0] *= 2*M_PI*2*M_PI; + k[0] *= 2*M_PI*2*M_PI; + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + counter++; + } + + for (int n = 1; n < order+1; ++n) { + i[0] = (-(pow(n,2)+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); + j[0] = (-(pow(n,2)+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); + k[0] = 0; + + i[0] *= 2*M_PI*2*M_PI; + j[0] *= 2*M_PI*2*M_PI; + k[0] *= 2*M_PI*2*M_PI; + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + counter++; + } + + i[0] = 0; + j[0] = 0; + k[0] = 0; + for (int n = 0; n < order+1; ++n) { + i[0] += rc[n] * (+2*(n)*sin(n*phi)*sin(phi)-(pow(n, 2)+1)*cos(n*phi)*cos(phi)); + j[0] += rc[n] * (-2*(n)*sin(n*phi)*cos(phi)-(pow(n, 2)+1)*cos(n*phi)*sin(phi)); + } + for (int n = 1; n < order+1; ++n) { + i[0] += rs[n-1] * (-(pow(n,2)+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); + j[0] += rs[n-1] * (-(pow(n,2)+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); + } + i[0] *= 2*M_PI*2*M_PI; + j[0] *= 2*M_PI*2*M_PI; + k[0] *= 2*M_PI*2*M_PI; + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] + - 2 * j[0] * q[3]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] + + 2 * i[0] * q[3] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] + - 2 * i[0] * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] + + 2 * j[0] * q[1]; + counter++; + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] + + 2 * j[0] * q[2]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] + + 2 * i[0] * q[2] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] + - 4 * j[0] * q[1]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] + + 2 * i[0] * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] + + 2 * j[0] * q[0]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] + + 2 * j[0] * q[1]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] + + 2 * i[0] * q[1] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; + data(m, 2, counter) = - 2 * i[0] * q[0] + - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] + + 2 * j[0] * q[3]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] + - 2 * j[0] * q[0]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] + + 2 * i[0] * q[0] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] + - 4 * j[0] * q[3]; + data(m, 2, counter) = 2 * i[0] * q[1] + + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] + + 2 * j[0] * q[2]; + counter++; + + for (int i = 0; i < 3; ++i) { + data(m, 0, counter) = 0; + data(m, 1, counter) = 0; + data(m, 2, counter) = 0; + + counter++; + } + } +} + +template +void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { + data *= 0; + for (int m = 0; m < numquadpoints; ++m) { + double phi = 2 * M_PI * quadpoints[m]; + int counter = 0; + Array i = xt::zeros({1}); + Array j = xt::zeros({1}); + Array k = xt::zeros({1}); + for (int n = 0; n < order+1; ++n) { + i[0] = ( + +(3*pow(n, 2) + 1)*cos(n*phi)*sin(phi) + +(pow(n, 2) + 3)*(n)*sin(n*phi)*cos(phi) + ); + j[0] = ( + +(pow(n, 2) + 3)*(n)*sin(n*phi)*sin(phi) + -(3*pow(n, 2) + 1)*cos(n*phi)*cos(phi) + ); + k[0] = 0; + + i[0] *= 2*M_PI*2*M_PI*2*M_PI; + j[0] *= 2*M_PI*2*M_PI*2*M_PI; + k[0] *= 2*M_PI*2*M_PI*2*M_PI; + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + counter++; + } + + for (int n = 1; n < order+1; ++n) { + i[0] = ( + -(pow(n,2)+3) * (n) * cos(n*phi)*cos(phi) + +(3*pow(n,2)+1) * sin(n*phi)*sin(phi) + ); + j[0] = ( + -(pow(n,2)+3)*(n)*cos(n*phi)*sin(phi) + -(3*pow(n,2)+1)*sin(n*phi)*cos(phi) + ); + k[0] = 0; + + i[0] *= 2*M_PI*2*M_PI*2*M_PI; + j[0] *= 2*M_PI*2*M_PI*2*M_PI; + k[0] *= 2*M_PI*2*M_PI*2*M_PI; + + data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); + data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); + data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + + counter++; + } + + i[0] = 0; + j[0] = 0; + k[0] = 0; + for (int n = 0; n < order+1; ++n) { + i[0] += rc[n]*( + +(3*pow(n, 2) + 1)*cos(n*phi)*sin(phi) + +(pow(n, 2) + 3)*(n)*sin(n*phi)*cos(phi) + ); + j[0] += rc[n]*( + +(pow(n, 2) + 3)*(n)*sin(n*phi)*sin(phi) + -(3*pow(n, 2) + 1)*cos(n*phi)*cos(phi) + ); + } + for (int n = 1; n < order+1; ++n) { + i[0] += rs[n-1]*( + -(pow(n,2)+3) * (n) * cos(n*phi)*cos(phi) + +(3*pow(n,2)+1) * sin(n*phi)*sin(phi) + ); + j[0] += rs[n-1]*( + -(pow(n,2)+3)*(n)*cos(n*phi)*sin(phi) + -(3*pow(n,2)+1)*sin(n*phi)*cos(phi) + ); + } + i[0] *= 2*M_PI*2*M_PI*2*M_PI; + j[0] *= 2*M_PI*2*M_PI*2*M_PI; + k[0] *= 2*M_PI*2*M_PI*2*M_PI; + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] + - 2 * j[0] * q[3]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] + + 2 * i[0] * q[3] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] + - 2 * i[0] * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] + + 2 * j[0] * q[1]; + counter++; + + data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] + + 2 * j[0] * q[2]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] + + 2 * i[0] * q[2] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] + - 4 * j[0] * q[1]; + data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] + + 2 * i[0] * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] + + 2 * j[0] * q[0]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] + + 2 * j[0] * q[1]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] + + 2 * i[0] * q[1] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; + data(m, 2, counter) = - 2 * i[0] * q[0] + - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] + + 2 * j[0] * q[3]; + counter++; + + data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] + - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] + - 2 * j[0] * q[0]; + data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] + + 2 * i[0] * q[0] + + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] + - 4 * j[0] * q[3]; + data(m, 2, counter) = 2 * i[0] * q[1] + + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] + - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] + + 2 * j[0] * q[2]; + counter++; + + for (int i = 0; i < 3; ++i) { + data(m, 0, counter) = 0; + data(m, 1, counter) = 0; + data(m, 2, counter) = 0; + + counter++; + } + } +} + + + +#include "xtensor-python/pyarray.hpp" // Numpy bindings +typedef xt::pyarray Array; +template class CurvePlanarFourier; diff --git a/src/simsoptpp/curveplanarfourier.h b/src/simsoptpp/curveplanarfourier.h new file mode 100644 index 000000000..4febd687d --- /dev/null +++ b/src/simsoptpp/curveplanarfourier.h @@ -0,0 +1,122 @@ +#pragma once + +#include "curve.h" + +template +class CurvePlanarFourier : public Curve { + /* + CurvePlanarFourier is a curve that is represented as a plane rotated about the + x and y axis using the following Fourier series: + + r(phi) = \sum_{n=0}^{order} x_{c,n}cos(n*nfp*phi) + \sum_{n=1}^order x_{s,n}sin(n*nfp*phi) + + with rotation about an axis and angle determine by a set of quarternions + q = [cos(\theta/2), x * sin(\theta/2), y * sin(\theta/2), z * sin(\theta/2)] + + The dofs are stored in the order + + [r_{c,0},...,r_{c,order},r_{s,1},...,r_{s,order},t_{x},t_{y}] + + */ + public: + const int order; + const int nfp; + const bool stellsym; + using Curve::quadpoints; + using Curve::numquadpoints; + using Curve::check_the_persistent_cache; + + Array rc; + Array rs; + Array q; + Array center; + + CurvePlanarFourier(int _numquadpoints, int _order, int _nfp, bool _stellsym) : Curve(_numquadpoints), order(_order), nfp(_nfp), stellsym(_stellsym) { + rc = xt::zeros({order + 1}); + rs = xt::zeros({order}); + q = xt::zeros({4}); + center = xt::zeros({3}); + } + + CurvePlanarFourier(vector _quadpoints, int _order, int _nfp, bool _stellsym) : Curve(_quadpoints), order(_order), nfp(_nfp), stellsym(_stellsym) { + rc = xt::zeros({order + 1}); + rs = xt::zeros({order}); + q = xt::zeros({4}); + center = xt::zeros({3}); + } + + CurvePlanarFourier(Array _quadpoints, int _order, int _nfp, bool _stellsym) : Curve(_quadpoints), order(_order), nfp(_nfp), stellsym(_stellsym) { + rc = xt::zeros({order + 1}); + rs = xt::zeros({order}); + q = xt::zeros({4}); + center = xt::zeros({3}); + } + + inline int num_dofs() override { + return (2*order+1)+7; + } + + void set_dofs_impl(const vector& dofs) override { + int counter = 0; + double s = 0; + for (int i = 0; i < order + 1; ++i) + rc.data()[i] = dofs[counter++]; + for (int i = 0; i < order; ++i) + rs.data()[i] = dofs[counter++]; + for (int i = 0; i < 4; ++i){ + q.data()[i] = dofs[counter++]; + s += q[i] * q[i]; + } + /* Converts to unit quaternion */ + if(s != 0) { + for (int i = 0; i < 4; ++i) + q.data()[i] = q[i] / std::sqrt(s); + } + else { + q.data()[0] = 1; + } + for (int i = 0; i < 3; ++i){ + center.data()[i] = dofs[counter++]; + } + } + + vector get_dofs() override { + auto res = vector(num_dofs(), 0.); + int counter = 0; + for (int i = 0; i < order + 1; ++i) + res[counter++] = rc[i]; + for (int i = 0; i < order; ++i) + res[counter++] = rs[i]; + for (int i = 0; i < 4; ++i) + res[counter++] = q[i]; + for (int i = 0; i < 3; ++i) + res[counter++] = center[i]; + return res; + } + + Array& dgamma_by_dcoeff() override { + return check_the_persistent_cache("dgamma_by_dcoeff", {numquadpoints, 3, num_dofs()}, [this](Array& A) { return dgamma_by_dcoeff_impl(A);}); + } + Array& dgammadash_by_dcoeff() override { + return check_the_persistent_cache("dgammadash_by_dcoeff", {numquadpoints, 3, num_dofs()}, [this](Array& A) { return dgammadash_by_dcoeff_impl(A);}); + } + Array& dgammadashdash_by_dcoeff() override { + return check_the_persistent_cache("dgammadashdash_by_dcoeff", {numquadpoints, 3, num_dofs()}, [this](Array& A) { return dgammadashdash_by_dcoeff_impl(A);}); + } + Array& dgammadashdashdash_by_dcoeff() override { + return check_the_persistent_cache("dgammadashdashdash_by_dcoeff", {numquadpoints, 3, num_dofs()}, [this](Array& A) { return dgammadashdashdash_by_dcoeff_impl(A);}); + } + + + void gamma_impl(Array& data, Array& quadpoints) override; + void gammadash_impl(Array& data) override; + void gammadashdash_impl(Array& data) override; + void gammadashdashdash_impl(Array& data) override; + void dgamma_by_dcoeff_impl(Array& data) override; + void dgammadash_by_dcoeff_impl(Array& data) override; + void dgammadashdash_by_dcoeff_impl(Array& data) override; + void dgammadashdashdash_by_dcoeff_impl(Array& data) override; + + + +}; diff --git a/src/simsoptpp/python_curves.cpp b/src/simsoptpp/python_curves.cpp index 58adbecd3..ada7a2225 100644 --- a/src/simsoptpp/python_curves.cpp +++ b/src/simsoptpp/python_curves.cpp @@ -13,6 +13,8 @@ namespace py = pybind11; typedef CurveXYZFourier PyCurveXYZFourier; #include "curverzfourier.h" typedef CurveRZFourier PyCurveRZFourier; +#include "curveplanarfourier.h" +typedef CurvePlanarFourier PyCurvePlanarFourier; template class PyCurveXYZFourierTrampoline : public PyCurveTrampoline { public: @@ -55,6 +57,27 @@ template class PyCurveRZFourierT PyCurveRZFourierBase::gamma_impl(data, quadpoints); } }; + +template class PyCurvePlanarFourierTrampoline : public PyCurveTrampoline { + public: + using PyCurveTrampoline::PyCurveTrampoline; // Inherit constructors + + int num_dofs() override { + return PyCurvePlanarFourierBase::num_dofs(); + } + + void set_dofs_impl(const vector& _dofs) override { + PyCurvePlanarFourierBase::set_dofs_impl(_dofs); + } + + vector get_dofs() override { + return PyCurvePlanarFourierBase::get_dofs(); + } + + void gamma_impl(PyArray& data, PyArray& quadpoints) override { + PyCurvePlanarFourierBase::gamma_impl(data, quadpoints); + } +}; template void register_common_curve_methods(S &c) { c.def("gamma", &T::gamma) .def("gamma_impl", &T::gamma_impl) @@ -110,4 +133,16 @@ void init_curves(py::module_ &m) { .def_readonly("stellsym", &PyCurveRZFourier::stellsym) .def_readonly("nfp", &PyCurveRZFourier::nfp); register_common_curve_methods(pycurverzfourier); + + auto pycurveplanarfourier = py::class_, PyCurvePlanarFourierTrampoline, PyCurve>(m, "CurvePlanarFourier") + //.def(py::init()) + .def(py::init, int, int, bool>()) + .def_readwrite("rc", &PyCurvePlanarFourier::rc) + .def_readwrite("rs", &PyCurvePlanarFourier::rs) + .def_readwrite("q", &PyCurvePlanarFourier::q) + .def_readwrite("center", &PyCurvePlanarFourier::center) + .def_readonly("order", &PyCurvePlanarFourier::order) + .def_readonly("stellsym", &PyCurvePlanarFourier::stellsym) + .def_readonly("nfp", &PyCurvePlanarFourier::nfp); + register_common_curve_methods(pycurveplanarfourier); } diff --git a/tests/geo/test_curve.py b/tests/geo/test_curve.py index 5bd49ddc1..817430220 100644 --- a/tests/geo/test_curve.py +++ b/tests/geo/test_curve.py @@ -9,6 +9,7 @@ from simsopt._core.json import GSONEncoder, GSONDecoder, SIMSON from simsopt.geo.curvexyzfourier import CurveXYZFourier, JaxCurveXYZFourier from simsopt.geo.curverzfourier import CurveRZFourier +from simsopt.geo.curveplanarfourier import CurvePlanarFourier from simsopt.geo.curvehelical import CurveHelical from simsopt.geo.curve import RotatedCurve, curves_to_vtk from simsopt.geo import parameters @@ -46,7 +47,6 @@ def taylor_test(f, df, x, epsilons=None, direction=None): fminuseps = f(x - eps * direction) dfest = (fpluseps-fminuseps)/(2*eps) err = np.linalg.norm(dfest - dfx) - # print(err) assert err < 1e-9 or err < 0.3 * err_old if err < 1e-9: break @@ -72,6 +72,8 @@ def get_curve(curvetype, rotated, x=np.asarray([0.5])): curve = CurveHelical(x, order, 5, 2, 1.0, 0.3) elif curvetype == "CurveHelicalInitx0": curve = CurveHelical(x, order, 5, 2, 1.0, 0.3, x0=np.ones((2*order,))) + elif curvetype == "CurvePlanarFourier": + curve = CurvePlanarFourier(x, order, 2, True) else: assert False @@ -80,7 +82,7 @@ def get_curve(curvetype, rotated, x=np.asarray([0.5])): dofs[1] = 1. dofs[2*order + 3] = 1. dofs[4*order + 3] = 1. - elif curvetype in ["CurveRZFourier"]: + elif curvetype in ["CurveRZFourier", "CurvePlanarFourier"]: dofs[0] = 1. dofs[1] = 0.1 dofs[order+1] = 0.1 @@ -97,9 +99,7 @@ def get_curve(curvetype, rotated, x=np.asarray([0.5])): class Testing(unittest.TestCase): - curvetypes = ["CurveXYZFourier", "JaxCurveXYZFourier", "CurveRZFourier", "CurveHelical", - "CurveHelicalInitx0"] - + curvetypes = ["CurveXYZFourier", "JaxCurveXYZFourier", "CurveRZFourier", "CurvePlanarFourier", "CurveHelical", "CurveHelicalInitx0"] def test_curve_helical_xyzfourier(self): x = np.asarray([0.6]) curve1 = CurveHelical(x, 2, 5, 2, 1.0, 0.3) diff --git a/tests/test_files/input.NewConfiguration b/tests/test_files/input.NewConfiguration new file mode 100644 index 000000000..9adf5fa4e --- /dev/null +++ b/tests/test_files/input.NewConfiguration @@ -0,0 +1,113 @@ +&INDATA +!----- Runtime Parameters ----- + DELT = 9.00E-01 + NITER = 10000 + NSTEP = 200 + TCON0 = 2.00E+00 + +! NS_ARRAY = 16 50 +! NITER_ARRAY = 600 3000 +! FTOL_ARRAY = 1.0E-16 1.0E-13 + +! NS_ARRAY = 12 25 50 +! NITER_ARRAY = 600 1000 6000 +! FTOL_ARRAY = 1.0E-17 1.0e-17 1.0e-15 + +! NS_ARRAY = 12 25 50 75 +! NITER_ARRAY = 600 1000 2500 10000 +! FTOL_ARRAY = 1.0E-17 1.0e-17 1.0e-17 1.0e-17 + + NS_ARRAY = 12 25 50 75 100 150 201 + NITER_ARRAY = 1200 2000 3000 4000 5000 6000 20000 + FTOL_ARRAY = 1.0E-17 1.0e-17 1.0e-17 1.0e-17 1.0e-17 1.0e-17 2.0e-17 + + PRECON_TYPE = 'none' + PREC2D_THRESHOLD = 1.000000E-19 +!----- Grid Parameters ----- + LASYM = F + NFP = 0004 + MPOL = 0008 + NTOR = 0008 + PHIEDGE = 0.0381790210242581 +!----- Free Boundary Parameters ----- + LFREEB = F + NVACSKIP = 6 +!----- Pressure Parameters ----- + GAMMA = 0.000000000000E+000 + BLOAT = 1.000000000000E+000 + SPRES_PED = 1.000000000000E+000 + PRES_SCALE = 1.000000000000E+000 + PMASS_TYPE = 'power_series' + AM = 000000000E+00 +!----- Current/Iota Parameters ----- + CURTOR = 0 + NCURR = 1 + PIOTA_TYPE = 'power_series' + PCURR_TYPE = 'power_series' +!----- Axis Parameters ----- + RAXIS_CC = 0 + ZAXIS_CS = 0 +!----- Boundary Parameters ----- +! n comes before m! +RBC( 0, 0) = 1.000000000000000e+00, ZBS( 0, 0) = -0.000000000000000e+00 +RBC( 1, 0) = 1.798197877372061e-01, ZBS( 1, 0) = 1.526874285925055e-01 +RBC( 2, 0) = 1.734951154350431e-02, ZBS( 2, 0) = 1.866334230413251e-02 +RBC( 3, 0) = 2.577160162049330e-03, ZBS( 3, 0) = 1.199711292212324e-03 +RBC( 4, 0) = -1.637889983682740e-04, ZBS( 4, 0) = 6.984345011786886e-05 +RBC( 5, 0) = -2.425305167830765e-05, ZBS( 5, 0) = -2.548557148257138e-05 +RBC( -5, 1) = -8.577683632032374e-05, ZBS( -5, 1) = 2.045490523320995e-05 +RBC( -4, 1) = -3.374047917343044e-04, ZBS( -4, 1) = 5.046849551418733e-04 +RBC( -3, 1) = -3.641359983759378e-03, ZBS( -3, 1) = 3.782490654681902e-03 +RBC( -2, 1) = -2.444833020873945e-02, ZBS( -2, 1) = 2.427925370183856e-02 +RBC( -1, 1) = -8.731762429558673e-02, ZBS( -1, 1) = 4.517210283176742e-02 +RBC( 0, 1) = 1.380390474734288e-01, ZBS( 0, 1) = 1.310968006001034e-01 +RBC( 1, 1) = 2.903189084133577e-02, ZBS( 1, 1) = 3.270191607891355e-02 +RBC( 2, 1) = 6.875247108489111e-03, ZBS( 2, 1) = 6.803576261710397e-03 +RBC( 3, 1) = 8.150566273801188e-04, ZBS( 3, 1) = 8.594345731469456e-04 +RBC( 4, 1) = -2.843729541521199e-05, ZBS( 4, 1) = -1.177273734326507e-05 +RBC( 5, 1) = 1.828959533446362e-05, ZBS( 5, 1) = -1.615216261142120e-05 +RBC( -5, 2) = 2.187727631099286e-05, ZBS( -5, 2) = -7.400469361173993e-05 +RBC( -4, 2) = 8.393516055641350e-04, ZBS( -4, 2) = -4.483876523047104e-04 +RBC( -3, 2) = 1.971788481361341e-03, ZBS( -3, 2) = -3.174905588243931e-03 +RBC( -2, 2) = 5.269805664655518e-03, ZBS( -2, 2) = -7.113162328175970e-03 +RBC( -1, 2) = 2.116933661799145e-02, ZBS( -1, 2) = 1.865602467381490e-02 +RBC( 0, 2) = 1.536055908756419e-02, ZBS( 0, 2) = 9.451140140723166e-03 +RBC( 1, 2) = -1.177074525788361e-03, ZBS( 1, 2) = -4.394443738790604e-04 +RBC( 2, 2) = 1.300915708157302e-03, ZBS( 2, 2) = 1.022384351225018e-03 +RBC( 3, 2) = 2.747377558866586e-05, ZBS( 3, 2) = -6.300323824473890e-05 +RBC( 4, 2) = 9.334314906640049e-05, ZBS( 4, 2) = 6.552426964270398e-05 +RBC( 5, 2) = -5.617421098748800e-06, ZBS( 5, 2) = -1.848848555889170e-07 +RBC( -5, 3) = 2.874225777670480e-06, ZBS( -5, 3) = 7.868289246153724e-05 +RBC( -4, 3) = -1.903878083029936e-04, ZBS( -4, 3) = 3.682504964925082e-05 +RBC( -3, 3) = 2.220407427826208e-05, ZBS( -3, 3) = 6.281678187469348e-04 +RBC( -2, 3) = -1.082472074236150e-03, ZBS( -2, 3) = 6.445833193595944e-04 +RBC( -1, 3) = 6.435380216410359e-05, ZBS( -1, 3) = 1.141350665160774e-03 +RBC( 0, 3) = 1.069417168790915e-04, ZBS( 0, 3) = 3.802855234303916e-04 +RBC( 1, 3) = 4.983980241995697e-04, ZBS( 1, 3) = 6.843953564643375e-04 +RBC( 2, 3) = 3.325266953783200e-04, ZBS( 2, 3) = 2.395037991595740e-04 +RBC( 3, 3) = -8.380550535631315e-05, ZBS( 3, 3) = -2.858606506850391e-06 +RBC( 4, 3) = 8.168748496456451e-05, ZBS( 4, 3) = 3.828660987048127e-05 +RBC( 5, 3) = -1.172958658426462e-05, ZBS( 5, 3) = -2.567553564985603e-07 +RBC( -5, 4) = 1.930663967799810e-05, ZBS( -5, 4) = 5.848712999415494e-06 +RBC( -4, 4) = 5.914443815425555e-05, ZBS( -4, 4) = -9.777520270947895e-05 +RBC( -3, 4) = -1.535671893320628e-04, ZBS( -3, 4) = -1.968457634323347e-04 +RBC( -2, 4) = 9.254995677768834e-05, ZBS( -2, 4) = -1.254944494739196e-04 +RBC( -1, 4) = 2.217517688289458e-04, ZBS( -1, 4) = 7.133325449383868e-05 +RBC( 0, 4) = 4.623699812020439e-04, ZBS( 0, 4) = 3.336146039802283e-04 +RBC( 1, 4) = -4.834681321758439e-05, ZBS( 1, 4) = -1.984613542379469e-05 +RBC( 2, 4) = 1.449578757996227e-04, ZBS( 2, 4) = 3.445613069241063e-05 +RBC( 3, 4) = -5.390410338650556e-05, ZBS( 3, 4) = -6.043337987396479e-05 +RBC( 4, 4) = -2.755169485866935e-05, ZBS( 4, 4) = -3.234200905245086e-05 +RBC( 5, 4) = -1.031528435324214e-05, ZBS( 5, 4) = -8.346877197760745e-06 +RBC( -5, 5) = -8.230328283192286e-06, ZBS( -5, 5) = -4.962452471737940e-07 +RBC( -4, 5) = -4.283219579566894e-05, ZBS( -4, 5) = 2.554677526708830e-05 +RBC( -3, 5) = 7.171674894766820e-06, ZBS( -3, 5) = 4.411924318063437e-05 +RBC( -2, 5) = 1.686400668654943e-05, ZBS( -2, 5) = -5.849246530755695e-06 +RBC( -1, 5) = -3.106338530700742e-06, ZBS( -1, 5) = 1.479053323007641e-06 +RBC( 0, 5) = -3.106894329327918e-05, ZBS( 0, 5) = -4.555573189096034e-05 +RBC( 1, 5) = -2.117004285123679e-05, ZBS( 1, 5) = 4.954122546236333e-06 +RBC( 2, 5) = 1.404444565956858e-06, ZBS( 2, 5) = 2.921397801630777e-06 +RBC( 3, 5) = -1.491037166951584e-05, ZBS( 3, 5) = -1.337158933881559e-05 +RBC( 4, 5) = -1.062017757240239e-05, ZBS( 4, 5) = -1.038497225885287e-05 +RBC( 5, 5) = -3.055942324592806e-06, ZBS( 5, 5) = -2.630290187244904e-06 +/ From d282021621f9d559fa0386f7dc44e6e6086963fc Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Tue, 29 Aug 2023 11:53:02 -0400 Subject: [PATCH 02/61] unnormalized dofs --- src/simsoptpp/curveplanarfourier.cpp | 505 ++++++++++++++++----------- src/simsoptpp/curveplanarfourier.h | 16 +- 2 files changed, 303 insertions(+), 218 deletions(-) diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index 66398db6b..3bc8e755f 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -5,6 +5,19 @@ template void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { int numquadpoints = quadpoints.size(); data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + + for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; for (int i = 0; i < order+1; ++i) { @@ -27,15 +40,27 @@ void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { j = data(m, 1); k = data(m, 2); - data(m, 0) = (i - 2 * (q[2] * q[2] + q[3] * q[3]) * i + 2 * (q[1] * q[2] - q[3] * q[0]) * j + 2 * (q[1] * q[3] + q[2] * q[0]) * k) + center[0]; - data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i + j - 2 * (q[1] * q[1] + q[3] * q[3]) * j + 2 * (q[2] * q[3] - q[1] * q[0]) * k) + center[1]; - data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i + 2 * (q[2] * q[3] + q[1] * q[0]) * j + k - 2 * (q[1] * q[1] + q[2] * q[2]) * k) + center[2]; + data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k) + center[0]; + data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k) + center[1]; + data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k) + center[2]; } } template void CurvePlanarFourier::gammadash_impl(Array& data) { data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; for (int i = 0; i < order+1; ++i) { @@ -59,9 +84,9 @@ void CurvePlanarFourier::gammadash_impl(Array& data) { Array k = xt::zeros({1}); k[0] = data(m, 2); - data(m, 0) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); } } @@ -69,6 +94,18 @@ void CurvePlanarFourier::gammadash_impl(Array& data) { template void CurvePlanarFourier::gammadashdash_impl(Array& data) { data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; for (int i = 0; i < order+1; ++i) { @@ -94,9 +131,9 @@ void CurvePlanarFourier::gammadashdash_impl(Array& data) { Array k = xt::zeros({1}); k[0] = data(m, 2); - data(m, 0) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); } } @@ -104,6 +141,18 @@ void CurvePlanarFourier::gammadashdash_impl(Array& data) { template void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; for (int i = 0; i < order+1; ++i) { @@ -139,9 +188,9 @@ void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { Array k = xt::zeros({1}); k[0] = data(m, 2); - data(m, 0) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); } } @@ -149,6 +198,18 @@ void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { template void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; @@ -161,9 +222,9 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { j[0] = cos(n*phi) * sin(phi); k[0] = 0; - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; } @@ -173,9 +234,9 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { j[0] = sin(n*phi) * sin(phi); k[0] = 0; - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; } @@ -193,54 +254,54 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { j[0] += rs[n-1] * sin(n*phi) * sin(phi); } - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] - - 2 * j[0] * q[3]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] - + 2 * i[0] * q[3] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] - - 2 * i[0] * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] - + 2 * j[0] * q[1]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]; counter++; - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] - + 2 * j[0] * q[2]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] - + 2 * i[0] * q[2] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] - - 4 * j[0] * q[1]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] - + 2 * i[0] * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] - + 2 * j[0] * q[0]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] - + 2 * j[0] * q[1]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] - + 2 * i[0] * q[1] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; - data(m, 2, counter) = - 2 * i[0] * q[0] - - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] - + 2 * j[0] * q[3]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; + data(m, 2, counter) = - 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] - - 2 * j[0] * q[0]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] - + 2 * i[0] * q[0] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] - - 4 * j[0] * q[3]; - data(m, 2, counter) = 2 * i[0] * q[1] - + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] - + 2 * j[0] * q[2]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]; + data(m, 2, counter) = 2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]; counter++; @@ -258,6 +319,18 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { template void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; @@ -272,9 +345,9 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { i[0] *= (2*M_PI); j[0] *= (2*M_PI); - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; @@ -288,9 +361,9 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { i[0] *= (2*M_PI); j[0] *= (2*M_PI); - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; @@ -308,54 +381,54 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { j[0] += rs[n-1] * ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)) * 2 * M_PI; } - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] - - 2 * j[0] * q[3]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] - + 2 * i[0] * q[3] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] - - 2 * i[0] * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] - + 2 * j[0] * q[1]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]; counter++; - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] - + 2 * j[0] * q[2]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] - + 2 * i[0] * q[2] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] - - 4 * j[0] * q[1]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] - + 2 * i[0] * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] - + 2 * j[0] * q[0]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] - + 2 * j[0] * q[1]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] - + 2 * i[0] * q[1] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; - data(m, 2, counter) = - 2 * i[0] * q[0] - - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] - + 2 * j[0] * q[3]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; + data(m, 2, counter) = - 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] - - 2 * j[0] * q[0]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] - + 2 * i[0] * q[0] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] - - 4 * j[0] * q[3]; - data(m, 2, counter) = 2 * i[0] * q[1] - + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] - + 2 * j[0] * q[2]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]; + data(m, 2, counter) = 2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]; counter++; for (int i = 0; i < 2; ++i) { @@ -372,6 +445,18 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { template void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; @@ -387,9 +472,9 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; } @@ -403,9 +488,9 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; } @@ -425,54 +510,54 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI; - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] - - 2 * j[0] * q[3]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] - + 2 * i[0] * q[3] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] - - 2 * i[0] * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] - + 2 * j[0] * q[1]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]; counter++; - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] - + 2 * j[0] * q[2]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] - + 2 * i[0] * q[2] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] - - 4 * j[0] * q[1]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] - + 2 * i[0] * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] - + 2 * j[0] * q[0]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] - + 2 * j[0] * q[1]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] - + 2 * i[0] * q[1] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; - data(m, 2, counter) = - 2 * i[0] * q[0] - - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] - + 2 * j[0] * q[3]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; + data(m, 2, counter) = - 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] - - 2 * j[0] * q[0]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] - + 2 * i[0] * q[0] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] - - 4 * j[0] * q[3]; - data(m, 2, counter) = 2 * i[0] * q[1] - + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] - + 2 * j[0] * q[2]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]; + data(m, 2, counter) = 2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]; counter++; for (int i = 0; i < 3; ++i) { @@ -488,6 +573,18 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { template void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { data *= 0; + + /* Converts q dofs to unit quaternion */ + Array q_norm = xt::zeros({4}); + double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + if(s != 0) { + for (int i = 0; i < 4; ++i) + q_norm[i] = q[i] / std::sqrt(s); + } + else { + q_norm[0] = 1; + } + for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; @@ -509,9 +606,9 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; } @@ -531,9 +628,9 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q[2] * q[2] + q[3] * q[3]) * i[0] + 2 * (q[1] * q[2] - q[3] * q[0]) * j[0] + 2 * (q[1] * q[3] + q[2] * q[0]) * k[0]); - data(m, 1, counter) = (2 * (q[1] * q[2] + q[3] * q[0]) * i[0] + j[0] - 2 * (q[1] * q[1] + q[3] * q[3]) * j[0] + 2 * (q[2] * q[3] - q[1] * q[0]) * k[0]); - data(m, 2, counter) = (2 * (q[1] * q[3] - q[2] * q[0]) * i[0] + 2 * (q[2] * q[3] + q[1] * q[0]) * j[0] + k[0] - 2 * (q[1] * q[1] + q[2] * q[2]) * k[0]); + data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); counter++; } @@ -565,54 +662,54 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI*2*M_PI; - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[0] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[0] - - 2 * j[0] * q[3]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[0] - + 2 * i[0] * q[3] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[0]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[0] - - 2 * i[0] * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[0] - + 2 * j[0] * q[1]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]; counter++; - data(m, 0, counter) = 4 * i[0] * (q[2] * q[2] + q[3] * q[3]) * q[1] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[1] - + 2 * j[0] * q[2]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[1] - + 2 * i[0] * q[2] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[1] - - 4 * j[0] * q[1]; - data(m, 2, counter) = - 4 * i[0] * (q[1] * q[3] - q[2] * q[0]) * q[1] - + 2 * i[0] * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[1] - + 2 * j[0] * q[0]; + data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]; + data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[0] * q[0] + q[1] * q[1]) * q[2] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[2] - + 2 * j[0] * q[1]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[2] - + 2 * i[0] * q[1] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[2]; - data(m, 2, counter) = - 2 * i[0] * q[0] - - 4 * i[0] * (q[1] * q[3] - q[0] * q[2]) * q[2] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[2] - + 2 * j[0] * q[3]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; + data(m, 2, counter) = - 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]; counter++; - data(m, 0, counter) = - 4 * i[0] * (q[1] * q[1] + q[0] * q[0]) * q[3] - - 4 * j[0] * (q[1] * q[2] - q[0] * q[3]) * q[3] - - 2 * j[0] * q[0]; - data(m, 1, counter) = - 4 * i[0] * (q[1] * q[2] + q[3] * q[0]) * q[3] - + 2 * i[0] * q[0] - + 4 * j[0] * (q[1] * q[1] + q[3] * q[3]) * q[3] - - 4 * j[0] * q[3]; - data(m, 2, counter) = 2 * i[0] * q[1] - + 4 * i[0] * (q[2] * q[0] - q[1] * q[3]) * q[3] - - 4 * j[0] * (q[1] * q[0] + q[2] * q[3]) * q[3] - + 2 * j[0] * q[2]; + data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]; + data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]; + data(m, 2, counter) = 2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]; counter++; for (int i = 0; i < 3; ++i) { diff --git a/src/simsoptpp/curveplanarfourier.h b/src/simsoptpp/curveplanarfourier.h index 4febd687d..d07d93c8b 100644 --- a/src/simsoptpp/curveplanarfourier.h +++ b/src/simsoptpp/curveplanarfourier.h @@ -58,26 +58,14 @@ class CurvePlanarFourier : public Curve { void set_dofs_impl(const vector& dofs) override { int counter = 0; - double s = 0; for (int i = 0; i < order + 1; ++i) rc.data()[i] = dofs[counter++]; for (int i = 0; i < order; ++i) rs.data()[i] = dofs[counter++]; - for (int i = 0; i < 4; ++i){ + for (int i = 0; i < 4; ++i) q.data()[i] = dofs[counter++]; - s += q[i] * q[i]; - } - /* Converts to unit quaternion */ - if(s != 0) { - for (int i = 0; i < 4; ++i) - q.data()[i] = q[i] / std::sqrt(s); - } - else { - q.data()[0] = 1; - } - for (int i = 0; i < 3; ++i){ + for (int i = 0; i < 3; ++i) center.data()[i] = dofs[counter++]; - } } vector get_dofs() override { From bc3ff7f281d2b4a6106b2daf408beca2f05ede0b Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Thu, 28 Sep 2023 11:59:30 -0400 Subject: [PATCH 03/61] planar coil unnormalized update --- src/simsoptpp/curveplanarfourier.cpp | 1096 +++++++++++++++++++++++--- 1 file changed, 1000 insertions(+), 96 deletions(-) diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index 3bc8e755f..ceda2e9aa 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -254,54 +254,280 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { j[0] += rs[n-1] * sin(n*phi) * sin(phi); } - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - 2 * i[0] * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]; + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[2] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]; + + 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; - data(m, 2, counter) = - 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]; + + 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + 2 * i[0] * q_norm[0] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]; - data(m, 2, counter) = 2 * i[0] * q_norm[1] + - 4 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]; + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; @@ -381,54 +607,280 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { j[0] += rs[n-1] * ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)) * 2 * M_PI; } - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - 2 * i[0] * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]; + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[2] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]; + + 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; - data(m, 2, counter) = - 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]; + + 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + 2 * i[0] * q_norm[0] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]; - data(m, 2, counter) = 2 * i[0] * q_norm[1] + - 4 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]; + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; for (int i = 0; i < 2; ++i) { @@ -510,54 +962,280 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI; - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - 2 * i[0] * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]; + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[2] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]; + + 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; - data(m, 2, counter) = - 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]; + + 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + 2 * i[0] * q_norm[0] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]; - data(m, 2, counter) = 2 * i[0] * q_norm[1] + - 4 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]; + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; for (int i = 0; i < 3; ++i) { @@ -662,54 +1340,280 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { j[0] *= 2*M_PI*2*M_PI*2*M_PI; k[0] *= 2*M_PI*2*M_PI*2*M_PI; - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - 2 * i[0] * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]; + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = 4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[2] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]; - data(m, 2, counter) = - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + 2 * i[0] * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]; + + 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]; - data(m, 2, counter) = - 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i[0] * q_norm[0] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j[0] * q_norm[3]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]; + + 2 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j[0] * q_norm[2]) + * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; - data(m, 0, counter) = - 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j[0] * q_norm[3]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[2]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[1]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]; - data(m, 1, counter) = - 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + - 2 * j[0] * q_norm[0]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i[0] * q_norm[3] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[2] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j[0] * q_norm[1]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i[0] * q_norm[1] + + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + 2 * i[0] * q_norm[0] + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]; - data(m, 2, counter) = 2 * i[0] * q_norm[1] + - 4 * j[0] * q_norm[3]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + + + data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i[0] * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j[0] * q_norm[1]) + * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i[0] * q_norm[3] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j[0] * q_norm[0]) + * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (- 2 * i[0] * q_norm[0] + - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j[0] * q_norm[3]) + * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + + (2 * i[0] * q_norm[1] + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]; + + 2 * j[0] * q_norm[2]) + * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); counter++; for (int i = 0; i < 3; ++i) { From 8e7a2187eb521396feb804647a13f969d92a6dee Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Thu, 28 Sep 2023 12:43:09 -0400 Subject: [PATCH 04/61] Updated create_equally_spaced_planar_curves to prevent overlapping curves --- src/simsopt/geo/curve.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simsopt/geo/curve.py b/src/simsopt/geo/curve.py index 863c37f3c..ed5530c99 100644 --- a/src/simsopt/geo/curve.py +++ b/src/simsopt/geo/curve.py @@ -893,7 +893,7 @@ def create_equally_spaced_planar_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, curves = [] from simsopt.geo.curveplanarfourier import CurvePlanarFourier for k in range(ncurves): - angle = k*(2*np.pi) / ((1+int(stellsym))*nfp*ncurves) + angle = (k+0.5)*(2*np.pi) / ((1+int(stellsym))*nfp*ncurves) curve = CurvePlanarFourier(numquadpoints, order, nfp, stellsym) rcCoeffs = np.zeros(order+1) From 77ed76f63dc362eac299d45f5950190bda77eea6 Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Tue, 3 Oct 2023 13:23:20 -0400 Subject: [PATCH 05/61] Added planar coil example file --- .../stage_two_optimization_planar_coils.py | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100755 examples/2_Intermediate/stage_two_optimization_planar_coils.py diff --git a/examples/2_Intermediate/stage_two_optimization_planar_coils.py b/examples/2_Intermediate/stage_two_optimization_planar_coils.py new file mode 100755 index 000000000..a621a10b1 --- /dev/null +++ b/examples/2_Intermediate/stage_two_optimization_planar_coils.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +r""" +In this example we solve a FOCUS like Stage II coil optimisation problem: the +goal is to find coils that generate a specific target normal field on a given +surface. In this particular case we consider a vacuum field, so the target is +just zero. + +The objective is given by + + J = (1/2) \int |B dot n|^2 ds + + LENGTH_WEIGHT * (sum CurveLength) + + DISTANCE_WEIGHT * MininumDistancePenalty(DISTANCE_THRESHOLD) + + CURVATURE_WEIGHT * CurvaturePenalty(CURVATURE_THRESHOLD) + + MSC_WEIGHT * MeanSquaredCurvaturePenalty(MSC_THRESHOLD) + +if any of the weights are increased, or the thresholds are tightened, the coils +are more regular and better separated, but the target normal field may not be +achieved as well. This example demonstrates the adjustment of weights and +penalties via the use of the `Weight` class. + +The target equilibrium is the QA configuration of arXiv:2108.03711. +""" + +import os +from pathlib import Path +import numpy as np +from scipy.optimize import minimize +from simsopt.objectives import Weight +from simsopt.geo import SurfaceRZFourier +from simsopt.objectives import SquaredFlux +from simsopt.objectives import QuadraticPenalty +from simsopt.geo import curves_to_vtk, create_equally_spaced_planar_curves +from simsopt.field import BiotSavart +from simsopt.field import Current, coils_via_symmetries +from simsopt.geo import CurveLength, CurveCurveDistance, \ + MeanSquaredCurvature, LpCurveCurvature, CurveSurfaceDistance, LinkingNumber + +# Number of unique coil shapes, i.e. the number of coils per half field period: +# (Since the configuration has nfp = 2, multiply by 4 to get the total number of coils.) +ncoils = 4 + +# Major radius for the initial circular coils: +R0 = 1.0 + +# Minor radius for the initial circular coils: +R1 = 0.5 + +# Number of Fourier modes describing each Cartesian component of each coil: +order = 5 + +# Weight on the curve lengths in the objective function. We use the `Weight` +# class here to later easily adjust the scalar value and rerun the optimization +# without having to rebuild the objective. +LENGTH_WEIGHT = Weight(10) + +# Threshold and weight for the coil-to-coil distance penalty in the objective function: +CC_THRESHOLD = 0.08 +CC_WEIGHT = 1000 + +# Threshold and weight for the coil-to-surface distance penalty in the objective function: +CS_THRESHOLD = 0.12 +CS_WEIGHT = 10 + +# Threshold and weight for the curvature penalty in the objective function: +CURVATURE_THRESHOLD = 10. +CURVATURE_WEIGHT = 1e-6 + +# Threshold and weight for the mean squared curvature penalty in the objective function: +MSC_THRESHOLD = 10 +MSC_WEIGHT = 1e-6 + +# Number of iterations to perform: +ci = "CI" in os.environ and os.environ['CI'].lower() in ['1', 'true'] +MAXITER = 50 if ci else 400 + +# File for the desired boundary magnetic surface: +TEST_DIR = (Path(__file__).parent / ".." / ".." / "tests" / "test_files").resolve() +filename = TEST_DIR / 'input.LandremanPaul2021_QA' + +# Directory for output +OUT_DIR = "./output/" +os.makedirs(OUT_DIR, exist_ok=True) + +####################################################### +# End of input parameters. +####################################################### + +# Initialize the boundary magnetic surface: +nphi = 32 +ntheta = 32 +s = SurfaceRZFourier.from_vmec_input(filename, range="half period", nphi=nphi, ntheta=ntheta) + +# Create the initial coils: +base_curves = create_equally_spaced_planar_curves(ncoils, s.nfp, stellsym=True, R0=R0, R1=R1, order=order) +base_currents = [Current(1e5) for i in range(ncoils)] +# Since the target field is zero, one possible solution is just to set all +# currents to 0. To avoid the minimizer finding that solution, we fix one +# of the currents: +base_currents[0].fix_all() + +coils = coils_via_symmetries(base_curves, base_currents, s.nfp, True) +bs = BiotSavart(coils) +bs.set_points(s.gamma().reshape((-1, 3))) + +curves = [c.curve for c in coils] +curves_to_vtk(curves, OUT_DIR + "curves_init") +pointData = {"B_N": np.sum(bs.B().reshape((nphi, ntheta, 3)) * s.unitnormal(), axis=2)[:, :, None]} +s.to_vtk(OUT_DIR + "surf_init", extra_data=pointData) + +# Define the individual terms objective function: +Jf = SquaredFlux(s, bs) +Jls = [CurveLength(c) for c in base_curves] +Jccdist = CurveCurveDistance(curves, CC_THRESHOLD, num_basecurves=ncoils) #Error +Jcsdist = CurveSurfaceDistance(curves, s, CS_THRESHOLD) +Jcs = [LpCurveCurvature(c, 2, CURVATURE_THRESHOLD) for c in base_curves] +Jmscs = [MeanSquaredCurvature(c) for c in base_curves] +linkNum = LinkingNumber(curves) + +# Form the total objective function. To do this, we can exploit the +# fact that Optimizable objects with J() and dJ() functions can be +# multiplied by scalars and added: +JF = Jf \ + + LENGTH_WEIGHT * QuadraticPenalty(sum(Jls), 2.6*ncoils) \ + + CC_WEIGHT * Jccdist \ + + CS_WEIGHT * Jcsdist \ + + CURVATURE_WEIGHT * sum(Jcs) \ + + MSC_WEIGHT * sum(QuadraticPenalty(J, MSC_THRESHOLD) for J in Jmscs) \ + + QuadraticPenalty(linkNum, 0.1) + +# We don't have a general interface in SIMSOPT for optimisation problems that +# are not in least-squares form, so we write a little wrapper function that we +# pass directly to scipy.optimize.minimize + +def fun(dofs): + JF.x = dofs + J = JF.J() + grad = JF.dJ() + jf = Jf.J() + BdotN = np.mean(np.abs(np.sum(bs.B().reshape((nphi, ntheta, 3)) * s.unitnormal(), axis=2))) + MaxBdotN = np.max(np.abs(np.sum(bs.B().reshape((nphi, ntheta, 3)) * s.unitnormal(), axis=2))) + mean_AbsB = np.mean(bs.AbsB()) + outstr = f"J={J:.1e}, Jf={jf:.1e}, ⟨B·n⟩={BdotN:.1e}" + cl_string = ", ".join([f"{J.J():.1f}" for J in Jls]) + kap_string = ", ".join(f"{np.max(c.kappa()):.1f}" for c in base_curves) + msc_string = ", ".join(f"{J.J():.1f}" for J in Jmscs) + outstr += f", Len=sum([{cl_string}])={sum(J.J() for J in Jls):.1f}, ϰ=[{kap_string}], ∫ϰ²/L=[{msc_string}]" + outstr += f", C-C-Sep={Jccdist.shortest_distance():.2f}, C-S-Sep={Jcsdist.shortest_distance():.2f}" + outstr += f", ║∇J║={np.linalg.norm(grad):.1e}" + outstr += f", ⟨B·n⟩/|B|={BdotN/mean_AbsB:.1e}" + outstr += f", (Max B·n)/|B|={MaxBdotN/mean_AbsB:.1e}" + outstr += f", Link Number = {linkNum.J()}" + print(outstr) + return J, grad + + +print(""" +################################################################################ +### Perform a Taylor test ###################################################### +################################################################################ +""") +f = fun +dofs = JF.x +np.random.seed(1) +h = np.random.uniform(size=dofs.shape) +J0, dJ0 = f(dofs) +dJh = sum(dJ0 * h) +for eps in [1e-3, 1e-4, 1e-5, 1e-6, 1e-7]: + J1, _ = f(dofs + eps*h) + J2, _ = f(dofs - eps*h) + print("err", (J1-J2)/(2*eps) - dJh) + +print(""" +################################################################################ +### Run the optimisation ####################################################### +################################################################################ +""") +res = minimize(fun, dofs, jac=True, method='L-BFGS-B', options={'maxiter': MAXITER, 'maxcor': 300}, tol=1e-15) +curves_to_vtk(curves, OUT_DIR + f"curves_opt_short") +pointData = {"B_N": np.sum(bs.B().reshape((nphi, ntheta, 3)) * s.unitnormal(), axis=2)[:, :, None]} +s.to_vtk(OUT_DIR + "surf_opt_short", extra_data=pointData) + + +# We now use the result from the optimization as the initial guess for a +# subsequent optimization with reduced penalty for the coil length. This will +# result in slightly longer coils but smaller `B·n` on the surface. +dofs = res.x +LENGTH_WEIGHT *= 0.1 +res = minimize(fun, dofs, jac=True, method='L-BFGS-B', options={'maxiter': MAXITER, 'maxcor': 300}, tol=1e-15) +curves_to_vtk(curves, OUT_DIR + f"curves_opt_long") +pointData = {"B_N": np.sum(bs.B().reshape((nphi, ntheta, 3)) * s.unitnormal(), axis=2)[:, :, None]} +s.to_vtk(OUT_DIR + "surf_opt_long", extra_data=pointData) + +# Save the optimized coil shapes and currents so they can be loaded into other scripts for analysis: +bs.save(OUT_DIR + "biot_savart_opt.json") From 9d1f036418c2272e2396790963eb33f8f312331b Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Tue, 3 Oct 2023 13:42:33 -0400 Subject: [PATCH 06/61] Better documentation --- src/simsopt/geo/curve.py | 6 +++++- src/simsopt/geo/curveplanarfourier.py | 17 ++++++++++++++++- src/simsoptpp/curveplanarfourier.h | 15 ++++++++++----- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/simsopt/geo/curve.py b/src/simsopt/geo/curve.py index ed5530c99..925e01738 100644 --- a/src/simsopt/geo/curve.py +++ b/src/simsopt/geo/curve.py @@ -885,7 +885,11 @@ def create_equally_spaced_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, order=6 def create_equally_spaced_planar_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, order=6, numquadpoints=None): """ - Insert text here + Create ``ncurves`` curves of type + :obj:`~simsopt.geo.curveplanarfourier.CurvePlanarFourier` of order + ``order`` that will result in circular equally spaced coils (major + radius ``R0`` and minor radius ``R1``) after applying + :obj:`~simsopt.field.coil.coils_via_symmetries`. """ if numquadpoints is None: diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py index 78b590548..1ef453d18 100644 --- a/src/simsopt/geo/curveplanarfourier.py +++ b/src/simsopt/geo/curveplanarfourier.py @@ -9,7 +9,22 @@ class CurvePlanarFourier(sopp.CurvePlanarFourier, Curve): r""" - Insert text here + ``CurvePlanarFourier`` is a curve that is represented by a polar coordinate fourier serires, a rotation quaternion, and a center point following the form: + .. math:: + r(\phi) &= \sum_{m=0}^{\text{order}} r_{c,m}\cos(n_{\text{fp}} m \phi) + \sum_{m=1}^{\text{order}} r_{s,m}\sin(n_{\text{fp}} m \phi) + \bf{q} &= [q_0,q_i,q_j,q_k] &= [\cos(\theta / 2), \hat{x}\sin(\theta / 2), \hat{y}\sin(\theta / 2), \hat{z}\sin(\theta / 2)] + where :math:'\theta' is the counterclockwise rotation about a unit axis :math:'(\hat{x},\hat{y},\hat{z})'. + + The quaternion is normalized for calculations to prevent scaling. The dofs themselves are not normalized. This results in a redundancy in the optimization, + where several different sets of dofs may correspond to the same normalized quaternion. + Normalizing the dofs directly would create a dependence between the quaternion dofs, which may cause issues during optimization. + + The dofs are stored in the order + + .. math:: + [r_{c,0}, \cdots, r_{c,\text{order}}, r_{s,1}, \cdots, r_{s,\text{order}}, q_0, q_i, q_j, q_k, x_{\text{center}}, y_{\text{center}}, z_{\text{center}}] + + """ def __init__(self, quadpoints, order, nfp, stellsym, dofs=None): diff --git a/src/simsoptpp/curveplanarfourier.h b/src/simsoptpp/curveplanarfourier.h index d07d93c8b..4b8b4baee 100644 --- a/src/simsoptpp/curveplanarfourier.h +++ b/src/simsoptpp/curveplanarfourier.h @@ -5,17 +5,22 @@ template class CurvePlanarFourier : public Curve { /* - CurvePlanarFourier is a curve that is represented as a plane rotated about the - x and y axis using the following Fourier series: + CurvePlanarFourier is a curve that is represented using the following Fourier series: r(phi) = \sum_{n=0}^{order} x_{c,n}cos(n*nfp*phi) + \sum_{n=1}^order x_{s,n}sin(n*nfp*phi) - with rotation about an axis and angle determine by a set of quarternions - q = [cos(\theta/2), x * sin(\theta/2), y * sin(\theta/2), z * sin(\theta/2)] + with rotation about an axis and angle determined by a set of quarternions + q = [q_0, q_1, q_2, q_3] = [cos(\theta/2), x * sin(\theta/2), y * sin(\theta/2), z * sin(\theta/2)] + + Quaternions are normalized to prevent scaling the curves, but remain unnormalized as dofs to prevent optimization error. + + A center vector is used to specify the location of the center of the curve: + + c = [c_x, c_y, c_z] The dofs are stored in the order - [r_{c,0},...,r_{c,order},r_{s,1},...,r_{s,order},t_{x},t_{y}] + [r_{c,0},...,r_{c,order},r_{s,1},...,r_{s,order}, q_0, q_1, q_2, q_3, c_x, c_y, c_z] */ public: From b03fa7d6404bfbb95792770ee326e41ecc97dcc1 Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Tue, 3 Oct 2023 13:50:01 -0400 Subject: [PATCH 07/61] Linted --- examples/2_Intermediate/stage_two_optimization_planar_coils.py | 3 ++- src/simsopt/geo/curve.py | 3 ++- src/simsopt/geo/curveplanarfourier.py | 2 +- tests/geo/test_curve.py | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/2_Intermediate/stage_two_optimization_planar_coils.py b/examples/2_Intermediate/stage_two_optimization_planar_coils.py index a621a10b1..e3eb2dfaf 100755 --- a/examples/2_Intermediate/stage_two_optimization_planar_coils.py +++ b/examples/2_Intermediate/stage_two_optimization_planar_coils.py @@ -110,7 +110,7 @@ # Define the individual terms objective function: Jf = SquaredFlux(s, bs) Jls = [CurveLength(c) for c in base_curves] -Jccdist = CurveCurveDistance(curves, CC_THRESHOLD, num_basecurves=ncoils) #Error +Jccdist = CurveCurveDistance(curves, CC_THRESHOLD, num_basecurves=ncoils) # Error Jcsdist = CurveSurfaceDistance(curves, s, CS_THRESHOLD) Jcs = [LpCurveCurvature(c, 2, CURVATURE_THRESHOLD) for c in base_curves] Jmscs = [MeanSquaredCurvature(c) for c in base_curves] @@ -131,6 +131,7 @@ # are not in least-squares form, so we write a little wrapper function that we # pass directly to scipy.optimize.minimize + def fun(dofs): JF.x = dofs J = JF.J() diff --git a/src/simsopt/geo/curve.py b/src/simsopt/geo/curve.py index 925e01738..1b68e47f5 100644 --- a/src/simsopt/geo/curve.py +++ b/src/simsopt/geo/curve.py @@ -883,6 +883,7 @@ def create_equally_spaced_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, order=6 curves.append(curve) return curves + def create_equally_spaced_planar_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, order=6, numquadpoints=None): """ Create ``ncurves`` curves of type @@ -906,7 +907,7 @@ def create_equally_spaced_planar_curves(ncurves, nfp, stellsym, R0=1.0, R1=0.5, center = [R0 * cos(angle), R0 * sin(angle), 0] rotation = [1, -cos(angle), -sin(angle), 0] dofs = np.zeros(len(curve.get_dofs())) - + j = 0 for i in rcCoeffs: dofs[j] = i diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py index 1ef453d18..ddf8cec36 100644 --- a/src/simsopt/geo/curveplanarfourier.py +++ b/src/simsopt/geo/curveplanarfourier.py @@ -23,7 +23,7 @@ class CurvePlanarFourier(sopp.CurvePlanarFourier, Curve): .. math:: [r_{c,0}, \cdots, r_{c,\text{order}}, r_{s,1}, \cdots, r_{s,\text{order}}, q_0, q_i, q_j, q_k, x_{\text{center}}, y_{\text{center}}, z_{\text{center}}] - + """ diff --git a/tests/geo/test_curve.py b/tests/geo/test_curve.py index 817430220..59c480c48 100644 --- a/tests/geo/test_curve.py +++ b/tests/geo/test_curve.py @@ -100,6 +100,7 @@ def get_curve(curvetype, rotated, x=np.asarray([0.5])): class Testing(unittest.TestCase): curvetypes = ["CurveXYZFourier", "JaxCurveXYZFourier", "CurveRZFourier", "CurvePlanarFourier", "CurveHelical", "CurveHelicalInitx0"] + def test_curve_helical_xyzfourier(self): x = np.asarray([0.6]) curve1 = CurveHelical(x, 2, 5, 2, 1.0, 0.3) From e2a76499ef619439a7ea2ad11fd04baa9ed5878d Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Wed, 4 Oct 2023 06:56:36 -0400 Subject: [PATCH 08/61] Tweaks to docs --- docs/source/simsopt.geo.rst | 8 ++++++ .../stage_two_optimization_planar_coils.py | 26 +++++++++++-------- examples/run_serial_examples | 1 + src/simsopt/geo/__init__.py | 2 ++ src/simsopt/geo/curveplanarfourier.py | 26 ++++++++++++++----- 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/docs/source/simsopt.geo.rst b/docs/source/simsopt.geo.rst index 9bb006c3c..0a1bf5c32 100644 --- a/docs/source/simsopt.geo.rst +++ b/docs/source/simsopt.geo.rst @@ -60,6 +60,14 @@ simsopt.geo.curverzfourier module :undoc-members: :show-inheritance: +simsopt.geo.curveplanarfourier module +------------------------------------- + +.. automodule:: simsopt.geo.curveplanarfourier + :members: + :undoc-members: + :show-inheritance: + simsopt.geo.curvexyzfourier module ---------------------------------- diff --git a/examples/2_Intermediate/stage_two_optimization_planar_coils.py b/examples/2_Intermediate/stage_two_optimization_planar_coils.py index e3eb2dfaf..c84525868 100755 --- a/examples/2_Intermediate/stage_two_optimization_planar_coils.py +++ b/examples/2_Intermediate/stage_two_optimization_planar_coils.py @@ -1,5 +1,10 @@ #!/usr/bin/env python r""" +This coil optimization script is similar to stage_two_optimization.py. However +in this version, the coils are constrained to be planar, by using the curve type +CurvePlanarFourier. Also the LinkingNumber objective is used to prevent coils +from becoming topologically linked with each other. + In this example we solve a FOCUS like Stage II coil optimisation problem: the goal is to find coils that generate a specific target normal field on a given surface. In this particular case we consider a vacuum field, so the target is @@ -12,6 +17,7 @@ + DISTANCE_WEIGHT * MininumDistancePenalty(DISTANCE_THRESHOLD) + CURVATURE_WEIGHT * CurvaturePenalty(CURVATURE_THRESHOLD) + MSC_WEIGHT * MeanSquaredCurvaturePenalty(MSC_THRESHOLD) + + LinkingNumber if any of the weights are increased, or the thresholds are tightened, the coils are more regular and better separated, but the target normal field may not be @@ -25,15 +31,14 @@ from pathlib import Path import numpy as np from scipy.optimize import minimize -from simsopt.objectives import Weight -from simsopt.geo import SurfaceRZFourier -from simsopt.objectives import SquaredFlux -from simsopt.objectives import QuadraticPenalty -from simsopt.geo import curves_to_vtk, create_equally_spaced_planar_curves -from simsopt.field import BiotSavart -from simsopt.field import Current, coils_via_symmetries -from simsopt.geo import CurveLength, CurveCurveDistance, \ - MeanSquaredCurvature, LpCurveCurvature, CurveSurfaceDistance, LinkingNumber +from simsopt.field import BiotSavart, Current, coils_via_symmetries +from simsopt.geo import ( + CurveLength, CurveCurveDistance, + MeanSquaredCurvature, LpCurveCurvature, CurveSurfaceDistance, LinkingNumber, + SurfaceRZFourier, curves_to_vtk, create_equally_spaced_planar_curves, +) +from simsopt.objectives import Weight, SquaredFlux, QuadraticPenalty +from simsopt.util import in_github_actions # Number of unique coil shapes, i.e. the number of coils per half field period: # (Since the configuration has nfp = 2, multiply by 4 to get the total number of coils.) @@ -70,8 +75,7 @@ MSC_WEIGHT = 1e-6 # Number of iterations to perform: -ci = "CI" in os.environ and os.environ['CI'].lower() in ['1', 'true'] -MAXITER = 50 if ci else 400 +MAXITER = 50 if in_github_actions else 400 # File for the desired boundary magnetic surface: TEST_DIR = (Path(__file__).parent / ".." / ".." / "tests" / "test_files").resolve() diff --git a/examples/run_serial_examples b/examples/run_serial_examples index 163ff6ad4..4d7ee176a 100755 --- a/examples/run_serial_examples +++ b/examples/run_serial_examples @@ -16,6 +16,7 @@ set -ex ./2_Intermediate/QSC.py ./2_Intermediate/boozer.py ./2_Intermediate/stage_two_optimization.py +./2_Intermediate/stage_two_optimization_planar.py ./2_Intermediate/stage_two_optimization_stochastic.py ./2_Intermediate/stage_two_optimization_finite_beta.py ./2_Intermediate/strain_optimization.py diff --git a/src/simsopt/geo/__init__.py b/src/simsopt/geo/__init__.py index bc6d0efe2..beb5e57b6 100644 --- a/src/simsopt/geo/__init__.py +++ b/src/simsopt/geo/__init__.py @@ -8,6 +8,7 @@ from .curvexyzfourier import * from .curveperturbed import * from .curveobjectives import * +from .curveplanarfourier import * from .framedcurve import * from .finitebuild import * from .plotting import * @@ -28,6 +29,7 @@ __all__ = (curve.__all__ + curvehelical.__all__ + curverzfourier.__all__ + curvexyzfourier.__all__ + curveperturbed.__all__ + curveobjectives.__all__ + + curveplanarfourier.__all__ + finitebuild.__all__ + plotting.__all__ + boozersurface.__all__ + qfmsurface.__all__ + surface.__all__ + diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py index ddf8cec36..476ff9600 100644 --- a/src/simsopt/geo/curveplanarfourier.py +++ b/src/simsopt/geo/curveplanarfourier.py @@ -9,15 +9,27 @@ class CurvePlanarFourier(sopp.CurvePlanarFourier, Curve): r""" - ``CurvePlanarFourier`` is a curve that is represented by a polar coordinate fourier serires, a rotation quaternion, and a center point following the form: + ``CurvePlanarFourier`` is a curve that is represented by a polar coordinate + Fourier serires, a rotation quaternion, and a center point following the + form: + .. math:: - r(\phi) &= \sum_{m=0}^{\text{order}} r_{c,m}\cos(n_{\text{fp}} m \phi) + \sum_{m=1}^{\text{order}} r_{s,m}\sin(n_{\text{fp}} m \phi) - \bf{q} &= [q_0,q_i,q_j,q_k] &= [\cos(\theta / 2), \hat{x}\sin(\theta / 2), \hat{y}\sin(\theta / 2), \hat{z}\sin(\theta / 2)] - where :math:'\theta' is the counterclockwise rotation about a unit axis :math:'(\hat{x},\hat{y},\hat{z})'. - The quaternion is normalized for calculations to prevent scaling. The dofs themselves are not normalized. This results in a redundancy in the optimization, - where several different sets of dofs may correspond to the same normalized quaternion. - Normalizing the dofs directly would create a dependence between the quaternion dofs, which may cause issues during optimization. + r(\phi) &= \sum_{m=0}^{\text{order}} r_{c,m}\cos(m \phi) + \sum_{m=1}^{\text{order}} r_{s,m}\sin(m \phi) + + \bf{q} &= [q_0,q_i,q_j,q_k] + + &= [\cos(\theta / 2), \hat{x}\sin(\theta / 2), \hat{y}\sin(\theta / 2), \hat{z}\sin(\theta / 2)] + + where :math:`\theta` is the counterclockwise rotation about a unit axis + :math:`(\hat{x},\hat{y},\hat{z})`. + + The quaternion is normalized for calculations to prevent scaling. The dofs + themselves are not normalized. This results in a redundancy in the + optimization, where several different sets of dofs may correspond to the + same normalized quaternion. Normalizing the dofs directly would create a + dependence between the quaternion dofs, which may cause issues during + optimization. The dofs are stored in the order From ae5daa811ce5a70c9959bee2b2b6447cc5df01c4 Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Wed, 4 Oct 2023 07:58:12 -0400 Subject: [PATCH 09/61] fix filename --- examples/run_serial_examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/run_serial_examples b/examples/run_serial_examples index 4d7ee176a..b87f64702 100755 --- a/examples/run_serial_examples +++ b/examples/run_serial_examples @@ -16,7 +16,7 @@ set -ex ./2_Intermediate/QSC.py ./2_Intermediate/boozer.py ./2_Intermediate/stage_two_optimization.py -./2_Intermediate/stage_two_optimization_planar.py +./2_Intermediate/stage_two_optimization_planar_coils.py ./2_Intermediate/stage_two_optimization_stochastic.py ./2_Intermediate/stage_two_optimization_finite_beta.py ./2_Intermediate/strain_optimization.py From ff23c3c498241465bd1e6dfc48ada195bfb8d5ed Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Wed, 1 Nov 2023 21:08:09 -0400 Subject: [PATCH 10/61] Fixed several issues requested for commit --- .../stage_two_optimization_planar_coils.py | 2 +- src/simsopt/geo/curveplanarfourier.py | 15 +- src/simsoptpp/curveplanarfourier.cpp | 2573 ++++++++--------- src/simsoptpp/curveplanarfourier.h | 2 + tests/geo/test_curve.py | 1 - tests/geo/test_equally_spaced_planar_coils.py | 26 + 6 files changed, 1293 insertions(+), 1326 deletions(-) create mode 100644 tests/geo/test_equally_spaced_planar_coils.py diff --git a/examples/2_Intermediate/stage_two_optimization_planar_coils.py b/examples/2_Intermediate/stage_two_optimization_planar_coils.py index c84525868..d32ca4da8 100755 --- a/examples/2_Intermediate/stage_two_optimization_planar_coils.py +++ b/examples/2_Intermediate/stage_two_optimization_planar_coils.py @@ -114,7 +114,7 @@ # Define the individual terms objective function: Jf = SquaredFlux(s, bs) Jls = [CurveLength(c) for c in base_curves] -Jccdist = CurveCurveDistance(curves, CC_THRESHOLD, num_basecurves=ncoils) # Error +Jccdist = CurveCurveDistance(curves, CC_THRESHOLD, num_basecurves=ncoils) Jcsdist = CurveSurfaceDistance(curves, s, CS_THRESHOLD) Jcs = [LpCurveCurvature(c, 2, CURVATURE_THRESHOLD) for c in base_curves] Jmscs = [MeanSquaredCurvature(c) for c in base_curves] diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py index 476ff9600..264e85a86 100644 --- a/src/simsopt/geo/curveplanarfourier.py +++ b/src/simsopt/geo/curveplanarfourier.py @@ -23,13 +23,14 @@ class CurvePlanarFourier(sopp.CurvePlanarFourier, Curve): where :math:`\theta` is the counterclockwise rotation about a unit axis :math:`(\hat{x},\hat{y},\hat{z})`. - - The quaternion is normalized for calculations to prevent scaling. The dofs - themselves are not normalized. This results in a redundancy in the - optimization, where several different sets of dofs may correspond to the - same normalized quaternion. Normalizing the dofs directly would create a - dependence between the quaternion dofs, which may cause issues during - optimization. + + A quaternion is used for rotation rather than other methods for rotation to + prevent gimbal locking during optimization. The quaternion is normalized for + calculations to prevent scaling. The dofs themselves are not normalized. This + results in a redundancy in the optimization, where several different sets of + dofs may correspond to the same normalized quaternion. Normalizing the dofs + directly would create a dependence between the quaternion dofs, which may cause + issues during optimization. The dofs are stored in the order diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index ceda2e9aa..a3db9e2bf 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -1,22 +1,25 @@ #include "curveplanarfourier.h" - template -void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { - int numquadpoints = quadpoints.size(); - data *= 0; - - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); +double CurvePlanarFourier::inv_magnitude() { double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); + double sqrt_inv_s = 1 / std::sqrt(s); + return sqrt_inv_s; } else { - q_norm[0] = 1; + return 1; } +} + +template +void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { + int numquadpoints = quadpoints.size(); + data *= 0; + + Array q_norm = q * inv_magnitude(); + for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; @@ -24,9 +27,6 @@ void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { data(k, 0) += rc[i] * cos(i*phi) * cos(phi); data(k, 1) += rc[i] * cos(i*phi) * sin(phi); } - } - for (int k = 0; k < numquadpoints; ++k) { - double phi = 2 * M_PI * quadpoints[k]; for (int i = 1; i < order+1; ++i) { data(k, 0) += rs[i-1] * sin(i*phi) * cos(phi); data(k, 1) += rs[i-1] * sin(i*phi) * sin(phi); @@ -40,6 +40,7 @@ void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { j = data(m, 1); k = data(m, 2); + /* Performs quaternion based rotation, see https://www.cis.upenn.edu/~cis5150/ws-book-Ib.pdf page 575, 576 for details regarding this rotation*/ data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k) + center[0]; data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k) + center[1]; data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k) + center[2]; @@ -50,16 +51,8 @@ template void CurvePlanarFourier::gammadash_impl(Array& data) { data *= 0; - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); - double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; - if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); - } - else { - q_norm[0] = 1; - } + double inv_sqrt_s = inv_magnitude(); + Array q_norm = q * inv_sqrt_s; for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; @@ -67,26 +60,26 @@ void CurvePlanarFourier::gammadash_impl(Array& data) { data(k, 0) += rc[i] * ( -(i) * sin(i*phi) * cos(phi) - cos(i*phi) * sin(phi)); data(k, 1) += rc[i] * ( -(i) * sin(i*phi) * sin(phi) + cos(i*phi) * cos(phi)); } - } - for (int k = 0; k < numquadpoints; ++k) { - double phi = 2 * M_PI * quadpoints[k]; for (int i = 1; i < order+1; ++i) { data(k, 0) += rs[i-1] * ( (i) * cos(i*phi) * cos(phi) - sin(i*phi) * sin(phi)); data(k, 1) += rs[i-1] * ( (i) * cos(i*phi) * sin(phi) + sin(i*phi) * cos(phi)); } } + data *= (2*M_PI); for (int m = 0; m < numquadpoints; ++m) { - Array i = xt::zeros({1}); - i[0] = data(m, 0); - Array j = xt::zeros({1}); - j[0] = data(m, 1); - Array k = xt::zeros({1}); - k[0] = data(m, 2); - - data(m, 0) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + double i; + double j; + double k; + i = data(m, 0); + j = data(m, 1); + k = data(m, 2); + + + /* Performs quaternion based rotation, see https://www.cis.upenn.edu/~cis5150/ws-book-Ib.pdf page 575, 576 for details regarding this rotation*/ + data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); } } @@ -95,45 +88,33 @@ template void CurvePlanarFourier::gammadashdash_impl(Array& data) { data *= 0; - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); - double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; - if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); - } - else { - q_norm[0] = 1; - } + Array q_norm = q * inv_magnitude(); for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; for (int i = 0; i < order+1; ++i) { - data(k, 0) += rc[i] * (+2*(i)*sin(i*phi)*sin(phi)-(pow(i, 2)+1)*cos(i*phi)*cos(phi)); - data(k, 1) += rc[i] * (-2*(i)*sin(i*phi)*cos(phi)-(pow(i, 2)+1)*cos(i*phi)*sin(phi)); + data(k, 0) += rc[i] * (+2*(i)*sin(i*phi)*sin(phi)-(i*i+1)*cos(i*phi)*cos(phi)); + data(k, 1) += rc[i] * (-2*(i)*sin(i*phi)*cos(phi)-(i*i+1)*cos(i*phi)*sin(phi)); } - data(k, 2) = 0; - } - for (int k = 0; k < numquadpoints; ++k) { - double phi = 2 * M_PI * quadpoints[k]; for (int i = 1; i < order+1; ++i) { - data(k, 0) += rs[i-1] * (-(pow(i,2)+1)*sin(i*phi)*cos(phi) - 2*(i)*cos(i*phi)*sin(phi)); - data(k, 1) += rs[i-1] * (-(pow(i,2)+1)*sin(i*phi)*sin(phi) + 2*(i)*cos(i*phi)*cos(phi)); + data(k, 0) += rs[i-1] * (-(i*i+1)*sin(i*phi)*cos(phi) - 2*(i)*cos(i*phi)*sin(phi)); + data(k, 1) += rs[i-1] * (-(i*i+1)*sin(i*phi)*sin(phi) + 2*(i)*cos(i*phi)*cos(phi)); } - data(k, 2) = 0; } data *= 2*M_PI*2*M_PI; for (int m = 0; m < numquadpoints; ++m) { - Array i = xt::zeros({1}); - i[0] = data(m, 0); - Array j = xt::zeros({1}); - j[0] = data(m, 1); - Array k = xt::zeros({1}); - k[0] = data(m, 2); + double i; + double j; + double k; + i = data(m, 0); + j = data(m, 1); + k = data(m, 2); + - data(m, 0) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + /* Performs quaternion based rotation*/ + data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); } } @@ -142,55 +123,45 @@ template void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { data *= 0; - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); - double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; - if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); - } - else { - q_norm[0] = 1; - } + Array q_norm = q * inv_magnitude(); for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; for (int i = 0; i < order+1; ++i) { data(k, 0) += rc[i]*( - +(3*pow(i, 2) + 1)*cos(i*phi)*sin(phi) - +(pow(i, 2) + 3)*(i)*sin(i*phi)*cos(phi) + +(3*i*i + 1)*cos(i*phi)*sin(phi) + +(i*i + 3)*(i)*sin(i*phi)*cos(phi) ); data(k, 1) += rc[i]*( - +(pow(i, 2) + 3)*(i)*sin(i*phi)*sin(phi) - -(3*pow(i, 2) + 1)*cos(i*phi)*cos(phi) + +(i*i + 3)*(i)*sin(i*phi)*sin(phi) + -(3*i*i + 1)*cos(i*phi)*cos(phi) ); } - } - for (int k = 0; k < numquadpoints; ++k) { - double phi = 2 * M_PI * quadpoints[k]; for (int i = 1; i < order+1; ++i) { data(k, 0) += rs[i-1]*( - -(pow(i,2)+3) * (i) * cos(i*phi)*cos(phi) - +(3*pow(i,2)+1) * sin(i*phi)*sin(phi) + -(i*i+3) * (i) * cos(i*phi)*cos(phi) + +(3*i*i+1) * sin(i*phi)*sin(phi) ); data(k, 1) += rs[i-1]*( - -(pow(i,2)+3)*(i)*cos(i*phi)*sin(phi) - -(3*pow(i,2)+1)*sin(i*phi)*cos(phi) + -(i*i+3)*(i)*cos(i*phi)*sin(phi) + -(3*i*i+1)*sin(i*phi)*cos(phi) ); } } data *= 2*M_PI*2*M_PI*2*M_PI; for (int m = 0; m < numquadpoints; ++m) { - Array i = xt::zeros({1}); - i[0] = data(m, 0); - Array j = xt::zeros({1}); - j[0] = data(m, 1); - Array k = xt::zeros({1}); - k[0] = data(m, 2); + double i; + double j; + double k; + i = data(m, 0); + j = data(m, 1); + k = data(m, 2); + - data(m, 0) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + /* Performs quaternion based rotation*/ + data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); } } @@ -199,335 +170,327 @@ template void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { data *= 0; - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); - double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; - if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); - } - else { - q_norm[0] = 1; - } + Array q_norm = q * inv_magnitude(); for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; - Array i = xt::zeros({1}); - Array j = xt::zeros({1}); - Array k = xt::zeros({1}); + double i; + double j; + double k; for (int n = 0; n < order+1; ++n) { - i[0] = cos(n*phi) * cos(phi); - j[0] = cos(n*phi) * sin(phi); - k[0] = 0; + i = cos(n*phi) * cos(phi); + j = cos(n*phi) * sin(phi); + k = 0; - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } for (int n = 1; n < order+1; ++n) { - i[0] = sin(n*phi) * cos(phi); - j[0] = sin(n*phi) * sin(phi); - k[0] = 0; + i = sin(n*phi) * cos(phi); + j = sin(n*phi) * sin(phi); + k = 0; - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } - i[0] = 0; - j[0] = 0; - k[0] = 0; + i = 0; + j = 0; + k = 0; for (int n = 0; n < order+1; ++n) { - i[0] += rc[n] * cos(n*phi) * cos(phi); - j[0] += rc[n] * cos(n*phi) * sin(phi); + i += rc[n] * cos(n*phi) * cos(phi); + j += rc[n] * cos(n*phi) * sin(phi); } for (int n = 1; n < order+1; ++n) { - i[0] += rs[n-1] * sin(n*phi) * cos(phi); - j[0] += rs[n-1] * sin(n*phi) * sin(phi); + i += rs[n-1] * sin(n*phi) * cos(phi); + j += rs[n-1] * sin(n*phi) * sin(phi); } + double inv_sqrt_s = inv_magnitude(); - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; @@ -546,341 +509,333 @@ template void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { data *= 0; - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); - double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; - if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); - } - else { - q_norm[0] = 1; - } + Array q_norm = q * inv_magnitude(); for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; - Array i = xt::zeros({1}); - Array j = xt::zeros({1}); - Array k = xt::zeros({1}); + double i; + double j; + double k; for (int n = 0; n < order+1; ++n) { - i[0] = ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)); - j[0] = ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)); - k[0] = 0; + i = ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)); + j = ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)); + k = 0; - i[0] *= (2*M_PI); - j[0] *= (2*M_PI); + i *= (2*M_PI); + j *= (2*M_PI); - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } for (int n = 1; n < order+1; ++n) { - i[0] = ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)); - j[0] = ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)); - k[0] = 0; + i = ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)); + j = ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)); + k = 0; - i[0] *= (2*M_PI); - j[0] *= (2*M_PI); + i *= (2*M_PI); + j *= (2*M_PI); - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } - i[0] = 0; - j[0] = 0; - k[0] = 0; + i = 0; + j = 0; + k = 0; for (int n = 0; n < order+1; ++n) { - i[0] += rc[n] * ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)) * 2 * M_PI; - j[0] += rc[n] * ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)) * 2 * M_PI; + i += rc[n] * ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)) * 2 * M_PI; + j += rc[n] * ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)) * 2 * M_PI; } for (int n = 1; n < order+1; ++n) { - i[0] += rs[n-1] * ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)) * 2 * M_PI; - j[0] += rs[n-1] * ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)) * 2 * M_PI; + i += rs[n-1] * ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)) * 2 * M_PI; + j += rs[n-1] * ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)) * 2 * M_PI; } - - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + double inv_sqrt_s = inv_magnitude(); + + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; for (int i = 0; i < 2; ++i) { @@ -898,344 +853,336 @@ template void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { data *= 0; - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); - double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; - if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); - } - else { - q_norm[0] = 1; - } + Array q_norm = q * inv_magnitude(); for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; - Array i = xt::zeros({1}); - Array j = xt::zeros({1}); - Array k = xt::zeros({1}); + double i; + double j; + double k; for (int n = 0; n < order+1; ++n) { - i[0] = (+2*(n)*sin(n*phi)*sin(phi)-(pow(n, 2)+1)*cos(n*phi)*cos(phi)); - j[0] = (-2*(n)*sin(n*phi)*cos(phi)-(pow(n, 2)+1)*cos(n*phi)*sin(phi)); - k[0] = 0; + i = (+2*(n)*sin(n*phi)*sin(phi)-(n*n+1)*cos(n*phi)*cos(phi)); + j = (-2*(n)*sin(n*phi)*cos(phi)-(n*n+1)*cos(n*phi)*sin(phi)); + k = 0; - i[0] *= 2*M_PI*2*M_PI; - j[0] *= 2*M_PI*2*M_PI; - k[0] *= 2*M_PI*2*M_PI; + i *= 2*M_PI*2*M_PI; + j *= 2*M_PI*2*M_PI; + k *= 2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } for (int n = 1; n < order+1; ++n) { - i[0] = (-(pow(n,2)+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); - j[0] = (-(pow(n,2)+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); - k[0] = 0; + i = (-(n*n+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); + j = (-(n*n+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); + k = 0; - i[0] *= 2*M_PI*2*M_PI; - j[0] *= 2*M_PI*2*M_PI; - k[0] *= 2*M_PI*2*M_PI; + i *= 2*M_PI*2*M_PI; + j *= 2*M_PI*2*M_PI; + k *= 2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } - i[0] = 0; - j[0] = 0; - k[0] = 0; + i = 0; + j = 0; + k = 0; for (int n = 0; n < order+1; ++n) { - i[0] += rc[n] * (+2*(n)*sin(n*phi)*sin(phi)-(pow(n, 2)+1)*cos(n*phi)*cos(phi)); - j[0] += rc[n] * (-2*(n)*sin(n*phi)*cos(phi)-(pow(n, 2)+1)*cos(n*phi)*sin(phi)); + i += rc[n] * (+2*(n)*sin(n*phi)*sin(phi)-(n*n+1)*cos(n*phi)*cos(phi)); + j += rc[n] * (-2*(n)*sin(n*phi)*cos(phi)-(n*n+1)*cos(n*phi)*sin(phi)); } for (int n = 1; n < order+1; ++n) { - i[0] += rs[n-1] * (-(pow(n,2)+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); - j[0] += rs[n-1] * (-(pow(n,2)+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); + i += rs[n-1] * (-(n*n+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); + j += rs[n-1] * (-(n*n+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); } - i[0] *= 2*M_PI*2*M_PI; - j[0] *= 2*M_PI*2*M_PI; - k[0] *= 2*M_PI*2*M_PI; + i *= 2*M_PI*2*M_PI; + j *= 2*M_PI*2*M_PI; + k *= 2*M_PI*2*M_PI; + double inv_sqrt_s = inv_magnitude(); - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; for (int i = 0; i < 3; ++i) { @@ -1252,368 +1199,360 @@ template void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { data *= 0; - /* Converts q dofs to unit quaternion */ - Array q_norm = xt::zeros({4}); - double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; - if(s != 0) { - for (int i = 0; i < 4; ++i) - q_norm[i] = q[i] / std::sqrt(s); - } - else { - q_norm[0] = 1; - } + Array q_norm = q * inv_magnitude(); for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; - Array i = xt::zeros({1}); - Array j = xt::zeros({1}); - Array k = xt::zeros({1}); + double i; + double j; + double k; for (int n = 0; n < order+1; ++n) { - i[0] = ( - +(3*pow(n, 2) + 1)*cos(n*phi)*sin(phi) - +(pow(n, 2) + 3)*(n)*sin(n*phi)*cos(phi) + i = ( + +(3*n*n + 1)*cos(n*phi)*sin(phi) + +(n*n + 3)*(n)*sin(n*phi)*cos(phi) ); - j[0] = ( - +(pow(n, 2) + 3)*(n)*sin(n*phi)*sin(phi) - -(3*pow(n, 2) + 1)*cos(n*phi)*cos(phi) + j = ( + +(n*n + 3)*(n)*sin(n*phi)*sin(phi) + -(3*n*n + 1)*cos(n*phi)*cos(phi) ); - k[0] = 0; + k = 0; - i[0] *= 2*M_PI*2*M_PI*2*M_PI; - j[0] *= 2*M_PI*2*M_PI*2*M_PI; - k[0] *= 2*M_PI*2*M_PI*2*M_PI; + i *= 2*M_PI*2*M_PI*2*M_PI; + j *= 2*M_PI*2*M_PI*2*M_PI; + k *= 2*M_PI*2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } for (int n = 1; n < order+1; ++n) { - i[0] = ( - -(pow(n,2)+3) * (n) * cos(n*phi)*cos(phi) - +(3*pow(n,2)+1) * sin(n*phi)*sin(phi) + i = ( + -(n*n+3) * (n) * cos(n*phi)*cos(phi) + +(3*n*n+1) * sin(n*phi)*sin(phi) ); - j[0] = ( - -(pow(n,2)+3)*(n)*cos(n*phi)*sin(phi) - -(3*pow(n,2)+1)*sin(n*phi)*cos(phi) + j = ( + -(n*n+3)*(n)*cos(n*phi)*sin(phi) + -(3*n*n+1)*sin(n*phi)*cos(phi) ); - k[0] = 0; + k = 0; - i[0] *= 2*M_PI*2*M_PI*2*M_PI; - j[0] *= 2*M_PI*2*M_PI*2*M_PI; - k[0] *= 2*M_PI*2*M_PI*2*M_PI; + i *= 2*M_PI*2*M_PI*2*M_PI; + j *= 2*M_PI*2*M_PI*2*M_PI; + k *= 2*M_PI*2*M_PI*2*M_PI; - data(m, 0, counter) = (i[0] - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i[0] + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j[0] + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k[0]); - data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i[0] + j[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j[0] + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k[0]); - data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i[0] + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j[0] + k[0] - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k[0]); + data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); + data(m, 1, counter) = (2 * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * i + j - 2 * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * j + 2 * (q_norm[2] * q_norm[3] - q_norm[1] * q_norm[0]) * k); + data(m, 2, counter) = (2 * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * i + 2 * (q_norm[2] * q_norm[3] + q_norm[1] * q_norm[0]) * j + k - 2 * (q_norm[1] * q_norm[1] + q_norm[2] * q_norm[2]) * k); counter++; } - i[0] = 0; - j[0] = 0; - k[0] = 0; + i = 0; + j = 0; + k = 0; for (int n = 0; n < order+1; ++n) { - i[0] += rc[n]*( - +(3*pow(n, 2) + 1)*cos(n*phi)*sin(phi) - +(pow(n, 2) + 3)*(n)*sin(n*phi)*cos(phi) + i += rc[n]*( + +(3*n*n + 1)*cos(n*phi)*sin(phi) + +(n*n + 3)*(n)*sin(n*phi)*cos(phi) ); - j[0] += rc[n]*( - +(pow(n, 2) + 3)*(n)*sin(n*phi)*sin(phi) - -(3*pow(n, 2) + 1)*cos(n*phi)*cos(phi) + j += rc[n]*( + +(n*n + 3)*(n)*sin(n*phi)*sin(phi) + -(3*n*n + 1)*cos(n*phi)*cos(phi) ); } for (int n = 1; n < order+1; ++n) { - i[0] += rs[n-1]*( - -(pow(n,2)+3) * (n) * cos(n*phi)*cos(phi) - +(3*pow(n,2)+1) * sin(n*phi)*sin(phi) + i += rs[n-1]*( + -(n*n+3) * (n) * cos(n*phi)*cos(phi) + +(3*n*n+1) * sin(n*phi)*sin(phi) ); - j[0] += rs[n-1]*( - -(pow(n,2)+3)*(n)*cos(n*phi)*sin(phi) - -(3*pow(n,2)+1)*sin(n*phi)*cos(phi) + j += rs[n-1]*( + -(n*n+3)*(n)*cos(n*phi)*sin(phi) + -(3*n*n+1)*sin(n*phi)*cos(phi) ); } - i[0] *= 2*M_PI*2*M_PI*2*M_PI; - j[0] *= 2*M_PI*2*M_PI*2*M_PI; - k[0] *= 2*M_PI*2*M_PI*2*M_PI; + i *= 2*M_PI*2*M_PI*2*M_PI; + j *= 2*M_PI*2*M_PI*2*M_PI; + k *= 2*M_PI*2*M_PI*2*M_PI; + double inv_sqrt_s = inv_magnitude(); - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[0] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[0] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[0] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[0] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[1] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[1] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (inv_sqrt_s - q[1] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[1] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[2] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (- q[3] * q[2] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (inv_sqrt_s - q[2] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (- q[3] * q[2] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; - data(m, 0, counter) = (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] - - 2 * j[0] * q_norm[3]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[0] + - 2 * j * q_norm[3]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - + (4 * i[0] * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[2]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + + (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[2]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[1]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) + (- 4 * i * (q_norm[0] * q_norm[0] + q_norm[1] * q_norm[1]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[1]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + - (- 4 * i[0] * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] - - 2 * j[0] * q_norm[0]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 1, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] - + 2 * i[0] * q_norm[3] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[2] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] - - 4 * j[0] * q_norm[1]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] - + 2 * i[0] * q_norm[1] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] - + 2 * i[0] * q_norm[0] - + 4 * j[0] * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] - - 4 * j[0] * q_norm[3]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); - - - data(m, 2, counter) = (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] - - 2 * i[0] * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] - + 2 * j[0] * q_norm[1]) - * (- q[0] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] - + 2 * i[0] * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] - + 2 * j[0] * q_norm[0]) - * (- q[1] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (- 2 * i[0] * q_norm[0] - - 4 * i[0] * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] - + 2 * j[0] * q_norm[3]) - * (- q[2] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))) - + - (2 * i[0] * q_norm[1] - + 4 * i[0] * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] - - 4 * j[0] * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] - + 2 * j[0] * q_norm[2]) - * (1 / std::sqrt(s) - q[3] * q[3] / (std::sqrt(s) * std::sqrt(s) * std::sqrt(s))); + (- 4 * i * (q_norm[1] * q_norm[1] + q_norm[0] * q_norm[0]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[2] - q_norm[0] * q_norm[3]) * q_norm[3] + - 2 * j * q_norm[0]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 1, counter) = (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[0] + + 2 * i * q_norm[3] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[0]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[2] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[1] + - 4 * j * q_norm[1]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[2] + + 2 * i * q_norm[1] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[2]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[2] + q_norm[3] * q_norm[0]) * q_norm[3] + + 2 * i * q_norm[0] + + 4 * j * (q_norm[1] * q_norm[1] + q_norm[3] * q_norm[3]) * q_norm[3] + - 4 * j * q_norm[3]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); + + + data(m, 2, counter) = (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[0] + - 2 * i * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[0] + + 2 * j * q_norm[1]) + * (- q[0] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 4 * i * (q_norm[1] * q_norm[3] - q_norm[2] * q_norm[0]) * q_norm[1] + + 2 * i * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[1] + + 2 * j * q_norm[0]) + * (- q[1] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (- 2 * i * q_norm[0] + - 4 * i * (q_norm[1] * q_norm[3] - q_norm[0] * q_norm[2]) * q_norm[2] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[2] + + 2 * j * q_norm[3]) + * (- q[2] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s) + + + (2 * i * q_norm[1] + + 4 * i * (q_norm[2] * q_norm[0] - q_norm[1] * q_norm[3]) * q_norm[3] + - 4 * j * (q_norm[1] * q_norm[0] + q_norm[2] * q_norm[3]) * q_norm[3] + + 2 * j * q_norm[2]) + * (inv_sqrt_s - q[3] * q[3] * inv_sqrt_s * inv_sqrt_s * inv_sqrt_s); counter++; for (int i = 0; i < 3; ++i) { diff --git a/src/simsoptpp/curveplanarfourier.h b/src/simsoptpp/curveplanarfourier.h index 4b8b4baee..f365ba88e 100644 --- a/src/simsoptpp/curveplanarfourier.h +++ b/src/simsoptpp/curveplanarfourier.h @@ -101,6 +101,8 @@ class CurvePlanarFourier : public Curve { } + double inv_magnitude(); + void gamma_impl(Array& data, Array& quadpoints) override; void gammadash_impl(Array& data) override; void gammadashdash_impl(Array& data) override; diff --git a/tests/geo/test_curve.py b/tests/geo/test_curve.py index 59c480c48..275b6464b 100644 --- a/tests/geo/test_curve.py +++ b/tests/geo/test_curve.py @@ -509,6 +509,5 @@ def test_load_curves_from_makegrid_file(self): os.remove("coils.file_to_load") - if __name__ == "__main__": unittest.main() diff --git a/tests/geo/test_equally_spaced_planar_coils.py b/tests/geo/test_equally_spaced_planar_coils.py new file mode 100644 index 000000000..4470430fd --- /dev/null +++ b/tests/geo/test_equally_spaced_planar_coils.py @@ -0,0 +1,26 @@ +import unittest +from simsopt.geo.curve import create_equally_spaced_curves, create_equally_spaced_planar_curves +from simsopt.field import coils_via_symmetries, BiotSavart, Current + +class Testing(unittest.TestCase): + def test_equally_spaced_planar_coils(self): + ncoils = 4 + nfp = 4 + stellsym = False + + curves = create_equally_spaced_curves(ncoils, nfp, False) + currents = [Current(1e5) for i in range(ncoils)] + + curves_planar = create_equally_spaced_planar_curves(ncoils, nfp, False) + currents_planar = [Current(1e5) for i in range(ncoils)] + + coils = coils_via_symmetries(curves, currents, nfp, stellsym) + coils_planar = coils_via_symmetries(curves_planar, currents_planar, nfp, stellsym) + bs = BiotSavart(coils) + bs_planar = BiotSavart(coils_planar) + err = bs.AbsB()[0][0] - bs_planar.AbsB()[0][0] + print(err) + assert(err < 3e-10) + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From 30bbfc60419007182b8504d8fe39ac4e35616248 Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Wed, 1 Nov 2023 21:12:49 -0400 Subject: [PATCH 11/61] removed input.NewConfiguration --- tests/test_files/input.NewConfiguration | 113 ------------------------ 1 file changed, 113 deletions(-) delete mode 100644 tests/test_files/input.NewConfiguration diff --git a/tests/test_files/input.NewConfiguration b/tests/test_files/input.NewConfiguration deleted file mode 100644 index 9adf5fa4e..000000000 --- a/tests/test_files/input.NewConfiguration +++ /dev/null @@ -1,113 +0,0 @@ -&INDATA -!----- Runtime Parameters ----- - DELT = 9.00E-01 - NITER = 10000 - NSTEP = 200 - TCON0 = 2.00E+00 - -! NS_ARRAY = 16 50 -! NITER_ARRAY = 600 3000 -! FTOL_ARRAY = 1.0E-16 1.0E-13 - -! NS_ARRAY = 12 25 50 -! NITER_ARRAY = 600 1000 6000 -! FTOL_ARRAY = 1.0E-17 1.0e-17 1.0e-15 - -! NS_ARRAY = 12 25 50 75 -! NITER_ARRAY = 600 1000 2500 10000 -! FTOL_ARRAY = 1.0E-17 1.0e-17 1.0e-17 1.0e-17 - - NS_ARRAY = 12 25 50 75 100 150 201 - NITER_ARRAY = 1200 2000 3000 4000 5000 6000 20000 - FTOL_ARRAY = 1.0E-17 1.0e-17 1.0e-17 1.0e-17 1.0e-17 1.0e-17 2.0e-17 - - PRECON_TYPE = 'none' - PREC2D_THRESHOLD = 1.000000E-19 -!----- Grid Parameters ----- - LASYM = F - NFP = 0004 - MPOL = 0008 - NTOR = 0008 - PHIEDGE = 0.0381790210242581 -!----- Free Boundary Parameters ----- - LFREEB = F - NVACSKIP = 6 -!----- Pressure Parameters ----- - GAMMA = 0.000000000000E+000 - BLOAT = 1.000000000000E+000 - SPRES_PED = 1.000000000000E+000 - PRES_SCALE = 1.000000000000E+000 - PMASS_TYPE = 'power_series' - AM = 000000000E+00 -!----- Current/Iota Parameters ----- - CURTOR = 0 - NCURR = 1 - PIOTA_TYPE = 'power_series' - PCURR_TYPE = 'power_series' -!----- Axis Parameters ----- - RAXIS_CC = 0 - ZAXIS_CS = 0 -!----- Boundary Parameters ----- -! n comes before m! -RBC( 0, 0) = 1.000000000000000e+00, ZBS( 0, 0) = -0.000000000000000e+00 -RBC( 1, 0) = 1.798197877372061e-01, ZBS( 1, 0) = 1.526874285925055e-01 -RBC( 2, 0) = 1.734951154350431e-02, ZBS( 2, 0) = 1.866334230413251e-02 -RBC( 3, 0) = 2.577160162049330e-03, ZBS( 3, 0) = 1.199711292212324e-03 -RBC( 4, 0) = -1.637889983682740e-04, ZBS( 4, 0) = 6.984345011786886e-05 -RBC( 5, 0) = -2.425305167830765e-05, ZBS( 5, 0) = -2.548557148257138e-05 -RBC( -5, 1) = -8.577683632032374e-05, ZBS( -5, 1) = 2.045490523320995e-05 -RBC( -4, 1) = -3.374047917343044e-04, ZBS( -4, 1) = 5.046849551418733e-04 -RBC( -3, 1) = -3.641359983759378e-03, ZBS( -3, 1) = 3.782490654681902e-03 -RBC( -2, 1) = -2.444833020873945e-02, ZBS( -2, 1) = 2.427925370183856e-02 -RBC( -1, 1) = -8.731762429558673e-02, ZBS( -1, 1) = 4.517210283176742e-02 -RBC( 0, 1) = 1.380390474734288e-01, ZBS( 0, 1) = 1.310968006001034e-01 -RBC( 1, 1) = 2.903189084133577e-02, ZBS( 1, 1) = 3.270191607891355e-02 -RBC( 2, 1) = 6.875247108489111e-03, ZBS( 2, 1) = 6.803576261710397e-03 -RBC( 3, 1) = 8.150566273801188e-04, ZBS( 3, 1) = 8.594345731469456e-04 -RBC( 4, 1) = -2.843729541521199e-05, ZBS( 4, 1) = -1.177273734326507e-05 -RBC( 5, 1) = 1.828959533446362e-05, ZBS( 5, 1) = -1.615216261142120e-05 -RBC( -5, 2) = 2.187727631099286e-05, ZBS( -5, 2) = -7.400469361173993e-05 -RBC( -4, 2) = 8.393516055641350e-04, ZBS( -4, 2) = -4.483876523047104e-04 -RBC( -3, 2) = 1.971788481361341e-03, ZBS( -3, 2) = -3.174905588243931e-03 -RBC( -2, 2) = 5.269805664655518e-03, ZBS( -2, 2) = -7.113162328175970e-03 -RBC( -1, 2) = 2.116933661799145e-02, ZBS( -1, 2) = 1.865602467381490e-02 -RBC( 0, 2) = 1.536055908756419e-02, ZBS( 0, 2) = 9.451140140723166e-03 -RBC( 1, 2) = -1.177074525788361e-03, ZBS( 1, 2) = -4.394443738790604e-04 -RBC( 2, 2) = 1.300915708157302e-03, ZBS( 2, 2) = 1.022384351225018e-03 -RBC( 3, 2) = 2.747377558866586e-05, ZBS( 3, 2) = -6.300323824473890e-05 -RBC( 4, 2) = 9.334314906640049e-05, ZBS( 4, 2) = 6.552426964270398e-05 -RBC( 5, 2) = -5.617421098748800e-06, ZBS( 5, 2) = -1.848848555889170e-07 -RBC( -5, 3) = 2.874225777670480e-06, ZBS( -5, 3) = 7.868289246153724e-05 -RBC( -4, 3) = -1.903878083029936e-04, ZBS( -4, 3) = 3.682504964925082e-05 -RBC( -3, 3) = 2.220407427826208e-05, ZBS( -3, 3) = 6.281678187469348e-04 -RBC( -2, 3) = -1.082472074236150e-03, ZBS( -2, 3) = 6.445833193595944e-04 -RBC( -1, 3) = 6.435380216410359e-05, ZBS( -1, 3) = 1.141350665160774e-03 -RBC( 0, 3) = 1.069417168790915e-04, ZBS( 0, 3) = 3.802855234303916e-04 -RBC( 1, 3) = 4.983980241995697e-04, ZBS( 1, 3) = 6.843953564643375e-04 -RBC( 2, 3) = 3.325266953783200e-04, ZBS( 2, 3) = 2.395037991595740e-04 -RBC( 3, 3) = -8.380550535631315e-05, ZBS( 3, 3) = -2.858606506850391e-06 -RBC( 4, 3) = 8.168748496456451e-05, ZBS( 4, 3) = 3.828660987048127e-05 -RBC( 5, 3) = -1.172958658426462e-05, ZBS( 5, 3) = -2.567553564985603e-07 -RBC( -5, 4) = 1.930663967799810e-05, ZBS( -5, 4) = 5.848712999415494e-06 -RBC( -4, 4) = 5.914443815425555e-05, ZBS( -4, 4) = -9.777520270947895e-05 -RBC( -3, 4) = -1.535671893320628e-04, ZBS( -3, 4) = -1.968457634323347e-04 -RBC( -2, 4) = 9.254995677768834e-05, ZBS( -2, 4) = -1.254944494739196e-04 -RBC( -1, 4) = 2.217517688289458e-04, ZBS( -1, 4) = 7.133325449383868e-05 -RBC( 0, 4) = 4.623699812020439e-04, ZBS( 0, 4) = 3.336146039802283e-04 -RBC( 1, 4) = -4.834681321758439e-05, ZBS( 1, 4) = -1.984613542379469e-05 -RBC( 2, 4) = 1.449578757996227e-04, ZBS( 2, 4) = 3.445613069241063e-05 -RBC( 3, 4) = -5.390410338650556e-05, ZBS( 3, 4) = -6.043337987396479e-05 -RBC( 4, 4) = -2.755169485866935e-05, ZBS( 4, 4) = -3.234200905245086e-05 -RBC( 5, 4) = -1.031528435324214e-05, ZBS( 5, 4) = -8.346877197760745e-06 -RBC( -5, 5) = -8.230328283192286e-06, ZBS( -5, 5) = -4.962452471737940e-07 -RBC( -4, 5) = -4.283219579566894e-05, ZBS( -4, 5) = 2.554677526708830e-05 -RBC( -3, 5) = 7.171674894766820e-06, ZBS( -3, 5) = 4.411924318063437e-05 -RBC( -2, 5) = 1.686400668654943e-05, ZBS( -2, 5) = -5.849246530755695e-06 -RBC( -1, 5) = -3.106338530700742e-06, ZBS( -1, 5) = 1.479053323007641e-06 -RBC( 0, 5) = -3.106894329327918e-05, ZBS( 0, 5) = -4.555573189096034e-05 -RBC( 1, 5) = -2.117004285123679e-05, ZBS( 1, 5) = 4.954122546236333e-06 -RBC( 2, 5) = 1.404444565956858e-06, ZBS( 2, 5) = 2.921397801630777e-06 -RBC( 3, 5) = -1.491037166951584e-05, ZBS( 3, 5) = -1.337158933881559e-05 -RBC( 4, 5) = -1.062017757240239e-05, ZBS( 4, 5) = -1.038497225885287e-05 -RBC( 5, 5) = -3.055942324592806e-06, ZBS( 5, 5) = -2.630290187244904e-06 -/ From b5fc112ff2e7ab2283f9c406ea4c8fdd36f90408 Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Wed, 1 Nov 2023 21:18:03 -0400 Subject: [PATCH 12/61] ran autopep --- src/simsopt/geo/curveplanarfourier.py | 2 +- tests/geo/test_curve.py | 1 + tests/geo/test_equally_spaced_planar_coils.py | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py index 264e85a86..0f3bbd60c 100644 --- a/src/simsopt/geo/curveplanarfourier.py +++ b/src/simsopt/geo/curveplanarfourier.py @@ -23,7 +23,7 @@ class CurvePlanarFourier(sopp.CurvePlanarFourier, Curve): where :math:`\theta` is the counterclockwise rotation about a unit axis :math:`(\hat{x},\hat{y},\hat{z})`. - + A quaternion is used for rotation rather than other methods for rotation to prevent gimbal locking during optimization. The quaternion is normalized for calculations to prevent scaling. The dofs themselves are not normalized. This diff --git a/tests/geo/test_curve.py b/tests/geo/test_curve.py index 275b6464b..59c480c48 100644 --- a/tests/geo/test_curve.py +++ b/tests/geo/test_curve.py @@ -509,5 +509,6 @@ def test_load_curves_from_makegrid_file(self): os.remove("coils.file_to_load") + if __name__ == "__main__": unittest.main() diff --git a/tests/geo/test_equally_spaced_planar_coils.py b/tests/geo/test_equally_spaced_planar_coils.py index 4470430fd..4dc4fa722 100644 --- a/tests/geo/test_equally_spaced_planar_coils.py +++ b/tests/geo/test_equally_spaced_planar_coils.py @@ -2,6 +2,7 @@ from simsopt.geo.curve import create_equally_spaced_curves, create_equally_spaced_planar_curves from simsopt.field import coils_via_symmetries, BiotSavart, Current + class Testing(unittest.TestCase): def test_equally_spaced_planar_coils(self): ncoils = 4 @@ -20,7 +21,8 @@ def test_equally_spaced_planar_coils(self): bs_planar = BiotSavart(coils_planar) err = bs.AbsB()[0][0] - bs_planar.AbsB()[0][0] print(err) - assert(err < 3e-10) + assert (err < 3e-10) + if __name__ == "__main__": unittest.main() \ No newline at end of file From ebf55f5c7d668e336309d804bfb0d3f70d888e91 Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Wed, 1 Nov 2023 21:57:24 -0400 Subject: [PATCH 13/61] Linting fixes --- .../2_Intermediate/stage_two_optimization_planar_coils.py | 4 ++-- src/simsopt/geo/curveplanarfourier.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/2_Intermediate/stage_two_optimization_planar_coils.py b/examples/2_Intermediate/stage_two_optimization_planar_coils.py index d32ca4da8..956525085 100755 --- a/examples/2_Intermediate/stage_two_optimization_planar_coils.py +++ b/examples/2_Intermediate/stage_two_optimization_planar_coils.py @@ -180,7 +180,7 @@ def fun(dofs): ################################################################################ """) res = minimize(fun, dofs, jac=True, method='L-BFGS-B', options={'maxiter': MAXITER, 'maxcor': 300}, tol=1e-15) -curves_to_vtk(curves, OUT_DIR + f"curves_opt_short") +curves_to_vtk(curves, OUT_DIR + "curves_opt_short") pointData = {"B_N": np.sum(bs.B().reshape((nphi, ntheta, 3)) * s.unitnormal(), axis=2)[:, :, None]} s.to_vtk(OUT_DIR + "surf_opt_short", extra_data=pointData) @@ -191,7 +191,7 @@ def fun(dofs): dofs = res.x LENGTH_WEIGHT *= 0.1 res = minimize(fun, dofs, jac=True, method='L-BFGS-B', options={'maxiter': MAXITER, 'maxcor': 300}, tol=1e-15) -curves_to_vtk(curves, OUT_DIR + f"curves_opt_long") +curves_to_vtk(curves, OUT_DIR + "curves_opt_long") pointData = {"B_N": np.sum(bs.B().reshape((nphi, ntheta, 3)) * s.unitnormal(), axis=2)[:, :, None]} s.to_vtk(OUT_DIR + "surf_opt_long", extra_data=pointData) diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py index 0f3bbd60c..99b3ec8fe 100644 --- a/src/simsopt/geo/curveplanarfourier.py +++ b/src/simsopt/geo/curveplanarfourier.py @@ -1,7 +1,6 @@ import numpy as np import simsoptpp as sopp -from .._core.json import GSONDecoder from .curve import Curve __all__ = ['CurvePlanarFourier'] From d76c397c56da1de5526626d73efd0df0366e703b Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Wed, 1 Nov 2023 23:03:09 -0400 Subject: [PATCH 14/61] added round() to linkingnumber --- src/simsopt/geo/curveobjectives.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simsopt/geo/curveobjectives.py b/src/simsopt/geo/curveobjectives.py index baf41d598..bb81ec318 100644 --- a/src/simsopt/geo/curveobjectives.py +++ b/src/simsopt/geo/curveobjectives.py @@ -520,7 +520,7 @@ def J(self): integrals = sopp.linkNumber(R1, R2, dR1, dR2) * dS * dT linkNum[i-1][j-1] = 1/(4*np.pi) * (integrals) linkNumSum = sum(sum(abs(linkNum))) - return linkNumSum + return round(linkNumSum) @derivative_dec def dJ(self): From ec3581920dbd3a1dec8d5ad07b09c4a6b101364b Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Wed, 1 Nov 2023 23:04:09 -0400 Subject: [PATCH 15/61] removed penalty from linking number in example --- examples/2_Intermediate/stage_two_optimization_planar_coils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/2_Intermediate/stage_two_optimization_planar_coils.py b/examples/2_Intermediate/stage_two_optimization_planar_coils.py index 956525085..8c9d62b94 100755 --- a/examples/2_Intermediate/stage_two_optimization_planar_coils.py +++ b/examples/2_Intermediate/stage_two_optimization_planar_coils.py @@ -129,7 +129,7 @@ + CS_WEIGHT * Jcsdist \ + CURVATURE_WEIGHT * sum(Jcs) \ + MSC_WEIGHT * sum(QuadraticPenalty(J, MSC_THRESHOLD) for J in Jmscs) \ - + QuadraticPenalty(linkNum, 0.1) + + linkNum # We don't have a general interface in SIMSOPT for optimisation problems that # are not in least-squares form, so we write a little wrapper function that we From e740cbf8deef15839766c88888603f9f58669f69 Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Tue, 14 Nov 2023 07:32:55 -0500 Subject: [PATCH 16/61] Testing create_equally_spaced_planar_curves at multiple points; moved test --- src/simsoptpp/curveplanarfourier.h | 11 +++--- tests/field/test_coil.py | 34 +++++++++++++++++-- tests/geo/test_equally_spaced_planar_coils.py | 28 --------------- 3 files changed, 39 insertions(+), 34 deletions(-) delete mode 100644 tests/geo/test_equally_spaced_planar_coils.py diff --git a/src/simsoptpp/curveplanarfourier.h b/src/simsoptpp/curveplanarfourier.h index f365ba88e..b3a686c0d 100644 --- a/src/simsoptpp/curveplanarfourier.h +++ b/src/simsoptpp/curveplanarfourier.h @@ -5,16 +5,19 @@ template class CurvePlanarFourier : public Curve { /* - CurvePlanarFourier is a curve that is represented using the following Fourier series: + CurvePlanarFourier is a curve that is restricted to lie in a plane. In + the plane, the curve is represented using a Fourier series in plane polar coordinates: r(phi) = \sum_{n=0}^{order} x_{c,n}cos(n*nfp*phi) + \sum_{n=1}^order x_{s,n}sin(n*nfp*phi) - with rotation about an axis and angle determined by a set of quarternions + The plane is rotated using a quarternion + q = [q_0, q_1, q_2, q_3] = [cos(\theta/2), x * sin(\theta/2), y * sin(\theta/2), z * sin(\theta/2)] - Quaternions are normalized to prevent scaling the curves, but remain unnormalized as dofs to prevent optimization error. + The dofs for the quaternion need not generally have unit norm. The + quaternion is normalized before being applied to the curve to prevent scaling the curve. - A center vector is used to specify the location of the center of the curve: + A translation vector is used to specify the location of the center of the curve: c = [c_x, c_y, c_z] diff --git a/tests/field/test_coil.py b/tests/field/test_coil.py index 0b1125b34..47dee47fa 100644 --- a/tests/field/test_coil.py +++ b/tests/field/test_coil.py @@ -7,8 +7,8 @@ from simsopt.geo.curvexyzfourier import CurveXYZFourier, JaxCurveXYZFourier from simsopt.geo.curverzfourier import CurveRZFourier from simsopt.geo.curvehelical import CurveHelical -from simsopt.geo.curve import RotatedCurve -from simsopt.field.coil import Coil, Current, ScaledCurrent, CurrentSum +from simsopt.geo.curve import RotatedCurve, create_equally_spaced_curves, create_equally_spaced_planar_curves +from simsopt.field.coil import Coil, Current, ScaledCurrent, CurrentSum, coils_via_symmetries from simsopt.field.coil import coils_to_makegrid, coils_to_focus, load_coils_from_makegrid_file from simsopt.field.biotsavart import BiotSavart from simsopt._core.json import GSONEncoder, GSONDecoder, SIMSON @@ -187,6 +187,36 @@ def test_load_coils_from_makegrid_file(self): np.testing.assert_allclose(B, loaded_B) np.testing.assert_allclose(gamma, loaded_gamma) + def test_equally_spaced_planar_curves(self): + ncoils = 4 + nfp = 4 + stellsym = False + R0 = 2.3 + R1 = 0.9 + + curves = create_equally_spaced_curves(ncoils, nfp, stellsym, R0=R0, R1=R1) + currents = [Current(1e5) for i in range(ncoils)] + + curves_planar = create_equally_spaced_planar_curves(ncoils, nfp, stellsym, R0=R0, R1=R1) + currents_planar = [Current(1e5) for i in range(ncoils)] + + coils = coils_via_symmetries(curves, currents, nfp, stellsym) + coils_planar = coils_via_symmetries(curves_planar, currents_planar, nfp, stellsym) + bs = BiotSavart(coils) + bs_planar = BiotSavart(coils_planar) + + x1d = np.linspace(R0, R0 + 0.3, 4) + y1d = np.linspace(0, 0.2, 3) + z1d = np.linspace(-0.2, 0.4, 5) + x, y, z = np.meshgrid(x1d, y1d, z1d) + points = np.ascontiguousarray(np.array([x.ravel(), y.ravel(), z.ravel()]).T) + + bs.set_points(points) + bs_planar.set_points(points) + + np.testing.assert_allclose(bs.B(), bs_planar.B(), atol=1e-16) + + if __name__ == "__main__": unittest.main() diff --git a/tests/geo/test_equally_spaced_planar_coils.py b/tests/geo/test_equally_spaced_planar_coils.py deleted file mode 100644 index 4dc4fa722..000000000 --- a/tests/geo/test_equally_spaced_planar_coils.py +++ /dev/null @@ -1,28 +0,0 @@ -import unittest -from simsopt.geo.curve import create_equally_spaced_curves, create_equally_spaced_planar_curves -from simsopt.field import coils_via_symmetries, BiotSavart, Current - - -class Testing(unittest.TestCase): - def test_equally_spaced_planar_coils(self): - ncoils = 4 - nfp = 4 - stellsym = False - - curves = create_equally_spaced_curves(ncoils, nfp, False) - currents = [Current(1e5) for i in range(ncoils)] - - curves_planar = create_equally_spaced_planar_curves(ncoils, nfp, False) - currents_planar = [Current(1e5) for i in range(ncoils)] - - coils = coils_via_symmetries(curves, currents, nfp, stellsym) - coils_planar = coils_via_symmetries(curves_planar, currents_planar, nfp, stellsym) - bs = BiotSavart(coils) - bs_planar = BiotSavart(coils_planar) - err = bs.AbsB()[0][0] - bs_planar.AbsB()[0][0] - print(err) - assert (err < 3e-10) - - -if __name__ == "__main__": - unittest.main() \ No newline at end of file From aab93ed0acdaf42d435abb249c1d7658df2dbc2e Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Tue, 14 Nov 2023 08:03:01 -0500 Subject: [PATCH 17/61] CurvePlanarFourier: Reduce number of trig evaluations --- src/simsoptpp/curveplanarfourier.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index a3db9e2bf..6001edff5 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -4,10 +4,8 @@ template double CurvePlanarFourier::inv_magnitude() { double s = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; if(s != 0) { - double sqrt_inv_s = 1 / std::sqrt(s); - return sqrt_inv_s; - } - else { + return 1 / std::sqrt(s); + } else { return 1; } @@ -15,6 +13,7 @@ double CurvePlanarFourier::inv_magnitude() { template void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { + double sinphi, cosphi, siniphi, cosiphi; int numquadpoints = quadpoints.size(); data *= 0; @@ -23,13 +22,15 @@ void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; - for (int i = 0; i < order+1; ++i) { - data(k, 0) += rc[i] * cos(i*phi) * cos(phi); - data(k, 1) += rc[i] * cos(i*phi) * sin(phi); - } + sinphi = sin(phi); + cosphi = cos(phi); + data(k, 0) = rc[0] * cosphi; + data(k, 1) = rc[0] * sinphi; for (int i = 1; i < order+1; ++i) { - data(k, 0) += rs[i-1] * sin(i*phi) * cos(phi); - data(k, 1) += rs[i-1] * sin(i*phi) * sin(phi); + siniphi = sin(i * phi); + cosiphi = cos(i * phi); + data(k, 0) += (rc[i] * cosiphi + rs[i-1] * siniphi) * cosphi; + data(k, 1) += (rc[i] * cosiphi + rs[i-1] * siniphi) * sinphi; } } for (int m = 0; m < numquadpoints; ++m) { From bb88259e2f19adb3a968c94129f5821a06d97d84 Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Tue, 14 Nov 2023 09:05:40 -0500 Subject: [PATCH 18/61] CurvePlanarFourier tidying up --- src/simsopt/geo/curveplanarfourier.py | 25 ++++++++++----- src/simsoptpp/curveplanarfourier.cpp | 46 +++++++++------------------ src/simsoptpp/curveplanarfourier.h | 13 ++++---- 3 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/simsopt/geo/curveplanarfourier.py b/src/simsopt/geo/curveplanarfourier.py index 99b3ec8fe..4880d05d6 100644 --- a/src/simsopt/geo/curveplanarfourier.py +++ b/src/simsopt/geo/curveplanarfourier.py @@ -8,24 +8,33 @@ class CurvePlanarFourier(sopp.CurvePlanarFourier, Curve): r""" - ``CurvePlanarFourier`` is a curve that is represented by a polar coordinate - Fourier serires, a rotation quaternion, and a center point following the - form: + ``CurvePlanarFourier`` is a curve that is restricted to lie in a plane. The + shape of the curve within the plane is represented by a Fourier series in + polar coordinates. The resulting planar curve is then rotated in three + dimensions using a quaternion, and finally a translation is applied. The + Fourier series in polar coordinates is .. math:: - r(\phi) &= \sum_{m=0}^{\text{order}} r_{c,m}\cos(m \phi) + \sum_{m=1}^{\text{order}} r_{s,m}\sin(m \phi) + r(\phi) = \sum_{m=0}^{\text{order}} r_{c,m}\cos(m \phi) + \sum_{m=1}^{\text{order}} r_{s,m}\sin(m \phi). + + The rotation quaternion is + + .. math:: \bf{q} &= [q_0,q_i,q_j,q_k] &= [\cos(\theta / 2), \hat{x}\sin(\theta / 2), \hat{y}\sin(\theta / 2), \hat{z}\sin(\theta / 2)] - where :math:`\theta` is the counterclockwise rotation about a unit axis - :math:`(\hat{x},\hat{y},\hat{z})`. + where :math:`\theta` is the counterclockwise rotation angle about a unit axis + :math:`(\hat{x},\hat{y},\hat{z})`. Details of the quaternion rotation can be + found for example in pages 575-576 of + https://www.cis.upenn.edu/~cis5150/ws-book-Ib.pdf. + A quaternion is used for rotation rather than other methods for rotation to - prevent gimbal locking during optimization. The quaternion is normalized for - calculations to prevent scaling. The dofs themselves are not normalized. This + prevent gimbal locking during optimization. The quaternion is normalized + before being applied to prevent scaling of the curve. The dofs themselves are not normalized. This results in a redundancy in the optimization, where several different sets of dofs may correspond to the same normalized quaternion. Normalizing the dofs directly would create a dependence between the quaternion dofs, which may cause diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index 6001edff5..2d5a3cc55 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -34,12 +34,9 @@ void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { } } for (int m = 0; m < numquadpoints; ++m) { - double i; - double j; - double k; - i = data(m, 0); - j = data(m, 1); - k = data(m, 2); + double i = data(m, 0); + double j = data(m, 1); + double k = data(m, 2); /* Performs quaternion based rotation, see https://www.cis.upenn.edu/~cis5150/ws-book-Ib.pdf page 575, 576 for details regarding this rotation*/ data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k) + center[0]; @@ -69,13 +66,9 @@ void CurvePlanarFourier::gammadash_impl(Array& data) { data *= (2*M_PI); for (int m = 0; m < numquadpoints; ++m) { - double i; - double j; - double k; - i = data(m, 0); - j = data(m, 1); - k = data(m, 2); - + double i = data(m, 0); + double j = data(m, 1); + double k = data(m, 2); /* Performs quaternion based rotation, see https://www.cis.upenn.edu/~cis5150/ws-book-Ib.pdf page 575, 576 for details regarding this rotation*/ data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); @@ -104,13 +97,9 @@ void CurvePlanarFourier::gammadashdash_impl(Array& data) { } data *= 2*M_PI*2*M_PI; for (int m = 0; m < numquadpoints; ++m) { - double i; - double j; - double k; - i = data(m, 0); - j = data(m, 1); - k = data(m, 2); - + double i = data(m, 0); + double j = data(m, 1); + double k = data(m, 2); /* Performs quaternion based rotation*/ data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); @@ -151,13 +140,9 @@ void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { } data *= 2*M_PI*2*M_PI*2*M_PI; for (int m = 0; m < numquadpoints; ++m) { - double i; - double j; - double k; - i = data(m, 0); - j = data(m, 1); - k = data(m, 2); - + double i = data(m, 0); + double j = data(m, 1); + double k = data(m, 2); /* Performs quaternion based rotation*/ data(m, 0) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); @@ -495,12 +480,11 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { counter++; + data(m, 0, counter) = 0; + data(m, 1, counter) = 0; + data(m, 2, counter) = 0; for (int i = 0; i < 3; ++i) { - data(m, 0, counter) = 0; - data(m, 1, counter) = 0; - data(m, 2, counter) = 0; data(m, i, counter) = 1; - counter++; } } diff --git a/src/simsoptpp/curveplanarfourier.h b/src/simsoptpp/curveplanarfourier.h index b3a686c0d..7575ff673 100644 --- a/src/simsoptpp/curveplanarfourier.h +++ b/src/simsoptpp/curveplanarfourier.h @@ -11,10 +11,13 @@ class CurvePlanarFourier : public Curve { r(phi) = \sum_{n=0}^{order} x_{c,n}cos(n*nfp*phi) + \sum_{n=1}^order x_{s,n}sin(n*nfp*phi) The plane is rotated using a quarternion - + q = [q_0, q_1, q_2, q_3] = [cos(\theta/2), x * sin(\theta/2), y * sin(\theta/2), z * sin(\theta/2)] - The dofs for the quaternion need not generally have unit norm. The + Details of the quaternion rotation can be found for example in pages + 575-576 of https://www.cis.upenn.edu/~cis5150/ws-book-Ib.pdf. + + The simsopt dofs for the quaternion need not generally have unit norm. The quaternion is normalized before being applied to the curve to prevent scaling the curve. A translation vector is used to specify the location of the center of the curve: @@ -103,9 +106,6 @@ class CurvePlanarFourier : public Curve { return check_the_persistent_cache("dgammadashdashdash_by_dcoeff", {numquadpoints, 3, num_dofs()}, [this](Array& A) { return dgammadashdashdash_by_dcoeff_impl(A);}); } - - double inv_magnitude(); - void gamma_impl(Array& data, Array& quadpoints) override; void gammadash_impl(Array& data) override; void gammadashdash_impl(Array& data) override; @@ -115,6 +115,7 @@ class CurvePlanarFourier : public Curve { void dgammadashdash_by_dcoeff_impl(Array& data) override; void dgammadashdashdash_by_dcoeff_impl(Array& data) override; - +private: + double inv_magnitude(); }; From 1c439a42d64c648023b105c998b562b39daa073e Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Tue, 14 Nov 2023 09:17:15 -0500 Subject: [PATCH 19/61] Undo bug I introduced in the previous commit --- src/simsoptpp/curveplanarfourier.cpp | 6 +++--- src/simsoptpp/curveplanarfourier.h | 6 +++--- src/simsoptpp/python_curves.cpp | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index 2d5a3cc55..9c282b3e0 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -480,10 +480,10 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { counter++; - data(m, 0, counter) = 0; - data(m, 1, counter) = 0; - data(m, 2, counter) = 0; for (int i = 0; i < 3; ++i) { + data(m, 0, counter) = 0; + data(m, 1, counter) = 0; + data(m, 2, counter) = 0; data(m, i, counter) = 1; counter++; } diff --git a/src/simsoptpp/curveplanarfourier.h b/src/simsoptpp/curveplanarfourier.h index 7575ff673..901bde313 100644 --- a/src/simsoptpp/curveplanarfourier.h +++ b/src/simsoptpp/curveplanarfourier.h @@ -5,8 +5,8 @@ template class CurvePlanarFourier : public Curve { /* - CurvePlanarFourier is a curve that is restricted to lie in a plane. In - the plane, the curve is represented using a Fourier series in plane polar coordinates: + CurvePlanarFourier is a curve that is restricted to lie in a plane. In + the plane, the curve is represented using a Fourier series in plane polar coordinates: r(phi) = \sum_{n=0}^{order} x_{c,n}cos(n*nfp*phi) + \sum_{n=1}^order x_{s,n}sin(n*nfp*phi) @@ -24,7 +24,7 @@ class CurvePlanarFourier : public Curve { c = [c_x, c_y, c_z] - The dofs are stored in the order + The dofs are stored in the order [r_{c,0},...,r_{c,order},r_{s,1},...,r_{s,order}, q_0, q_1, q_2, q_3, c_x, c_y, c_z] diff --git a/src/simsoptpp/python_curves.cpp b/src/simsoptpp/python_curves.cpp index ada7a2225..90760ee4b 100644 --- a/src/simsoptpp/python_curves.cpp +++ b/src/simsoptpp/python_curves.cpp @@ -135,7 +135,6 @@ void init_curves(py::module_ &m) { register_common_curve_methods(pycurverzfourier); auto pycurveplanarfourier = py::class_, PyCurvePlanarFourierTrampoline, PyCurve>(m, "CurvePlanarFourier") - //.def(py::init()) .def(py::init, int, int, bool>()) .def_readwrite("rc", &PyCurvePlanarFourier::rc) .def_readwrite("rs", &PyCurvePlanarFourier::rs) From 63dd1123f4a8856bc07b1ce23196ef3adc96b814 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Fri, 17 Nov 2023 12:06:47 -0500 Subject: [PATCH 20/61] Initial commit of frame_twist. --- src/simsopt/geo/framedcurve.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/simsopt/geo/framedcurve.py b/src/simsopt/geo/framedcurve.py index dc883418f..7a7e6ef5d 100644 --- a/src/simsopt/geo/framedcurve.py +++ b/src/simsopt/geo/framedcurve.py @@ -31,6 +31,13 @@ def __init__(self, curve, rotation=None): self.rotation = rotation Curve.__init__(self, depends_on=deps) + def frame_twist(self): + t, n, _ = self.rotated_frame() + _, ndash, _ = self.rotated_frame_dash() + T = (n[:,0] * (ndash[:,1]*t[:,2] - ndash[:,2]*t[:,1]) \ + + n[:,1] * (ndash[:,2]*t[:,0] - ndash[:,0]*t[:,2]) \ + + n[:,2] * (ndash[:,0]*t[:,1] - ndash[:,1]*t[:,0])) + return np.sum(T)/(len(T)*2*np.pi) class FramedCurveFrenet(FramedCurve): r""" From 295f41e88b311515732c0533849478a5e17f03fe Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sat, 18 Nov 2023 15:53:17 -0500 Subject: [PATCH 21/61] Change the license to MIT in setup.cfg --- setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index a57a63b56..57ac6f15a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,8 +3,8 @@ name = simsopt description: Framework for optimizing stellarators long_description = file: README.md long_description_content_type = text/markdown -license = GNU Lesser General Public License Version 3 -license_files = COPYING, COPYING.LESSER +license = MIT +license_files = LICENSE author = "Matt Landreman, Bharat Medasani, Florian Wechsung" author_email = mattland@umd.edu, mbkumar@gmail.com, wechsung@nyu.edu maintainer = "Bharat Medasani" From 239e4053a8bc943257fc32a88343224a2eece9b7 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 19 Nov 2023 07:26:13 -0500 Subject: [PATCH 22/61] Almost complete implementation of new build with scikit-build-core --- CMakeLists.txt | 9 ++-- pyproject.toml | 98 +++++++++++++++++++++++++++++++++++-- setup.cfg | 112 ------------------------------------------ setup.py | 130 ------------------------------------------------- 4 files changed, 100 insertions(+), 249 deletions(-) delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 838e8e197..a064c9dfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,13 @@ cmake_minimum_required(VERSION 3.15) -project(simsoptpp) +project(simsoptpp LANGUAGES CXX) #set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(Python_FIND_STRATEGY LOCATION) -find_package(Python 3 COMPONENTS Interpreter Development.Module NumPy) +find_package(Python REQUIRED COMPONENTS Interpreter Development.Module NumPy) +find_package(pybind11 CONFIG REQUIRED) message(status "Python executable is ${Python_EXECUTABLE}") message(status "Python Development Module found value is ${Python_Development.Module_FOUND}") @@ -106,7 +107,7 @@ else() message(STATUS "Boost include dirs are ${Boost_INCLUDE_DIRS}") endif() -add_subdirectory(thirdparty/pybind11) +# add_subdirectory(thirdparty/pybind11) add_subdirectory(thirdparty/fmt EXCLUDE_FROM_ALL) set(XTENSOR_USE_OPENMP 0) set(XTENSOR_USE_TBB 0) @@ -164,4 +165,4 @@ target_link_libraries(profiling PRIVATE fmt::fmt-header-only) #install(TARGETS ${PROJECT_NAME} # #LIBRARY # DESTINATION src/${PROJECT_NAME}) -#install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${PROJECT_NAME}) +install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION .) diff --git a/pyproject.toml b/pyproject.toml index f877c5587..e8ed60a4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,100 @@ [build-system] -requires = ["setuptools>=45", "wheel", "oldest-supported-numpy", "cmake", "ninja", "setuptools_scm[toml]>=6.0"] -build-backend = "setuptools.build_meta" +requires = [ + "scikit-build-core>=0.3.3", + "pybind11", + "oldest-supported-numpy", + "setuptools_scm>=8.0", + 'tomli; python_version < "3.11"',] +build-backend = "scikit_build_core.build" -[tools.setuptools_scm] +[project] +name = "simsopt" +license = {text = "MIT License"} +description="Framework for optimizing stellarators" +readme = "README.md" +# long_description = file: README.md +# long_description_content_type = text/markdown +requires-python = ">=3.8" +authors = [ + {name = "Matt Landreman", email = "mattland@umd.edu"}, + {name = "Bharat Medasani", email = "mbkumar@gmail.com"}, + {name = "Florian Wechsung", email = "wechsung@nyu.edu"} +] +maintainers = [ + {name = "Bharat Medasani", email = "mbkumar@gmail.com"}, + {name = "Matt Landreman", email = "mattland@umd.edu"}, +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering :: Physics", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX :: Linux", + "Environment :: Console", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10" +] +keywords = [ + "plasma physics", + "plasma", + "magnetohydrodynamics", + "mhd", + "nuclear fusion reactor", + "fusion", + "stellarator", + "vmec", + "spec", + "optimization", + "Biot-Savart", + "magnetostatics" +] +dependencies = [ + 'numpy >= 1.21', + 'jax >= 0.2.5', + 'jaxlib >= 0.1.56', + 'scipy >= 1.5.4', + 'Deprecated >= 1.2.10', + 'nptyping >= 1.3.0', + 'monty >= 2021.6.10', + 'ruamel.yaml', + 'sympy', + 'f90nml', + 'randomgen', + 'pyevtk', + 'matplotlib' +] +dynamic = ["version"] + +[project.optional-dependencies] +SPEC = ["py_spec >= 3.0.1", "pyoculus >= 0.1.1", "h5py >= 3.1.0"] +MPI = ["mpi4py >= 3.0.3"] +VIS = ["vtk >= 8.1.2", "PyQt5", "mayavi"] +DOCS = ["sphinx", "sphinx-rtd-theme"] + +[project.urls] +Homepage = "https://github.com/hiddenSymmetries/simsopt" +Download = "https://pypi.org/project/simsopt" +Issues = "https://github.com/hiddenSymmetries/simsopt/issues" +Documentation = "https://simsopt.readthedocs.io" +Repository = "https://github.com/hiddenSymmetries/simsopt" + +[tool.setuptools_scm] +write_to = "src/simsopt/_version.py" +local_scheme = "git-describe" + +[tool.scikit-build] +metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" +sdist.include = ["src/package/_version.py"] +build-dir = "build/{wheel_tag}" + +[tool.scikit-build.generate] +path = "package/_version.py" +template = ''' +version = "${version}" +''' [tool.ruff] src = ["src/simsopt"] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index a57a63b56..000000000 --- a/setup.cfg +++ /dev/null @@ -1,112 +0,0 @@ -[metadata] -name = simsopt -description: Framework for optimizing stellarators -long_description = file: README.md -long_description_content_type = text/markdown -license = GNU Lesser General Public License Version 3 -license_files = COPYING, COPYING.LESSER -author = "Matt Landreman, Bharat Medasani, Florian Wechsung" -author_email = mattland@umd.edu, mbkumar@gmail.com, wechsung@nyu.edu -maintainer = "Bharat Medasani" -maintainer_email = mbkumar@gmail.com -url = https://github.com/hiddenSymmetries/simsopt -download_url = https://pypi.org/project/simsopt -project_urls = - Bug Tracker = https://github.com/hiddenSymmetries/simsopt/issues - Documentation = https://simsopt.readthedocs.io - Source Code = https://github.com/hiddenSymmetries/simsopt/archive/master.zip -classifier = - Development Status :: 3 - Alpha - Intended Audience :: Science/Research - Topic :: Scientific/Engineering :: Physics - License :: OSI Approved :: MIT License - Operating System :: MacOS :: MacOS X - Operating System :: POSIX :: Linux - Environment :: Console - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 -keywords = - plasma physics - plasma - magnetohydrodynamics - mhd - nuclear fusion reactor - fusion - stellarator - vmec - spec - optimization - Biot-Savart - magnetostatics - -[options] -install_requires = - numpy >= 1.21 - jax >= 0.2.5 - jaxlib >= 0.1.56 - scipy >= 1.5.4 - Deprecated >= 1.2.10 - nptyping >= 1.3.0 - monty >= 2021.6.10 - ruamel.yaml - sympy - f90nml - randomgen - pyevtk - matplotlib -package_dir = - =src -packages = find: - -[options.extras_require] -SPEC = - py_spec >= 3.0.1 - pyoculus >= 0.1.1 - h5py >= 3.1.0 -MPI = - mpi4py >= 3.0.3 -VIS = - vtk >= 8.1.2 - PyQt5 - mayavi -DOCS = - sphinx - sphinx-rtd-theme - -[options.packages.find] -where = src - -[options.package_data] -* = - input.default - defaults.sp - log_config.yaml - NCSX.dat - HSX.dat - W7-X.dat - GIULIANI_length18_nsurfaces5.ma - GIULIANI_length18_nsurfaces5.curves - GIULIANI_length18_nsurfaces5.currents - GIULIANI_length20_nsurfaces5.ma - GIULIANI_length20_nsurfaces5.curves - GIULIANI_length20_nsurfaces5.currents - GIULIANI_length22_nsurfaces5.ma - GIULIANI_length22_nsurfaces5.curves - GIULIANI_length22_nsurfaces5.currents - GIULIANI_length24_nsurfaces5.ma - GIULIANI_length24_nsurfaces5.curves - GIULIANI_length24_nsurfaces5.currents - GIULIANI_length18_nsurfaces9.ma - GIULIANI_length18_nsurfaces9.curves - GIULIANI_length18_nsurfaces9.currents - GIULIANI_length20_nsurfaces9.ma - GIULIANI_length20_nsurfaces9.curves - GIULIANI_length20_nsurfaces9.currents - GIULIANI_length22_nsurfaces9.ma - GIULIANI_length22_nsurfaces9.curves - GIULIANI_length22_nsurfaces9.currents - GIULIANI_length24_nsurfaces9.ma - GIULIANI_length24_nsurfaces9.curves - GIULIANI_length24_nsurfaces9.currents diff --git a/setup.py b/setup.py deleted file mode 100644 index 97344c6e0..000000000 --- a/setup.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import subprocess -from pathlib import Path -from setuptools import setup, Extension -from setuptools.command.build_ext import build_ext - -import setuptools_scm - -# Convert distutils Windows platform specifiers to CMake -A arguments -PLAT_TO_CMAKE = { - "win32": "Win32", - "win-amd64": "x64", - "win-arm32": "ARM", - "win-arm64": "ARM64", -} - - -# A CMakeExtension needs a sourcedir instead of a file list. -# The name must be the _single_ output extension from the CMake build. -# If you need multiple extensions, see scikit-build. -class CMakeExtension(Extension): - def __init__(self, name, sourcedir=""): - Extension.__init__(self, name, sources=[]) - self.sourcedir = os.path.abspath(sourcedir) - - -class CMakeBuild(build_ext): - # debug: bool = True - def build_extension(self, ext): - extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) - - # required for auto-detection of auxiliary "native" libs - if not extdir.endswith(os.path.sep): - extdir += os.path.sep - - cfg = "Debug" if self.debug else "Release" - cfg = os.getenv("CMAKE_BUILD_TYPE", cfg) - print(f"Choose CMAKE_BUILD_TYPE={cfg}", flush=True) - - # CMake lets you override the generator - we need to check this. - # Can be set with Conda-Build, for example. - cmake_generator = os.environ.get("CMAKE_GENERATOR", "") - - # Set Python_EXECUTABLE instead if you use PYBIND11_FINDPYTHON - # EXAMPLE_VERSION_INFO shows you how to pass a value into the C++ code - # from Python. - - PYTHON_ROOT = str((Path(sys.executable).parent / "..").resolve()) - cmake_args = [ - "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}".format(extdir), - "-DPYTHON_EXECUTABLE={}".format(sys.executable), - "-DEXAMPLE_VERSION_INFO={}".format(self.distribution.get_version()), - "-DCMAKE_BUILD_TYPE={}".format(cfg), # not used on MSVC, but no harm - "-DPython_ROOT_DIR={}".format(PYTHON_ROOT), - ] - build_args = [] - - if self.compiler.compiler_type != "msvc": - # Using Ninja-build since it a) is available as a wheel and b) - # multithreads automatically. MSVC would require all variables be - # exported for Ninja to pick it up, which is a little tricky to do. - # Users can override the generator with CMAKE_GENERATOR in CMake - # 3.15+. - if not cmake_generator: - cmake_args += ["-GNinja"] - - else: - - # Single config generators are handled "normally" - single_config = any(x in cmake_generator for x in {"NMake", "Ninja"}) - - # CMake allows an arch-in-generator style for backward compatibility - contains_arch = any(x in cmake_generator for x in {"ARM", "Win64"}) - - # Specify the arch if using MSVC generator, but only if it doesn't - # contain a backward-compatibility arch spec already in the - # generator name. - if not single_config and not contains_arch: - cmake_args += ["-A", PLAT_TO_CMAKE[self.plat_name]] - - # Multi-config generators have a different way to specify configs - if not single_config: - cmake_args += [ - "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir) - ] - build_args += ["--config", cfg] - - # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level - # across all generators. - if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ: - # self.parallel is a Python 3 only way to set parallel jobs by hand - # using -j in the build_ext call, not supported by pip or PyPA-build. - if hasattr(self, "parallel") and self.parallel: - # CMake 3.12+ only. - build_args += ["-j{}".format(self.parallel)] - - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) - - subprocess.check_call( - ["cmake", ext.sourcedir] + cmake_args, cwd=self.build_temp - ) - subprocess.check_call( - ["cmake", "--build", ".", "--target", "simsoptpp"] + build_args, cwd=self.build_temp - ) - - -def my_local_scheme(version: setuptools_scm.version.ScmVersion) -> str: - """My local node and date version.""" - node_and_date = setuptools_scm.version.get_local_node_and_date(version) - dirty = ".dirty" if version.dirty else "" - return str(node_and_date) + dirty - -version = setuptools_scm.get_version( - write_to=Path(".") / "src" / "simsopt" / "_version.py", - version_scheme="post-release", - local_scheme=my_local_scheme, -) - - -setup( - # use_scm_version=True, - version=version, - setup_requires=["setuptools_scm"], - ext_modules=[CMakeExtension("simsoptpp")], - cmdclass={"build_ext": CMakeBuild} -) From c61599c3b525c758334c3767b18e5685605b3b0e Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 19 Nov 2023 22:43:04 -0500 Subject: [PATCH 23/61] Change localscheme to dirty --- pyproject.toml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e8ed60a4a..b6183968e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,18 +83,13 @@ Repository = "https://github.com/hiddenSymmetries/simsopt" [tool.setuptools_scm] write_to = "src/simsopt/_version.py" -local_scheme = "git-describe" +local_scheme = "dirty" [tool.scikit-build] metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" -sdist.include = ["src/package/_version.py"] +sdist.include = ["src/simsopt/_version.py"] build-dir = "build/{wheel_tag}" -[tool.scikit-build.generate] -path = "package/_version.py" -template = ''' -version = "${version}" -''' [tool.ruff] src = ["src/simsopt"] From 24c80d3a09ae16d4d72e3e3b2a838402ed14a468 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 08:48:03 -0500 Subject: [PATCH 24/61] Update CMakeLists for macos runner in CI builds --- CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a064c9dfc..14f8ffc49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,8 +41,12 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) include(CheckCXXCompilerFlag) IF(DEFINED ENV{CI}) - message(STATUS "CI environment detected. Set compilation flags targetting Westmere microarch.") - set(CMAKE_CXX_FLAGS "-O3 -march=westmere") + if (APPLE) + set(CMAKE_CXX_FLAGS "-O3") + else() + message(STATUS "CI environment detected. Set compilation flags targetting Westmere microarch.") + set(CMAKE_CXX_FLAGS "-O3 -march=westmere") + endif() elseif(DEFINED ENV{CONDA_BUILD}) message(STATUS "conda build environment detected. Let conda set compilation flags accordingly.") # set(CMAKE_CXX_FLAGS "-O3 -march=ivybridge -mfma -ffp-contract=fast") From c34bdf076ba1cd8154825982e4f9c23ec5756860 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 09:07:29 -0500 Subject: [PATCH 25/61] Bump python version to 3.9 in workflows --- .github/workflows/ci.yml | 2 +- .github/workflows/conda.yml | 2 +- .github/workflows/extensive_ci.yml | 2 +- .github/workflows/linting.yml | 2 +- .github/workflows/non_simd_tests.yml | 2 +- .github/workflows/wheel.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea407082a..0c2cd4eaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8.17] # To sync with coveragerc use 3 level + python-version: [3.9.17] # To sync with coveragerc use 3 level test-type: [unit, integrated] steps: diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index 35b1ce59f..f8d3e4214 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: platform: [ubuntu-latest, macos-11] - python-version: ["3.8"] + python-version: ["3.9"] runs-on: ${{ matrix.platform }} diff --git a/.github/workflows/extensive_ci.yml b/.github/workflows/extensive_ci.yml index bc1bef2c8..09981cfbb 100644 --- a/.github/workflows/extensive_ci.yml +++ b/.github/workflows/extensive_ci.yml @@ -247,7 +247,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8.17 + python-version: 3.9.17 - name: Install coverage run: pip install coverage diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 43e4ac956..ccbd8d01f 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8] + python-version: [3.9] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/non_simd_tests.yml b/.github/workflows/non_simd_tests.yml index f8e06e610..961878a73 100644 --- a/.github/workflows/non_simd_tests.yml +++ b/.github/workflows/non_simd_tests.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.8.15] # To sync with coveragerc use 3 level + python-version: [3.9.17] # To sync with coveragerc use 3 level steps: # First print out lots of information. We do this in separate diff --git a/.github/workflows/wheel.yml b/.github/workflows/wheel.yml index 4b7f6468d..e925d413e 100644 --- a/.github/workflows/wheel.yml +++ b/.github/workflows/wheel.yml @@ -45,7 +45,7 @@ jobs: - uses: actions/setup-python@v4 name: Install Python with: - python-version: '3.8' + python-version: '3.9' - name: Download all submodules run: git submodule update --init From f16b11cee2d837cbdea0a0b591d5b605a6e18788 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 09:47:44 -0500 Subject: [PATCH 26/61] Remove CMAKE option in simsopt installation in ci workflow --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c2cd4eaa..57cc924a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -130,8 +130,6 @@ jobs: run: | cd SPEC pip install . - # python setup.py bdist_wheel - # pip install dist/*.whl - name: Try import spec run: python -c "import spec.spec_f90wrapped as spec; print(spec.constants.version)" @@ -159,7 +157,8 @@ jobs: run: python -c "print(dir()); import vmec; print(dir()); print(dir(vmec)); print('package:', vmec.__package__); print('spec:', vmec.__spec__); print('doc:', vmec.__doc__); print('file:', vmec.__file__); print('path:', vmec.__path__)" - name: Install simsopt package - run: env CMAKE_BUILD_TYPE=Debug pip install -v .[MPI,SPEC] + # run: env CMAKE_BUILD_TYPE=Debug pip install -v .[MPI,SPEC] + run: pip install -v ".[MPI,SPEC]" - name: Verify that importing simsopt does not automatically initialize MPI run: ./tests/verify_MPI_not_initialized.py From da5660a9e5d1c44bba65f631b9abe16cac44c9a7 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 10:13:52 -0500 Subject: [PATCH 27/61] Update conda recipe --- conda.recipe/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index a434fd608..2b25f4df7 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -28,9 +28,9 @@ requirements: host: - pip - wheel - - setuptools - numpy {{ numpy }} - "setuptools_scm[toml]" + - scikit-build-core - python {{ python }} run: From dec2483f73f16bbb4c439ab207710dee5d41964f Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 10:19:27 -0500 Subject: [PATCH 28/61] Trying for mpi4py to be installed along with simsopt --- .github/workflows/conda.yml | 2 +- pyproject.toml | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index f8d3e4214..b178720e0 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -41,7 +41,7 @@ jobs: channel-priority: strict - name: Prepare - run: conda install -y conda-build conda-verify setuptools_scm anaconda-client + run: conda install -y conda-build conda-verify setuptools_scm anaconda-client scikit-build-core - name: Build and upload if: github.event_name == 'release' && github.event.action == 'published' diff --git a/pyproject.toml b/pyproject.toml index b6183968e..ea11be3fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,13 +52,13 @@ keywords = [ "magnetostatics" ] dependencies = [ - 'numpy >= 1.21', - 'jax >= 0.2.5', - 'jaxlib >= 0.1.56', - 'scipy >= 1.5.4', - 'Deprecated >= 1.2.10', - 'nptyping >= 1.3.0', - 'monty >= 2021.6.10', + 'numpy>=1.21', + 'jax>=0.2.5', + 'jaxlib>=0.1.56', + 'scipy>=1.5.4', + 'Deprecated>=1.2.10', + 'nptyping>=1.3.0', + 'monty>=2021.6.10', 'ruamel.yaml', 'sympy', 'f90nml', @@ -69,8 +69,8 @@ dependencies = [ dynamic = ["version"] [project.optional-dependencies] -SPEC = ["py_spec >= 3.0.1", "pyoculus >= 0.1.1", "h5py >= 3.1.0"] -MPI = ["mpi4py >= 3.0.3"] +SPEC = ["py_spec>=3.0.1", "pyoculus>=0.1.1", "h5py>=3.1.0"] +MPI = ["mpi4py>=3.0.3"] VIS = ["vtk >= 8.1.2", "PyQt5", "mayavi"] DOCS = ["sphinx", "sphinx-rtd-theme"] From f9079523cec66445606749aab1cfe86db758ddb2 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 11:13:44 -0500 Subject: [PATCH 29/61] optional packages not getting installed on runners for some reason --- .github/workflows/ci.yml | 2 +- .github/workflows/extensive_ci.yml | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57cc924a1..7a924069d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: - name: Install python dependencies run: | sudo apt-get install graphviz graphviz-dev - pip install wheel numpy scipy f90nml h5py scikit-build cmake qsc sympy pyevtk matplotlib ninja plotly networkx pygraphviz + pip install wheel numpy scipy f90nml h5py scikit-build cmake qsc sympy pyevtk matplotlib ninja plotly networkx pygraphviz mpi4py py_spec pyoculus h5py - name: Install booz_xform run: pip install -v git+https://github.com/hiddenSymmetries/booz_xform diff --git a/.github/workflows/extensive_ci.yml b/.github/workflows/extensive_ci.yml index 09981cfbb..9584bd807 100644 --- a/.github/workflows/extensive_ci.yml +++ b/.github/workflows/extensive_ci.yml @@ -165,7 +165,9 @@ jobs: - name: Install simsopt package if: contains(matrix.packages, 'spec') || contains(matrix.packages, 'all') - run: pip install -v .[MPI,SPEC] + run: | + pip install -v . + pip install mpi4py py_spec pyoculus h5py - name: Install simsopt package if: contains(matrix.packages, 'none') @@ -173,7 +175,9 @@ jobs: - name: Install simsopt package if: contains(matrix.packages, 'vmec') - run: pip install -v .[MPI] + run: | + pip install -v . + pip install mpi4py - name: Run serial examples as part of integrated tests if: contains(matrix.test-type, 'integrated') && (contains(matrix.packages, 'none') || contains(matrix.packages, 'all')) From 9f08b8514bf2fddce7fea2a885f16bdc470fcf96 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 12:41:52 -0500 Subject: [PATCH 30/61] Add pybind11 to build and host requirements in conda recipe --- conda.recipe/meta.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index 2b25f4df7..1a4a4eec6 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -24,6 +24,8 @@ requirements: - libgomp # [linux] - "setuptools_scm[toml]" - boost + - pybind11 + - scikit-build-core host: - pip @@ -32,6 +34,7 @@ requirements: - "setuptools_scm[toml]" - scikit-build-core - python {{ python }} + - pybind11 run: - python From 79fef3dff44978f7cba516e4add19d4987e66762 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Mon, 20 Nov 2023 21:48:00 -0500 Subject: [PATCH 31/61] add git tag to meta.yml --- conda.recipe/meta.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index 1a4a4eec6..a42b3ed0b 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -1,9 +1,9 @@ -{% set data = load_setup_py_data(setup_file='../setup.py', from_recipe_dir=True) %} -{% set version = data.get('version') %} +# {% set data = load_setup_py_data(setup_file='../setup.py', from_recipe_dir=True) %} +# {% set version = data.get('version') %} package: name: simsopt - version: {{ version }} + version: {{ GIT_DESCRIBE_TAG }}+{{ GIT_BUILD_STR }} source: path: .. From be7ac34fc2d95315f75f5957121c98d367751b93 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Tue, 21 Nov 2023 00:11:07 -0500 Subject: [PATCH 32/61] Bug fixes in conda recipe --- conda.recipe/meta.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index a42b3ed0b..8fbbed465 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -1,6 +1,3 @@ -# {% set data = load_setup_py_data(setup_file='../setup.py', from_recipe_dir=True) %} -# {% set version = data.get('version') %} - package: name: simsopt version: {{ GIT_DESCRIBE_TAG }}+{{ GIT_BUILD_STR }} @@ -52,13 +49,11 @@ requirements: - pyevtk about: - home: {{ data.get('url') }} summary: simplified framework for stellarator optimization license: MIT license_file: "LICENSE" description: doc_url: https://simsopt.readthedocs.io/ - dev_url: {{ data.get('url') }} extra: recipe-maintainers: From d0a62d5ae945622293fbf8e2701790b9f542e3b3 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Tue, 21 Nov 2023 08:36:57 -0500 Subject: [PATCH 33/61] Change python 3.10 patch version in workflows --- .coveragerc | 2 +- .github/workflows/extensive_ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.coveragerc b/.coveragerc index 503c19b88..3fb72cf98 100644 --- a/.coveragerc +++ b/.coveragerc @@ -6,4 +6,4 @@ source = simsopt sources = /opt/hostedtoolcache/Python/3.8.17/x64/lib/python3.8/site-packages /opt/hostedtoolcache/Python/3.9.17/x64/lib/python3.9/site-packages - /opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages + /opt/hostedtoolcache/Python/3.10.13/x64/lib/python3.10/site-packages diff --git a/.github/workflows/extensive_ci.yml b/.github/workflows/extensive_ci.yml index 9584bd807..5d9614210 100644 --- a/.github/workflows/extensive_ci.yml +++ b/.github/workflows/extensive_ci.yml @@ -29,7 +29,7 @@ jobs: matrix: test-type: [unit, integrated] packages: [all, vmec, spec, none] - python-version: [3.8.17, 3.9.17, 3.10.12] # To sync with coveragerc use 3 levels with python version + python-version: [3.8.17, 3.9.17, 3.10.13] # To sync with coveragerc use 3 levels with python version include: - python-version: 3.9.17 test-type: unit From ec5f6a11a495c8555321a6feaa7edc01ce87c1c9 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Tue, 21 Nov 2023 09:31:09 -0500 Subject: [PATCH 34/61] Update meta.yaml metadata with strings --- conda.recipe/meta.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index 8fbbed465..4abd5a27c 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -49,11 +49,13 @@ requirements: - pyevtk about: + home: https://github.com/hiddenSymmetries/simsopt summary: simplified framework for stellarator optimization license: MIT license_file: "LICENSE" description: doc_url: https://simsopt.readthedocs.io/ + dev_url: https://github.com/hiddenSymmetries/simsopt extra: recipe-maintainers: From 5f4c63cfe5c41dc8ecb132759ef355c1fb436977 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Wed, 22 Nov 2023 08:51:38 -0600 Subject: [PATCH 35/61] Try not installing packages before --- .github/workflows/ci.yml | 4 ++-- pyproject.toml | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a924069d..5cebb4b76 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: - name: Install python dependencies run: | sudo apt-get install graphviz graphviz-dev - pip install wheel numpy scipy f90nml h5py scikit-build cmake qsc sympy pyevtk matplotlib ninja plotly networkx pygraphviz mpi4py py_spec pyoculus h5py + # pip install sympy pyevtk matplotlib plotly networkx pygraphviz mpi4py py_spec pyoculus h5py - name: Install booz_xform run: pip install -v git+https://github.com/hiddenSymmetries/booz_xform @@ -158,7 +158,7 @@ jobs: - name: Install simsopt package # run: env CMAKE_BUILD_TYPE=Debug pip install -v .[MPI,SPEC] - run: pip install -v ".[MPI,SPEC]" + run: pip install -v ".[MPI,SPEC,VIS]" - name: Verify that importing simsopt does not automatically initialize MPI run: ./tests/verify_MPI_not_initialized.py diff --git a/pyproject.toml b/pyproject.toml index ea11be3fb..7090f883a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,26 +52,26 @@ keywords = [ "magnetostatics" ] dependencies = [ - 'numpy>=1.21', - 'jax>=0.2.5', - 'jaxlib>=0.1.56', - 'scipy>=1.5.4', - 'Deprecated>=1.2.10', - 'nptyping>=1.3.0', - 'monty>=2021.6.10', - 'ruamel.yaml', - 'sympy', - 'f90nml', - 'randomgen', - 'pyevtk', - 'matplotlib' + "numpy>=1.21", + "jax>=0.2.5", + "jaxlib>=0.1.56", + "scipy>=1.5.4", + "Deprecated>=1.2.10", + "nptyping>=1.3.0", + "monty>=2021.6.10", + "ruamel.yaml", + "sympy", + "f90nml", + "randomgen", + "pyevtk", + "matplotlib" ] dynamic = ["version"] [project.optional-dependencies] SPEC = ["py_spec>=3.0.1", "pyoculus>=0.1.1", "h5py>=3.1.0"] MPI = ["mpi4py>=3.0.3"] -VIS = ["vtk >= 8.1.2", "PyQt5", "mayavi"] +VIS = ["vtk >= 8.1.2", "PyQt5", "mayavi", "plotly", "networkx"] DOCS = ["sphinx", "sphinx-rtd-theme"] [project.urls] From 0dfe6bb71fb11106eb887d6935343316308bc7ab Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Wed, 22 Nov 2023 10:47:04 -0600 Subject: [PATCH 36/61] Add back pip installation of packages for SPEC --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cebb4b76..9a802bc9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: - name: Install python dependencies run: | sudo apt-get install graphviz graphviz-dev - # pip install sympy pyevtk matplotlib plotly networkx pygraphviz mpi4py py_spec pyoculus h5py + pip install numpy cmake ninja wheel setuptools sympy qsc pyevtk matplotlib plotly networkx pygraphviz mpi4py py_spec pyoculus h5py - name: Install booz_xform run: pip install -v git+https://github.com/hiddenSymmetries/booz_xform From 9de3a7758ce76f5b0f55fce085696c725a6a7ad6 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Wed, 22 Nov 2023 10:58:49 -0600 Subject: [PATCH 37/61] Add back scikit-build for SPEC --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a802bc9b..2b442e54b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: - name: Install python dependencies run: | sudo apt-get install graphviz graphviz-dev - pip install numpy cmake ninja wheel setuptools sympy qsc pyevtk matplotlib plotly networkx pygraphviz mpi4py py_spec pyoculus h5py + pip install numpy cmake scikit-build f90nml ninja wheel setuptools sympy qsc pyevtk matplotlib plotly networkx pygraphviz mpi4py py_spec pyoculus h5py - name: Install booz_xform run: pip install -v git+https://github.com/hiddenSymmetries/booz_xform From b5febae14a8085121d1e1c69ae0f15dac81c716c Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Wed, 22 Nov 2023 13:10:39 -0600 Subject: [PATCH 38/61] Get coverage working --- pyproject.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 7090f883a..2679ce84d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,3 +105,13 @@ extend-exclude = ["thirdparty"] "tests/geo/test_curve.py" = ["F401"] "tests/geo/test_surface.py" = ["F401"] "tests/mhd/test_virtual_casing.py" = ["F841"] + +[tool.coverage.run] +parallel = true +relative_files = true +source = ["simsopt"] + +[tool.coverage.paths] +source = [ + "*/lib*/python*/site-packages/simsopt" +] From 85311563830d564cefb6c225b3075028d3b3d7b6 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Wed, 22 Nov 2023 15:44:12 -0600 Subject: [PATCH 39/61] Get the location of python --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b442e54b..1517219dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,6 +49,11 @@ jobs: set -ex ls -l + - name: Print python location + run: | + set -ex + which python + - name: apt-get stuff needed for libstell and vmec run: | sudo apt-get update From 9b71e9ab06cbbd6145ebc13e47f938820428e22e Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Wed, 22 Nov 2023 17:31:48 -0600 Subject: [PATCH 40/61] Try with 3.10 in the coverage upload section --- .github/workflows/extensive_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/extensive_ci.yml b/.github/workflows/extensive_ci.yml index 5d9614210..7f5b0095a 100644 --- a/.github/workflows/extensive_ci.yml +++ b/.github/workflows/extensive_ci.yml @@ -251,7 +251,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.9.17 + python-version: 3.10.13 - name: Install coverage run: pip install coverage From 6678a9c6452ae4f83b73c01f26dec40960a846e5 Mon Sep 17 00:00:00 2001 From: Alex Wiedman Date: Fri, 24 Nov 2023 13:21:43 -0500 Subject: [PATCH 41/61] removed extraneous transcendental functions --- src/simsoptpp/curveplanarfourier.cpp | 192 ++++++++++++++++++--------- 1 file changed, 132 insertions(+), 60 deletions(-) diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index a3db9e2bf..e5e7fcdc3 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -23,13 +23,19 @@ void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosiphi = 0; + double siniphi = 0; for (int i = 0; i < order+1; ++i) { - data(k, 0) += rc[i] * cos(i*phi) * cos(phi); - data(k, 1) += rc[i] * cos(i*phi) * sin(phi); + cosiphi = cos(i*phi); + data(k, 0) += rc[i] * cosiphi * cosphi; + data(k, 1) += rc[i] * cosiphi * sinphi; } for (int i = 1; i < order+1; ++i) { - data(k, 0) += rs[i-1] * sin(i*phi) * cos(phi); - data(k, 1) += rs[i-1] * sin(i*phi) * sin(phi); + siniphi = sin(i*phi); + data(k, 0) += rs[i-1] * siniphi * cosphi; + data(k, 1) += rs[i-1] * siniphi * sinphi; } } for (int m = 0; m < numquadpoints; ++m) { @@ -56,13 +62,21 @@ void CurvePlanarFourier::gammadash_impl(Array& data) { for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosiphi = 0; + double siniphi = 0; for (int i = 0; i < order+1; ++i) { - data(k, 0) += rc[i] * ( -(i) * sin(i*phi) * cos(phi) - cos(i*phi) * sin(phi)); - data(k, 1) += rc[i] * ( -(i) * sin(i*phi) * sin(phi) + cos(i*phi) * cos(phi)); + cosiphi = cos(i*phi); + siniphi = sin(i*phi); + data(k, 0) += rc[i] * ( -(i) * siniphi * cosphi - cosiphi * sinphi); + data(k, 1) += rc[i] * ( -(i) * siniphi * sinphi + cosiphi * cosphi); } for (int i = 1; i < order+1; ++i) { - data(k, 0) += rs[i-1] * ( (i) * cos(i*phi) * cos(phi) - sin(i*phi) * sin(phi)); - data(k, 1) += rs[i-1] * ( (i) * cos(i*phi) * sin(phi) + sin(i*phi) * cos(phi)); + cosiphi = cos(i*phi); + siniphi = sin(i*phi); + data(k, 0) += rs[i-1] * ( (i) * cosiphi * cosphi - siniphi * sinphi); + data(k, 1) += rs[i-1] * ( (i) * cosiphi * sinphi + siniphi * cosphi); } } @@ -92,13 +106,21 @@ void CurvePlanarFourier::gammadashdash_impl(Array& data) { for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosiphi = 0; + double siniphi = 0; for (int i = 0; i < order+1; ++i) { - data(k, 0) += rc[i] * (+2*(i)*sin(i*phi)*sin(phi)-(i*i+1)*cos(i*phi)*cos(phi)); - data(k, 1) += rc[i] * (-2*(i)*sin(i*phi)*cos(phi)-(i*i+1)*cos(i*phi)*sin(phi)); + cosiphi = cos(i*phi); + siniphi = sin(i*phi); + data(k, 0) += rc[i] * (+2*(i)*siniphi*sinphi-(i*i+1)*cosiphi*cosphi); + data(k, 1) += rc[i] * (-2*(i)*siniphi*cosphi-(i*i+1)*cosiphi*sinphi); } for (int i = 1; i < order+1; ++i) { - data(k, 0) += rs[i-1] * (-(i*i+1)*sin(i*phi)*cos(phi) - 2*(i)*cos(i*phi)*sin(phi)); - data(k, 1) += rs[i-1] * (-(i*i+1)*sin(i*phi)*sin(phi) + 2*(i)*cos(i*phi)*cos(phi)); + cosiphi = cos(i*phi); + siniphi = sin(i*phi); + data(k, 0) += rs[i-1] * (-(i*i+1)*siniphi*cosphi - 2*(i)*cosiphi*sinphi); + data(k, 1) += rs[i-1] * (-(i*i+1)*siniphi*sinphi + 2*(i)*cosiphi*cosphi); } } data *= 2*M_PI*2*M_PI; @@ -127,24 +149,33 @@ void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosiphi = 0; + double siniphi = 0; + for (int i = 0; i < order+1; ++i) { + cosiphi = cos(i*phi); + siniphi = sin(i*phi); data(k, 0) += rc[i]*( - +(3*i*i + 1)*cos(i*phi)*sin(phi) - +(i*i + 3)*(i)*sin(i*phi)*cos(phi) + +(3*i*i + 1)*cosiphi*sinphi + +(i*i + 3)*(i)*siniphi*cosphi ); data(k, 1) += rc[i]*( - +(i*i + 3)*(i)*sin(i*phi)*sin(phi) - -(3*i*i + 1)*cos(i*phi)*cos(phi) + +(i*i + 3)*(i)*siniphi*sinphi + -(3*i*i + 1)*cosiphi*cosphi ); } for (int i = 1; i < order+1; ++i) { + cosiphi = cos(i*phi); + siniphi = sin(i*phi); data(k, 0) += rs[i-1]*( - -(i*i+3) * (i) * cos(i*phi)*cos(phi) - +(3*i*i+1) * sin(i*phi)*sin(phi) + -(i*i+3) * (i) * cosiphi*cosphi + +(3*i*i+1) * siniphi*sinphi ); data(k, 1) += rs[i-1]*( - -(i*i+3)*(i)*cos(i*phi)*sin(phi) - -(3*i*i+1)*sin(i*phi)*cos(phi) + -(i*i+3)*(i)*cosiphi*sinphi + -(3*i*i+1)*siniphi*cosphi ); } } @@ -179,9 +210,14 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { double j; double k; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosnphi = 0; + double sinnphi = 0; + for (int n = 0; n < order+1; ++n) { - i = cos(n*phi) * cos(phi); - j = cos(n*phi) * sin(phi); + i = cos(n*phi) * cosphi; + j = cos(n*phi) * sinphi; k = 0; data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); @@ -192,8 +228,8 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { } for (int n = 1; n < order+1; ++n) { - i = sin(n*phi) * cos(phi); - j = sin(n*phi) * sin(phi); + i = sin(n*phi) * cosphi; + j = sin(n*phi) * sinphi; k = 0; data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); @@ -208,12 +244,12 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { k = 0; for (int n = 0; n < order+1; ++n) { - i += rc[n] * cos(n*phi) * cos(phi); - j += rc[n] * cos(n*phi) * sin(phi); + i += rc[n] * cos(n*phi) * cosphi; + j += rc[n] * cos(n*phi) * sinphi; } for (int n = 1; n < order+1; ++n) { - i += rs[n-1] * sin(n*phi) * cos(phi); - j += rs[n-1] * sin(n*phi) * sin(phi); + i += rs[n-1] * sin(n*phi) * cosphi; + j += rs[n-1] * sin(n*phi) * sinphi; } double inv_sqrt_s = inv_magnitude(); @@ -513,13 +549,19 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosnphi = 0; + double sinnphi = 0; int counter = 0; double i; double j; double k; for (int n = 0; n < order+1; ++n) { - i = ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)); - j = ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)); + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i = ( -(n) * sinnphi * cosphi - cosnphi * sinphi); + j = ( -(n) * sinnphi * sinphi + cosnphi * cosphi); k = 0; i *= (2*M_PI); @@ -534,8 +576,10 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { } for (int n = 1; n < order+1; ++n) { - i = ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)); - j = ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)); + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i = ( (n) * cosnphi * cosphi - sinnphi * sinphi); + j = ( (n) * cosnphi * sinphi + sinnphi * cosphi); k = 0; i *= (2*M_PI); @@ -553,12 +597,16 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { j = 0; k = 0; for (int n = 0; n < order+1; ++n) { - i += rc[n] * ( -(n) * sin(n*phi) * cos(phi) - cos(n*phi) * sin(phi)) * 2 * M_PI; - j += rc[n] * ( -(n) * sin(n*phi) * sin(phi) + cos(n*phi) * cos(phi)) * 2 * M_PI; + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i += rc[n] * ( -(n) * sinnphi * cosphi - cosnphi * sinphi) * 2 * M_PI; + j += rc[n] * ( -(n) * sinnphi * sinphi + cosnphi * cosphi) * 2 * M_PI; } for (int n = 1; n < order+1; ++n) { - i += rs[n-1] * ( (n) * cos(n*phi) * cos(phi) - sin(n*phi) * sin(phi)) * 2 * M_PI; - j += rs[n-1] * ( (n) * cos(n*phi) * sin(phi) + sin(n*phi) * cos(phi)) * 2 * M_PI; + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i += rs[n-1] * ( (n) * cosnphi * cosphi - sinnphi * sinphi) * 2 * M_PI; + j += rs[n-1] * ( (n) * cosnphi * sinphi + sinnphi * cosphi) * 2 * M_PI; } double inv_sqrt_s = inv_magnitude(); @@ -857,13 +905,19 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosnphi = 0; + double sinnphi = 0; int counter = 0; double i; double j; double k; for (int n = 0; n < order+1; ++n) { - i = (+2*(n)*sin(n*phi)*sin(phi)-(n*n+1)*cos(n*phi)*cos(phi)); - j = (-2*(n)*sin(n*phi)*cos(phi)-(n*n+1)*cos(n*phi)*sin(phi)); + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i = (+2*(n)*sinnphi*sinphi-(n*n+1)*cosnphi*cosphi); + j = (-2*(n)*sinnphi*cosphi-(n*n+1)*cosnphi*sinphi); k = 0; i *= 2*M_PI*2*M_PI; @@ -878,8 +932,10 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { } for (int n = 1; n < order+1; ++n) { - i = (-(n*n+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); - j = (-(n*n+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i = (-(n*n+1)*sinnphi*cosphi - 2*(n)*cosnphi*sinphi); + j = (-(n*n+1)*sinnphi*sinphi + 2*(n)*cosnphi*cosphi); k = 0; i *= 2*M_PI*2*M_PI; @@ -897,12 +953,16 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { j = 0; k = 0; for (int n = 0; n < order+1; ++n) { - i += rc[n] * (+2*(n)*sin(n*phi)*sin(phi)-(n*n+1)*cos(n*phi)*cos(phi)); - j += rc[n] * (-2*(n)*sin(n*phi)*cos(phi)-(n*n+1)*cos(n*phi)*sin(phi)); + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i += rc[n] * (+2*(n)*sinnphi*sinphi-(n*n+1)*cosnphi*cosphi); + j += rc[n] * (-2*(n)*sinnphi*cosphi-(n*n+1)*cosnphi*sinphi); } for (int n = 1; n < order+1; ++n) { - i += rs[n-1] * (-(n*n+1)*sin(n*phi)*cos(phi) - 2*(n)*cos(n*phi)*sin(phi)); - j += rs[n-1] * (-(n*n+1)*sin(n*phi)*sin(phi) + 2*(n)*cos(n*phi)*cos(phi)); + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); + i += rs[n-1] * (-(n*n+1)*sinnphi*cosphi - 2*(n)*cosnphi*sinphi); + j += rs[n-1] * (-(n*n+1)*sinnphi*sinphi + 2*(n)*cosnphi*cosphi); } i *= 2*M_PI*2*M_PI; j *= 2*M_PI*2*M_PI; @@ -1203,18 +1263,24 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; + double cosphi = cos(phi); + double sinphi = sin(phi); + double cosnphi = 0; + double sinnphi = 0; int counter = 0; double i; double j; double k; for (int n = 0; n < order+1; ++n) { + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); i = ( - +(3*n*n + 1)*cos(n*phi)*sin(phi) - +(n*n + 3)*(n)*sin(n*phi)*cos(phi) + +(3*n*n + 1)*cosnphi*sinphi + +(n*n + 3)*(n)*sinnphi*cosphi ); j = ( - +(n*n + 3)*(n)*sin(n*phi)*sin(phi) - -(3*n*n + 1)*cos(n*phi)*cos(phi) + +(n*n + 3)*(n)*sinnphi*sinphi + -(3*n*n + 1)*cosnphi*cosphi ); k = 0; @@ -1230,13 +1296,15 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { } for (int n = 1; n < order+1; ++n) { + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); i = ( - -(n*n+3) * (n) * cos(n*phi)*cos(phi) - +(3*n*n+1) * sin(n*phi)*sin(phi) + -(n*n+3) * (n) * cosnphi*cosphi + +(3*n*n+1) * sinnphi*sinphi ); j = ( - -(n*n+3)*(n)*cos(n*phi)*sin(phi) - -(3*n*n+1)*sin(n*phi)*cos(phi) + -(n*n+3)*(n)*cosnphi*sinphi + -(3*n*n+1)*sinnphi*cosphi ); k = 0; @@ -1255,23 +1323,27 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { j = 0; k = 0; for (int n = 0; n < order+1; ++n) { + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); i += rc[n]*( - +(3*n*n + 1)*cos(n*phi)*sin(phi) - +(n*n + 3)*(n)*sin(n*phi)*cos(phi) + +(3*n*n + 1)*cosnphi*sinphi + +(n*n + 3)*(n)*sinnphi*cosphi ); j += rc[n]*( - +(n*n + 3)*(n)*sin(n*phi)*sin(phi) - -(3*n*n + 1)*cos(n*phi)*cos(phi) + +(n*n + 3)*(n)*sinnphi*sinphi + -(3*n*n + 1)*cosnphi*cosphi ); } for (int n = 1; n < order+1; ++n) { + cosnphi = cos(n*phi); + sinnphi = sin(n*phi); i += rs[n-1]*( - -(n*n+3) * (n) * cos(n*phi)*cos(phi) - +(3*n*n+1) * sin(n*phi)*sin(phi) + -(n*n+3) * (n) * cosnphi*cosphi + +(3*n*n+1) * sinnphi*sinphi ); j += rs[n-1]*( - -(n*n+3)*(n)*cos(n*phi)*sin(phi) - -(3*n*n+1)*sin(n*phi)*cos(phi) + -(n*n+3)*(n)*cosnphi*sinphi + -(3*n*n+1)*sinnphi*cosphi ); } i *= 2*M_PI*2*M_PI*2*M_PI; From 1cfc787aeeb1f1e444c7782f98c7ee60240323b4 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 10:18:51 -0500 Subject: [PATCH 42/61] Test without 3.10 in coverage --- .coveragerc | 1 - .github/workflows/extensive_ci.yml | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.coveragerc b/.coveragerc index 3fb72cf98..e7be127fe 100644 --- a/.coveragerc +++ b/.coveragerc @@ -6,4 +6,3 @@ source = simsopt sources = /opt/hostedtoolcache/Python/3.8.17/x64/lib/python3.8/site-packages /opt/hostedtoolcache/Python/3.9.17/x64/lib/python3.9/site-packages - /opt/hostedtoolcache/Python/3.10.13/x64/lib/python3.10/site-packages diff --git a/.github/workflows/extensive_ci.yml b/.github/workflows/extensive_ci.yml index 7f5b0095a..fe220e9d2 100644 --- a/.github/workflows/extensive_ci.yml +++ b/.github/workflows/extensive_ci.yml @@ -29,7 +29,7 @@ jobs: matrix: test-type: [unit, integrated] packages: [all, vmec, spec, none] - python-version: [3.8.17, 3.9.17, 3.10.13] # To sync with coveragerc use 3 levels with python version + python-version: [3.8.17, 3.9.17] # , 3.10.13] # To sync with coveragerc use 3 levels with python version include: - python-version: 3.9.17 test-type: unit @@ -251,7 +251,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.10.13 + python-version: 3.9.17 - name: Install coverage run: pip install coverage From ab72b08a5036a3e1e03eb7604ccab6b85ffb8e52 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 11:04:56 -0500 Subject: [PATCH 43/61] New coveragerc to fix the issue in runner --- .coveragerc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.coveragerc b/.coveragerc index e7be127fe..2f74e1948 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,8 +1,12 @@ [run] parallel = true source = simsopt +relative_files = true [paths] sources = - /opt/hostedtoolcache/Python/3.8.17/x64/lib/python3.8/site-packages - /opt/hostedtoolcache/Python/3.9.17/x64/lib/python3.9/site-packages + src/ + /**/lib/python3.8/site-packages + /**/lib/python3.9/site-packages + /**/lib/python3.10/site-packages + /**/lib/python3.11/site-packages From 924ad7d9c4e206f871a995963be6ba554326f25b Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 12:27:59 -0500 Subject: [PATCH 44/61] Add back python 3.10 to extensive ci --- .github/workflows/extensive_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/extensive_ci.yml b/.github/workflows/extensive_ci.yml index fe220e9d2..5d9614210 100644 --- a/.github/workflows/extensive_ci.yml +++ b/.github/workflows/extensive_ci.yml @@ -29,7 +29,7 @@ jobs: matrix: test-type: [unit, integrated] packages: [all, vmec, spec, none] - python-version: [3.8.17, 3.9.17] # , 3.10.13] # To sync with coveragerc use 3 levels with python version + python-version: [3.8.17, 3.9.17, 3.10.13] # To sync with coveragerc use 3 levels with python version include: - python-version: 3.9.17 test-type: unit From 97a12f7e50f0fb3d3306be7e7364805abb3b82a5 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 12:29:06 -0500 Subject: [PATCH 45/61] Rename CI to tests to better reflect the workflow --- .github/workflows/{extensive_ci.yml => extensive_test.yml} | 0 .github/workflows/{ci.yml => tests.yml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{extensive_ci.yml => extensive_test.yml} (100%) rename .github/workflows/{ci.yml => tests.yml} (100%) diff --git a/.github/workflows/extensive_ci.yml b/.github/workflows/extensive_test.yml similarity index 100% rename from .github/workflows/extensive_ci.yml rename to .github/workflows/extensive_test.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/tests.yml similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/tests.yml From c214133e9a35d2ac11b2555ea5cbf753bf056c2d Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 12:42:45 -0500 Subject: [PATCH 46/61] Shift coverage defs to pyproject.toml --- .coveragerc | 12 ------------ pyproject.toml | 3 ++- 2 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 2f74e1948..000000000 --- a/.coveragerc +++ /dev/null @@ -1,12 +0,0 @@ -[run] -parallel = true -source = simsopt -relative_files = true - -[paths] -sources = - src/ - /**/lib/python3.8/site-packages - /**/lib/python3.9/site-packages - /**/lib/python3.10/site-packages - /**/lib/python3.11/site-packages diff --git a/pyproject.toml b/pyproject.toml index 2679ce84d..13f0e9298 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -113,5 +113,6 @@ source = ["simsopt"] [tool.coverage.paths] source = [ - "*/lib*/python*/site-packages/simsopt" + "src", + "/**/lib*/python*/site-packages" ] From f50633d17c9fe6578a0730e43f05e315e0081e76 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 12:47:43 -0500 Subject: [PATCH 47/61] Remove level 3 in python version specification --- .github/workflows/extensive_test.yml | 8 ++++---- .github/workflows/non_simd_tests.yml | 2 +- .github/workflows/tests.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/extensive_test.yml b/.github/workflows/extensive_test.yml index 5d9614210..b0e19fd31 100644 --- a/.github/workflows/extensive_test.yml +++ b/.github/workflows/extensive_test.yml @@ -29,12 +29,12 @@ jobs: matrix: test-type: [unit, integrated] packages: [all, vmec, spec, none] - python-version: [3.8.17, 3.9.17, 3.10.13] # To sync with coveragerc use 3 levels with python version + python-version: [3.8, 3.9, 3.10] include: - - python-version: 3.9.17 + - python-version: 3.9 test-type: unit packages: none - - python-version: 3.9.17 + - python-version: 3.9 test-type: integrated packages: none @@ -251,7 +251,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.9.17 + python-version: 3.9 - name: Install coverage run: pip install coverage diff --git a/.github/workflows/non_simd_tests.yml b/.github/workflows/non_simd_tests.yml index 961878a73..946a91db5 100644 --- a/.github/workflows/non_simd_tests.yml +++ b/.github/workflows/non_simd_tests.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.9.17] # To sync with coveragerc use 3 level + python-version: [3.9] steps: # First print out lots of information. We do this in separate diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1517219dd..ebff4fa57 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.9.17] # To sync with coveragerc use 3 level + python-version: [3.9] test-type: [unit, integrated] steps: From a735697b5c12f1b8cc4c444a87e30631c691c13e Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 15:09:48 -0500 Subject: [PATCH 48/61] Add strings surrounding 3.10 --- .github/workflows/extensive_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/extensive_test.yml b/.github/workflows/extensive_test.yml index b0e19fd31..43183f13f 100644 --- a/.github/workflows/extensive_test.yml +++ b/.github/workflows/extensive_test.yml @@ -29,7 +29,7 @@ jobs: matrix: test-type: [unit, integrated] packages: [all, vmec, spec, none] - python-version: [3.8, 3.9, 3.10] + python-version: [3.8, 3.9, "3.10"] include: - python-version: 3.9 test-type: unit From aa8a6c8b5ad73c9ae2f9272e3bc962f02c7d6a00 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Sun, 26 Nov 2023 20:37:27 -0500 Subject: [PATCH 49/61] Bring back coveragerc file --- .coveragerc | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 000000000..2f74e1948 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,12 @@ +[run] +parallel = true +source = simsopt +relative_files = true + +[paths] +sources = + src/ + /**/lib/python3.8/site-packages + /**/lib/python3.9/site-packages + /**/lib/python3.10/site-packages + /**/lib/python3.11/site-packages From 60cb677420b9b2ac2456e0eb11522921f31ce6ff Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Mon, 27 Nov 2023 10:05:25 -0500 Subject: [PATCH 50/61] curveplanarfourier.cpp: Reduced number of calls to trig functions --- src/simsoptpp/curveplanarfourier.cpp | 157 +++++++++++---------------- 1 file changed, 64 insertions(+), 93 deletions(-) diff --git a/src/simsoptpp/curveplanarfourier.cpp b/src/simsoptpp/curveplanarfourier.cpp index fc778247b..9e11bc3e8 100644 --- a/src/simsoptpp/curveplanarfourier.cpp +++ b/src/simsoptpp/curveplanarfourier.cpp @@ -24,17 +24,13 @@ void CurvePlanarFourier::gamma_impl(Array& data, Array& quadpoints) { double phi = 2 * M_PI * quadpoints[k]; double cosphi = cos(phi); double sinphi = sin(phi); - double cosiphi = 0; - double siniphi = 0; - for (int i = 0; i < order+1; ++i) { - cosiphi = cos(i*phi); - data(k, 0) += rc[i] * cosiphi * cosphi; - data(k, 1) += rc[i] * cosiphi * sinphi; - } + data(k, 0) = rc[0] * cosphi; + data(k, 1) = rc[0] * sinphi; for (int i = 1; i < order+1; ++i) { + cosiphi = cos(i*phi); siniphi = sin(i*phi); - data(k, 0) += rs[i-1] * siniphi * cosphi; - data(k, 1) += rs[i-1] * siniphi * sinphi; + data(k, 0) += (rc[i] * cosiphi + rs[i-1] * siniphi) * cosphi; + data(k, 1) += (rc[i] * cosiphi + rs[i-1] * siniphi) * sinphi; } } for (int m = 0; m < numquadpoints; ++m) { @@ -56,23 +52,20 @@ void CurvePlanarFourier::gammadash_impl(Array& data) { double inv_sqrt_s = inv_magnitude(); Array q_norm = q * inv_sqrt_s; + double cosiphi, siniphi; for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; double cosphi = cos(phi); double sinphi = sin(phi); - double cosiphi = 0; - double siniphi = 0; - for (int i = 0; i < order+1; ++i) { - cosiphi = cos(i*phi); - siniphi = sin(i*phi); - data(k, 0) += rc[i] * ( -(i) * siniphi * cosphi - cosiphi * sinphi); - data(k, 1) += rc[i] * ( -(i) * siniphi * sinphi + cosiphi * cosphi); - } + data(k, 0) = rc[0] * (-sinphi); + data(k, 1) = rc[0] * (cosphi); for (int i = 1; i < order+1; ++i) { cosiphi = cos(i*phi); siniphi = sin(i*phi); - data(k, 0) += rs[i-1] * ( (i) * cosiphi * cosphi - siniphi * sinphi); - data(k, 1) += rs[i-1] * ( (i) * cosiphi * sinphi + siniphi * cosphi); + data(k, 0) += rc[i] * ( -(i) * siniphi * cosphi - cosiphi * sinphi) + + rs[i-1] * ( (i) * cosiphi * cosphi - siniphi * sinphi); + data(k, 1) += rc[i] * ( -(i) * siniphi * sinphi + cosiphi * cosphi) + + rs[i-1] * ( (i) * cosiphi * sinphi + siniphi * cosphi); } } @@ -96,23 +89,20 @@ void CurvePlanarFourier::gammadashdash_impl(Array& data) { Array q_norm = q * inv_magnitude(); + double cosiphi, siniphi; for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; double cosphi = cos(phi); double sinphi = sin(phi); - double cosiphi = 0; - double siniphi = 0; - for (int i = 0; i < order+1; ++i) { - cosiphi = cos(i*phi); - siniphi = sin(i*phi); - data(k, 0) += rc[i] * (+2*(i)*siniphi*sinphi-(i*i+1)*cosiphi*cosphi); - data(k, 1) += rc[i] * (-2*(i)*siniphi*cosphi-(i*i+1)*cosiphi*sinphi); - } + data(k, 0) = rc[0] * (-cosphi); + data(k, 1) = rc[0] * (-sinphi); for (int i = 1; i < order+1; ++i) { cosiphi = cos(i*phi); siniphi = sin(i*phi); - data(k, 0) += rs[i-1] * (-(i*i+1)*siniphi*cosphi - 2*(i)*cosiphi*sinphi); - data(k, 1) += rs[i-1] * (-(i*i+1)*siniphi*sinphi + 2*(i)*cosiphi*cosphi); + data(k, 0) += rc[i] * (+2*(i)*siniphi*sinphi-(i*i+1)*cosiphi*cosphi) + + rs[i-1] * (-(i*i+1)*siniphi*cosphi - 2*(i)*cosiphi*sinphi); + data(k, 1) += rc[i] * (-2*(i)*siniphi*cosphi-(i*i+1)*cosiphi*sinphi) + + rs[i-1] * (-(i*i+1)*siniphi*sinphi + 2*(i)*cosiphi*cosphi); } } data *= 2*M_PI*2*M_PI; @@ -135,33 +125,28 @@ void CurvePlanarFourier::gammadashdashdash_impl(Array& data) { Array q_norm = q * inv_magnitude(); + double cosiphi, siniphi; for (int k = 0; k < numquadpoints; ++k) { double phi = 2 * M_PI * quadpoints[k]; double cosphi = cos(phi); double sinphi = sin(phi); - double cosiphi = 0; - double siniphi = 0; - for (int i = 0; i < order+1; ++i) { + data(k, 0) = rc[0]*(+sinphi); + data(k, 1) = rc[0]*(-cosphi); + for (int i = 1; i < order+1; ++i) { cosiphi = cos(i*phi); siniphi = sin(i*phi); data(k, 0) += rc[i]*( +(3*i*i + 1)*cosiphi*sinphi +(i*i + 3)*(i)*siniphi*cosphi + ) + rs[i-1]*( + -(i*i+3) * (i) * cosiphi*cosphi + +(3*i*i+1) * siniphi*sinphi ); data(k, 1) += rc[i]*( +(i*i + 3)*(i)*siniphi*sinphi -(3*i*i + 1)*cosiphi*cosphi - ); - } - for (int i = 1; i < order+1; ++i) { - cosiphi = cos(i*phi); - siniphi = sin(i*phi); - data(k, 0) += rs[i-1]*( - -(i*i+3) * (i) * cosiphi*cosphi - +(3*i*i+1) * siniphi*sinphi - ); - data(k, 1) += rs[i-1]*( + ) + rs[i-1]*( -(i*i+3)*(i)*cosiphi*sinphi -(3*i*i+1)*siniphi*cosphi ); @@ -187,6 +172,7 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { Array q_norm = q * inv_magnitude(); + double cosnphi, sinnphi; for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; int counter = 0; @@ -200,8 +186,9 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { double sinnphi = 0; for (int n = 0; n < order+1; ++n) { - i = cos(n*phi) * cosphi; - j = cos(n*phi) * sinphi; + cosnphi = cos(n * phi); + i = cosnphi * cosphi; + j = cosnphi * sinphi; k = 0; data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); @@ -212,8 +199,9 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { } for (int n = 1; n < order+1; ++n) { - i = sin(n*phi) * cosphi; - j = sin(n*phi) * sinphi; + sinnphi = sin(n * phi); + i = sinnphi * cosphi; + j = sinnphi * sinphi; k = 0; data(m, 0, counter) = (i - 2 * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * i + 2 * (q_norm[1] * q_norm[2] - q_norm[3] * q_norm[0]) * j + 2 * (q_norm[1] * q_norm[3] + q_norm[2] * q_norm[0]) * k); @@ -223,17 +211,15 @@ void CurvePlanarFourier::dgamma_by_dcoeff_impl(Array& data) { counter++; } - i = 0; - j = 0; + i = rc[0] * cosphi; + j = rc[0] * sinphi; k = 0; - for (int n = 0; n < order+1; ++n) { - i += rc[n] * cos(n*phi) * cosphi; - j += rc[n] * cos(n*phi) * sinphi; - } for (int n = 1; n < order+1; ++n) { - i += rs[n-1] * sin(n*phi) * cosphi; - j += rs[n-1] * sin(n*phi) * sinphi; + cosnphi = cos(n * phi); + sinnphi = sin(n * phi); + i += (rc[n] * cosnphi + rs[n-1] * sinnphi) * cosphi; + j += (rc[n] * cosnphi + rs[n-1] * sinnphi) * sinphi; } double inv_sqrt_s = inv_magnitude(); @@ -530,12 +516,11 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { Array q_norm = q * inv_magnitude(); + double cosnphi, sinnphi; for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; double cosphi = cos(phi); double sinphi = sin(phi); - double cosnphi = 0; - double sinnphi = 0; int counter = 0; double i; double j; @@ -576,21 +561,19 @@ void CurvePlanarFourier::dgammadash_by_dcoeff_impl(Array& data) { } - i = 0; - j = 0; + i = rc[0] * (-sinphi); + j = rc[0] * (cosphi); k = 0; - for (int n = 0; n < order+1; ++n) { - cosnphi = cos(n*phi); - sinnphi = sin(n*phi); - i += rc[n] * ( -(n) * sinnphi * cosphi - cosnphi * sinphi) * 2 * M_PI; - j += rc[n] * ( -(n) * sinnphi * sinphi + cosnphi * cosphi) * 2 * M_PI; - } for (int n = 1; n < order+1; ++n) { cosnphi = cos(n*phi); sinnphi = sin(n*phi); - i += rs[n-1] * ( (n) * cosnphi * cosphi - sinnphi * sinphi) * 2 * M_PI; - j += rs[n-1] * ( (n) * cosnphi * sinphi + sinnphi * cosphi) * 2 * M_PI; + i += rc[n] * ( -(n) * sinnphi * cosphi - cosnphi * sinphi) + + rs[n-1] * ( (n) * cosnphi * cosphi - sinnphi * sinphi); + j += rc[n] * ( -(n) * sinnphi * sinphi + cosnphi * cosphi) + + rs[n-1] * ( (n) * cosnphi * sinphi + sinnphi * cosphi); } + i *= (2*M_PI); + j *= (2*M_PI); double inv_sqrt_s = inv_magnitude(); data(m, 0, counter) = (4 * i * (q_norm[2] * q_norm[2] + q_norm[3] * q_norm[3]) * q_norm[0] @@ -886,12 +869,11 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { Array q_norm = q * inv_magnitude(); + double cosnphi, sinnphi; for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; double cosphi = cos(phi); double sinphi = sin(phi); - double cosnphi = 0; - double sinnphi = 0; int counter = 0; double i; double j; @@ -932,20 +914,16 @@ void CurvePlanarFourier::dgammadashdash_by_dcoeff_impl(Array& data) { counter++; } - i = 0; - j = 0; + i = rc[0] * (-cosphi); + j = rc[0] * (-sinphi); k = 0; - for (int n = 0; n < order+1; ++n) { - cosnphi = cos(n*phi); - sinnphi = sin(n*phi); - i += rc[n] * (+2*(n)*sinnphi*sinphi-(n*n+1)*cosnphi*cosphi); - j += rc[n] * (-2*(n)*sinnphi*cosphi-(n*n+1)*cosnphi*sinphi); - } for (int n = 1; n < order+1; ++n) { cosnphi = cos(n*phi); sinnphi = sin(n*phi); - i += rs[n-1] * (-(n*n+1)*sinnphi*cosphi - 2*(n)*cosnphi*sinphi); - j += rs[n-1] * (-(n*n+1)*sinnphi*sinphi + 2*(n)*cosnphi*cosphi); + i += rc[n] * (+2*(n)*sinnphi*sinphi-(n*n+1)*cosnphi*cosphi) + + rs[n-1] * (-(n*n+1)*sinnphi*cosphi - 2*(n)*cosnphi*sinphi); + j += rc[n] * (-2*(n)*sinnphi*cosphi-(n*n+1)*cosnphi*sinphi) + + rs[n-1] * (-(n*n+1)*sinnphi*sinphi + 2*(n)*cosnphi*cosphi); } i *= 2*M_PI*2*M_PI; j *= 2*M_PI*2*M_PI; @@ -1244,12 +1222,11 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { Array q_norm = q * inv_magnitude(); + double cosnphi, sinnphi; for (int m = 0; m < numquadpoints; ++m) { double phi = 2 * M_PI * quadpoints[m]; double cosphi = cos(phi); double sinphi = sin(phi); - double cosnphi = 0; - double sinnphi = 0; int counter = 0; double i; double j; @@ -1302,29 +1279,23 @@ void CurvePlanarFourier::dgammadashdashdash_by_dcoeff_impl(Array& data) { counter++; } - i = 0; - j = 0; + i = rc[0]*(sinphi); + j = rc[0]*(-cosphi); k = 0; - for (int n = 0; n < order+1; ++n) { + for (int n = 1; n < order+1; ++n) { cosnphi = cos(n*phi); sinnphi = sin(n*phi); i += rc[n]*( +(3*n*n + 1)*cosnphi*sinphi +(n*n + 3)*(n)*sinnphi*cosphi + ) + rs[n-1]*( + -(n*n+3) * (n) * cosnphi*cosphi + +(3*n*n+1) * sinnphi*sinphi ); j += rc[n]*( +(n*n + 3)*(n)*sinnphi*sinphi -(3*n*n + 1)*cosnphi*cosphi - ); - } - for (int n = 1; n < order+1; ++n) { - cosnphi = cos(n*phi); - sinnphi = sin(n*phi); - i += rs[n-1]*( - -(n*n+3) * (n) * cosnphi*cosphi - +(3*n*n+1) * sinnphi*sinphi - ); - j += rs[n-1]*( + ) + rs[n-1]*( -(n*n+3)*(n)*cosnphi*sinphi -(3*n*n+1)*sinnphi*cosphi ); From 50f41d6b020d09d9a13f179a42752487ef0ed911 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Tue, 28 Nov 2023 08:20:20 -0500 Subject: [PATCH 51/61] remove dirty local from setuptools --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 13f0e9298..14966b351 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ Repository = "https://github.com/hiddenSymmetries/simsopt" [tool.setuptools_scm] write_to = "src/simsopt/_version.py" -local_scheme = "dirty" +# local_scheme = "dirty" [tool.scikit-build] metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" From 39ca311d3fd6b52e749df3f581e48b77f9bcaf88 Mon Sep 17 00:00:00 2001 From: Bharat Medasani Date: Thu, 7 Dec 2023 10:35:37 +1100 Subject: [PATCH 52/61] Update strain_optimization.py Update some parameters in the strain optimization example. Give credit to Paul Huslage --- examples/2_Intermediate/strain_optimization.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/2_Intermediate/strain_optimization.py b/examples/2_Intermediate/strain_optimization.py index cb04ba2b7..5871c9c05 100755 --- a/examples/2_Intermediate/strain_optimization.py +++ b/examples/2_Intermediate/strain_optimization.py @@ -9,12 +9,14 @@ 86 (2020), doi:10.1017/S0022377820001208. The orientation of the tape is defined with respect to the Frenet-Serret Frame + +Authors: Paul Huslage, Elizabeth Paul """ import numpy as np from scipy.optimize import minimize from simsopt.geo import CoilStrain, LPTorsionalStrainPenalty, LPBinormalCurvatureStrainPenalty -from simsopt.geo import FrameRotation, FramedCurveFrenet, CurveXYZFourier +from simsopt.geo import FrameRotation, FramedCurveCentroid, CurveXYZFourier from simsopt.configs import get_hsx_data from simsopt.util import in_github_actions @@ -26,15 +28,15 @@ curve_scaled = CurveXYZFourier(curve.quadpoints, curve.order) curve_scaled.x = curve.x * scale_factor # scale coil to magnify the strains rot_order = 10 # order of the Fourier expression for the rotation of the filament pack -width = 1e-3 # tape width +width = 3e-3 # tape width curve_scaled.fix_all() # fix curve DOFs -> only optimize winding angle rotation = FrameRotation(curve_scaled.quadpoints, rot_order) -framedcurve = FramedCurveFrenet(curve_scaled, rotation) +framedcurve = FramedCurveCentroid(curve_scaled, rotation) -tor_threshold = 0.02 # Threshold for strain parameters -cur_threshold = 0.02 +tor_threshold = 0.002 # Threshold for strain parameters +cur_threshold = 0.002 Jtor = LPTorsionalStrainPenalty(framedcurve, p=2, threshold=tor_threshold) Jbin = LPBinormalCurvatureStrainPenalty( From 05e2beac1d11e04bbd1d5dadebd06da31eb03fed Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Wed, 13 Dec 2023 10:08:49 -0500 Subject: [PATCH 53/61] Initial commit. --- examples/2_Intermediate/tracing_boozer.py | 8 +-- src/simsopt/field/tracing.py | 67 +++++++++++++++-------- src/simsoptpp/python_tracing.cpp | 10 ++-- src/simsoptpp/tracing.h | 46 +++++++++++++--- tests/field/test_particle.py | 16 +++--- 5 files changed, 99 insertions(+), 48 deletions(-) diff --git a/examples/2_Intermediate/tracing_boozer.py b/examples/2_Intermediate/tracing_boozer.py index 36a994f88..0bc614e91 100755 --- a/examples/2_Intermediate/tracing_boozer.py +++ b/examples/2_Intermediate/tracing_boozer.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt from simsopt.field import (BoozerRadialInterpolant, InterpolatedBoozerField, trace_particles_boozer, - MinToroidalFluxStoppingCriterion, MaxToroidalFluxStoppingCriterion, + ToroidalFluxStoppingCriterion, ToroidalTransitStoppingCriterion, compute_resonances) from simsopt.mhd import Vmec from simsopt.util import in_github_actions @@ -75,7 +75,7 @@ gc_tys, gc_zeta_hits = trace_particles_boozer( field, stz_inits, vpar_inits, tmax=1e-2, mass=mass, charge=ELEMENTARY_CHARGE, - Ekin=Ekin, tol=1e-8, mode='gc_vac', stopping_criteria=[MaxToroidalFluxStoppingCriterion(0.99), MinToroidalFluxStoppingCriterion(0.01), ToroidalTransitStoppingCriterion(100, True)], + Ekin=Ekin, tol=1e-8, mode='gc_vac', stopping_criteria=[ToroidalFluxStoppingCriterion(0.99,False), ToroidalFluxStoppingCriterion(0.01,True), ToroidalTransitStoppingCriterion(100, True)], forget_exact_path=False) Nparticles = len(gc_tys) @@ -112,7 +112,7 @@ gc_tys, gc_zeta_hits = trace_particles_boozer( field, stz_inits, vpar_inits, tmax=1e-2, mass=mass, charge=ELEMENTARY_CHARGE, - Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[MinToroidalFluxStoppingCriterion(0.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(30, True)], + Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[ToroidalFluxStoppingCriterion(0.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(30, True)], forget_exact_path=False) resonances = compute_resonances(gc_tys, gc_zeta_hits, ma=None, delta=0.01) @@ -134,7 +134,7 @@ gc_tys, gc_zeta_hits = trace_particles_boozer( field, stz_res, vpar_res, tmax=1e-2, mass=mass, charge=ELEMENTARY_CHARGE, - Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[MinToroidalFluxStoppingCriterion(0.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(30, True)], + Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[ToroidalFluxStoppingCriterion(0.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(30, True)], forget_exact_path=False) if not in_github_actions: diff --git a/src/simsopt/field/tracing.py b/src/simsopt/field/tracing.py index f07947859..8e7fc035d 100644 --- a/src/simsopt/field/tracing.py +++ b/src/simsopt/field/tracing.py @@ -738,66 +738,87 @@ def __init__(self, classifier): else: sopp.LevelsetStoppingCriterion.__init__(self, classifier) - -class MinToroidalFluxStoppingCriterion(sopp.MinToroidalFluxStoppingCriterion): +class ToroidalFluxStoppingCriterion(sopp.ToroidalFluxStoppingCriterion): """ - Stop the iteration once a particle falls below a critical value of + Stop the iteration once a particle falls above or below a critical value of ``s``, the normalized toroidal flux. This :class:`StoppingCriterion` is - important to use when tracing particles in flux coordinates, as the poloidal - angle becomes ill-defined at the magnetic axis. This should only be used - when tracing trajectories in a flux coordinate system (i.e., :class:`trace_particles_boozer`). + important to use when tracing particles in flux coordinates. For example, + the poloidal angle becomes ill-defined at the magnetic axis. This should + only be used when tracing trajectories in a flux coordinate system (i.e., + :class:`trace_particles_boozer`). Usage: .. code-block:: - stopping_criteria=[MinToroidalFluxStopingCriterion(s)] + stopping_criteria=[ToroidalFluxStopingCriterion(crit_s,min_bool)] - where ``s`` is the value of the minimum normalized toroidal flux. + where ``crit_s`` is the value of the critical normalized toroidal flux and + ``min_bool'' is a boolean indicating whether to stop when + ``s'' is less than the critical value (``true'') or + greater than the critical value (``false''). """ pass -class MaxToroidalFluxStoppingCriterion(sopp.MaxToroidalFluxStoppingCriterion): +class ToroidalTransitStoppingCriterion(sopp.ToroidalTransitStoppingCriterion): """ - Stop the iteration once a particle falls above a critical value of - ``s``, the normalized toroidal flux. This should only be used when tracing - trajectories in a flux coordinate system (i.e., :class:`trace_particles_boozer`). + Stop the iteration once the maximum number of toroidal transits is reached. Usage: .. code-block:: - stopping_criteria=[MaxToroidalFluxStopingCriterion(s)] + stopping_criteria=[ToroidalTransitStoppingCriterion(ntransits,flux)] - where ``s`` is the value of the maximum normalized toroidal flux. + where ``ntransits`` is the maximum number of toroidal transits and ``flux`` + is a boolean indicating whether tracing is being performed in a flux coordinate system. """ pass -class ToroidalTransitStoppingCriterion(sopp.ToroidalTransitStoppingCriterion): +class IterationStoppingCriterion(sopp.IterationStoppingCriterion): """ - Stop the iteration once the maximum number of toroidal transits is reached. + Stop the iteration once the maximum number of iterations is reached. + """ + pass + +class RStoppingCriterion(sopp.RStoppingCriterion): + """ + Stop the iteration once a particle falls above or below a critical value of + ``R``, the radial cylindrical coordinate. Usage: .. code-block:: - stopping_criteria=[ToroidalTransitStoppingCriterion(ntransits,flux)] + stopping_criteria=[RStopingCriterion(crit_r,min_bool)] - where ``ntransits`` is the maximum number of toroidal transits and ``flux`` - is a boolean indicating whether tracing is being performed in a flux coordinate system. + where ``crit_r`` is the value of the critical coordinate and + ``min_bool'' is a boolean indicating whether to stop when + ``R'' is less than the critical value (``true'') or + greater than the critical value (``false''). """ pass - -class IterationStoppingCriterion(sopp.IterationStoppingCriterion): +class ZStoppingCriterion(sopp.ZStoppingCriterion): """ - Stop the iteration once the maximum number of iterations is reached. + Stop the iteration once a particle falls above or below a critical value of + ``Z``, the cylindrical vertical coordinate. + + Usage: + + .. code-block:: + + stopping_criteria=[ZStopingCriterion(crit_z,min_bool)] + + where ``crit_z`` is the value of the critical coordinate and + ``min_bool'' is a boolean indicating whether to stop when + ``Z'' is less than the critical value (``true'') or + greater than the critical value (``false''). """ pass - def plot_poincare_data(fieldlines_phi_hits, phis, filename, mark_lost=False, aspect='equal', dpi=300, xlims=None, ylims=None, surf=None, s=2, marker='o'): """ diff --git a/src/simsoptpp/python_tracing.cpp b/src/simsoptpp/python_tracing.cpp index 00674765e..a3122ca57 100644 --- a/src/simsoptpp/python_tracing.cpp +++ b/src/simsoptpp/python_tracing.cpp @@ -17,10 +17,12 @@ void init_tracing(py::module_ &m){ py::class_>(m, "StoppingCriterion"); py::class_, StoppingCriterion>(m, "IterationStoppingCriterion") .def(py::init()); - py::class_, StoppingCriterion>(m, "MaxToroidalFluxStoppingCriterion") - .def(py::init()); - py::class_, StoppingCriterion>(m, "MinToroidalFluxStoppingCriterion") - .def(py::init()); + py::class_, StoppingCriterion>(m, "RStoppingCriterion") + .def(py::init()); + py::class_, StoppingCriterion>(m, "ZStoppingCriterion") + .def(py::init()); + py::class_, StoppingCriterion>(m, "ToroidalFluxStoppingCriterion") + .def(py::init()); py::class_, StoppingCriterion>(m, "ToroidalTransitStoppingCriterion") .def(py::init()); py::class_, shared_ptr>, StoppingCriterion>(m, "LevelsetStoppingCriterion") diff --git a/src/simsoptpp/tracing.h b/src/simsoptpp/tracing.h index a29e05259..4a0a7a6b4 100644 --- a/src/simsoptpp/tracing.h +++ b/src/simsoptpp/tracing.h @@ -44,23 +44,51 @@ class ToroidalTransitStoppingCriterion : public StoppingCriterion { }; }; -class MaxToroidalFluxStoppingCriterion : public StoppingCriterion{ +class ToroidalFluxStoppingCriterion : public StoppingCriterion{ private: - double max_s; + double crit_s; + bool min_bool; public: - MaxToroidalFluxStoppingCriterion(double max_s) : max_s(max_s) {}; + ToroidalFluxStoppingCriterion(double crit_s, bool min_bool) : crit_s(crit_s), min_bool(min_bool) {}; bool operator()(int iter, double t, double s, double theta, double zeta) override { - return s>=max_s; + if (min_bool) { + return s<=crit_s; + } else { + return s>=crit_s; + } + }; }; -class MinToroidalFluxStoppingCriterion : public StoppingCriterion{ +class ZStoppingCriterion : public StoppingCriterion{ private: - double min_s; + double crit_z; + bool min_bool; public: - MinToroidalFluxStoppingCriterion(double min_s) : min_s(min_s) {}; - bool operator()(int iter, double t, double s, double theta, double zeta) override { - return s<=min_s; + ZStoppingCriterion(double crit_z, bool min_bool) : crit_z(crit_z), min_bool(min_bool) {}; + bool operator()(int iter, double t, double x, double y, double z) override { + if (min_bool) { + return z<=crit_z; + } else { + return z>=crit_z; + } + + }; +}; + +class RStoppingCriterion : public StoppingCriterion{ + private: + double crit_r; + bool min_bool; + public: + RStoppingCriterion(double crit_r, bool min_bool) : crit_r(crit_r), min_bool(min_bool) {}; + bool operator()(int iter, double t, double x, double y, double z) override { + if (min_bool) { + return std::sqrt(x*x+y*y)<=crit_r; + } else { + return std::sqrt(x*x+y*y)>=crit_r; + } + }; }; diff --git a/tests/field/test_particle.py b/tests/field/test_particle.py index d335d5a3e..5ec5f6ee8 100644 --- a/tests/field/test_particle.py +++ b/tests/field/test_particle.py @@ -12,7 +12,7 @@ from simsopt.field.tracing import trace_particles_starting_on_curve, SurfaceClassifier, \ particles_to_vtk, LevelsetStoppingCriterion, compute_gc_radius, gc_to_fullorbit_initial_guesses, \ IterationStoppingCriterion, trace_particles_starting_on_surface, trace_particles_boozer, \ - MinToroidalFluxStoppingCriterion, MaxToroidalFluxStoppingCriterion, ToroidalTransitStoppingCriterion, \ + ToroidalFluxStoppingCriterion, ToroidalTransitStoppingCriterion, \ compute_poloidal_transits, compute_toroidal_transits, trace_particles, compute_resonances from simsopt.geo.surfacerzfourier import SurfaceRZFourier from simsopt.field.boozermagneticfield import BoozerAnalytic @@ -451,7 +451,7 @@ def test_energy_momentum_conservation_boozer(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_vac', - stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12) # pick 100 random points on each trace, and ensure that @@ -515,7 +515,7 @@ def test_energy_momentum_conservation_boozer(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_noK', - stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12) max_energy_gc_error = np.array([]) @@ -567,7 +567,7 @@ def test_energy_momentum_conservation_boozer(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc', - stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12) max_energy_gc_error = np.array([]) @@ -607,7 +607,7 @@ def test_energy_momentum_conservation_boozer(self): # Now trace with forget_exact_path = False. Check that gc_phi_hits is the same gc_tys, gc_phi_hits_2 = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_noK', - stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12, forget_exact_path=True) for i in range(len(gc_phi_hits_2)): @@ -652,7 +652,7 @@ def test_compute_poloidal_toroidal_transits(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_vac', - stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(1, True)], + stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(1, True)], tol=1e-12) mpol = compute_poloidal_transits(gc_tys) @@ -726,7 +726,7 @@ def test_toroidal_flux_stopping_criterion(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_vac', - stopping_criteria=[MinToroidalFluxStoppingCriterion(0.4), MaxToroidalFluxStoppingCriterion(0.6)], + stopping_criteria=[ToroidalFluxStoppingCriterion(0.4,True), ToroidalFluxStoppingCriterion(0.6,False)], tol=1e-12) for i in range(Nparticles): @@ -768,7 +768,7 @@ def test_compute_resonances(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[0], mode='gc_vac', - stopping_criteria=[MinToroidalFluxStoppingCriterion(0.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[ToroidalFluxStoppingCriterion(0.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], tol=1e-8) resonances = compute_resonances(gc_tys, gc_phi_hits, delta=0.01) From d382dded09cdec1eee72b21894b565025fe54f1a Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Wed, 13 Dec 2023 10:16:23 -0500 Subject: [PATCH 54/61] update to __all__. --- src/simsopt/field/tracing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simsopt/field/tracing.py b/src/simsopt/field/tracing.py index 8e7fc035d..a30a76c06 100644 --- a/src/simsopt/field/tracing.py +++ b/src/simsopt/field/tracing.py @@ -16,7 +16,7 @@ logger = logging.getLogger(__name__) __all__ = ['SurfaceClassifier', 'LevelsetStoppingCriterion', - 'MinToroidalFluxStoppingCriterion', 'MaxToroidalFluxStoppingCriterion', + 'ToroidalFluxStoppingCriterion','RStoppingCriterion','ZStoppingCriterion', 'IterationStoppingCriterion', 'ToroidalTransitStoppingCriterion', 'compute_fieldlines', 'compute_resonances', 'compute_poloidal_transits', 'compute_toroidal_transits', From ab9083d81faf66b4ce872bacf800e817ddbbc659 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Wed, 13 Dec 2023 14:14:00 -0500 Subject: [PATCH 55/61] Revert changes to framedcurve. --- src/simsopt/geo/framedcurve.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/simsopt/geo/framedcurve.py b/src/simsopt/geo/framedcurve.py index 7a7e6ef5d..dc883418f 100644 --- a/src/simsopt/geo/framedcurve.py +++ b/src/simsopt/geo/framedcurve.py @@ -31,13 +31,6 @@ def __init__(self, curve, rotation=None): self.rotation = rotation Curve.__init__(self, depends_on=deps) - def frame_twist(self): - t, n, _ = self.rotated_frame() - _, ndash, _ = self.rotated_frame_dash() - T = (n[:,0] * (ndash[:,1]*t[:,2] - ndash[:,2]*t[:,1]) \ - + n[:,1] * (ndash[:,2]*t[:,0] - ndash[:,0]*t[:,2]) \ - + n[:,2] * (ndash[:,0]*t[:,1] - ndash[:,1]*t[:,0])) - return np.sum(T)/(len(T)*2*np.pi) class FramedCurveFrenet(FramedCurve): r""" From 16a964042268d2acf8f94fcb29ca040de53ad31c Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Sat, 23 Dec 2023 11:03:51 -0500 Subject: [PATCH 56/61] Added unit test. --- tests/field/test_fieldline.py | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/tests/field/test_fieldline.py b/tests/field/test_fieldline.py index 1ebcfb09f..821ea0bc6 100644 --- a/tests/field/test_fieldline.py +++ b/tests/field/test_fieldline.py @@ -3,7 +3,7 @@ import numpy as np from simsopt.field.magneticfieldclasses import ToroidalField, PoloidalField, InterpolatedField, UniformInterpolationRule -from simsopt.field.tracing import compute_fieldlines, particles_to_vtk, plot_poincare_data +from simsopt.field.tracing import compute_fieldlines, particles_to_vtk, plot_poincare_data, RStoppingCriterion, ZStoppingCriterion from simsopt.field.biotsavart import BiotSavart from simsopt.configs.zoo import get_ncsx_data from simsopt.field.coil import coils_via_symmetries, Coil, Current @@ -136,7 +136,36 @@ def test_poincare_caryhanson(self): Z0 = [ma.gamma()[0, 2]] phis = np.arctan2(ma.gamma()[:, 1], ma.gamma()[:, 0]) res_tys, res_phi_hits = compute_fieldlines( - bs, R0, Z0, tmax=2, phis=phis, stopping_criteria=[]) - + bs, R0, Z0, tmax=2, phis=phis) for i in range(len(res_phi_hits[0])): assert np.linalg.norm(ma.gamma()[i+1, :] - res_phi_hits[0][i, 2:5]) < 2e-3 + + # Text StoppingCriterion in R and Z + # For each case, check that stopping criterion was met. + # Check that R/Z is less than/greater than the maximum/minimum value. + Rmax = 1 + res_tys, res_phi_hits = compute_fieldlines( + bs, [Rmax-0.02], [1], tmax=2000, stopping_criteria=[RStoppingCriterion(Rmax,False)]) + assert res_phi_hits[0][0,1] == -1 + assert np.all(np.sqrt(res_tys[0][:, 1]**2 + res_tys[0][:, 2]**2) < Rmax) + + Rmin = 0.3 + res_tys, res_phi_hits = compute_fieldlines( + bs, [Rmin+0.02], [0.3], tmax=500, stopping_criteria=[RStoppingCriterion(Rmin,True)]) + assert res_phi_hits[0][0,1] == -1 + assert np.all(np.sqrt(res_tys[0][:, 1]**2 + res_tys[0][:, 2]**2) > Rmin) + + Zmin = -0.1 + res_tys, res_phi_hits = compute_fieldlines( + bs, [0.97], [Zmin+0.02], tmax=2000, stopping_criteria=[ZStoppingCriterion(Zmin,True)] + ) + assert res_phi_hits[0][0,1] == -1 + assert np.all(res_tys[0][:, 3] > Zmin) + + Zmax = 0.5 + res_tys, res_phi_hits = compute_fieldlines( + bs, [0.5], [Zmax-0.02], tmax=2000, stopping_criteria=[ZStoppingCriterion(Zmax,False)] + ) + assert res_phi_hits[0][0,1] == -1 + assert np.all(res_tys[0][:, 3] < Zmax) + From 2087a79c6b13033c1912c22b8ab7aaa4e3201fe6 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Sat, 23 Dec 2023 15:01:33 -0500 Subject: [PATCH 57/61] Revert to min/max convention for stopping criteria. --- src/simsopt/field/tracing.py | 90 +++++++++++++++++++++++--------- src/simsoptpp/python_tracing.cpp | 18 ++++--- src/simsoptpp/tracing.h | 68 ++++++++++++++---------- tests/field/test_fieldline.py | 11 ++-- tests/field/test_particle.py | 16 +++--- 5 files changed, 130 insertions(+), 73 deletions(-) diff --git a/src/simsopt/field/tracing.py b/src/simsopt/field/tracing.py index a30a76c06..0896d37ca 100644 --- a/src/simsopt/field/tracing.py +++ b/src/simsopt/field/tracing.py @@ -16,7 +16,9 @@ logger = logging.getLogger(__name__) __all__ = ['SurfaceClassifier', 'LevelsetStoppingCriterion', - 'ToroidalFluxStoppingCriterion','RStoppingCriterion','ZStoppingCriterion', + 'MinToroidalFluxStoppingCriterion','MaxToroidalFluxStoppingCriterion', + 'MinRStoppingCriterion','MinZStoppingCriterion', + 'MaxRStoppingCriterion','MaxZStoppingCriterion', 'IterationStoppingCriterion', 'ToroidalTransitStoppingCriterion', 'compute_fieldlines', 'compute_resonances', 'compute_poloidal_transits', 'compute_toroidal_transits', @@ -738,29 +740,41 @@ def __init__(self, classifier): else: sopp.LevelsetStoppingCriterion.__init__(self, classifier) -class ToroidalFluxStoppingCriterion(sopp.ToroidalFluxStoppingCriterion): +class MinToroidalFluxStoppingCriterion(sopp.MinToroidalFluxStoppingCriterion): """ - Stop the iteration once a particle falls above or below a critical value of + Stop the iteration once a particle falls below a critical value of ``s``, the normalized toroidal flux. This :class:`StoppingCriterion` is - important to use when tracing particles in flux coordinates. For example, - the poloidal angle becomes ill-defined at the magnetic axis. This should - only be used when tracing trajectories in a flux coordinate system (i.e., - :class:`trace_particles_boozer`). + important to use when tracing particles in flux coordinates, as the poloidal + angle becomes ill-defined at the magnetic axis. This should only be used + when tracing trajectories in a flux coordinate system (i.e., :class:`trace_particles_boozer`). Usage: .. code-block:: - stopping_criteria=[ToroidalFluxStopingCriterion(crit_s,min_bool)] + stopping_criteria=[MinToroidalFluxStopingCriterion(s)] - where ``crit_s`` is the value of the critical normalized toroidal flux and - ``min_bool'' is a boolean indicating whether to stop when - ``s'' is less than the critical value (``true'') or - greater than the critical value (``false''). + where ``s`` is the value of the minimum normalized toroidal flux. """ pass +class MaxToroidalFluxStoppingCriterion(sopp.MaxToroidalFluxStoppingCriterion): + """ + Stop the iteration once a particle falls above a critical value of + ``s``, the normalized toroidal flux. This should only be used when tracing + trajectories in a flux coordinate system (i.e., :class:`trace_particles_boozer`). + + Usage: + + .. code-block:: + + stopping_criteria=[MaxToroidalFluxStopingCriterion(s)] + + where ``s`` is the value of the maximum normalized toroidal flux. + """ + pass + class ToroidalTransitStoppingCriterion(sopp.ToroidalTransitStoppingCriterion): """ Stop the iteration once the maximum number of toroidal transits is reached. @@ -783,39 +797,63 @@ class IterationStoppingCriterion(sopp.IterationStoppingCriterion): """ pass -class RStoppingCriterion(sopp.RStoppingCriterion): +class MinRStoppingCriterion(sopp.MinRStoppingCriterion): + """ + Stop the iteration once a particle falls below a critical value of + ``R``, the radial cylindrical coordinate. + + Usage: + + .. code-block:: + + stopping_criteria=[MinRStopingCriterion(crit_r)] + + where ``crit_r`` is the value of the critical coordinate. + """ + pass + +class MinZStoppingCriterion(sopp.MinZStoppingCriterion): + """ + Stop the iteration once a particle falls below a critical value of + ``Z``, the cylindrical vertical coordinate. + + Usage: + + .. code-block:: + + stopping_criteria=[MinZStopingCriterion(crit_z)] + + where ``crit_z`` is the value of the critical coordinate. + """ + pass + +class MaxRStoppingCriterion(sopp.MaxRStoppingCriterion): """ - Stop the iteration once a particle falls above or below a critical value of + Stop the iteration once a particle goes above a critical value of ``R``, the radial cylindrical coordinate. Usage: .. code-block:: - stopping_criteria=[RStopingCriterion(crit_r,min_bool)] + stopping_criteria=[MaxRStopingCriterion(crit_r,min_bool)] - where ``crit_r`` is the value of the critical coordinate and - ``min_bool'' is a boolean indicating whether to stop when - ``R'' is less than the critical value (``true'') or - greater than the critical value (``false''). + where ``crit_r`` is the value of the critical coordinate. """ pass -class ZStoppingCriterion(sopp.ZStoppingCriterion): +class MaxZStoppingCriterion(sopp.MaxZStoppingCriterion): """ - Stop the iteration once a particle falls above or below a critical value of + Stop the iteration once a particle gove above or below a critical value of ``Z``, the cylindrical vertical coordinate. Usage: .. code-block:: - stopping_criteria=[ZStopingCriterion(crit_z,min_bool)] + stopping_criteria=[MaxZStopingCriterion(crit_z,min_bool)] - where ``crit_z`` is the value of the critical coordinate and - ``min_bool'' is a boolean indicating whether to stop when - ``Z'' is less than the critical value (``true'') or - greater than the critical value (``false''). + where ``crit_z`` is the value of the critical coordinate. """ pass diff --git a/src/simsoptpp/python_tracing.cpp b/src/simsoptpp/python_tracing.cpp index a3122ca57..752a36475 100644 --- a/src/simsoptpp/python_tracing.cpp +++ b/src/simsoptpp/python_tracing.cpp @@ -17,12 +17,18 @@ void init_tracing(py::module_ &m){ py::class_>(m, "StoppingCriterion"); py::class_, StoppingCriterion>(m, "IterationStoppingCriterion") .def(py::init()); - py::class_, StoppingCriterion>(m, "RStoppingCriterion") - .def(py::init()); - py::class_, StoppingCriterion>(m, "ZStoppingCriterion") - .def(py::init()); - py::class_, StoppingCriterion>(m, "ToroidalFluxStoppingCriterion") - .def(py::init()); + py::class_, StoppingCriterion>(m, "MinRStoppingCriterion") + .def(py::init()); + py::class_, StoppingCriterion>(m, "MinZStoppingCriterion") + .def(py::init()); + py::class_, StoppingCriterion>(m, "MaxRStoppingCriterion") + .def(py::init()); + py::class_, StoppingCriterion>(m, "MaxZStoppingCriterion") + .def(py::init()); + py::class_, StoppingCriterion>(m, "MaxToroidalFluxStoppingCriterion") + .def(py::init()); + py::class_, StoppingCriterion>(m, "MinToroidalFluxStoppingCriterion") + .def(py::init()); py::class_, StoppingCriterion>(m, "ToroidalTransitStoppingCriterion") .def(py::init()); py::class_, shared_ptr>, StoppingCriterion>(m, "LevelsetStoppingCriterion") diff --git a/src/simsoptpp/tracing.h b/src/simsoptpp/tracing.h index 4a0a7a6b4..c59586825 100644 --- a/src/simsoptpp/tracing.h +++ b/src/simsoptpp/tracing.h @@ -44,51 +44,63 @@ class ToroidalTransitStoppingCriterion : public StoppingCriterion { }; }; -class ToroidalFluxStoppingCriterion : public StoppingCriterion{ +class MaxToroidalFluxStoppingCriterion : public StoppingCriterion{ private: - double crit_s; - bool min_bool; + double max_s; public: - ToroidalFluxStoppingCriterion(double crit_s, bool min_bool) : crit_s(crit_s), min_bool(min_bool) {}; + MaxToroidalFluxStoppingCriterion(double max_s) : max_s(max_s) {}; bool operator()(int iter, double t, double s, double theta, double zeta) override { - if (min_bool) { - return s<=crit_s; - } else { - return s>=crit_s; - } - + return s>=max_s; + }; +}; + +class MinToroidalFluxStoppingCriterion : public StoppingCriterion{ + private: + double min_s; + public: + MinToroidalFluxStoppingCriterion(double min_s) : min_s(min_s) {}; + bool operator()(int iter, double t, double s, double theta, double zeta) override { + return s<=min_s; }; }; -class ZStoppingCriterion : public StoppingCriterion{ +class MinZStoppingCriterion : public StoppingCriterion{ private: double crit_z; - bool min_bool; public: - ZStoppingCriterion(double crit_z, bool min_bool) : crit_z(crit_z), min_bool(min_bool) {}; + MinZStoppingCriterion(double crit_z) : crit_z(crit_z) {}; bool operator()(int iter, double t, double x, double y, double z) override { - if (min_bool) { - return z<=crit_z; - } else { - return z>=crit_z; - } - + return z<=crit_z; }; }; -class RStoppingCriterion : public StoppingCriterion{ +class MaxZStoppingCriterion : public StoppingCriterion{ + private: + double crit_z; + public: + MaxZStoppingCriterion(double crit_z) : crit_z(crit_z) {}; + bool operator()(int iter, double t, double x, double y, double z) override { + return z>=crit_z; + }; +}; + +class MinRStoppingCriterion : public StoppingCriterion{ private: double crit_r; - bool min_bool; public: - RStoppingCriterion(double crit_r, bool min_bool) : crit_r(crit_r), min_bool(min_bool) {}; + MinRStoppingCriterion(double crit_r) : crit_r(crit_r) {}; bool operator()(int iter, double t, double x, double y, double z) override { - if (min_bool) { - return std::sqrt(x*x+y*y)<=crit_r; - } else { - return std::sqrt(x*x+y*y)>=crit_r; - } - + return std::sqrt(x*x+y*y)<=crit_r; + }; +}; + +class MaxRStoppingCriterion : public StoppingCriterion{ + private: + double crit_r; + public: + MaxRStoppingCriterion(double crit_r) : crit_r(crit_r) {}; + bool operator()(int iter, double t, double x, double y, double z) override { + return std::sqrt(x*x+y*y)>=crit_r; }; }; diff --git a/tests/field/test_fieldline.py b/tests/field/test_fieldline.py index 821ea0bc6..49c7f5ab3 100644 --- a/tests/field/test_fieldline.py +++ b/tests/field/test_fieldline.py @@ -3,7 +3,8 @@ import numpy as np from simsopt.field.magneticfieldclasses import ToroidalField, PoloidalField, InterpolatedField, UniformInterpolationRule -from simsopt.field.tracing import compute_fieldlines, particles_to_vtk, plot_poincare_data, RStoppingCriterion, ZStoppingCriterion +from simsopt.field.tracing import compute_fieldlines, particles_to_vtk, plot_poincare_data, \ + MinRStoppingCriterion, MinZStoppingCriterion, MaxRStoppingCriterion, MaxZStoppingCriterion from simsopt.field.biotsavart import BiotSavart from simsopt.configs.zoo import get_ncsx_data from simsopt.field.coil import coils_via_symmetries, Coil, Current @@ -145,26 +146,26 @@ def test_poincare_caryhanson(self): # Check that R/Z is less than/greater than the maximum/minimum value. Rmax = 1 res_tys, res_phi_hits = compute_fieldlines( - bs, [Rmax-0.02], [1], tmax=2000, stopping_criteria=[RStoppingCriterion(Rmax,False)]) + bs, [Rmax-0.02], [1], tmax=2000, stopping_criteria=[MaxRStoppingCriterion(Rmax)]) assert res_phi_hits[0][0,1] == -1 assert np.all(np.sqrt(res_tys[0][:, 1]**2 + res_tys[0][:, 2]**2) < Rmax) Rmin = 0.3 res_tys, res_phi_hits = compute_fieldlines( - bs, [Rmin+0.02], [0.3], tmax=500, stopping_criteria=[RStoppingCriterion(Rmin,True)]) + bs, [Rmin+0.02], [0.3], tmax=500, stopping_criteria=[MinRStoppingCriterion(Rmin)]) assert res_phi_hits[0][0,1] == -1 assert np.all(np.sqrt(res_tys[0][:, 1]**2 + res_tys[0][:, 2]**2) > Rmin) Zmin = -0.1 res_tys, res_phi_hits = compute_fieldlines( - bs, [0.97], [Zmin+0.02], tmax=2000, stopping_criteria=[ZStoppingCriterion(Zmin,True)] + bs, [0.97], [Zmin+0.02], tmax=2000, stopping_criteria=[MinZStoppingCriterion(Zmin)] ) assert res_phi_hits[0][0,1] == -1 assert np.all(res_tys[0][:, 3] > Zmin) Zmax = 0.5 res_tys, res_phi_hits = compute_fieldlines( - bs, [0.5], [Zmax-0.02], tmax=2000, stopping_criteria=[ZStoppingCriterion(Zmax,False)] + bs, [0.5], [Zmax-0.02], tmax=2000, stopping_criteria=[MaxZStoppingCriterion(Zmax)] ) assert res_phi_hits[0][0,1] == -1 assert np.all(res_tys[0][:, 3] < Zmax) diff --git a/tests/field/test_particle.py b/tests/field/test_particle.py index 5ec5f6ee8..d335d5a3e 100644 --- a/tests/field/test_particle.py +++ b/tests/field/test_particle.py @@ -12,7 +12,7 @@ from simsopt.field.tracing import trace_particles_starting_on_curve, SurfaceClassifier, \ particles_to_vtk, LevelsetStoppingCriterion, compute_gc_radius, gc_to_fullorbit_initial_guesses, \ IterationStoppingCriterion, trace_particles_starting_on_surface, trace_particles_boozer, \ - ToroidalFluxStoppingCriterion, ToroidalTransitStoppingCriterion, \ + MinToroidalFluxStoppingCriterion, MaxToroidalFluxStoppingCriterion, ToroidalTransitStoppingCriterion, \ compute_poloidal_transits, compute_toroidal_transits, trace_particles, compute_resonances from simsopt.geo.surfacerzfourier import SurfaceRZFourier from simsopt.field.boozermagneticfield import BoozerAnalytic @@ -451,7 +451,7 @@ def test_energy_momentum_conservation_boozer(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_vac', - stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12) # pick 100 random points on each trace, and ensure that @@ -515,7 +515,7 @@ def test_energy_momentum_conservation_boozer(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_noK', - stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12) max_energy_gc_error = np.array([]) @@ -567,7 +567,7 @@ def test_energy_momentum_conservation_boozer(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc', - stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12) max_energy_gc_error = np.array([]) @@ -607,7 +607,7 @@ def test_energy_momentum_conservation_boozer(self): # Now trace with forget_exact_path = False. Check that gc_phi_hits is the same gc_tys, gc_phi_hits_2 = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_noK', - stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], tol=1e-12, forget_exact_path=True) for i in range(len(gc_phi_hits_2)): @@ -652,7 +652,7 @@ def test_compute_poloidal_toroidal_transits(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_vac', - stopping_criteria=[ToroidalFluxStoppingCriterion(.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(1, True)], + stopping_criteria=[MinToroidalFluxStoppingCriterion(.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(1, True)], tol=1e-12) mpol = compute_poloidal_transits(gc_tys) @@ -726,7 +726,7 @@ def test_toroidal_flux_stopping_criterion(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[], mode='gc_vac', - stopping_criteria=[ToroidalFluxStoppingCriterion(0.4,True), ToroidalFluxStoppingCriterion(0.6,False)], + stopping_criteria=[MinToroidalFluxStoppingCriterion(0.4), MaxToroidalFluxStoppingCriterion(0.6)], tol=1e-12) for i in range(Nparticles): @@ -768,7 +768,7 @@ def test_compute_resonances(self): gc_tys, gc_phi_hits = trace_particles_boozer(bsh, stz_inits, vpar_inits, tmax=tmax, mass=m, charge=q, Ekin=Ekin, zetas=[0], mode='gc_vac', - stopping_criteria=[ToroidalFluxStoppingCriterion(0.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(100, True)], + stopping_criteria=[MinToroidalFluxStoppingCriterion(0.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(100, True)], tol=1e-8) resonances = compute_resonances(gc_tys, gc_phi_hits, delta=0.01) From 02afa81c76e91c1fbc175deb72751f28248d7067 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Sat, 23 Dec 2023 15:46:52 -0500 Subject: [PATCH 58/61] Update to example. --- examples/2_Intermediate/tracing_boozer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/2_Intermediate/tracing_boozer.py b/examples/2_Intermediate/tracing_boozer.py index 0bc614e91..36a994f88 100755 --- a/examples/2_Intermediate/tracing_boozer.py +++ b/examples/2_Intermediate/tracing_boozer.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt from simsopt.field import (BoozerRadialInterpolant, InterpolatedBoozerField, trace_particles_boozer, - ToroidalFluxStoppingCriterion, + MinToroidalFluxStoppingCriterion, MaxToroidalFluxStoppingCriterion, ToroidalTransitStoppingCriterion, compute_resonances) from simsopt.mhd import Vmec from simsopt.util import in_github_actions @@ -75,7 +75,7 @@ gc_tys, gc_zeta_hits = trace_particles_boozer( field, stz_inits, vpar_inits, tmax=1e-2, mass=mass, charge=ELEMENTARY_CHARGE, - Ekin=Ekin, tol=1e-8, mode='gc_vac', stopping_criteria=[ToroidalFluxStoppingCriterion(0.99,False), ToroidalFluxStoppingCriterion(0.01,True), ToroidalTransitStoppingCriterion(100, True)], + Ekin=Ekin, tol=1e-8, mode='gc_vac', stopping_criteria=[MaxToroidalFluxStoppingCriterion(0.99), MinToroidalFluxStoppingCriterion(0.01), ToroidalTransitStoppingCriterion(100, True)], forget_exact_path=False) Nparticles = len(gc_tys) @@ -112,7 +112,7 @@ gc_tys, gc_zeta_hits = trace_particles_boozer( field, stz_inits, vpar_inits, tmax=1e-2, mass=mass, charge=ELEMENTARY_CHARGE, - Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[ToroidalFluxStoppingCriterion(0.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(30, True)], + Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[MinToroidalFluxStoppingCriterion(0.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(30, True)], forget_exact_path=False) resonances = compute_resonances(gc_tys, gc_zeta_hits, ma=None, delta=0.01) @@ -134,7 +134,7 @@ gc_tys, gc_zeta_hits = trace_particles_boozer( field, stz_res, vpar_res, tmax=1e-2, mass=mass, charge=ELEMENTARY_CHARGE, - Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[ToroidalFluxStoppingCriterion(0.01,True), ToroidalFluxStoppingCriterion(0.99,False), ToroidalTransitStoppingCriterion(30, True)], + Ekin=Ekin, zetas=[0], tol=1e-8, stopping_criteria=[MinToroidalFluxStoppingCriterion(0.01), MaxToroidalFluxStoppingCriterion(0.99), ToroidalTransitStoppingCriterion(30, True)], forget_exact_path=False) if not in_github_actions: From e9d1afe7a664ad30abeaacc3ebee061cf26a94fe Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Tue, 26 Dec 2023 19:31:35 -0500 Subject: [PATCH 59/61] Fixing docs. --- src/simsopt/field/tracing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/simsopt/field/tracing.py b/src/simsopt/field/tracing.py index 0896d37ca..e02ae3476 100644 --- a/src/simsopt/field/tracing.py +++ b/src/simsopt/field/tracing.py @@ -836,7 +836,7 @@ class MaxRStoppingCriterion(sopp.MaxRStoppingCriterion): .. code-block:: - stopping_criteria=[MaxRStopingCriterion(crit_r,min_bool)] + stopping_criteria=[MaxRStopingCriterion(crit_r)] where ``crit_r`` is the value of the critical coordinate. """ @@ -851,7 +851,7 @@ class MaxZStoppingCriterion(sopp.MaxZStoppingCriterion): .. code-block:: - stopping_criteria=[MaxZStopingCriterion(crit_z,min_bool)] + stopping_criteria=[MaxZStopingCriterion(crit_z)] where ``crit_z`` is the value of the critical coordinate. """ From 01aac459f4bfbd9c5e94bcc6c5ff88c68ed2ddb1 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Wed, 27 Dec 2023 11:10:10 -0500 Subject: [PATCH 60/61] Fix to docs. --- src/simsopt/field/tracing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simsopt/field/tracing.py b/src/simsopt/field/tracing.py index e02ae3476..5bd65695c 100644 --- a/src/simsopt/field/tracing.py +++ b/src/simsopt/field/tracing.py @@ -844,7 +844,7 @@ class MaxRStoppingCriterion(sopp.MaxRStoppingCriterion): class MaxZStoppingCriterion(sopp.MaxZStoppingCriterion): """ - Stop the iteration once a particle gove above or below a critical value of + Stop the iteration once a particle gove above a critical value of ``Z``, the cylindrical vertical coordinate. Usage: From 0c0c5f0888699c19c62b70cee60eebbcd576c8ae Mon Sep 17 00:00:00 2001 From: Matt Landreman Date: Mon, 15 Jan 2024 13:46:42 -0500 Subject: [PATCH 61/61] Add pres_scale as a dof of vmec objects; remove delt, tcon0, gamma --- src/simsopt/mhd/vmec.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/simsopt/mhd/vmec.py b/src/simsopt/mhd/vmec.py index beef7c96e..94af6cc98 100644 --- a/src/simsopt/mhd/vmec.py +++ b/src/simsopt/mhd/vmec.py @@ -168,8 +168,8 @@ class Vmec(Optimizable): Vmec object with different parameters; changing the parameters of one would change the parameters of the other. - An instance of this class owns just a few optimizable degrees of - freedom, particularly ``phiedge`` and ``curtor``. The optimizable + An instance of this class owns three optimizable degrees of + freedom: ``phiedge``, ``curtor``, and ``pres_scale``. The optimizable degrees of freedom associated with the boundary surface are owned by that surface object. @@ -373,7 +373,7 @@ def __init__(self, # Handle a few variables that are not Parameters: x0 = self.get_dofs() fixed = np.full(len(x0), True) - names = ['delt', 'tcon0', 'phiedge', 'curtor', 'gamma'] + names = ['phiedge', 'curtor', 'pres_scale'] super().__init__(x0=x0, fixed=fixed, names=names, depends_on=[self._boundary], external_dof_setter=Vmec.set_dofs) @@ -444,20 +444,17 @@ def iota_profile(self, iota_profile): def get_dofs(self): if not self.runnable: # Use default values from vmec_input - return np.array([1, 1, 1, 0, 0]) + return np.array([1.0, 0.0, 1.0]) else: - return np.array([self.indata.delt, self.indata.tcon0, - self.indata.phiedge, self.indata.curtor, - self.indata.gamma]) + return np.array([self.indata.phiedge, self.indata.curtor, + self.indata.pres_scale]) def set_dofs(self, x): if self.runnable: self.need_to_run_code = True - self.indata.delt = x[0] - self.indata.tcon0 = x[1] - self.indata.phiedge = x[2] - self.indata.curtor = x[3] - self.indata.gamma = x[4] + self.indata.phiedge = x[0] + self.indata.curtor = x[1] + self.indata.pres_scale = x[2] def recompute_bell(self, parent=None): self.need_to_run_code = True