Program Listing for File NuMagSANSlib_NucDataExplorer.h#

↰ Return to documentation for file (src/InputData/NucData/NuMagSANSlib_NucDataExplorer.h)

// File         : NuMagSANSlib_NucDataObserver.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>
#include <limits.h>

using namespace std;

struct NucDataProperties {

    string GlobalFolderPath;

    string SubFolderNames_Nom;
    int Number_Of_SubFolders;

    string SubFolder_FileNames_Nom;
    string SubFolder_FileNames_Type;
    int Number_Of_Files_In_SubFolder;

    int** NumberOfElements;

    unsigned long int* TotalAtomNumber; // Total number of atoms
};

// ###############################################################################################################################################
// helper functions
// ##############################################################################################################################
// ###############################################################################################################################################

void get_GlobalNucDataPath(std::string Local_NucDataPath, NucDataProperties* NucDataProp) {

    char tmp[PATH_MAX];
    getcwd(tmp, PATH_MAX); // Get the current working directory
    std::string tmp_string = tmp;
    // NucDataProp->GlobalFolderPath = tmp_string + "/" + Local_NucDataPath;
    NucDataProp->GlobalFolderPath = Local_NucDataPath;
    LogSystem::write("found global NucDataPath: " + NucDataProp->GlobalFolderPath);
    LogSystem::write("");
}

void NumberOfEntriesInNucFile(int* NumberOfColumns, string filename) {

    ifstream fin;
    fin.open(filename);
    std::string line;

    float x, y, z, Nuc;

    int line_counter = 0;
    int error_counter = 0;

    while (std::getline(fin, line)) {
        std::istringstream ss(line);
        if (ss >> x >> y >> z >> Nuc) {
            line_counter += 1;
        } else {
            error_counter++;
            //          std::cerr << "Error in row: " << line_counter + error_counter << ": " << line << "\n";
        }
    }
    fin.close();
    *NumberOfColumns = line_counter;
}

bool check_number_of_elements_in_folders_NucData(NucDataProperties* NucDataProp) {

    // Read number of elements in each subfolder
    int Number_Of_Elements[NucDataProp->Number_Of_SubFolders];
    string current_path;
    for (int k = 0; k < NucDataProp->Number_Of_SubFolders; k++) {
        current_path =
            NucDataProp->GlobalFolderPath + "/" + NucDataProp->SubFolderNames_Nom + "_" + std::to_string(k + 1);
        Number_Of_Elements[k] = count_NumberOfElements(current_path);
    }
    LogSystem::write("");

    // check whether number of elements in each subfolder is the same
    bool Check_Flag = true;
    for (int k = 1; k < NucDataProp->Number_Of_SubFolders; k++) {
        if (Number_Of_Elements[k] != Number_Of_Elements[0]) {
            Check_Flag = false;
            break;
        }
    }
    if (Check_Flag) {
        LogSystem::write("Each folder got the same number of elements: " + std::to_string(Number_Of_Elements[0]));
        NucDataProp->Number_Of_Files_In_SubFolder = Number_Of_Elements[0];
    }
    return Check_Flag;
}

bool check_element_names_NucData(NucDataProperties* NucDataProp) {

    // read names of elements in folder with index 1
    std::string ElementNames[NucDataProp->Number_Of_Files_In_SubFolder];
    std::string current_path;
    bool ElementNames_CheckFlag = false;
    std::string FileNames_Type[NucDataProp->Number_Of_SubFolders];
    std::string FileNames_Nom[NucDataProp->Number_Of_SubFolders];

    for (int k = 0; k < NucDataProp->Number_Of_SubFolders; k++) {

        ElementNames_CheckFlag = false;

        // read all element names in current_path directory
        current_path =
            NucDataProp->GlobalFolderPath + "/" + NucDataProp->SubFolderNames_Nom + "_" + std::to_string(k + 1);
        read_FolderNames(current_path, ElementNames, NucDataProp->Number_Of_Files_In_SubFolder);

        // check element names in folder 1
        CheckStrings_ElementNames(ElementNames, NucDataProp->Number_Of_Files_In_SubFolder, &ElementNames_CheckFlag,
                                  &FileNames_Nom[k], &FileNames_Type[k]);

        if (ElementNames_CheckFlag != true) {
            return false;
        }
    }

    // Compare Nom and Type
    for (int k = 1; k < NucDataProp->Number_Of_SubFolders; k++) {
        if (FileNames_Type[k] != FileNames_Type[0] || FileNames_Nom[k] != FileNames_Nom[0]) {
            return false;
        }
    }

    // Store correct Nom and Type
    NucDataProp->SubFolder_FileNames_Nom = FileNames_Nom[0];
    NucDataProp->SubFolder_FileNames_Type = FileNames_Type[0];

    return true;
}

