Program Listing for File NuMagSANSlib_SpectralData.h#

↰ Return to documentation for file (src/OutputData/SpectralData/NuMagSANSlib_SpectralData.h)

// File         : NuMagSANSlib_SANSData.h
// Author       : Dr. Michael Philipp ADAMS
// Company      : University of Luxembourg
// Department   : Department of Physics and Materials Sciences
// Group        : NanoMagnetism Group
// Group Leader : Prof. Andreas Michels
// Version      : 28 October 2025
// OS           : Linux Ubuntu
// Language     : CUDA C++

#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <math.h>
#include <string>
#include <vector>
#include <stdlib.h>
#include <time.h>
#include <cuda_runtime.h>
#include <cublas_v2.h>
#include <stdexcept>
#include <math.h>
#include <chrono>
#include <dirent.h>
#include <unistd.h>
#include <filesystem>

#include "NuMagSANSlib_SpectralDataStruct.h"
#include "NuMagSANSlib_SpectralData2csv.h"
#include "NuMagSANSlib_SpectralData2hdf5.h"

using namespace std;

void scale_SpectralData(ScalingFactors* ScalFactors, SpectralData* SpecData, InputFileData* InputData) {

    unsigned int Nq = *SpecData->Nq;
    unsigned int k_max = *SpecData->k_max;
    unsigned int L = 2 * Nq * (k_max + 1);
    unsigned int Lk = 2 * (k_max + 1);

    for (unsigned long int l = 0; l < L; l++) {

        // basic SANS cross sections
        SpecData->I_Nuc_unpolarized[l] = SpecData->I_Nuc_unpolarized[l] * ScalFactors->Nuc_SANS_SF;
        SpecData->I_Mag_unpolarized[l] = SpecData->I_Mag_unpolarized[l] * ScalFactors->Mag_SANS_SF;
        SpecData->I_Mag_polarized[l] = SpecData->I_Mag_polarized[l] * ScalFactors->Mag_SANS_SF;
        ;
        SpecData->I_NucMag[l] = SpecData->I_NucMag[l] * ScalFactors->NucMag_SANS_SF;
        SpecData->I_Mag_chiral[l] = SpecData->I_Mag_chiral[l] * ScalFactors->Mag_SANS_SF;

        // composed SANS cross sections
        SpecData->I_Mag_spin_flip[l] = SpecData->I_Mag_unpolarized[l] - SpecData->I_Mag_polarized[l];
        SpecData->I_Mag_spin_flip_pm[l] = SpecData->I_Mag_spin_flip[l] + SpecData->I_Mag_chiral[l];
        SpecData->I_Mag_spin_flip_mp[l] = SpecData->I_Mag_spin_flip[l] - SpecData->I_Mag_chiral[l];
        SpecData->I_Mag_non_spin_flip_pp[l] =
            SpecData->I_Nuc_unpolarized[l] + SpecData->I_NucMag[l] + SpecData->I_Mag_polarized[l];
        SpecData->I_Mag_non_spin_flip_mm[l] =
            SpecData->I_Nuc_unpolarized[l] - SpecData->I_NucMag[l] + SpecData->I_Mag_polarized[l];
        SpecData->I_Mag_sanspol_p[l] = SpecData->I_Mag_non_spin_flip_pp[l] + SpecData->I_Mag_spin_flip_pm[l];
        SpecData->I_Mag_sanspol_m[l] = SpecData->I_Mag_non_spin_flip_mm[l] + SpecData->I_Mag_spin_flip_mp[l];
    }

    // =====================================================
    // (2) scaling and normalization of the amplitude spectrum
    // =====================================================
    auto normalizeAmplitude = [&](float* A_array, float scaleFactor) {
        // (a) Scaling
        for (unsigned int k = 0; k < Lk; ++k)
            A_array[k] *= scaleFactor;

        // (b) compute norm of the ampliutde spectrum
        float normSum = 0.0f;
        for (unsigned int k = 0; k <= k_max; ++k) {
            float Ac = A_array[k];
            float As = A_array[k + (k_max + 1)];
            normSum += sqrtf(Ac * Ac + As * As);
        }

        if (normSum == 0.0f)
            return;

        // (c) normalization
        for (unsigned int k = 0; k <= k_max; ++k) {
            A_array[k] /= normSum;
            A_array[k + (k_max + 1)] /= normSum;
        }
    };

    // normalizing of the base amplitudes
    normalizeAmplitude(SpecData->A_Nuc_unpolarized, ScalFactors->Nuc_SANS_SF);
    normalizeAmplitude(SpecData->A_Mag_unpolarized, ScalFactors->Mag_SANS_SF);
    normalizeAmplitude(SpecData->A_Mag_polarized, ScalFactors->Mag_SANS_SF);
    normalizeAmplitude(SpecData->A_NucMag, ScalFactors->NucMag_SANS_SF);
    normalizeAmplitude(SpecData->A_Mag_chiral, ScalFactors->Mag_SANS_SF);

    // =====================================================
    // composition of the secondary amplitudes
    // =====================================================
    for (unsigned int k = 0; k < Lk; ++k) {
        SpecData->A_Mag_spin_flip[k] = SpecData->A_Mag_unpolarized[k] - SpecData->A_Mag_polarized[k];
        SpecData->A_Mag_spin_flip_pm[k] = SpecData->A_Mag_spin_flip[k] + SpecData->A_Mag_chiral[k];
        SpecData->A_Mag_spin_flip_mp[k] = SpecData->A_Mag_spin_flip[k] - SpecData->A_Mag_chiral[k];
        SpecData->A_Mag_non_spin_flip_pp[k] =
            SpecData->A_Nuc_unpolarized[k] + SpecData->A_NucMag[k] + SpecData->A_Mag_polarized[k];
        SpecData->A_Mag_non_spin_flip_mm[k] =
            SpecData->A_Nuc_unpolarized[k] - SpecData->A_NucMag[k] + SpecData->A_Mag_polarized[k];
        SpecData->A_Mag_sanspol_p[k] = SpecData->A_Mag_non_spin_flip_pp[k] + SpecData->A_Mag_spin_flip_pm[k];
        SpecData->A_Mag_sanspol_m[k] = SpecData->A_Mag_non_spin_flip_mm[k] + SpecData->A_Mag_spin_flip_mp[k];
    }

    // normalize the secondary amplitudes
    normalizeAmplitude(SpecData->A_Mag_spin_flip, 1.0f);
    normalizeAmplitude(SpecData->A_Mag_spin_flip_pm, 1.0f);
    normalizeAmplitude(SpecData->A_Mag_spin_flip_mp, 1.0f);
    normalizeAmplitude(SpecData->A_Mag_non_spin_flip_pp, 1.0f);
    normalizeAmplitude(SpecData->A_Mag_non_spin_flip_mm, 1.0f);
    normalizeAmplitude(SpecData->A_Mag_sanspol_p, 1.0f);
    normalizeAmplitude(SpecData->A_Mag_sanspol_m, 1.0f);
}

