Skip to content
Snippets Groups Projects
WTG_RUB.cpp 32.4 KiB
Newer Older
schoen's avatar
schoen committed
#define _USE_MATH_DEFINES
#include <math.h>
#include <string>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <fstream>
#include <exception>
#include <memory>
#include <filesystem>
schoen's avatar
schoen committed

#include "mpi.h"

//////////////////////////////////////////////////////////////////////////

#include "Core/DataTypes.h"
#include "PointerDefinitions.h"

#include "Core/LbmOrGks.h"
#include "Core/StringUtilities/StringUtil.h"

#include "Core/VectorTypes.h"
#include "Core/Logger/Logger.h"

#include <basics/config/ConfigurationFile.h>

schoen's avatar
schoen committed
//////////////////////////////////////////////////////////////////////////

#include "GridGenerator/grid/GridBuilder/LevelGridBuilder.h"
#include "GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
#include "GridGenerator/grid/BoundaryConditions/Side.h"
schoen's avatar
schoen committed
#include "GridGenerator/grid/BoundaryConditions/BoundaryCondition.h"
schoen's avatar
schoen committed
#include "GridGenerator/grid/GridFactory.h"
#include "GridGenerator/geometries/TriangularMesh/TriangularMesh.h"
#include "GridGenerator/geometries/Conglomerate/Conglomerate.h"

#include "GridGenerator/io/SimulationFileWriter/SimulationFileWriter.h"
#include "GridGenerator/io/GridVTKWriter/GridVTKWriter.h"
#include "GridGenerator/io/STLReaderWriter/STLReader.h"
#include "GridGenerator/io/STLReaderWriter/STLWriter.h"

//////////////////////////////////////////////////////////////////////////

#include "VirtualFluids_GPU/LBM/Simulation.h"
#include "VirtualFluids_GPU/Communication/Communicator.h"
#include "VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
#include "VirtualFluids_GPU/DataStructureInitializer/GridProvider.h"
#include "VirtualFluids_GPU/DataStructureInitializer/GridReaderFiles/GridReader.h"
#include "VirtualFluids_GPU/Parameter/Parameter.h"
#include "VirtualFluids_GPU/Output/FileWriter.h"

#include "VirtualFluids_GPU/Kernel/Utilities/KernelFactory/KernelFactoryImp.h"
#include "VirtualFluids_GPU/PreProcessor/PreProcessorFactory/PreProcessorFactoryImp.h"

#include "VirtualFluids_GPU/GPU/CudaMemoryManager.h"


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//          U s e r    s e t t i n g s
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

LbmOrGks lbmOrGks = LBM;

const real L  = 1.0;

const real velocity  = 1.0;

int variant = 1;
real rotationOfCity;
real z_offset = 0.0; // only if baseplate is in use (currently not!! not important)
schoen's avatar
schoen committed
int dataN;
std::vector<real> dataZ;
std::vector<real> dataVelocity;
std::string simulationName("");
schoen's avatar
schoen committed

// 1: original setup of Lennard Lux (6 level, 4.0 cm -> 1.25 mm)
// 2: setup 1 of MSch               (4 level, 1.0 cm -> 1.25 mm)
// 3: setup 2 of MSch               (5 level, 1.6 cm -> 1.0  mm)
int setupDomain = 3;

std::string path("D:/out/WTG_RUB"); //Mollok
std::string inputPath("D:/out/WTG_RUB/input/");

const uint timeStepStartOut = 0;
const uint timeStepOut = 10000;
const uint timeStepEnd = 100000;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void convertMPFile(SPtr <MultipleGridBuilder> gridBuilder, real& phi, std::vector<real>& origin, bool& measureVeloProfilesOnly, uint& maxLevel);

schoen's avatar
schoen committed
void addFineGrids(SPtr<MultipleGridBuilder> gridBuilder, uint &maxLevel, real &rotationOfCity);

schoen's avatar
schoen committed
void readVelocityProfile();