bool check_Subfolders_NucData(NucDataProperties* NucDataProp) {

    // count number of subfolders
    NucDataProp->Number_Of_SubFolders = count_NumberOfFolders(NucDataProp->GlobalFolderPath);
    LogSystem::write("Number of Subfolders: " + std::to_string(NucDataProp->Number_Of_SubFolders));

    // Read all subfolder names
    std::string SubFolderNames[NucDataProp->Number_Of_SubFolders];
    read_FolderNames(NucDataProp->GlobalFolderPath, SubFolderNames, NucDataProp->Number_Of_SubFolders);

    bool FolderNames_CheckFlag = false;
    CheckStrings_FolderNames(SubFolderNames, NucDataProp->Number_Of_SubFolders, &FolderNames_CheckFlag,
                             &NucDataProp->SubFolderNames_Nom);

    LogSystem::write("We found the Nom: " + NucDataProp->SubFolderNames_Nom);
    LogSystem::write("FolderNames CheckFlag: " + std::string(FolderNames_CheckFlag ? "true" : "false"));

    return FolderNames_CheckFlag;
}

bool check_Subfolder_FileNames_NucData(NucDataProperties* NucDataProp) {

    bool Elements_CheckFlag = check_number_of_elements_in_folders_NucData(NucDataProp);

    if (Elements_CheckFlag) {

        bool Element_Names_CheckFlag = check_element_names_NucData(NucDataProp);

        if (Element_Names_CheckFlag) {
            LogSystem::write("We found the Nom: " + NucDataProp->SubFolder_FileNames_Nom +
                             ", and the file Type: " + NucDataProp->SubFolder_FileNames_Type);
            LogSystem::write("");
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

bool check_FileDimensions_NucData(NucDataProperties* NucDataProp, bool FastLoad) {

    string filename;
    // allocate memory
    NucDataProp->NumberOfElements = new int*[NucDataProp->Number_Of_SubFolders];
    for (int i = 0; i < NucDataProp->Number_Of_SubFolders; i++) {
        NucDataProp->NumberOfElements[i] = new int[NucDataProp->Number_Of_Files_In_SubFolder];
    }
    // read the file information
    for (int i = 0; i < NucDataProp->Number_Of_SubFolders; i++) {
        for (int j = 0; j < NucDataProp->Number_Of_Files_In_SubFolder; j++) {
            if (!FastLoad || j == 0) {
                filename = NucDataProp->GlobalFolderPath + "/" + NucDataProp->SubFolderNames_Nom + "_" +
                           std::to_string(i + 1) + "/" + NucDataProp->SubFolder_FileNames_Nom + "_" +
                           std::to_string(j + 1) + "." + NucDataProp->SubFolder_FileNames_Type;
                // NumberOfNonZeroMagneticMomentsInFile(&NucDataProp->NumberOfNonZeroMoments[i][j],
                // &NucDataProp->NumberOfElements[i][j], filename);
                NumberOfEntriesInNucFile(&NucDataProp->NumberOfElements[i][j], filename);
            } else {
                NucDataProp->NumberOfElements[i][j] = NucDataProp->NumberOfElements[i][0];
            }
        }
    }
    return true;
}

void CountAtomNumbers_NucData(NucDataProperties* NucDataProp) {

    NucDataProp->TotalAtomNumber = new unsigned long int[NucDataProp->Number_Of_Files_In_SubFolder];

    for (int k = 0; k < NucDataProp->Number_Of_Files_In_SubFolder; k++) {
        NucDataProp->TotalAtomNumber[k] = 0;
        for (int i = 0; i < NucDataProp->Number_Of_SubFolders; i++) {
            NucDataProp->TotalAtomNumber[k] += NucDataProp->NumberOfElements[i][k];
        }
    }
}

bool ApplyReplicationImport_NucData(NucDataProperties* NucDataProp, int NumberOfReplications) {

    if (NumberOfReplications <= 0) {
        LogSystem::write(" ->-> Error: NucData_NumberOfReplications must be larger than zero.");
        return false;
    }

    if (NucDataProp->Number_Of_SubFolders != 1) {
        LogSystem::write(" ->-> Error: NucData replication import requires exactly one physical template object.");
        LogSystem::write("Physical NucData object folders: " + std::to_string(NucDataProp->Number_Of_SubFolders));
        return false;
    }

    LogSystem::write("NucData replication import active.");
    LogSystem::write("Physical NucData object folders: 1");
    LogSystem::write("Effective NucData object count: " + std::to_string(NumberOfReplications));

    std::vector<int> TemplateNumberOfElements(NucDataProp->Number_Of_Files_In_SubFolder);

    for (int j = 0; j < NucDataProp->Number_Of_Files_In_SubFolder; j++) {
        TemplateNumberOfElements[j] = NucDataProp->NumberOfElements[0][j];
    }

    delete[] NucDataProp->NumberOfElements[0];
    delete[] NucDataProp->NumberOfElements;

    NucDataProp->Number_Of_SubFolders = NumberOfReplications;
    NucDataProp->NumberOfElements = new int*[NucDataProp->Number_Of_SubFolders];

    for (int i = 0; i < NucDataProp->Number_Of_SubFolders; i++) {
        NucDataProp->NumberOfElements[i] = new int[NucDataProp->Number_Of_Files_In_SubFolder];
        for (int j = 0; j < NucDataProp->Number_Of_Files_In_SubFolder; j++) {
            NucDataProp->NumberOfElements[i][j] = TemplateNumberOfElements[j];
        }
    }

    return true;
}

// Routine that checks number of subfolders in MagData directory
bool NucData_Observer(std::string Local_NucDataPath, NucDataProperties* NucDataProp, InputFileData* InputData) {

    LogSystem::write("##########################################################################################");
    LogSystem::write("## Run - NucData Directory Explorer ######################################################");
    LogSystem::write("##########################################################################################");
    LogSystem::write("FastLoad mode: " + std::string(InputData->FastLoad_flag ? "true" : "false"));
    LogSystem::write("");

    bool CheckFlag = false;

    // get global path of the NucData directory
    get_GlobalNucDataPath(Local_NucDataPath, NucDataProp);

    // check the subfolder names
    bool Subfolder_CheckFlag = check_Subfolders_NucData(NucDataProp);

    // Check the files in each subfolder
    bool Subfolder_Elements_CheckFlag = check_Subfolder_FileNames_NucData(NucDataProp);

    bool FileDimensions_CheckFlag = check_FileDimensions_NucData(NucDataProp, InputData->FastLoad_flag);

    bool ReplicationImport_CheckFlag = true;
    if (InputData->NucData_ReplicationImport_flag) {
        ReplicationImport_CheckFlag =
            ApplyReplicationImport_NucData(NucDataProp, InputData->NucData_NumberOfReplications);
    }

    CountAtomNumbers_NucData(NucDataProp);

    for (int i = 0; i < NucDataProp->Number_Of_Files_In_SubFolder; i++) {
        LogSystem::write("total number of atoms in the data set " + std::to_string(i + 1) + ": " +
                         std::to_string(NucDataProp->TotalAtomNumber[i]));
    }

    LogSystem::write("##########################################################################################");
    LogSystem::write("## Stop - NucData Directory Explorer #####################################################");
    LogSystem::write("##########################################################################################");
    LogSystem::write("");

    if (Subfolder_CheckFlag && Subfolder_Elements_CheckFlag && FileDimensions_CheckFlag &&
        ReplicationImport_CheckFlag) {
        CheckFlag = true;
    }

    return CheckFlag;
}