void allocate_SpectralData_RAM(InputFileData* InputData, ScatteringData* SANSData, SpectralData* SpecData) {

    SpecData->Nq = (unsigned int*)malloc(sizeof(unsigned int));
    SpecData->Ntheta = (unsigned int*)malloc(sizeof(unsigned int));
    SpecData->k_max = (unsigned int*)malloc(sizeof(unsigned int));
    SpecData->dtheta = (float*)malloc(sizeof(float));

    *SpecData->Nq = InputData->N_q;
    *SpecData->Ntheta = InputData->N_theta;
    *SpecData->k_max = InputData->k_max;
    *SpecData->dtheta = *SANSData->dtheta;

    // allocate the q-space vector
    SpecData->q = (float*)malloc((*(SpecData->Nq)) * sizeof(float));
    memset(SpecData->q, 0, (*SpecData->Nq) * sizeof(float));
    memcpy(SpecData->q, SANSData->q_1D, (*SpecData->Nq) * sizeof(float));

    // allocate spectral arrays
    size_t len = 2 * (*(SpecData->Nq)) * ((*(SpecData->k_max)) + 1) * sizeof(float);
    SpecData->I_Nuc_unpolarized = (float*)malloc(len);
    SpecData->I_Mag_unpolarized = (float*)malloc(len);
    SpecData->I_Mag_polarized = (float*)malloc(len);
    SpecData->I_NucMag = (float*)malloc(len);
    SpecData->I_Mag_spin_flip = (float*)malloc(len);
    SpecData->I_Mag_chiral = (float*)malloc(len);
    SpecData->I_Mag_spin_flip_pm = (float*)malloc(len);
    SpecData->I_Mag_spin_flip_mp = (float*)malloc(len);
    SpecData->I_Mag_non_spin_flip_pp = (float*)malloc(len);
    SpecData->I_Mag_non_spin_flip_mm = (float*)malloc(len);
    SpecData->I_Mag_sanspol_p = (float*)malloc(len);
    SpecData->I_Mag_sanspol_m = (float*)malloc(len);

    // --- Initialize to zero ---
    memset(SpecData->I_Nuc_unpolarized, 0, len);
    memset(SpecData->I_Mag_unpolarized, 0, len);
    memset(SpecData->I_Mag_polarized, 0, len);
    memset(SpecData->I_NucMag, 0, len);
    memset(SpecData->I_Mag_spin_flip, 0, len);
    memset(SpecData->I_Mag_chiral, 0, len);
    memset(SpecData->I_Mag_spin_flip_pm, 0, len);
    memset(SpecData->I_Mag_spin_flip_mp, 0, len);
    memset(SpecData->I_Mag_non_spin_flip_pp, 0, len);
    memset(SpecData->I_Mag_non_spin_flip_mm, 0, len);
    memset(SpecData->I_Mag_sanspol_p, 0, len);
    memset(SpecData->I_Mag_sanspol_m, 0, len);

    // allocate spectral arrays
    size_t lenA = 2 * ((*(SpecData->k_max)) + 1) * sizeof(float);
    SpecData->A_Nuc_unpolarized = (float*)malloc(lenA);
    SpecData->A_Mag_unpolarized = (float*)malloc(lenA);
    SpecData->A_Mag_polarized = (float*)malloc(lenA);
    SpecData->A_NucMag = (float*)malloc(lenA);
    SpecData->A_Mag_spin_flip = (float*)malloc(lenA);
    SpecData->A_Mag_chiral = (float*)malloc(lenA);
    SpecData->A_Mag_spin_flip_pm = (float*)malloc(lenA);
    SpecData->A_Mag_spin_flip_mp = (float*)malloc(lenA);
    SpecData->A_Mag_non_spin_flip_pp = (float*)malloc(lenA);
    SpecData->A_Mag_non_spin_flip_mm = (float*)malloc(lenA);
    SpecData->A_Mag_sanspol_p = (float*)malloc(lenA);
    SpecData->A_Mag_sanspol_m = (float*)malloc(lenA);

    // --- Initialize to zero ---
    memset(SpecData->A_Nuc_unpolarized, 0, lenA);
    memset(SpecData->A_Mag_unpolarized, 0, lenA);
    memset(SpecData->A_Mag_polarized, 0, lenA);
    memset(SpecData->A_NucMag, 0, lenA);
    memset(SpecData->A_Mag_spin_flip, 0, lenA);
    memset(SpecData->A_Mag_chiral, 0, lenA);
    memset(SpecData->A_Mag_spin_flip_pm, 0, lenA);
    memset(SpecData->A_Mag_spin_flip_mp, 0, lenA);
    memset(SpecData->A_Mag_non_spin_flip_pp, 0, lenA);
    memset(SpecData->A_Mag_non_spin_flip_mm, 0, lenA);
    memset(SpecData->A_Mag_sanspol_p, 0, lenA);
    memset(SpecData->A_Mag_sanspol_m, 0, lenA);
}