schoen's avatar
schoen committed
std::string chooseVariation();

void multipleLevel(const std::string& configPath)
{
    logging::Logger::addStream(&std::cout);
    logging::Logger::setDebugLevel(logging::Logger::Level::INFO_LOW);
    logging::Logger::timeStamp(logging::Logger::ENABLE);
    logging::Logger::enablePrintedRankNumbers(logging::Logger::ENABLE);

    auto gridFactory = GridFactory::make();
    gridFactory->setGridStrategy(Device::CPU);
    gridFactory->setTriangularMeshDiscretizationMethod(TriangularMeshDiscretizationMethod::POINT_IN_OBJECT);

    auto gridBuilder = MultipleGridBuilder::makeShared(gridFactory);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    real dx = 0;
    real viscosityLB = (real)1.0e-03;
schoen's avatar
schoen committed
    uint maxLevel    = 1;

    if (setupDomain == 1) {
schoen's avatar
schoen committed
        maxLevel    = 5;
        viscosityLB = (real)3.75e-06; // LB units
schoen's avatar
schoen committed
    } else if (setupDomain == 2) {
schoen's avatar
schoen committed
        maxLevel    = 3;
        viscosityLB = (real)1.5e-05; // LB units
schoen's avatar
schoen committed
    } else if (setupDomain == 3) {
        dx          = (real)1.6;
schoen's avatar
schoen committed
        maxLevel    = 4;
        viscosityLB = (real)9.375e-06; // LB units
schoen's avatar
schoen committed
    }
    
    real x_min = 0.0;
    real x_max = 1250.0;
    real y_min = 0.0;
    real y_max = 190.0;
    real z_min = 0.0 + z_offset;
    real z_max = 160.0 + z_offset;

    //TriangularMesh *RubSTL      = TriangularMesh::make(inputPath + "stl/Var02_0deg_FD_b.stl");
    TriangularMesh *RubSTL      = TriangularMesh::make(inputPath + "stl/" + chooseVariation() + ".stl");
    std::vector<real> originOfCityXY = { 600.0, y_max / 2, z_offset };
schoen's avatar
schoen committed

schoen's avatar
schoen committed
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // OPTIONS

    int maxLevelAtInflow = maxLevel;
    // there are max. 3 levels (0,1,2) at inflow-/x_min-Side if maxLevel >= 3; OTHERWISE: maxLevel
    if (maxLevel >= 3)
        maxLevelAtInflow = 2;

    // MeasurePoints [MP01-15: lvl maxLevel],[MP16-41: lvl 1]; disable when reducing numberOfLevels --> dx might be too
    // large if MP01-15 are used with low resolution dx, MPs might be placed in solid City-geometry
    bool useMP                   = true;
    bool measureVeloProfilesOnly = false;

    // Two Components: true->DiffOn, false->DiffOff
    bool diffOnOff = false;

    // Resetting diff or flow field, e.g. after restart, do not reset diff/flow at start of measureRun ;-)
    bool reset_diff = true;
    bool reset_flow = true;
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
schoen's avatar
schoen committed

    gridBuilder->addCoarseGrid(x_min, y_min, z_min, 
                               x_max, y_max, z_max, dx);

    gridBuilder->setNumberOfLayers(0, 0);

    addFineGrids(gridBuilder, maxLevel, rotationOfCity);

    //// adding solid CityGeometry to gridbuilder
    gridBuilder->addGeometry(RubSTL);

	gridBuilder->setPeriodicBoundaryCondition(false, false, false);

	gridBuilder->buildGrids(lbmOrGks, false); // buildGrids() has to be called before setting the BCs!!!!

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    vf::gpu::Communicator* comm = vf::gpu::Communicator::getInstanz();

    vf::basics::ConfigurationFile config;
    config.load(configPath);

    SPtr<Parameter> para = std::make_shared<Parameter>(config, comm->getNummberOfProcess(), comm->getPID());
schoen's avatar
schoen committed

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    const real velocityLB = (real)0.0844; // LB units
schoen's avatar
schoen committed

	//const real vx = velocityLB / (real)sqrt(2.0); // LB units
	//const real vy = velocityLB / (real)sqrt(2.0); // LB units

    *logging::out << logging::Logger::INFO_HIGH << "velocity  [dx/dt] = " << velocityLB << " \n";
    *logging::out << logging::Logger::INFO_HIGH << "viscosity [dx^2/dt] = " << viscosityLB << "\n";

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	para->setDevices(std::vector<uint>{(uint)0});

    para->setOutputPath( path );
    para->setOutputPrefix( "Unified_" + simulationName );
schoen's avatar
schoen committed

    para->setFName(para->getOutputPath() + "/" + para->getOutputPrefix());

    para->setPrintFiles(true);

    para->setMaxLevel(maxLevel);

    para->setVelocity(velocityLB);
    para->setViscosity(viscosityLB);

    para->setVelocityRatio(velocity/ velocityLB);

	para->setMainKernel("CumulantK17CompChim"); // CumulantK17Unified, CumulantK17CompChim
schoen's avatar
schoen committed

	para->setInitialCondition([&](real coordX, real coordY, real coordZ, real &rho, real &vx, real &vy, real &vz) {
        rho = (real)0.0;
        vx  = (real)0.0; //(6 * velocityLB * coordZ * (L - coordZ) / (L * L));
        vy  = (real)0.0;
        vz  = (real)0.0;
    });

    para->setTOut( timeStepOut );
    para->setTEnd( timeStepEnd );

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    gridBuilder->setVelocityBoundaryCondition(SideType::MX, velocityLB, 0.0, 0.0);
    gridBuilder->setVelocityBoundaryCondition(SideType::PY, 0.0, 0.0, 0.0);
    gridBuilder->setVelocityBoundaryCondition(SideType::MY, 0.0, 0.0, 0.0);
    gridBuilder->setVelocityBoundaryCondition(SideType::PZ, 0.0, 0.0, 0.0);
    gridBuilder->setVelocityBoundaryCondition(SideType::MZ, 0.0, 0.0, 0.0);
    gridBuilder->setVelocityBoundaryCondition(SideType::GEOMETRY, 0.0, 0.0, 0.0);

    gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);

