Commit 802d7908 authored by BRAMAS Berenger's avatar BRAMAS Berenger
Browse files

Add a test for the rotation based kernel and a file to compute the rotation matrix

parent 1c0a45bf
This diff is collapsed.
// ===================================================================================
// Logiciel initial: ScalFmm Version 0.5
// Co-auteurs : Olivier Coulaud, Bérenger Bramas.
// Propriétaires : INRIA.
// Copyright © 2011-2012, diffusé sous les termes et conditions d’une licence propriétaire.
// Initial software: ScalFmm Version 0.5
// Co-authors: Olivier Coulaud, Bérenger Bramas.
// Owners: INRIA.
// Copyright © 2011-2012, spread under the terms and conditions of a proprietary license.
// ===================================================================================
#include <limits>
#include <iostream>
#include "../../Src/Components/FSimpleLeaf.hpp"
#include "../../Src/Containers/FVector.hpp"
#include "../../Src/Containers/FOctree.hpp"
#include "../../Src/Core/FFmmAlgorithm.hpp"
#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp"
#include "../../Src/Kernels/Rotation/FRotationKernel.hpp"
#include "../../Src/Utils/FMath.hpp"
#include "../../Src/Utils/FMemUtils.hpp"
#include "../../Src/Utils/FParameters.hpp"
#include "../../Src/Core/FFmmAlgorithm.hpp"
#include "../../Src/Core/FFmmAlgorithmThread.hpp"
#include "../../Src/Core/FFmmAlgorithmTask.hpp"
#include "../../Src/Files/FFmaLoader.hpp"
/** We need to know the position of the particle in the array */
class IndexedParticle : public FSphericalParticle {
int index;
public:
IndexedParticle(): index(-1){}
int getIndex() const{
return index;
}
void setIndex( const int inIndex ){
index = inIndex;
}
};
int main(int argc, char** argv){
static const int P = 1;
typedef IndexedParticle ParticleClass;
typedef FRotationCell<P> CellClass;
typedef FVector<ParticleClass> ContainerClass;
typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass;
typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass;
typedef FRotationKernel<ParticleClass, CellClass, ContainerClass , P> KernelClass;
typedef FFmmAlgorithm<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClass;
typedef FFmmAlgorithmThread<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassThread;
typedef FFmmAlgorithmTask<OctreeClass, ParticleClass, CellClass, ContainerClass, KernelClass, LeafClass > FmmClassTask;
///////////////////////What we do/////////////////////////////
std::cout << ">> This executable has to be used to test Spherical algorithm.\n";
std::cout << ">> You can pass -sequential or -task (thread by default).\n";
//////////////////////////////////////////////////////////////
const int NbLevels = FParameters::getValue(argc,argv,"-h", 5);
const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3);
FTic counter;
const char* const filename = FParameters::getStr(argc,argv,"-f", "../Data/test20k.fma");
std::cout << "Opening : " << filename << "\n";
FFmaLoader<ParticleClass> loader(filename);
if(!loader.isOpen()){
std::cout << "Loader Error, " << filename << " is missing\n";
return 1;
}
// -----------------------------------------------------
OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());
// -----------------------------------------------------
std::cout << "Creating & Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl;
std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl;
counter.tic();
//loader.fillTree(tree);
ParticleClass* const particles = new ParticleClass[loader.getNumberOfParticles()];
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(particles[idxPart]);
particles[idxPart].setIndex( idxPart );
tree.insert(particles[idxPart]);
}
counter.tac();
std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl;
// -----------------------------------------------------
std::cout << "Create kernel ..." << std::endl;
counter.tic();
KernelClass kernels(P, NbLevels, loader.getBoxWidth(), loader.getCenterOfBox());
counter.tac();
std::cout << "Done " << " in " << counter.elapsed() << "s)." << std::endl;
// -----------------------------------------------------
std::cout << "Working on particles ..." << std::endl;
if( FParameters::findParameter(argc,argv,"-sequential") != FParameters::NotFound){
FmmClass algo(&tree,&kernels);
counter.tic();
algo.execute();
}
else if( FParameters::findParameter(argc,argv,"-task") != FParameters::NotFound){
FmmClassTask algo(&tree,&kernels);
counter.tic();
algo.execute();
}
else {
FmmClassThread algo(&tree,&kernels);
counter.tic();
algo.execute();
}
counter.tac();
std::cout << "Done " << "(@Algorithm = " << counter.elapsed() << "s)." << std::endl;
{ // get sum forces&potential
FReal potential = 0;
FPoint forces;
OctreeClass::Iterator octreeIterator(&tree);
octreeIterator.gotoBottomLeft();
do{
ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets());
while( iter.hasNotFinished() ){
potential += iter.data().getPotential() * iter.data().getPhysicalValue();
forces += iter.data().getForces();
iter.gotoNext();
}
} while(octreeIterator.moveRight());
std::cout << "Foces Sum x = " << forces.getX() << " y = " << forces.getY() << " z = " << forces.getZ() << std::endl;
std::cout << "Potential = " << potential << std::endl;
}
// -----------------------------------------------------
{
std::cout << "Compute direct interaction for all\n";
for(int idxTarget = 0 ; idxTarget < loader.getNumberOfParticles() ; ++idxTarget){
for(int idxOther = idxTarget + 1 ; idxOther < loader.getNumberOfParticles() ; ++idxOther){
kernels.particlesMutualInteraction(&particles[idxTarget], &particles[idxOther]);
}
}
std::cout << "Compute Diff...\n";
FMath::FAccurater potentialDiff;
FMath::FAccurater fx, fy, fz;
{ // Check that each particle has been summed with all other
typename OctreeClass::Iterator octreeIterator(&tree);
octreeIterator.gotoBottomLeft();
do{
typename ContainerClass::BasicIterator leafIter(*octreeIterator.getCurrentListTargets());
while( leafIter.hasNotFinished() ){
const ParticleClass& other = particles[leafIter.data().getIndex()];
potentialDiff.add(other.getPotential(),leafIter.data().getPotential());
std::cout << "Direct Potential = " << other.getPotential() << " Fmm Potential = " << leafIter.data().getPotential() << std::endl; // Remove Me
fx.add(other.getForces().getX(),leafIter.data().getForces().getX());
fy.add(other.getForces().getY(),leafIter.data().getForces().getY());
fz.add(other.getForces().getZ(),leafIter.data().getForces().getZ());
leafIter.gotoNext();
}
} while(octreeIterator.moveRight());
}
// Print for information
std::cout << "Potential diff is = " << potentialDiff.getL2Norm() << " " << potentialDiff.getInfNorm() << std::endl;
std::cout << "Fx diff is = " << fx.getL2Norm() << " " << fx.getInfNorm() << std::endl;
std::cout << "Fy diff is = " << fy.getL2Norm() << " " << fy.getInfNorm() << std::endl;
std::cout << "Fz diff is = " << fz.getL2Norm() << " " << fz.getInfNorm() << std::endl;
}
delete[] particles;
return 0;
}
// ===================================================================================
// Logiciel initial: ScalFmm Version 0.5
// Co-auteurs : Olivier Coulaud, Bérenger Bramas.
// Propriétaires : INRIA.
// Copyright © 2011-2012, diffusé sous les termes et conditions d’une licence propriétaire.
// Initial software: ScalFmm Version 0.5
// Co-authors: Olivier Coulaud, Bérenger Bramas.
// Owners: INRIA.
// Copyright © 2011-2012, spread under the terms and conditions of a proprietary license.
// ===================================================================================
#include <limits>
#include <iostream>
#include "../../Src/Kernels/Spherical/FSphericalCell.hpp"
#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp"
#include "../../Src/Kernels/Spherical/FSphericalRotationKernel.hpp"
#include "../../Src/Components/FSimpleLeaf.hpp"
#include "../../Src/Containers/FVector.hpp"
#include "../../Src/Containers/FOctree.hpp"
#include "../../Src/Core/FFmmAlgorithm.hpp"
#include "../../Src/Kernels/Spherical/FSphericalParticle.hpp"
#include "../../Src/Kernels/Rotation/FRotationKernel.hpp"
#include "../../Src/Utils/FMath.hpp"
#include "../../Src/Utils/FMemUtils.hpp"
int atLm(const int l, const int m){
return (l*(l+1))/2 + m;
}
template < class T >
T Sgn(const T a){
if(a < 0) return T(-1);
else if(a > 0) return T(1);
return T(0);
}
template < class T >
T fact(const T a){
if(a<0) printf("Error factorial negative!! a=%d\n",a);
int result = 1;
for(int i = 1; i<= a ; ++i){
result *= i;
}
return T(result);
}
template < class T >
FReal combin(const T& a, const T& b){
if(a-b<0) printf("Error combi negative!! a=%d b=%d\n",a,b);
return FReal(fact(a)) / FReal(fact(b)*fact(a-b));
}
int Min(const int a , const int b){
return (a<b?a:b);
}
int Max(const int a , const int b){
return (a>b?a:b);
}
FReal analytical(const FReal cosTheta, const FReal sinTheta, const int l , const int m, const int k){
if( l >= 0 && -l <= k && k <= l && FMath::Abs(k) <= m && m <= l ){
FReal sum = 0;
for(int n = Max(-(m+k),0) ; n <= Min(l-m,l-k) ; ++n){
sum += FMath::pow(-1.0, l-m-n) * combin(l-k, n) * combin(l+k, l-m-n) * FMath::pow(1.0+cosTheta,n) * FMath::pow(1.0-cosTheta, l-m-n);
}
return (1.0/FMath::pow(2.0,l)) * FMath::Sqrt(FReal(fact(l-m)*fact(l+m))/FReal(fact(l-k)*fact(l+k)))
* FMath::pow(1.0 + Sgn(k)*cosTheta, FMath::Abs(k)) * FMath::pow(sinTheta, m - FMath::Abs(k)) * sum;
}
else if( (l > 0 && -l <= m && m < 0 && FMath::Abs(m) <= k && k <= l)
|| (l > 0 && 0 <= m && m < l && m < k && k <= l )) {
return FMath::pow(-1.0, m+k) * analytical(cosTheta,sinTheta, l, k ,m);
}
else if( l > 0 && -l <= m && m < l && -l <= k && k < -m ){
return FMath::pow(-1.0, m+k) * analytical(cosTheta,sinTheta, l, -m, -k);
}
else{
return -999999.99999;
}
}
FReal analyticalDachsel(const FReal cosTheta, const FReal sinTheta, const int l , const int m, const int k){
/*if(l >= 0 && -l <= m && m <= l && FMath::Abs(m) <= k && k <= l) {
return FMath::pow(-1.0, k+m) * analyticalDachsel(cosTheta,sinTheta, l, k ,m);
}
else if( l > 0 && -l <= m && m <= l-1 && -l <= k && k <= -(m+1) ){
return FMath::pow(-1.0, m+k) * analyticalDachsel(cosTheta,sinTheta, l, -m, -k);
}*/
if( m < k ){
return FMath::pow(-1.0, k+m) * analyticalDachsel(cosTheta,sinTheta, l, k ,m);
}
else if( m < -k ){
return FMath::pow(-1.0, m+k) * analyticalDachsel(cosTheta,sinTheta, l, -m, -k);
}
else {
FReal sum = 0;
for(int n = 0 ; n <= l-m ; ++n){
sum += FMath::pow(-1.0, l-m-n) * combin(l-k, n) * combin(l+k, l-m-n) * FMath::pow(1.0+cosTheta,n) * FMath::pow(1.0-cosTheta, l-m-n);
}
return (1.0/FMath::pow(2.0,l)) * FMath::Sqrt(FReal(fact(l-m)*fact(l+m))/FReal(fact(l-k)*fact(l+k)))
* FMath::pow(1.0 + Sgn(k)*cosTheta, FMath::Abs(k)) * FMath::pow(sinTheta, m - FMath::Abs(k)) * sum;
}
}
int main(){
static const int P = 2;
static const int SizeArray = (P+1)*(P+1);
//const FReal cosTheta = FMath::Cos(FMath::FPiDiv2/FReal(2.0));
//const FReal sinTheta = FMath::Sin(FMath::FPiDiv2/FReal(2.0));
const FPoint relativPos(FReal(0.1),FReal(0.1),FReal(0.1));
const FSpherical relativPosSphere(relativPos);
const FReal Betha = 2.186276;//FMath::FPi/2; //2*FMath::FPi-FMath::FPi/2
const FReal cosTheta = FMath::Cos(Betha); // relativPosSphere.getCosTheta();
const FReal sinTheta = FMath::Sin(Betha); // relativPosSphere.getSinTheta();
std::cout << "cosTheta = " << cosTheta << "\n";
std::cout << "sinTheta = " << sinTheta << "\n";
// Rotation matrix d[l][m][k]
FReal d[P+1][2*P+1][2*P+1];
FMemUtils::setall((FReal*)d, FReal(std::numeric_limits<FReal>::quiet_NaN()), (P+1)*(2*P+1)*(2*P+1));
/////////////////////////////////////////////////////////////
// First method, Page 3,4
// Fast and accurate determination of Wigner rotation matrices
// in FMM
/////////////////////////////////////////////////////////////
FReal legendre_f[SizeArray];
{ // init legendre-f values
// Equ 24
// P~{0,0} = 1
legendre_f[0] = 1.0;
{ // P~{l,l} = sqrt(2l-1 / 2l) sin(theta) P~{l-1,l-1} , For l > 0
for(int l = 1; l <= P ; ++l ){
legendre_f[atLm(l,l)] = FMath::Sqrt(FReal((2.0*l-1) / (2.0*l))) * sinTheta * legendre_f[atLm(l-1,l-1)];
}
}
{ // P~{l,l-1} = sqrt(2l-1) cos(theta) P~{l-1,l-1} , For l > 0
for(int l = 1; l <= P ; ++l ){
legendre_f[atLm(l,l-1)] = FMath::Sqrt(FReal(2*l-1)) * cosTheta * legendre_f[atLm(l-1,l-1)];
}
}
{
// For l > 1, 0 <= k < l-1
// P~{l,k} = (2l-1) cos(theta) P{l-1,k} - sqrt((l-k-1)(l+k-1) P~{l-2,k}
// / sqrt((l-k)(l+k))
for(int l = 2; l <= P ; ++l ){
for( int k = 0 ; k < l - 1 ; ++k ){
legendre_f[atLm(l,k)] =
(FReal(2*l - 1 ) * cosTheta * legendre_f[atLm(l-1,k)] - FMath::Sqrt(FReal((l-k-1)*(l+k-1))) * legendre_f[atLm(l-2,k)])
/ FMath::Sqrt(FReal((l-k)*(l+k)));
}
}
}
}
{ // Initial condition
// Equ 21
// For l > 0,
// & -l <= k < 0, d{l,0,k} = sqrt((l+k)!/(l-k)!) P{l,-k} = P~{l,-k}
// & k = 0, d{l,0,k} = P{l,0}
// & 0 < k <= l, d{l,0,k} = -1^k sqrt((l-k)!/(l+k)!) P{l,k} = -1^k P~{l,k}
for(int l = 0 ; l <= P ; ++l){
// k < 0
for(int k = -l ; k < 0 ; ++k){
d[l][P+0][P+k] = legendre_f[atLm(l,-k)];
}
// k == 0
d[l][P+0][P+0] = legendre_f[atLm(l,0)];
// 0 < k
for(int k = 1 ; k <= l ; ++k){
d[l][P+0][P+k] = FMath::pow(FReal(-1),k) * legendre_f[atLm(l,k)];
}
}
}
{
for(int l = 1 ; l <= P ; ++l){
for(int m = 0 ; m < l ; ++m){
// Equ 18
// For l > 0, 0 <= m < l, -l < k <= l, cos(theta) >= 0
// d{l,m+1,k} = sqrt( l(l+1) - k(k-1) / l(l+1) - m(m+1)) d{l,m,k-1}
// - (m+k) sin(theta) d{l,m,k} / sqrt(l(l+1) - m(m+1)) (1+cos(theta))
for(int k = -l+1 ; k <= l ; ++k){
d[l][P+m+1][P+k] =
FMath::Sqrt(FReal(l*(l+1)-k*(k-1))/FReal(l*(l+1)-m*(m+1))) * d[l][P+m][P+k-1]
- FReal(m+k)*sinTheta*d[l][P+m][P+k]/(FMath::Sqrt(FReal(l*(l+1)-m*(m+1)))*(1+cosTheta));
}
// Equ 19
// For l > 0, 0 <= m < l, cos(theta) >= 0
// d{l,m+1,-l} = (l-m) sin(theta) d{l,m,-l}
// / sqrt(l(l+1)-m(m+1)) (1+cos(theta))
d[l][P+m+1][P-l] = FReal(l-m)*sinTheta*d[l][P+m][P-l]/(FMath::Sqrt(FReal(l*(l+1)-m*(m+1)))*(1+cosTheta));
}
// Equ 20
// d{l,m,k} = -1^(m+k) d{l,-m,-k} , For l > 0, -l <= m < 0, -l <= k <= l
for(int m = -l ; m < 0 ; ++m){
for(int k = -l ; k <= l ; ++k){
d[l][P+m][P+k] = FMath::pow( FReal(-1.0), m+k) * d[l][P-m][P-k];
}
}
}
}
// Print
std::cout << "Print result\n";
for(int l = 0 ; l <= P ; ++l){
for(int m = -l ; m <= l ; ++m ){
for(int k = -l ; k <= l ; ++k ){
std::cout << d[l][P+m][P+k] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
FMemUtils::setall((FReal*)d, FReal(std::numeric_limits<FReal>::quiet_NaN()), (P+1)*(2*P+1)*(2*P+1));
/////////////////////////////////////////////////////////////
// Second method, Page 4
// Fast and accurate determination of Wigner rotation matrices
// in FMM
/////////////////////////////////////////////////////////////
FReal g[SizeArray];
{// Equ 29
// g{0,0} = 1
g[0] = 1;
// g{l,0} = sqrt( (2l - 1) / 2l) g{l-1,0} for l > 0
for(int l = 1; l <= P ; ++l ){
g[atLm(l,0)] = FMath::Sqrt(FReal((l*2.0-1.0)/(l*2.0))) * g[atLm(l-1,0)];
}
// g{l,m} = sqrt( (l - m + 1) / (l+m)) g{l,m-1} for l > 0, 0 < m <= l
for(int l = 1; l <= P ; ++l ){
for(int m = 1; m <= l ; ++m ){
g[atLm(l,m)] = FMath::Sqrt(FReal((l-m+1))/FReal((l+m))) * g[atLm(l,m-1)];
}
}
}
{ // initial
// Equ 28
// d{l,m,l} = -1^(l+m) g{l,m} (1+cos(theta))^m sin(theta)^(l-m) , For l > 0, 0 <= m <= l
for(int l = 0 ; l <= P ; ++l){
for(int m = 0 ; m <= l ; ++m){
d[l][P+m][P+l] = FMath::pow( FReal(-1.0), l+m) * g[atLm(l,m)] * FMath::pow( FReal(1) + cosTheta, m) * FMath::pow(sinTheta, l-m);
}
}
}
{
for(int l = 1 ; l <= P ; ++l){
for(int k = l ; k > -l ; --k){
// Equ 25
// For l > 0, 0 <= m < l, -l < k <= l, cos(theta) >= 0
// d{l,m,k-1} = sqrt( l(l+1) - m(m+1) / l(l+1) - k(k-1)) d{l,m+1,k}
// + (m+k) sin(theta) d{l,m,k} / sqrt(l(l+1) - k(k-1)) (1+cos(theta))
for(int m = 0 ; m < l ; ++m){
d[l][P+m][P+k-1] =
(FMath::Sqrt(FReal(l*(l+1)-m*(m+1))/FReal(l*(l+1)-k*(k-1))) * d[l][P+m+1][P+k])
+ (FReal(m+k)*sinTheta*d[l][P+m][P+k]/(FMath::Sqrt(FReal(l*(l+1)-k*(k-1)))*(1+cosTheta)));
}
// Equ 26
// For l > 0, -l < k <= l, cos(theta) >= 0
// d{l,l,k-1} = (l+k) sin(theta) d{l,l,k}
// / sqrt(l(l+1)-k(k-1)) (1+cos(theta))
d[l][P+l][P+k-1] = FReal(l+k)*sinTheta*d[l][P+l][P+k]/(FMath::Sqrt(FReal(l*(l+1)-k*(k-1)))*(1+cosTheta));
}
// Equ 27
// d{l,m,k} = -1^(m+k) d{l,-m,-k} , For l > 0, -l <= m < 0, -l <= k <= l
for(int m = -l ; m < 0 ; ++m){
for(int k = -l ; k <= l ; ++k){
d[l][P+m][P+k] = FMath::pow( FReal(-1), m+k) * d[l][P-m][P-k];
}
}
}
}
// Print
std::cout << "Print result\n";
for(int l = 0 ; l <= P ; ++l){
for(int m = -l ; m <= l ; ++m ){
for(int k = -l ; k <= l ; ++k ){
std::cout << d[l][P+m][P+k] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
FMemUtils::setall((FReal*)d, FReal(std::numeric_limits<FReal>::quiet_NaN()), (P+1)*(2*P+1)*(2*P+1));
/////////////////////////////////////////////////////////////
// Analatycall values
/////////////////////////////////////////////////////////////
std::cout << "Print result analytical\n";
for(int l = 0 ; l <= P ; ++l){
for(int m = -l ; m <= l ; ++m ){
for(int k = -l ; k <= l ; ++k ){
std::cout << analytical(cosTheta,sinTheta,l,m,k) << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
/////////////////////////////////////////////////////////////
// Analatycall values V2
/////////////////////////////////////////////////////////////
std::cout << "Print result analytical V2\n";
for(int l = 0 ; l <= P ; ++l){
for(int m = -l ; m <= l ; ++m ){
for(int k = -l ; k <= l ; ++k ){
std::cout << analyticalDachsel(cosTheta,sinTheta,l,m,k) << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
/////////////////////////////////////////////////////////////
// correct result for l=1
/////////////////////////////////////////////////////////////
std::cout << "Print L=1\n";
{
FReal resL[9];
resL[0] = FMath::pow(FMath::Cos(Betha/2.0),2);
resL[1] = -FMath::Sin(Betha)/FMath::Sqrt(2.0);
resL[2] = FMath::pow(FMath::Sin(Betha/2.0),2);
resL[3] = FMath::Sin(Betha)/FMath::Sqrt(2.0);;
resL[4] = FMath::Cos(Betha);
resL[5] = -FMath::Sin(Betha)/FMath::Sqrt(2.0);;
resL[6] = FMath::pow(FMath::Sin(Betha/2.0),2);
resL[7] = FMath::Sin(Betha)/FMath::Sqrt(2.0);
resL[8] = FMath::pow(FMath::Cos(Betha/2.0),2);
for(int m = 0 ; m < 3 ; ++m ){
for(int k = 0 ; k < 3 ; ++k ){
std::cout << resL[m*3 + k] << "\t";
}
std::cout << "\n";
}
}
/////////////////////////////////////////////////////////////
// correct result for l=2
/////////////////////////////////////////////////////////////
std::cout << "Print L=2\n";
{
FReal resL[25];
resL[0] = FMath::pow(FMath::Cos(Betha/2.0),4);
resL[1] = (-FMath::pow(FMath::Cos(Betha/2.0),2))*FMath::Sin(Betha);
resL[2] = (1.0/2.0)*FMath::Sqrt(3.0/2.0)*FMath::pow(FMath::Sin(Betha),2);
resL[3] = (-FMath::pow(FMath::Sin(Betha/2.0),2))*FMath::Sin(Betha);
resL[4] = FMath::pow(FMath::Sin(Betha/2.0),4);
resL[5] = FMath::pow(FMath::Cos(Betha/2.0),2)*FMath::Sin(Betha);
resL[6] = FMath::pow(FMath::Cos(Betha),2)- FMath::pow(FMath::Sin(Betha/2),2);
resL[