void allocate_SpectralData_GPU(SpectralData* SpecData, SpectralData* SpecData_gpu) {

    // Allocate scalar members on GPU
    cudaMalloc(&(SpecData_gpu->Nq), sizeof(unsigned int));
    cudaMalloc(&(SpecData_gpu->Ntheta), sizeof(unsigned int));
    cudaMalloc(&(SpecData_gpu->k_max), sizeof(unsigned int));
    cudaMalloc(&(SpecData_gpu->dtheta), sizeof(float));

    // Copy scalar values from host SpecData → device SpecData_gpu
    cudaMemcpy(SpecData_gpu->Nq, SpecData->Nq, sizeof(unsigned int), cudaMemcpyHostToDevice);
    cudaMemcpy(SpecData_gpu->Ntheta, SpecData->Ntheta, sizeof(unsigned int), cudaMemcpyHostToDevice);
    cudaMemcpy(SpecData_gpu->k_max, SpecData->k_max, sizeof(unsigned int), cudaMemcpyHostToDevice);
    cudaMemcpy(SpecData_gpu->dtheta, SpecData->dtheta, sizeof(float), cudaMemcpyHostToDevice);

    unsigned int Nq = *SpecData->Nq;
    unsigned int k_max = *SpecData->k_max;
    size_t len_q = Nq * sizeof(float);
    size_t len_I = 2 * Nq * (k_max + 1) * sizeof(float);
    size_t len_A = 2 * (k_max + 1) * sizeof(float);

    // Allocate arrays on GPU
    cudaMalloc(&(SpecData_gpu->q), len_q);
    cudaMemcpy(SpecData_gpu->q, SpecData->q, len_q, cudaMemcpyHostToDevice);

    cudaMalloc(&(SpecData_gpu->I_Nuc_unpolarized), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_unpolarized), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_polarized), len_I);
    cudaMalloc(&(SpecData_gpu->I_NucMag), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_spin_flip), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_chiral), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_spin_flip_pm), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_spin_flip_mp), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_non_spin_flip_pp), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_non_spin_flip_mm), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_sanspol_p), len_I);
    cudaMalloc(&(SpecData_gpu->I_Mag_sanspol_m), len_I);

    // Initialize GPU arrays with zeros
    cudaMemset(SpecData_gpu->I_Nuc_unpolarized, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_unpolarized, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_polarized, 0, len_I);
    cudaMemset(SpecData_gpu->I_NucMag, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_spin_flip, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_chiral, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_spin_flip_pm, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_spin_flip_mp, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_non_spin_flip_pp, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_non_spin_flip_mm, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_sanspol_p, 0, len_I);
    cudaMemset(SpecData_gpu->I_Mag_sanspol_m, 0, len_I);

    cudaMalloc(&(SpecData_gpu->A_Nuc_unpolarized), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_unpolarized), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_polarized), len_A);
    cudaMalloc(&(SpecData_gpu->A_NucMag), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_spin_flip), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_chiral), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_spin_flip_pm), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_spin_flip_mp), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_non_spin_flip_pp), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_non_spin_flip_mm), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_sanspol_p), len_A);
    cudaMalloc(&(SpecData_gpu->A_Mag_sanspol_m), len_A);

    // Initialize GPU arrays with zeros
    cudaMemset(SpecData_gpu->A_Nuc_unpolarized, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_unpolarized, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_polarized, 0, len_A);
    cudaMemset(SpecData_gpu->A_NucMag, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_spin_flip, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_chiral, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_spin_flip_pm, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_spin_flip_mp, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_non_spin_flip_pp, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_non_spin_flip_mm, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_sanspol_p, 0, len_A);
    cudaMemset(SpecData_gpu->A_Mag_sanspol_m, 0, len_A);

    cudaMalloc(&SpecData_gpu, sizeof(SpectralData));
    cudaMemcpy(SpecData_gpu, SpecData, sizeof(SpectralData), cudaMemcpyHostToDevice);

    cudaDeviceSynchronize();
}