schoen's avatar
schoen committed
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    readVelocityProfile();
    for (int level = 0; level <= maxLevelAtInflow; level++) {
        auto inflowBC = std::dynamic_pointer_cast<VelocityBoundaryCondition>(
            gridBuilder->getBoundaryCondition(SideType::MX, level));

        // lambda function [capture list](parameter list){function body}
        // for every z, loop is being run;
        if (inflowBC) {
            inflowBC->setVelocityProfile(
                gridBuilder->getGrid(level), [&](real x, real y, real z, real &vx, real &vy, real &vz) {
                    int i;
                    for (i = 0; i < dataN; i++) {
                        if ((z < dataZ[i]) || (z == dataZ[i]))
                            break;
                    } // remembers i

                    // if z is below current data point --> interpolation between previous and current datapoint
                    if (z < dataZ[i]) {
                        vx = velocityLB * (dataVelocity[i] + (dataVelocity[i + 1] - dataVelocity[i]) /
                                                                 (dataZ[i + 1] - dataZ[i]) * (z - dataZ[i]));
                    } else if (z == dataZ[i]) {
                        vx = velocityLB * dataVelocity[i];
                    }

                    // vx << std::endl; vx = velocityLB;
                    vy = 0.0;
                    vz = 0.0;
                });
        }
    }

    // Resetting Velocity Profile (returning to intial state; do not combine with restart)
    if (reset_flow) {
        para->setInitialCondition([&](real x, real y, real z, real &rho, real &vx, real &vy, real &vz) {
            int i;
            for (i = 0; i < dataN; i++) {
                if ((z < dataZ[i]) || (z == dataZ[i]))
                    break;
            }
            if (z < dataZ[i]) {
                vx = velocityLB * 0.588 *
                     (dataVelocity[i] +
                      (dataVelocity[i + 1] - dataVelocity[i]) / (dataZ[i + 1] - dataZ[i]) * (z - dataZ[i]));
            } else if (z == dataZ[i]) {
                vx = velocityLB * 0.588 * dataVelocity[i];
            }

            // std::cout << "LINE : " << __LINE__ << "\tdataZ = " << dataZ[i] << "\tz = " << z << "\tvx = " << vx <<
            // std::endl;

            // vx = velocityLB;
            vy  = 0.0;
            vz  = 0.0;
            rho = 0.0;
        });
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Intializing MeasurePoints
    para->setUseMeasurePoints(useMP);
    if (para->getUseMeasurePoints()) {
        convertMPFile(gridBuilder, rotationOfCity, originOfCityXY, measureVeloProfilesOnly, maxLevel);
        // Number log-Files for each MeasurePoint: numberOfMPFiles = timeStepEnd/ClockCycle
        para->setclockCycleForMP(timeStepEnd);
        // Number of  logged Timesteps for each file
        para->settimestepForMP(timeStepOut / 100);
        // para->settimestepForMP(timeStepOut);
        para->setmeasurePoints(inputPath + "measurePoints.dat");
    }
schoen's avatar
schoen committed


schoen's avatar
schoen committed
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    SPtr<CudaMemoryManager> cudaMemoryManager = CudaMemoryManager::make(para);

    SPtr<GridProvider> gridGenerator = GridProvider::makeGridGenerator(gridBuilder, para, cudaMemoryManager);

    Simulation sim;
    SPtr<FileWriter> fileWriter = SPtr<FileWriter>(new FileWriter());
    SPtr<KernelFactoryImp> kernelFactory = KernelFactoryImp::getInstance();
    SPtr<PreProcessorFactoryImp> preProcessorFactory = PreProcessorFactoryImp::getInstance();
    sim.setFactories(kernelFactory, preProcessorFactory);
    sim.init(para, gridGenerator, fileWriter, cudaMemoryManager);
    sim.run();
    sim.free();

}

