Program Listing for File NuMagSANSlib_MagData.h#
↰ Return to documentation for file (src/NuMagSANSlib_MagData.h)
// File : NuMagSANSlib_MagData.h
// Author : Michael Philipp ADAMS, M.Sc.
// Company : University of Luxembourg
// Department : Department of Physics and Materials Sciences
// Group : NanoMagnetism Group
// Group Leader : Prof. Andreas Michels
// Version : 26 November 2024
// 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>
using namespace std;
struct MagnetizationData{
float *RotMat; // rotation matrix R = [R0, R3, R6; R1, R4, R7; R2, R5, R8]
float*x; // position data x
float*y; // position data y
float*z; // position data z
float*mx; // magnetization data mx
float*my; // magnetization data my
float*mz; // magnetization data mz
unsigned long int* K; // number of objects (e.g., orientations)
unsigned long int* TotalAtomNumber; // total atom number
unsigned int* NumberOfElements;
unsigned int* NumberOfNonZeroMoments;
unsigned long int* N_act; // number of atoms in k-th object
unsigned long int* N_cum; // cummulated number of atoms from object to object
unsigned long int* N_avg; // average number of atoms per object
};
void allocate_MagnetizationDataRAM(MagnetizationData* MagData, \
MagDataProperties* MagDataProp, \
InputFileData* InputData, \
int MagData_File_Index){
bool ExcludeZeroMoments_flag = InputData->ExcludeZeroMoments_flag;
unsigned long int K = MagDataProp->Number_Of_SubFolders;
unsigned long int TotalAtomNumber = 0;
if(ExcludeZeroMoments_flag){
TotalAtomNumber = MagDataProp->TotalNZMAtomNumber[MagData_File_Index];
} else{
TotalAtomNumber = MagDataProp->TotalAtomNumber[MagData_File_Index-1];
}
MagData->x = (float*) malloc(TotalAtomNumber*sizeof(float));
MagData->y = (float*) malloc(TotalAtomNumber*sizeof(float));
MagData->z = (float*) malloc(TotalAtomNumber*sizeof(float));
MagData->mx = (float*) malloc(TotalAtomNumber*sizeof(float));
MagData->my = (float*) malloc(TotalAtomNumber*sizeof(float));
MagData->mz = (float*) malloc(TotalAtomNumber*sizeof(float));
MagData->K = (unsigned long int*) malloc(sizeof(unsigned long int));
MagData->TotalAtomNumber = (unsigned long int*) malloc(sizeof(unsigned long int));
MagData->RotMat = (float*) malloc(9*sizeof(float));
MagData->NumberOfElements = (unsigned int*) malloc(K*sizeof(unsigned int));
MagData->NumberOfNonZeroMoments = (unsigned int*) malloc(K*sizeof(unsigned int));
MagData->N_cum = (unsigned long int*) malloc(K*sizeof(unsigned long int));
MagData->N_act = (unsigned long int*) malloc(K*sizeof(unsigned long int));
MagData->N_avg = (unsigned long int*) malloc(sizeof(unsigned long int));
if (!MagData->x || !MagData->y || !MagData->z ||
!MagData->mx || !MagData->my || !MagData->mz ||
!MagData->N_avg || !MagData->K || !MagData->TotalAtomNumber || !MagData->RotMat) {
perror("Memory allocation failed");
exit(EXIT_FAILURE);
}
*MagData->N_avg = 0;
*MagData->K = K;
*MagData->TotalAtomNumber = TotalAtomNumber;
for(unsigned long int i = 0; i < TotalAtomNumber; i++){
MagData->x[i] = 0.0;
MagData->y[i] = 0.0;
MagData->z[i] = 0.0;
MagData->mx[i] = 0.0;
MagData->my[i] = 0.0;
MagData->mz[i] = 0.0;
}
for(unsigned int i = 0; i < K; i++){
MagData->NumberOfElements[i] = MagDataProp->NumberOfElements[i][MagData_File_Index-1];
MagData->NumberOfNonZeroMoments[i] = MagDataProp->NumberOfNonZeroMoments[i][MagData_File_Index-1];
MagData->N_cum[i] = 0;
MagData->N_act[i] = 0;
}
}
void allocate_MagnetizationDataGPU(MagnetizationData* MagData, \
MagnetizationData* MagData_gpu, \
int MagData_File_Index){
unsigned long int TotalAtomNumber = *MagData->TotalAtomNumber;
cudaMalloc(&MagData_gpu->x, TotalAtomNumber*sizeof(float));
cudaMalloc(&MagData_gpu->y, TotalAtomNumber*sizeof(float));
cudaMalloc(&MagData_gpu->z, TotalAtomNumber*sizeof(float));
cudaMalloc(&MagData_gpu->mx, TotalAtomNumber*sizeof(float));
cudaMalloc(&MagData_gpu->my, TotalAtomNumber*sizeof(float));
cudaMalloc(&MagData_gpu->mz, TotalAtomNumber*sizeof(float));
cudaMalloc(&MagData_gpu->K, sizeof(unsigned long int));
cudaMalloc(&MagData_gpu->TotalAtomNumber, sizeof(unsigned long int));
cudaMalloc(&MagData_gpu->RotMat, 9*sizeof(float));
cudaMalloc(&MagData_gpu->NumberOfElements, *MagData->K*sizeof(unsigned int));
cudaMalloc(&MagData_gpu->NumberOfNonZeroMoments, *MagData->K*sizeof(unsigned int));
cudaMalloc(&MagData_gpu->N_cum, *MagData->K*sizeof(unsigned long int));
cudaMalloc(&MagData_gpu->N_act, *MagData->K*sizeof(unsigned long int));
cudaMalloc(&MagData_gpu->N_avg, sizeof(unsigned long int));
cudaMemcpy(MagData_gpu->N_avg, MagData->N_avg, sizeof(unsigned long int), cudaMemcpyHostToDevice);
cudaMemcpy(MagData_gpu->K, MagData->K, sizeof(unsigned long int), cudaMemcpyHostToDevice);
cudaMemcpy(MagData_gpu->TotalAtomNumber, MagData->TotalAtomNumber, sizeof(unsigned long int), cudaMemcpyHostToDevice);
cudaMemcpy(MagData_gpu->RotMat, MagData->RotMat, 9*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(MagData_gpu->NumberOfElements, MagData->NumberOfElements, *MagData->K*sizeof(unsigned int), cudaMemcpyHostToDevice);
cudaMemcpy(MagData_gpu->NumberOfElements, MagData->NumberOfElements, *MagData->K*sizeof(unsigned int), cudaMemcpyHostToDevice);
cudaMemcpy(MagData_gpu->N_cum, MagData->N_cum, *MagData->K*sizeof(unsigned long int), cudaMemcpyHostToDevice);
cudaMemcpy(MagData_gpu->N_act, MagData->N_act, *MagData->K*sizeof(unsigned long int), cudaMemcpyHostToDevice);
LogSystem::write("");
// copy data from Host to Device
LogSystem::write("copy data from RAM to GPU...");
cudaMemcpy(MagData_gpu->x, MagData->x, TotalAtomNumber*sizeof(float), cudaMemcpyHostToDevice);
LogSystem::write(" x done...");
cudaMemcpy(MagData_gpu->y, MagData->y, TotalAtomNumber*sizeof(float), cudaMemcpyHostToDevice);
LogSystem::write(" y done...");
cudaMemcpy(MagData_gpu->z, MagData->z, TotalAtomNumber*sizeof(float), cudaMemcpyHostToDevice);
LogSystem::write(" z done...");
cudaMemcpy(MagData_gpu->mx, MagData->mx, TotalAtomNumber*sizeof(float), cudaMemcpyHostToDevice);
LogSystem::write(" mx done...");
cudaMemcpy(MagData_gpu->my, MagData->my, TotalAtomNumber*sizeof(float), cudaMemcpyHostToDevice);
LogSystem::write(" my done...");
cudaMemcpy(MagData_gpu->mz, MagData->mz, TotalAtomNumber*sizeof(float), cudaMemcpyHostToDevice);
LogSystem::write(" mz done...");
LogSystem::write("");
LogSystem::write("data transfer finished...");
LogSystem::write("");
cudaMalloc(&MagData_gpu, sizeof(MagnetizationData));
cudaMemcpy(MagData_gpu, MagData, sizeof(MagnetizationData), cudaMemcpyHostToDevice);
}
void read_MagnetizationData(MagnetizationData* MagData, \
MagDataProperties* MagDataProp, \
InputFileData* InputData, \
int MagData_File_Index){
LogSystem::write("");
LogSystem::write("read magnetization data to RAM...");
unsigned long int K = *MagData->K;
bool ExcludeZeroMoments_flag = InputData->ExcludeZeroMoments_flag;
for(int i = 0; i < 9; i++){
MagData->RotMat[i] = InputData->RotMat[i];
}
string filename;
unsigned long int n = 0;
float x_buf, y_buf, z_buf, mx_buf, my_buf, mz_buf;
ifstream fin;
float x_mean = 0.0;
float y_mean = 0.0;
float z_mean = 0.0;
unsigned long int N_cum = 0; // cummulative counter
unsigned long int N_act = 0; // actual number of atoms per file
for(unsigned long int k = 1; k <= K; k++){
if(ExcludeZeroMoments_flag){
N_act = MagData->NumberOfNonZeroMoments[k-1];
}else{
N_act = MagData->NumberOfElements[k-1];
}
MagData->N_act[k-1] = N_act;
filename = MagDataProp->GlobalFolderPath + "/" + MagDataProp->SubFolderNames_Nom + "_" + to_string(k) \
+ "/" + MagDataProp->SubFolder_FileNames_Nom + "_" + to_string(MagData_File_Index)\
+ "." + MagDataProp->SubFolder_FileNames_Type;
LogSystem::write(filename);
fin.open(filename);
n = 0;
x_mean = 0.0;
y_mean = 0.0;
z_mean = 0.0;
// read in the data and calculate the spatial average position
if(ExcludeZeroMoments_flag){
while(fin >> x_buf >> y_buf >> z_buf >> mx_buf >> my_buf >> mz_buf){
if(mx_buf != 0.0 || my_buf != 0.0 || mz_buf != 0.0){
MagData->x[n + N_cum] = x_buf * InputData->XYZ_Unit_Factor;
MagData->y[n + N_cum] = y_buf * InputData->XYZ_Unit_Factor;
MagData->z[n + N_cum] = z_buf * InputData->XYZ_Unit_Factor;
MagData->mx[n + N_cum] = mx_buf;
MagData->my[n + N_cum] = my_buf;
MagData->mz[n + N_cum] = mz_buf;
x_mean += MagData->x[n + N_cum]/N_act;
y_mean += MagData->y[n + N_cum]/N_act;
z_mean += MagData->z[n + N_cum]/N_act;
n += 1;
}
}
} else{
while(fin >> x_buf >> y_buf >> z_buf >> mx_buf >> my_buf >> mz_buf){
MagData->x[n + N_cum] = x_buf * InputData->XYZ_Unit_Factor;
MagData->y[n + N_cum] = y_buf * InputData->XYZ_Unit_Factor;
MagData->z[n + N_cum] = z_buf * InputData->XYZ_Unit_Factor;
MagData->mx[n + N_cum] = mx_buf;
MagData->my[n + N_cum] = my_buf;
MagData->mz[n + N_cum] = mz_buf;
x_mean += MagData->x[n + N_cum]/N_act;
y_mean += MagData->y[n + N_cum]/N_act;
z_mean += MagData->z[n + N_cum]/N_act;
n += 1;
}
}
fin.close();
// centering of the xyz-data set
for(int l = 0; l < N_act; l++){
MagData->x[l + N_cum] = MagData->x[l + N_cum] - x_mean;
MagData->y[l + N_cum] = MagData->y[l + N_cum] - y_mean;
MagData->z[l + N_cum] = MagData->z[l + N_cum] - z_mean;
}
// update of the cummulative counter
N_cum += N_act;
if(k<K){
MagData->N_cum[k] = N_cum;
}
LogSystem::write("N_act: " + std::to_string(N_act) + ", " + "N_cum: " + std::to_string(N_cum));
}
*MagData->N_avg = (unsigned long int) (((float)N_cum)/((float) K));
LogSystem::write("N_avg: " + to_string(*MagData->N_avg));
LogSystem::write("read (x, y, z, mx, my, mz) data to RAM finished...");
}
void init_MagnetizationData(MagnetizationData* MagData, \
MagnetizationData* MagData_gpu, \
MagDataProperties* MagDataProp, \
InputFileData* InputData, \
int MagData_File_Index){
allocate_MagnetizationDataRAM(MagData, MagDataProp, InputData, MagData_File_Index);
read_MagnetizationData(MagData, MagDataProp, InputData, MagData_File_Index);
allocate_MagnetizationDataGPU(MagData, MagData_gpu, MagData_File_Index);
}
void free_MagnetizationData(MagnetizationData *MagData, \
MagnetizationData *MagData_gpu){
LogSystem::write("free MagData...");
// cudaError_t err;
free(MagData->x);
free(MagData->y);
free(MagData->z);
free(MagData->mx);
free(MagData->my);
free(MagData->mz);
free(MagData->K);
free(MagData->TotalAtomNumber);
free(MagData->RotMat);
free(MagData->NumberOfElements);
free(MagData->NumberOfNonZeroMoments);
free(MagData->N_cum);
free(MagData->N_act);
free(MagData->N_avg);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->x);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->y);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->z);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->mx);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->my);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->mz);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->K);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->TotalAtomNumber);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->RotMat);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->NumberOfElements);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->NumberOfNonZeroMoments);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->N_cum);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->N_act);
cudaDeviceSynchronize();
cudaFree(MagData_gpu->N_avg);
cudaDeviceSynchronize();
LogSystem::write("free MagData finished...");
}
void disp_MagnetizationData(MagnetizationData *MagData){
for(int k=0; k < *MagData->TotalAtomNumber; k++){
cout << MagData->x[k] << " "\
<< MagData->y[k] << " "\
<< MagData->z[k] << " "\
<< MagData->mx[k] << " "\
<< MagData->my[k] << " "\
<< MagData->mz[k] << "\n";
}
}