void init_SpectralData(InputFileData* InputData, ScatteringData* SANSData, SpectralData* SpecData,
                       SpectralData* SpecData_gpu) {

    allocate_SpectralData_RAM(InputData, SANSData, SpecData);
    allocate_SpectralData_GPU(SpecData, SpecData_gpu);
}

void copyGPU2RAM_SpectralData(SpectralData* S, SpectralData* S_gpu) {

    cudaDeviceSynchronize();

    unsigned int Nq = *S->Nq;
    unsigned int k_max = *S->k_max;

    size_t len_I = 2 * Nq * (k_max + 1) * sizeof(float);
    size_t len_A = 2 * (k_max + 1) * sizeof(float);

    // Copy spectral arrays
    cudaMemcpy(S->I_Nuc_unpolarized, S_gpu->I_Nuc_unpolarized, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_unpolarized, S_gpu->I_Mag_unpolarized, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_polarized, S_gpu->I_Mag_polarized, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_NucMag, S_gpu->I_NucMag, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_spin_flip, S_gpu->I_Mag_spin_flip, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_chiral, S_gpu->I_Mag_chiral, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_spin_flip_pm, S_gpu->I_Mag_spin_flip_pm, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_spin_flip_mp, S_gpu->I_Mag_spin_flip_mp, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_non_spin_flip_pp, S_gpu->I_Mag_non_spin_flip_pp, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_non_spin_flip_mm, S_gpu->I_Mag_non_spin_flip_mm, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_sanspol_p, S_gpu->I_Mag_sanspol_p, len_I, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->I_Mag_sanspol_m, S_gpu->I_Mag_sanspol_m, len_I, cudaMemcpyDeviceToHost);

    // Copy spectral arrays
    cudaMemcpy(S->A_Nuc_unpolarized, S_gpu->A_Nuc_unpolarized, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_unpolarized, S_gpu->A_Mag_unpolarized, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_polarized, S_gpu->A_Mag_polarized, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_NucMag, S_gpu->A_NucMag, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_spin_flip, S_gpu->A_Mag_spin_flip, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_chiral, S_gpu->A_Mag_chiral, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_spin_flip_pm, S_gpu->A_Mag_spin_flip_pm, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_spin_flip_mp, S_gpu->A_Mag_spin_flip_mp, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_non_spin_flip_pp, S_gpu->A_Mag_non_spin_flip_pp, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_non_spin_flip_mm, S_gpu->A_Mag_non_spin_flip_mm, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_sanspol_p, S_gpu->A_Mag_sanspol_p, len_A, cudaMemcpyDeviceToHost);
    cudaMemcpy(S->A_Mag_sanspol_m, S_gpu->A_Mag_sanspol_m, len_A, cudaMemcpyDeviceToHost);

    // === 4. Synchronize to ensure data is ready ===
    cudaDeviceSynchronize();
}