schoen's avatar
schoen committed
void readVelocityProfile()
{
    // reads velocityProfile.txt, containing values for relative velocity (u_h) in relation to height (z). also fills
    // dataZ,dataVelocity vectors

    std::ifstream inFile;
    inFile.open(inputPath + "VeloProfile.txt");
    //inFile.open(inputPath + "velocityProfile.txt");

    if (inFile.fail()) {
        std::cerr << "Error opening File" << std::endl;
        exit(1);
    }

    int z;
    real velocity;

    // read
    inFile >> dataN;
    for (int k = 0; k < dataN; k++) {
        inFile >> z;
        dataZ.push_back(z + z_offset);

        inFile >> velocity;
        dataVelocity.push_back(velocity);
    }
    inFile.close();
}

schoen's avatar
schoen committed
void addFineGrids(SPtr<MultipleGridBuilder> gridBuilder, uint &maxLevel, real &rotationOfCity)
{
    if (setupDomain == 1) {
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
        // creates Cuboids (FG1 to FG3, lvl 1 to lvl 3) and add STLs (FG4 to FG5, lvl 4 to lvl 5) depending on maxLevel
        // and rotationOfCity; also adds FineGrids(FGs) to gridbuilder

        // GridList(CG = coarse grid, fg = fine grid)
        // CG  -> dx = 4 cm;      lvl 0
        // FG1 -> dx = 2 cm;      lvl 1
        // FG2 -> dx = 1 cm;      lvl 2
        // FG3 -> dx = 5 mm;      lvl 3
        // FG4 -> dx = 2,5 mm;    lvl 4
        // FG5 -> dx = 1,25 mm;   lvl 5
        //
        // FineGrid Level 1 ->dx = 2 cm; lvl 1
        auto FG1 = new Cuboid(-20, -20, -5 + z_offset, 800, 200, 75 + z_offset);

        // FineGrid Level 2 -> dx = 1 cm; lvl 2
        auto FG2_1 = new Cuboid(-20, -20, -5 + z_offset, 760, 200, 10 + z_offset);
        auto FG2_2 = new Cuboid(500, -20,  5 + z_offset, 680, 210, 50 + z_offset);
        auto FG2   = new Conglomerate();
        FG2->add(FG2_1);
        FG2->add(FG2_2);

        // FineGrid Level 3 ->dx = 5 mm; lvl 3
        auto FG3_1 = new Cuboid(517, -20, -5 + z_offset, 665, 200, 30 + z_offset);
        auto FG3_2 = new Cuboid(550, 58, -5 + z_offset, 650, 132, 40 + z_offset);
        auto FG3   = new Conglomerate();
        FG3->add(FG3_1);
        FG3->add(FG3_2);

        // Adding FineGrids 1 to 5 depending on maxLevel, FG4 and FG5 require different STL-files depending on
        // rotationOfCity
        if (maxLevel >= 1) {
            gridBuilder->addGrid(FG1, 1);
            if (maxLevel >= 2) {
                gridBuilder->addGrid(FG2, 2);
                if (maxLevel >= 3) {
                    gridBuilder->addGrid(FG3, 3);
                    if (maxLevel >= 4) {
                        if (rotationOfCity == 0.0) {
                            TriangularMesh *FG4 = TriangularMesh::make(inputPath + "stl/FG4_0deg.stl");
                            gridBuilder->addGrid(FG4, 4);
                        } else {
                            TriangularMesh *FG4 = TriangularMesh::make(inputPath + "stl/FG4_63deg.stl");
                            gridBuilder->addGrid(FG4, 4);
                        }

                        if (maxLevel == 5) {
                            if (rotationOfCity == 0.0) {
                                TriangularMesh *FG5 = TriangularMesh::make(inputPath + "stl/FG5_0deg.stl");
                                gridBuilder->addGrid(FG5, 5);
                            } else {
                                TriangularMesh *FG5 = TriangularMesh::make(inputPath + "stl/FG5_63deg.stl");
                                gridBuilder->addGrid(FG5, 5);
                            }
                        }
                    }
                }
            }
        }
    }
    else if (setupDomain == 2) {
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
        // creates Cuboids (FG1, lvl 1) and add STLs (FG2 to FG3, lvl 2 to lvl 3) depending on maxLevel
        // and rotationOfCity; also adds FineGrids(FGs) to gridbuilder
        //
        // GridList(CG = coarse grid, fg = fine grid)
        // CG  -> dx = 1 cm;      lvl 0
        // FG1 -> dx = 5 mm;      lvl 1
        // FG2 -> dx = 2,5 mm;    lvl 2
        // FG3 -> dx = 1,25 mm;   lvl 3
        //
        // FineGrid Level 1 -> dx = 5 mm; lvl 1
        //auto FG1_1 = new Cuboid(-20, -20, -5 + z_offset, 760, 200, 10 + z_offset);
        auto FG1_1 = new Cuboid(-20, -20, -5 + z_offset, 760, 200, 20 + z_offset);
        auto FG1_2 = new Cuboid(500, -20,  5 + z_offset, 680, 210, 50 + z_offset);
        auto FG1   = new Conglomerate();
        FG1->add(FG1_1);
        FG1->add(FG1_2);

        // Adding FineGrids 1 to 5 depending on maxLevel, FG4 and FG5 require different STL-files depending on
        // rotationOfCity
        if (maxLevel >= 1) {
            gridBuilder->addGrid(FG1, 1);
            if (maxLevel >= 2) {
                if (rotationOfCity == 0.0) {
                    TriangularMesh *FG2 = TriangularMesh::make(inputPath + "stl/FG4_0deg.stl");
                    gridBuilder->addGrid(FG2, 2);
                } else {
                    TriangularMesh *FG2 = TriangularMesh::make(inputPath + "stl/FG4_63deg.stl");
                    gridBuilder->addGrid(FG2, 2);
                }

                if (maxLevel == 3) {
                    if (rotationOfCity == 0.0) {
                        TriangularMesh *FG3 = TriangularMesh::make(inputPath + "stl/FG5_0deg.stl");
                        gridBuilder->addGrid(FG3, 3);
                    } else {
                        TriangularMesh *FG3 = TriangularMesh::make(inputPath + "stl/FG5_63deg.stl");
                        gridBuilder->addGrid(FG3, 3);
                    }
                }
            }
        }
    } 
    else if (setupDomain == 3) {
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
        // creates Cuboids (FG1 to FG2, lvl 1 to lvl 2) and add STLs (FG3 to FG4, lvl 3 to lvl 4) depending on maxLevel
        // and rotationOfCity; also adds FineGrids(FGs) to gridbuilder

        // GridList(CG = coarse grid, fg = fine grid)
        // CG  -> dx = 1.6 cm;   lvl 0
        // FG1 -> dx = 8.0 mm;   lvl 1
        // FG2 -> dx = 4.0 mm;   lvl 2
        // FG3 -> dx = 2.0 mm;   lvl 3
        // FG4 -> dx = 1.0 mm;   lvl 4
        //
        //// FineGrid Level 1 ->dx = 8.0 mm; lvl 1
        //auto FG1 = new Cuboid(-20, -20, -5 + z_offset, 800, 200, 75 + z_offset);

        // FineGrid Level 1 -> dx = 8.0 mm; lvl 1
        auto FG1_1 = new Cuboid(-20, -20, -5 + z_offset, 780, 200, 30 + z_offset);
        auto FG1_2 = new Cuboid(500, -20,  5 + z_offset, 720, 210, 75 + z_offset);
        auto FG1   = new Conglomerate();
        FG1->add(FG1_1);
        FG1->add(FG1_2);

        // FineGrid Level 2 -> dx = 4.0 mm; lvl 2
        auto FG2_1 = new Cuboid(-20, -20, -5 + z_offset, 760, 200, 10 + z_offset);
        auto FG2_2 = new Cuboid(520, -20,  5 + z_offset, 700, 210, 50 + z_offset);
        auto FG2   = new Conglomerate();
        FG2->add(FG2_1);
        FG2->add(FG2_2);

        // Adding FineGrids 1 to 4 depending on maxLevel, FG3 and FG4 require different STL-files depending on
        // rotationOfCity
        if (maxLevel >= 1) {
            gridBuilder->addGrid(FG1, 1);
            if (maxLevel >= 2) {
                gridBuilder->addGrid(FG2, 2);
                if (maxLevel >= 3) {
                    if (rotationOfCity == 0.0) {
                        TriangularMesh *FG3 = TriangularMesh::make(inputPath + "stl/FG4_0deg.stl");
                        gridBuilder->addGrid(FG3, 3);
                    } else {
                        TriangularMesh *FG3 = TriangularMesh::make(inputPath + "stl/FG4_63deg.stl");
                        gridBuilder->addGrid(FG3, 3);
                    }

                    if (maxLevel == 4) {
                        if (rotationOfCity == 0.0) {
                            TriangularMesh *FG4 = TriangularMesh::make(inputPath + "stl/FG5_0deg.stl");
                            gridBuilder->addGrid(FG4, 4);
                        } else {
                            TriangularMesh *FG4 = TriangularMesh::make(inputPath + "stl/FG5_63deg.stl");
                            gridBuilder->addGrid(FG4, 4);
                        }
                    }
                }
            }
        }
    }



}