void free_SpectralData(SpectralData* S, SpectralData* S_gpu) {

    free(S->Nq);
    free(S->Ntheta);
    free(S->k_max);
    free(S->dtheta);
    free(S->q);

    free(S->I_Nuc_unpolarized);
    free(S->I_Mag_unpolarized);
    free(S->I_Mag_polarized);
    free(S->I_NucMag);
    free(S->I_Mag_spin_flip);
    free(S->I_Mag_chiral);
    free(S->I_Mag_spin_flip_pm);
    free(S->I_Mag_spin_flip_mp);
    free(S->I_Mag_non_spin_flip_pp);
    free(S->I_Mag_non_spin_flip_mm);
    free(S->I_Mag_sanspol_p);
    free(S->I_Mag_sanspol_m);

    free(S->A_Nuc_unpolarized);
    free(S->A_Mag_unpolarized);
    free(S->A_Mag_polarized);
    free(S->A_NucMag);
    free(S->A_Mag_spin_flip);
    free(S->A_Mag_chiral);
    free(S->A_Mag_spin_flip_pm);
    free(S->A_Mag_spin_flip_mp);
    free(S->A_Mag_non_spin_flip_pp);
    free(S->A_Mag_non_spin_flip_mm);
    free(S->A_Mag_sanspol_p);
    free(S->A_Mag_sanspol_m);

    cudaDeviceSynchronize();
    cudaFree(S_gpu->Nq);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->Ntheta);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->k_max);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->dtheta);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->q);
    cudaDeviceSynchronize();

    cudaFree(S_gpu->I_Nuc_unpolarized);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_unpolarized);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_polarized);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_NucMag);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_spin_flip);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_chiral);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_spin_flip_pm);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_spin_flip_mp);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_non_spin_flip_pp);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_non_spin_flip_mm);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_sanspol_p);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->I_Mag_sanspol_m);
    cudaDeviceSynchronize();

    cudaFree(S_gpu->A_Nuc_unpolarized);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_unpolarized);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_polarized);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_NucMag);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_spin_flip);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_chiral);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_spin_flip_pm);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_spin_flip_mp);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_non_spin_flip_pp);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_non_spin_flip_mm);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_sanspol_p);
    cudaDeviceSynchronize();
    cudaFree(S_gpu->A_Mag_sanspol_m);
    cudaDeviceSynchronize();
}