void convertMPFile(SPtr<MultipleGridBuilder> gridBuilder, real &phi, std::vector<real> &originXY, bool &measureVeloProfilesOnly, uint &maxLevel)
{
    // File Reader&Writer for converting MP-Coordinates to Index: MeasurePoint placement requires "measurePoints.dat"
    // with name, node-ID and level. This function can read a txt-File containing the name, X-Y-Z-Coordinates and level
    // of measurePoints. After reading the txt-File and converting X-Y-Z to the node-ID, it writes "measurePoints.dat".
    // Justification for this function: Human Readability and no changes in measurepoint core functions

    // File Opening Procedure
    std::ifstream inFile;
    if (measureVeloProfilesOnly)
        inFile.open(inputPath + "measurePoints_veloProfiles.txt");
    else
        inFile.open(inputPath + "measurePoints.txt");

    // Check for error
    if (inFile.fail()) {
        std::cerr << "Error opening File" << std::endl;
        exit(1);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Reading Procedure
    std::cout << "phi in degrees:" << phi << std::endl;
    phi = phi * M_PI / 180;
    std::cout << "phi in radians:" << phi << std::endl;

    std::vector<std::string> MP_name;
    std::vector<real> MP_X, MP_Y, MP_Z;
    std::vector<int> MP_level, MP_k;

    std::string name;
    real X, Y, Z;
    uint level, numberOfMeasurePoints;

    inFile >> numberOfMeasurePoints;
    std::cout << "numberOfMeasurePoints: " << numberOfMeasurePoints << " ";
    std::cout << "Coordinates from File\n";
    for (uint k = 0; k < numberOfMeasurePoints; k++) {
        inFile >> name;
        MP_name.push_back(name);
        std::cout << "Name: " << MP_name[k] << " ";

        inFile >> X;
        MP_X.push_back(X);
        std::cout << "\t\tX: " << MP_X[k] << " ";

        inFile >> Y;
        MP_Y.push_back(Y);
        std::cout << "\t\tY: " << MP_Y[k] << " ";

        inFile >> Z;
        if (((variant > 3 && variant < 7) || (variant > 9 && variant <= 12)) && k == 14)
            Z += 2.25; // account for angled roof
        MP_Z.push_back(Z);
        std::cout << "\t\tZ: " << MP_Z[k] + z_offset << " ";

        inFile >> level;
        if (level > maxLevel)
            level = maxLevel;
        MP_level.push_back(level);
        std::cout << "\t\tLevel: " << MP_level[k] << std::endl;
    }
    inFile.close();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    real X_temp, Y_temp;
    // Transformation for phi radians around centre of city for MP[1..15]
    if (!phi == 0) {
        std::cout << "Calculating new Coordinates for MP01 to MP15 after Rotation of " << phi * 180 / M_PI
                  << "degrees (+: counter-clockwise / -: clockwise)\n";
        for (uint k = 0; k < 15; k++) {
            X_temp = originXY[0] + (MP_X[k] - originXY[0]) * cos(phi) - (MP_Y[k] - originXY[1]) * sin(phi);
            Y_temp = originXY[1] + (MP_X[k] - originXY[0]) * sin(phi) + (MP_Y[k] - originXY[1]) * cos(phi);
            std::cout << "Name:  " << MP_name[k] << " ";
            std::cout << "\t\tX: " << X_temp << " ";
            std::cout << "\t\tY: " << Y_temp << " ";
            std::cout << "\t\tZ: " << MP_Z[k] << " " << std::endl;

            MP_X[k] = X_temp;
            MP_Y[k] = Y_temp;
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Coordinates to Index Procedure
    // std::cout << "Converting Coordinates to Index..." << std::endl;
    for (uint k = 0; k < numberOfMeasurePoints; k++) {
        MP_k.push_back(
            gridBuilder->getGrid(MP_level[k])
                ->getSparseIndex(gridBuilder->getGrid(MP_level[k])->transCoordToIndex(MP_X[k], MP_Y[k], MP_Z[k])));
        if (MP_k[k] == -1) {
            std::cerr << "Error: Could not convert Coordinate to Sparse Index for MP " << k + 1 << std::endl;
        }
        std::cout << MP_name[k] << "\tID = "
                  << gridBuilder->getGrid(MP_level[k])
                         ->getSparseIndex(
                             gridBuilder->getGrid(MP_level[k])->transCoordToIndex(MP_X[k], MP_Y[k], MP_Z[k]))
                  << std::endl;
        // std::cout << "ID = " <<
        // gridBuilder->getGrid(0)->getSparseIndex(gridBuilder->getGrid(0)->transCoordToIndex(-0.500000,
        // -0.500000, 9.500000)) << std::endl;
    }
    // std::cout << "Done Converting Coordinates to Index..." << std::endl;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Writing Procedure
    // std::cout << "Writing new file..." << std::endl;
    std::ofstream outFile(inputPath + "measurePoints.dat");

    outFile << numberOfMeasurePoints << std::endl;
Martin Schönherr's avatar
Martin Schönherr committed
    for (uint j = 0; j < numberOfMeasurePoints; j++) {
        outFile << MP_name[j] << " " << MP_k[j] << " " << MP_level[j] << std::endl;
        // std::cout << MP_name[j] << "\t" << MP_k[j] << "\t" << MP_level[j] << std::endl;
    }
    // std::cout << "Done writing new file..." << std::endl;
    outFile.close();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

schoen's avatar
schoen committed
std::string chooseVariation()
{
    switch (variant) {
        case 1:
            simulationName = "Var01_0deg_FD_a";
            break;
        case 2:
            simulationName = "Var02_0deg_FD_b";
            break;
        case 3:
            simulationName = "Var03_0deg_FD_c";
            break;
        case 4:
            simulationName = "Var04_0deg_SD_a";
            break;
        case 5:
            simulationName = "Var05_0deg_SD_b";
            break;
        case 6:
            simulationName = "Var06_0deg_SD_c";
            break;
        case 7:
            simulationName = "Var07_63deg_FD_a";
            break;
        case 8:
            simulationName = "Var08_63deg_FD_b";
            break;
        case 9:
            simulationName = "Var09_63deg_FD_c";
            break;
        case 10:
            simulationName = "Var10_63deg_SD_a";
            break;
        case 11:
            simulationName = "Var11_63deg_SD_b";
            break;
        case 12:
            simulationName = "Var12_63deg_SD_c";
            break;
        default:
            std::cerr << "Warning: no variant selected. Running with Default variant V01!" << std::endl;
            simulationName = "Var01_0deg_FD_a";
            rotationOfCity = 0.0;
            return simulationName;
    }

    if ((0 < variant) && (variant <= 6))
        rotationOfCity = (real)0.0;
schoen's avatar
schoen committed
    else if ((6 < variant) && (variant <= 12))
        rotationOfCity = (real)63.295;
schoen's avatar
schoen committed

    std::cout << "Variant selected. Simulation name is: " << simulationName << std::endl;
    std::cout << "Rotation selected: " << rotationOfCity << std::endl;

    return simulationName;
}


int main( int argc, char* argv[])
{
    MPI_Init(&argc, &argv);
    if ( argv != NULL )
    {
        try
        {
            // assuming that the config files is stored parallel to this file.
            std::filesystem::path filePath = __FILE__;
            filePath.replace_filename("configDrivenCavity.txt");
schoen's avatar
schoen committed

            multipleLevel(filePath.string());
        }
schoen's avatar
schoen committed
        catch (const std::bad_alloc& e)
        { 
            *logging::out << logging::Logger::LOGGER_ERROR << "Bad Alloc:" << e.what() << "\n";
        }
        catch (const std::exception& e)
        {   
            *logging::out << logging::Logger::LOGGER_ERROR << e.what() << "\n";
        }
        catch (...)
        {
            *logging::out << logging::Logger::LOGGER_ERROR << "Unknown exception!\n";
        }
    }

   MPI_Finalize();
   return 0;
}